本文将介绍在 K8s+Docker+Gitlab-CI+SpringCloud 架构体系中的 Gitlab-CI 环节

准备工作

  1. 一台服务器(我采用的是一台阿里云ECS),我们将该该台服务器姑且命名为 serverA。
  2. 在 serverA 上安装 Docker(注:如何安装 Docker 不是本文的重点,所以不做介绍)。
  3. 在 serverA 上安装 Gitlab(注:如何安装 Gitlab 不是本文的重点,所以不做介绍)。
  4. 在 gitlab 中创建一个 project,例如:annoroad-alpha。

开始搭建

1、安装、运行 Gitlab Runner

由于公共镜像仓库中有Gitlab Runner相关镜像,所以我采用镜像的方式安装、运行 TA。首先登录 serverA(已安装 Docker),在 serverA 的命令行里敲入如下命令:

docker run -d --name gitlab-runner --restart always -v /var/run/docker.sock:/var/run/docker.sock -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner

“gitlab-runner” 为 Gitlab Runner 容器的名称。

2、在 Gitlab Runner 中注册一个共享的 Runner

在【步骤1】中启动的 gitlab-runner 容器中执行 register 操作,注册一个 Runner,这个 Runner 可以是共享的,我们也可以为每个 Gitlab 上的项目(例如:annoroad-alpha)注册一个专属的 Runner,这里我采用的是共享 Runner,在 serverA 的命令行里敲入如下命令:

docker exec -it gitlab-runner gitlab-runner register -n   --url http://192.168.10.28/   --registration-token 5aWJqSzmMSbUDx9Kzz95   --executor docker   --description "annoroad-ms-runner"   --tag-list "annoroad-ms-runner"   --docker-image "docker:latest"   --docker-volumes /var/run/docker.sock:/var/run/docker.sock

参数说明:

  • url、registration-token
    这两个参数需要从 Gitlab 的页面上来获得,如下图:
    在这里插入图片描述

  • description
    该 Runner 的描述信息

  • tag-list
    在 gitlab-ci.yml 文件中需要用到该参数,下图为 annoroad-alpha 的 gitlab-ci.yml 片段:
    在这里插入图片描述

  • executor
    说明在 Runner 中完成的构建任务,将会采用 Docker 容器的方式运行。

  • docker-image
    结合上边的 executor 参数,在这里可以指定 Docker 镜像的版本

  • docker-volumes
    由于采用的是 Docker 的方式完成构建任务,所以整个构建任务本身是在一个容器内完成的,而此时需要在容器中使用 docker 相关命令(将 jar 打包成 image 且推送到 register 上),这就会涉及到了「docker in docker」,也就是常见的「dind」 。

    针对这种在容器中执行 docker 命令的场景,可参考 这篇文章 中所说的几种方式。

    这里我采用了文中提到的第三种方式「Use Docker socket binding」方式,将 docker-volumes 参数设置为 /var/run/docker.sock,也就是将 /var/run/docker.sock 绑定装载到容器中,我的理解就是将宿主机上的 Docker 与容器绑定,这样在该容器内就可以使用 docker 命令了。

    需要注意的是:由于使用的都是宿主机上的 Docker 守护进程,所以 docker 命令产生的任何容器都将是 Gitlab Runner 的兄弟,而不是所运行程序的子进程。

通过以上的方式,我们就已经在 gitlab runner 中注册了一个名为 annoroad-ms-runner 的 runner。同时在 gitlab runner 的配置文件(/srv/gitlab-runner/config/config.toml)中会生成一段儿与该 runner 相关的配置信息,如下:

[root@gitlab-server cache]# vim /srv/gitlab-runner/config/config.toml

concurrent = 5 # 指定gitlab runner 能同时执行几个 project,默认是 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "annoroad-ms-runner"
  url = "http://192.168.10.28/"
  token = "2f89baa82a022a02b9e499db060563"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.docker]
    tls_verify = false
    image = "docker:latest"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache", "/root/.m2:/root/.m2"]
    pull_policy = "if-not-present" # 镜像拉取策略,如果当前镜像不存在才去拉取
    shm_size = 0

这里需要注意的是 gitlab runner 默认同一时刻只允许存在一个执行的 Pipeline(其他 Pipeline 只能等上一个执行完了才能执行),通过设置 concurrent,我们可以同时运行多个Pipeline。

还有一个要说清楚的是 config.toml 中的 token 是什么,如下图:

