CI/CD 概念

CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。CI/CD 的核心概念是持续集成、持续交付和持续部署。作为一种面向开发和运维团队的解决方案,CI/CD 主要针对在集成新代码时所引发的问题(亦称:“集成地狱”)。

具体而言,CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试阶段,到交付和部署)。

下图展示了当前比较典型的持续构建集成的一种做法。

图片

大概流程为我们研发工程师代码提交到 GitLab 之后,使用 GitLab 的流水线自动编译打包 docker 镜像,提交到 Harbor,然后通知 Kuboard 进行自动拉取镜像,部署最新代码。

废话不多说,我们进入实战环节。

先决条件

  1. 搭建 GitLab 服务
  2. 搭建 Harbor 服务
  3. 搭建 K8s 集群以及 Kuboard 服务

请注意,因为 k8s 在1.20.x(包含)版本以后弃用 docker 运行容器而采用containerd ,因此本案例采用的是 1.19.5 版本的 k8s 集群,安装时请留意。

安装注册 GitLab Runner

curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | sudo bash

# 搜索可用版本
yum list gitlab-runner --showuplicates | sort -r

# 指定版本安装
yum install gitlab-runner-10.8.2-1 -y --nogpgcheck

# 注册 runner,executor 选择使用 docker,表示在 docker 容器中执行我们的 ci 流程
sudo gitlab-runner register -n \
  --url http://gitlab.example.com/ \
  --registration-token YOUR-REGISTRATION-TOKEN \
  --executor docker \
  --docker-image "docker:20.10.16" \
  --docker-privileged \
  --docker-volumes "/certs/client" \
  --docker-volumes "/var/run/docker.sock:/var/run/docker.sock"

如何查看 registration-token?管理员账户登录GitLab,进入“管理区域”页面,左侧“概述”菜单下选择“Runners”,即可看到 registration-token。如下图
图片

项目配置 .gitlab-ci.yml

自定义 maven 镜像

因为我们的后端项目需要从 maven 私服拉取二方库,因此需要在将私服的 settings 配置文件加入到镜像中去,以便后续在 docker 容器中编译代码时可以访问 maven 私服拉取依赖。

创建Dockerfile 如下:

FROM maven:3.6.3-jdk-11-slim
ADD ./settings.xml /root/.m2/settings.xml

然后执行命令构建并推送 maven 镜像至镜像私服。

# 构建 maven 镜像
docker build -f /path/to/your/Dockerfile . -t harbor.example.com/respository/maven:3.6.3-jdk-11-slim
# 推送至私服,推送前记得使用 docker login 登录私服
docker push harbor.example.com/respository/maven:3.6.3-jdk-11-slim

获取 Kuboard CI 脚本

Kuboard 获取 CI 脚本非常简单,找到需要集成的项目,然后选择 "CI/CD 集成",根据提示选择(没有则创建)秘钥即可获得脚本,此脚本用于在将 docker 镜像推送私服后,通知 Kuboard 更新镜像。如下图所示。
基于 Gitlab + Harbor + K8s + Kuboard 的 CI 实践-小白菜博客
获取 cicd 脚本

后端配置模板

在项目根目录创建 .gitlab-ci.yml 文件,以 Java 项目为例,配置文件内容模板如下:

image: docker:20.10.16

variables:
  DOCKER_TLS_CERTDIR: "/certs"
  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"

# maven 缓存,不必每次打包都从远程仓库下载 jar 包
cache:
  paths:
    - .m2/repository
    - target/*.jar

stages:
  - build
  - package
  - deploy

build-jar:
  # 流程节点使用的基础镜像,使用该镜像创建容器,在容器中执行 script 中所配置的命令
  # 如果你是前端项目,可以变更改镜像,例如使用 node:latest,script 配置为 npm install build:prod
  image: harbor.mgdaas-int.com/arch/maven:3.6.3-jdk-11-slim
  stage: build
  script:
    - mvn clean package -DskipTests=true
  artifacts:
    paths:
      - target/*.jar
  cache:
    paths:
      - .m2/repository

build-docker-image:
  stage: package
  services:
    - name: docker:dind
      entrypoint: [ "dockerd-entrypoint.sh", "--tls=false" ]
  before_script:
    - docker login harbor.mgdaas-int.com --username admin --password Harbor123
  script:
    - docker  build . -t harbor.mgdaas-int.com/mgdaas-gateway/mgdaas-gateway:latest
    - docker push harbor.mgdaas-int.com/mgdaas-gateway/mgdaas-gateway:latest

notify-k8s:
  stage: deploy
  image: alpine:latest
  script:
    - sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
    - apk add --update curl
    # 此处为我们在 Kuboard 获取到的 CI 脚本
    - |
      curl -X PUT \
          -H "Content-Type: application/yaml" \
          -H "Cookie: KuboardUsername=zhangzangqian; KuboardAccessKey=zcsee8ax35nx.53p74dj4zpstx5t8fs7p2722z76564xt" \
          -d '{"kind":"deployments","namespace":"oa","name":"mgdaas-gateway"}' \
          "http://kuboard.mgdaas-int.com/kuboard-api/cluster/default/kind/CICDApi/zhangzangqian/resource/restartWorkload"

如此提交代码之后便可以看到 GitLab CI/CD 的流水线开始自动运行了。

基于 Gitlab + Harbor + K8s + Kuboard 的 CI 实践-小白菜博客
运行结果