项目简介

利用Container、Gitlab、Gitlab Runner(k8s)、SonarQube、Harbor、Jmeter、Maven、Java技术,搭建一个完整的 CI/CD 管道,实现当开发人员完成代码提交后,开始流水线工作,完成编译打包、单元测试、源码扫描、上传制品、部署服务到Docker容器、自动化测试工作。通过自动化构建、测试、代码质量检查和容器化部署,将开发人员从繁琐的手动操作中解放出来,提高团队的开发效率、软件质量和安全性,实现持续更新迭代和持续部署交付。

CI/CD流程图

gitops-gitlab+k8s.drawio.png

流程说明

  1. 开发人员将代码提交到Gitlab代码仓库时,触发持续构建和持续部署流程。
  2. k8s Runner通过maven镜像实现编译打包、单元测试操作。
  3. k8s Runner通过sonar-scanner镜像请求sonarqube服务,实现源码扫描操作。
  4. k8s Runner通过docker-dind镜像实现项目镜像构建并推送至Harbor镜像仓库。
  5. k8s Runner通过执行shell脚本完成镜像拉取以及启动容器服务操作。
  6. k8s Runner通过jmeter镜像实现自动化测试操作。
  7. 流水线执行完成后,将结果邮件通知给开发和运维人员。
  8. 用户访问项目服务器。

k8s资源列表

服务名称Service/ingress地址端口
镜像构建服务buildkitd.cicd.svc1234
代码托管服务gitlab.cicd.svc80
代码扫描服务sonarqube-sonarqube.cicd.svc9000
镜像仓库服务harbor.local.com443

准备工作

服务部署

镜像构建服务部署

关于镜像构建问题,如果k8s容器运行时为docker,可以直接使用docker in docker方案,启动一个docker:dind容器,通过绑定宿主机/var/run/docker.sock即可调用。
如果k8s容器运行时为container,则推荐使用nerdctl+buildkitd方案,启动一个buildkitd服务并暴露1234端口提供构建镜像服务,通过nerdctl命令请求buildkitd服务,执行镜像构建与推送操作,具体内容可参考
https://www.cuiliangblog.cn/detail/section/167380911
本次实验以container环境为例,通过nerdctl+buildkitd方案,实现构建并推送镜像。

  • buildkitd-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: buildkitd-config
  namespace: cicd
data:
  buildkitd.toml: |-
    debug = true
    [registry."docker.io"]
      mirrors = ["934du3yi.mirror.aliyuncs.com"]
    [registry."harbor.local.com"]
      http = false
  • buildkitd-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: buildkitd
  name: buildkitd
  namespace: cicd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: buildkitd
  template:
    metadata:
      labels:
        app: buildkitd
    spec:
      containers:
        - name: buildkitd
          # image: moby/buildkit:master-rootless
          image: harbor.local.com/cicd/buildkit:master-rootless
          args:
            - --addr
            - tcp://0.0.0.0:1234
            - --addr
            - unix:///run/user/1000/buildkit/buildkitd.sock
            - --config
            - /etc/buildkitd/buildkitd.toml
          resources:
            requests:
              memory: "1Gi"
              cpu: "1"
            limits:
              memory: "4Gi"
              cpu: "4"
          readinessProbe:
            exec:
              command:
                - buildctl
                - debug
                - workers
          livenessProbe:
            exec:
              command:
                - buildctl
                - debug
                - workers
          securityContext:
            privileged: true
          ports:
            - containerPort: 1234
          volumeMounts:
            - mountPath: /etc/buildkitd
              name: config
      volumes:
        - name: config
          configMap:
            name: buildkitd-config

  • buildkitd-svc.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: buildkitd
  name: buildkitd
  namespace: cicd
spec:
  ports:
    - port: 1234
      protocol: TCP
  selector:
    app: buildkitd

Runner镜像构建

Runner不仅要构建镜像,还需要操作k8s资源,因此需要构建一个名为gitlab-runner-agent的镜像,dockerfile内容如下:

FROM alpine:latest
USER root
COPY kubectl /usr/bin/kubectl
COPY nerdctl /usr/bin/nerdctl
COPY buildctl /usr/bin/buildctl

部署gitlab-runner与优化

部署gitlab-runner具体内容可参考https://www.cuiliangblog.cn/detail/section/172302364,此处不再赘述,注册后的runner效果如下:
image.png
部署完gitlab-runner后可根据实际情况进行runner优化,具体可参考文档:https://www.cuiliangblog.cn/detail/section/174152592

流水线镜像构建

需要构建maven、sonar-scanner、jmeter镜像,具体可参考文档:https://www.cuiliangblog.cn/detail/section/172326640

模板库资源更新

模板库具体介绍可参考文档:https://www.cuiliangblog.cn/detail/section/173479217,本文是在gitlab+Linux项目基础上补充模板库内容。