在这里插入图片描述

3、在 Gitlab 中为 project 配置 Runner

通过在 Gitlab 页面上进行相应的配置,把 annoroad-alpha 与共享 Runner 关联起来,如下图:

  1. 进入 Admin Area > Runners,找到注册的共享 Runner
    在这里插入图片描述

  2. 进入共享 Runner 编辑页面,找到 annoroad-alpha,并且将 TA 设置为 Enable
    在这里插入图片描述

  3. 完成
    在这里插入图片描述

    此时,annoraod-alpha 就已经和共享 Runner 关联上了(PS:其他 project 如果也使用共享 Runner,重复该步骤即可),我们再来看一下此时的 annoraod-alpha 是个什么状态 ??

    1. 进入 annoroad-alpha 项目,打开 CI/CD
      在这里插入图片描述
    2. 展开后的效果
      在这里插入图片描述
4、设置 Variables

下边设置的这些值将会在下边介绍的 .gitlab-ci.yml 中用到!!!!!
在这里插入图片描述

5、执行 Pipeline
  1. 进入 annoroad-alpha 项目,打开 CI/CD
    在这里插入图片描述
  2. 选择发布分支(master),执行 Pipeline
    在这里插入图片描述
    这里需要大家注意以下两点:
    1、执行 Pipeline 的分支必须都是保护分支,如果是您自己创建了一个 hotfix 分支,且该分支没被设置为保护分支,则在执行 Pipeline 的过程中会报错!!!
    2、在 Variables 中设置的 PROFILE,在下边介绍的 .gitlab-ci.yml 中会用到!!!!
6、如何将分支设置为保护分支 ?!

我们可以通过如下步骤,来将指定分支设置为保护分支,如下:

  • 步骤一
    在这里插入图片描述
  • 步骤二
    在这里插入图片描述

gitlab-ci.yml 文件说明

为了实现 gitlab-ci,需要在 Gitlab 的 project(例如:annoroad-alpha) 中创建一个 gitlab-ci.yml文件,内如如下:

# 本次构建的阶段:package、build、deploy
stages:
  - package
  - build
  - deploy

# define job variables at job level
variables:
  DOCKER_DRIVER: overlay2
  # $CI_PROJECT_NAME 是 Gitlab 的变量,表示当前正在构建的项目名称(事实上是项目文件夹名称)
  # K8S_DEPLOYMENT_NAME 是当前 project 在 k8s 中 deployment 的名称 
  K8S_DEPLOYMENT_NAME: $CI_PROJECT_NAME
  PROJECT_NAME: $CI_PROJECT_NAME-api
  # 该镜像为 stage:build 阶段的基础镜像,在该阶段用执行 kubectl 命令更新 deployment
  # annoroad-kubectl:2.0.0 镜像是基于 lachlanevenson/k8s-kubectl:v1.11.0 镜像
  ANNOROAD_KUBECTL_IMAGE: registry.cn-beijing.aliyuncs.com/annoroad-cloud/annoroad-kubectl:2.0.0

# 源码打包阶段
package:
  image: maven:3.5.4
  stage: package
  tags:
    # 本文中创建的 Runner
    - annoroad-ms-runner
  only:
    # 指定该阶段只能通过页面手动触发
    - web
  script:
    - echo "=============== 开始 源码打包 ==============="
    # 这里的 $PROFILE 是通过每次在 Gitlab 上执行 Pipeline 的时候需要指定变量值
    # 用 TA 来说明要发布的环境(例如:开发、测试、生产等等),在下边的 stage:deploy 阶段也需要用到 TA
    # 通过设置 -P$PROFILE 来告诉 maven 打包的时候取哪个环境的配置信息
    - mvn clean install -Dmaven.test.skip=true -P$PROFILE -U
  # 将打完的 jar 包保存3分钟,以供后续的stage:build 阶段使用
  # 如果不设置 artifacts,则 jar 包不会被保存,在下一个阶段要使用该jar包则会报错
  artifacts:
    # ${CI_JOB_NAME} 是 Gitlab 的变量,表示 gitlab-ci.yml 中定义的 job 的名称
    # ${CI_COMMIT_REF_NAME} 是 Gitlab 的变量,表示用于构建项目的分支或 tag 名称
    name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
    paths:
      - ./$PROJECT_NAME/target/$PROJECT_NAME.jar
    expire_in: 3 mins

# 镜像构建和打包推送阶段
build:
  stage: build
  tags:
    # 本文中创建的 Runner  
    - annoroad-ms-runner
  only:
    # 指定该阶段只能通过页面手动触发
    - web
  script:
    - echo "=============== 开始 镜像构建和打包推送 ==============="
    - chmod 755 gitlab-ci-dockerbuild.sh
    # 稍后再单独介绍 gitlab-ci-dockerbuild.sh 脚本
    # 这里要特别说明的是:
    #	$ANNOROAD_REGISTRY 
    #	 对应 annoroad-alpha 在 Gitlab 中 Settings -> CI/CD -> Variables 中设置的 ANNOROAD_REGISTRY
    #	$ANNOROAD_REGISTRY_USERNAME 
    #	 对应 annoroad-alpha 在 Gitlab 中 Settings -> CI/CD -> Variables 中设置的 ANNOROAD_REGISTRY_USERNAME
    #	$ANNOROAD_REGISTRY_PASSWORD 
    #	 对应 annoroad-alpha 在 Gitlab 中 Settings -> CI/CD -> Variables 中设置的 ANNOROAD_REGISTRY_PASSWORD
    #	$TEST_PORT 
    #	 对应 annoroad-alpha 在 Gitlab 中 Settings -> CI/CD -> Variables 中设置的 TEST_PORT
    #	$PRODUCT_PORT
    #	 对应 annoroad-alpha 在 Gitlab 中 Settings -> CI/CD -> Variables 中设置的 PRODUCT_PORT
    #	$PROFILE
    #	 该参数是通过在 Gitlab 上运行 Pipeline 的时候指定设置的,通过该参数用来指定发布的环境(开发、测试、生产等等)
  	- ./gitlab-ci-dockerbuild.sh $PROJECT_NAME $ANNOROAD_REGISTRY $ANNOROAD_REGISTRY_USERNAME $ANNOROAD_REGISTRY_PASSWORD $TEST_PORT $PRODUCT_PORT $PROFILE

# 应用部署阶段
deploy:
  stage: deploy
  image:
    name: $ANNOROAD_KUBECTL_IMAGE
    # 覆盖原镜像的entrypoint,要不然会直接退出
    entrypoint: [""]
  tags:
    # 本文中创建的 Runner  
    - annoroad-ms-runner
  only:
    # 指定该阶段只能通过页面手动触发  
    - web
  script:
    - echo "=============== 开始 应用部署 ==============="
    # 修改 $K8S_DEPLOYMENT_NAME 中的 ENV 的 DEPLOY_TAG 属性,使 k8s 重新发布 $K8S_DEPLOYMENT_NAME
    # $PROFILE 就是 stage:package 阶段中的 $PROFILE,用来指向 project 发布到哪个环境里
    - kubectl set env deploy/$K8S_DEPLOYMENT_NAME DEPLOY_TAG="$(date)" -n $PROFILE

stage:build 阶段执行了一个 shell 脚本(gitlab-ci-dockerbuild.sh),该脚本与 gitlab-ci.yml 同在 project(annoroad-alpha) 的根目录下,内容如下:

#!/bin/sh

server_name=$1
annoroad_registry=$2
annoroad_registry_username=$3
annoroad_registry_password=$4
test_port=$5
product_port=$6
env=$7

if [ $env = "product" ];then
  # 生产环境
  server_port=$product_port;
elif [ "$env" = "test" ];then
  # 测试环境
  server_port=$test_port;
elif [ "$env" = "" ];then
  echo "ERROR: PROFILE is empty !!!!!!!";
  return 1;
else
  echo "ERROR: invalid PROFILE($env) !!!!!!!";
  return 1;
fi

image_name=$annoroad_registry/annoroad-cloud/$server_name

# 将 gitlba-ci.yml 中 stage:package 阶段生成的 jar 包 cp 到指定目录,创建 project(annoroad-alpha)的 image
cp ./$server_name/target/$server_name.jar ./$server_name/src/main/docker
cd ./$server_name/src/main/docker

# 镜像构建
docker build --build-arg server_name=$server_name --build-arg server_port=$server_port -t $server_name .
docker tag $server_name $image_name

# 登录私有 registry
docker login --username=$annoroad_registry_username --password=$annoroad_registry_password $annoroad_registry

# 推送 image
docker push $image_name

# 删除本地镜像
docker rmi $server_name
docker rmi $image_name
Logo

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

更多推荐