deploy.yml

# 服务部署
.deploy-linux: # 部署到linux系统
  stage: deploy
  tags:
    - deploy
  script:
    - sh -x $DEPLOY_PATH $ARTIFACT_USER $ARTIFACTORY_KEY /opt/$ARTIFACT_URL_PATH $ARTIFACTORY_PUBLIC_URL/$ARTIFACT_REPO/$ARTIFACT_URL_PATH

.deploy-docker: # 部署到docker环境
  stage: deploy
  image: harbor.local.com/cicd/docker:dind # 在部署阶段使用docker:dind镜像操作
  tags:
    - docker
  script:
    - sh -x $DEPLOY_PATH $HARBOR_USER $HARBOR_PASSWORD $IMAGE_FULL_NAME $CI_PROJECT_NAME

.deploy-k8s: # 部署到k8s环境
  stage: deploy
  image: harbor.local.com/cicd/gitlab-runner-agent:v1.0 # 在部署阶段使用自定义镜像操作
  tags:
    - k8s
  script:
    - echo $NAME_SPACE
    - echo $DOMAIN_NAME
    - echo $IMAGE_FULL_NAME
    - sed -i "s|NAME_SPACE|${NAME_SPACE}|g" cicd/k8s.yaml
    - sed -i "s|DOMAIN_NAME|${DOMAIN_NAME}|g" cicd/k8s.yaml
    - sed -i "s|IMAGE_NAME|${IMAGE_FULL_NAME}|g" cicd/k8s.yaml
    - cat cicd/k8s.yaml
    - kubectl apply -f cicd/k8s.yaml

harbor.yml

# 镜像上传与下载
variables: # 全局变量
  HARBOR_URL: harbor.local.com # harbor仓库地址
  IMAGE_FULL_NAME: "$HARBOR_URL/$HARBOR_REPO/$IMAGE_NAME"

.docker-upload-harbor:
  stage: upload-harbor
  image: harbor.local.com/cicd/docker:dind # 在构建镜像阶段使用docker:dind镜像操作
  tags: # 在docker机器构建镜像
    - docker
  before_script:
    - cat $DOCKERFILE_PATH 
  script:
    - docker build -f $DOCKERFILE_PATH -t $IMAGE_FULL_NAME .
    - docker login $HARBOR_URL -u $HARBOR_USER -p $HARBOR_PASSWORD # 登录harbor
    - docker push $IMAGE_FULL_NAME # 上传镜像
    - docker rmi -f $IMAGE_FULL_NAME # 删除镜像

.docker-download-harbor:
  stage: download-harbor
  image: harbor.local.com/cicd/docker:dind # 在构建镜像阶段使用docker:dind镜像操作
  tags:
    - docker
  script:
    - docker login $HARBOR_URL -u $HARBOR_USER -p $HARBOR_PASSWORD # 登录harbor
    - docker pull $IMAGE_FULL_NAME # 下载镜像
  after_script:
    - docker images

.container-upload-harbor:
  stage: upload-harbor
  image: harbor.local.com/cicd/gitlab-runner-agent:v1.0 # 在构建镜像阶段使用自定义镜像操作
  tags: # 在k8s机器构建镜像
    - k8s
  before_script:
    - cat $DOCKERFILE_PATH 
  script:
    - nerdctl build --buildkit-host tcp://buildkitd.cicd.svc:1234 -f $DOCKERFILE_PATH -t $IMAGE_FULL_NAME .
    - nerdctl login $HARBOR_URL --insecure-registry -u $HARBOR_USER -p $HARBOR_PASSWORD # 登录harbor
    - nerdctl push $IMAGE_FULL_NAME --insecure-registry # 上传镜像
    - nerdctl rmi -f $IMAGE_FULL_NAME # 删除镜像

.container-download-harbor:
  stage: download-harbor
  image: harbor.local.com/cicd/gitlab-runner-agent:v1.0 # 在构建镜像阶段使用自定义镜像操作
  tags:
    - k8s
  script:
    - nerdctl login --insecure-registry $HARBOR_URL -u $HARBOR_USER -p $HARBOR_PASSWORD # 登录harbor
    - nerdctl pull $IMAGE_FULL_NAME --insecure-registry # 下载镜像
  after_script:
    - nerdctl images

流水线项目创建

项目代码仓库地址

gitee:https://gitee.com/cuiliang0302/spring_boot_demo
github:https://github.com/cuiliang0302/spring-boot-demo

gitlab项目权限配置

具体参考文档:https://www.cuiliangblog.cn/detail/section/169621642

配置密钥变量

进入项目——>设置——>CI/CD——>变量
新建SONAR_QUBE_TOEKN、HARBOR_PASSWORD两个变量,取消保护变量,并勾选隐藏变量。
变量配置信息内容如下:
下载.png
ARTIFACTORY_KEY cmVmdGtuOjAxOjE3NDk5OTgyMzk6SVA4bjlCRm9URWNlSUhUVDg3QW9yTm9HWllQ
SONAR_QUBE_TOEKN squ_5583fe4ce47851eb16a1ce638b4681d931505ccc
squ_16cc9225bf7fe70ce4f55a851efb41fede1fb80a

配置邮件发送

具体可参考文档:https://www.cuiliangblog.cn/detail/section/173068275

流水线配置

在项目根目录下创建.gitlab-ci.yml文件,流水线内容如下

include: # 引入模板库公共文件
  - project: 'devops/gitlabci-template'
    ref: master
    file: 'jobs/build.yml'
  - project: 'devops/gitlabci-template'
    ref: master
    file: 'jobs/test.yml'
  - project: 'devops/gitlabci-template'
    ref: master
    file: 'jobs/sonarqube.yml'
  - project: 'devops/gitlabci-template'
    ref: master
    file: 'jobs/harbor.yml'
  - project: 'devops/gitlabci-template'
    ref: master
    file: 'jobs/deploy.yml'
  - project: 'devops/gitlabci-template'
    ref: master
    file: 'jobs/jmeter.yml'

variables: # 全局变量
  SONAR_QUBE_PATH: "$CI_PROJECT_DIR/cicd/sonar-project.properties" # sonarqube配置文件地址
  # 镜像上传
  HARBOR_REPO: devops # harbor仓库名
  HARBOR_USER: admin # harbor用户名
  DOCKERFILE_PATH: cicd/Dockerfile # Dockerfile文件路径
  IMAGE_NAME: "$CI_PROJECT_NAME:$CI_COMMIT_BRANCH-$CI_COMMIT_SHORT_SHA" # 镜像名称
  # 服务部署
  DEPLOY_PATH: "$CI_PROJECT_DIR/cicd/deployment-docker.sh" # 服务部署脚本路径
  # 自动化测试
  JMETER_PATH: "$CI_PROJECT_DIR/cicd/jmeter/demo.jmx" # 自动化测试脚本路径

default:
  cache: # 全局缓存配置
    paths:
      - target/

stages:
  - build
  - code_scan
  - product
  - deploy
  - test

mvn: # 编译打包
  stage: build
  extends: .mvn-build
  image: harbor.local.com/cicd/maven:v3.9.3 # 构建阶段使用指定的maven镜像
  tags:
    - k8s
  
unit_test: # 单元测试
  stage: build
  extends: .mvn_unit_test
  image: harbor.local.com/cicd/maven:v3.9.3 # 构建阶段使用指定的maven镜像
  tags:
    - k8s

code_scan: # SonarQube代码扫描
  stage: code_scan
  extends: .sonarqube
  image: harbor.local.com/cicd/sonar-scanner-cli:10 # 代码扫描阶段使用sonar-scanner-cli镜像
  before_script:
    - ls target/
  tags:
    - k8s
  
product: # 上传到harbor仓库
  stage: product
  extends: .container-upload-harbor
  tags:
    - k8s

deploy_to_prod: # 部署到生产环境
  stage: deploy
  extends: .deploy-k8s
  rules:
    - if: '$CI_COMMIT_BRANCH == "master"'
  tags: 
    - k8s
  variables:
    NAME_SPACE: prod
    DOMAIN_NAME: prod.local.com
  after_script:
    - sleep 10
    - kubectl get pod -n $NAME_SPACE -o wide
  environment: # 生产环境
    name: production
    url: http://$DOMAIN_NAME

deploy_to_test: # 部署到测试环境
  stage: deploy
  extends: .deploy-k8s
  rules:
    - if: '$CI_COMMIT_BRANCH == "test"'
  tags: 
    - k8s
  variables:
    NAME_SPACE: prod
    DOMAIN_NAME: prod.local.com
  after_script:
    - sleep 10
    - kubectl get pod -n $NAME_SPACE -o wide
  environment: # 测试环境
    name: test
    url: http://$DOMAIN_NAME

pages: # 自动化测试并收集测试报告
  stage: test
  extends: .jmeter
  image: harbor.local.com/cicd/jmeter:5.6.3 # 自动化阶段使用jmeter镜像
  tags: 
    - k8s

结果验证

pod信息查看

[root@tiaoban ~]# kubectl get pod -n prod
NAME                    READY   STATUS    RESTARTS   AGE
demo-655457bb99-9s8hr   1/1     Running   0          51s

其他效果与之前gitlab+linux效果类似,区别在于本次全程使用k8s类型runner运行job任务。

查看更多

微信公众号

微信公众号同步更新,欢迎关注微信公众号《崔亮的博客》第一时间获取最近文章。

博客网站

崔亮的博客-专注devops自动化运维,传播优秀it运维技术文章。更多原创运维开发相关文章,欢迎访问https://www.cuiliangblog.cn

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