GitLab 容器化 CI 流程填坑记(一)

本文以SpringBoot项目的部署构建为例,对基于GItLab的CI流程进行简要介绍。

 

环境准备:

1. 系统环境:

操作系统:CentOS 7.2 1511

GitLab:v11.1.4

GitLab-runner:v11.2.0

Docker:17.03.2 ce

 

2. 应用环境:

应用框架:Spring boot v2.0.x

项目构建管理:Maven v3.5.x

 

CI集成流程:

关于证书(HTTPS需要,HTTP请忽略):

注:下述 "hostname.com" 请自行替换为GitLab域名

1. 完整自签证书:

sudo openssl genrsa -des3 -out /etc/gitlab/ssl/hostname.com.key 2048
sudo openssl req -new -key /etc/gitlab/ssl/hostname.com.key -out /etc/gitlab/ssl/hostname.com.csr
sudo openssl x509 -req -days 3650 -in /etc/gitlab/ssl/hostname.com.csr -signkey /etc/gitlab/ssl/hostname.com.key -out /etc/gitlab/ssl/hostname.com.crt

2. 服务端已有证书:

可直接通过浏览器导出证书,并将文件存为hostname.com.crt, 存于/etc/gitlab/ssl/(默认)目录下。

 

完成证书的获取后,可使用:

openssl s_client -connect hostname.com:443 -CAfile hostname.com.crt -state

进行证书的校验。

若返回0则表示无问题,如下图所示:

 

 

具体实现:

1. 安装GitLab:略(直接容器部署即可)

2. 在GitLab中创建项目:略

3. 安装runner:

gitlab-runner有多种安装方式,具体详见 gitlab-runner安装 ,本文采用的docker的方式进行runner的部署:

docker run -d --name bala-runner --restart always \
-v /etc/gitlab-runner/certs/hostname.com.crt:/usr/local/share/ca-certificates/hostname.com.crt \
-v /etc/gitlab-runner/certs/hostname.com.crt:/etc/gitlab-runner/certs/hostname.com.crt \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /root/build_cache:/cache \
gitlab/gitlab-runner:latest

注:

1. 第一和第二个 -v 实现证书目录内容的挂载;

2. 第三个 -v 实现docker.sock的挂载(因为后续要实现docker in docker的使用,即 docker executor);

3. 第四个 -v 实现gitlab-runner cache目录的挂载(可选),cache相关请参考 docker executor 下的cache部分。

 

4. 进入runner更新证书:

docker-enter 
update-ca-certificates

没有 docker-enter 可使用 docker exec -it /bin/bash 进入容器。

docker-enter配置方式请参考这里。

 

5. 注册runner:

runner注册的参数很多,可通过下述命令进行查看(config文档地址):

gitlab-runner register --help

这里,本文使用如下命令进行runner注册:

gitlab-runner register -n \
  --url https://hostname.com/ \
  --registration-token Bz7bb9xxxxxxxxxYxf91 \
  --tls-cert-file /etc/gitlab-runner/certs/hostname.com.crt \
  --executor docker \
  --pre-clone-script "git config --global http.sslVerify false" \
  --output-limit 81920 \
  --description "BalaBalaYi Runner" \
  --docker-image "balabalayi/maven-plus-docker:jdk-8-maven-3.5.4-docker-17.03" \
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock

注:

1.url 为 gitlab的地址;

2. registration-token 为项目下的token,可通过 gitlab -> project -> settings -> ci/cd 下获得,如图所示:

GitLab 容器化 CI 流程填坑记(一)_第1张图片

3. tls-cert-file 为证书目录,注意与启动runner容器时的挂载目录要一致;

4. executor,使用 docker 作为 executor;

5. pre-clone-script 表示 git clone 仓库代码前执行的命令,本文这里简化了git的过程,直接禁用了sslVerify,若对环境安全性要求高,请自行配置git ssl;

6. output-limit 为日志输出的大小限制,默认为4096 (4MB);

7. description 为 runner 的描述信息,请自定义;

8. docker-image 为 executor 所采用的默认 docker 镜像(会被gitlab-ci.yml中的配置覆盖)。这里,因为本文要使用mvn docker:build命令,因此采用了自己封装的镜像(包括 java8+maven3+docker17.03 环境);

9. docker-volumes ,因采用 "docker executor" ,必须挂载宿主机的docker.sock,

10. 如果需要挂载cache到宿主机,docker-volumes 还需添加宿主机目录到容器内cache目录(默认为/cache)的映射(可选)。

 

6. 编写.gitlab-ci.yml

.gitlab-ci.yml 是控制整个ci流程的核心配置文件,本文仅针对SpringBoot应用构建的几个要点进行阐述,其它请具体参考 gitlab-ci.yml 指导文档。

 

maven环境的引用:

在企业内部,实际项目的构建过程大多依赖私有仓库等设置,因此默认的maven环境是不能满足需要的。但是因为在本篇文章所涉及的CI流程中,无论是executor还是runner,都是以容器化的方式托管给GitLab进行操作,所以介绍下如何在该场景下便捷地引用maven的配置,方法有三:

1. 通过自定义官方的maven镜像的dockerfile,重新配置指定目录下的settings.xml,并在内部实现变量,方便后续在CI流程中通过外部定义变量的方式,实现maven自定义动态配置的导入。

结论:此方法可行。但是maven的配置较多,如果企业内部依赖maven的配置较多,此方法依旧较复杂。何况还要涉及dockerfile的修改及镜像的构建。

 

2. 如果配置极少,可直接在 before_script 通过sed等命令,添加配置内容至settings.xml(以默认的settings.xml为基准) 。

结论:此方法在自定义配置项目较少时可用,配置项若较多,则异常繁琐。

 

3. 将maven的settings.xml拷贝一份,置于项目根目录下(与pom文件一起),作为项目本身的配置文件之一。在.gitlab-ci.yml中定义新的maven变量引用(mvn-setting.xml是自定义的名称):

variables:
  MAVEN_CLI_OPTS: "-s ./mvn-settings.xml --batch-mode"

然后,在每个stage下对应的脚本命令中,都可通过引用此变量来执行maven命令:

- mvn $MAVEN_CLI_OPTS clean deploy docker:build -DpushImage

结论:此方法最为简单粗暴,无须担心自定义的maven配置是否复杂。缺点是项目多维护了一个配置文件(其实都多了.gitlab-ci.yml了,也不在乎多这一个)。

 

docker构建所需环境:

如果要实现 docker build 及其它 docker 命令,需要对应的docker环境,上述 /var/run/docker.sock 的挂载就是为此服务的。

除了与宿主机的docker.sock的共享,另外还需要当前环境下的docker安装。在此针对SpringBoot应用构建,有两种方式如下:

1. 使用 maven 的 dockerbuild 插件,通过 mvn 命令在一个 stage 中完成打包以及 docker 的镜像构建:

此方法需要使用者自行构建一个包含 JDK+MAVEN+DOCKER 环境的容器镜像,然后使用此镜像作为 executor 的镜像执行CI流程。采用此方法一个命令即可完成打包,推送jar至仓库,构建docker镜像,推动docker镜像至仓库:

mvn $MAVEN_CLI_OPTS clean deploy docker:build -DskipTests -DpushImage

 

2. 分为两个stage,分别完成打包和镜像构建:

此方法,需要使用 cache 或是 artifact 在 package stage 步骤中保留打包后的jar及相关目标文件,然后在 build stage 步骤中引用 cache 或是 artifact 保存下来的目标内容进行后续的镜像构建。大致的脚本流程如下:

image: docker:latest

services:
  - docker:dind

stages:
  - package
  - build

# 打包
package:
  image: maven:3-jdk-8
  stage: package
  script:
    - docker login ip:port -u xxx -p xxxx
    - mvn clean deploy 
  cache:
    key: target
    paths:
      - target/*
   

# 构建
deploy:
  stage: deploy
  script:
    - docker login ip:port -u xxx -p xxxx
    - docker build xxx xxx
    - docker push xxx

上述代码只是一个示例,cache 和 artifacts 的使用还请参考 这里,具体语法还请参考 gitlab-ci.yml 指导文档 。

 

docker的部署运行:

目前,部署运行环境主要为两种,传统的宿主机环境(物理机或是虚拟机)以及kubernetes集群。

1. 宿主机:

此方法大多需要通过ssh实现远程命令控制,在此给出一个简单的方法,使用sshpass:

deploy:
  stage: deploy
  script:
    - apt-get install -y sshpass
    - sshpass -p "$DEPLOY_HOST_PASSWORD" ssh -o StrictHostKeyChecking=no -tt root@$DEPLOY_HOST_IP 'if [ -n "`docker ps -qa --filter name=xxx`" ];then docker rm -f xxx;fi'
    - sshpass -p "$DEPLOY_HOST_PASSWORD" ssh -o StrictHostKeyChecking=no -tt root@$DEPLOY_HOST_IP "docker login $REGISTRY_HOST:$REGISTRY_PUBLIC_PORT -u $REGISTRY_ADMIN_USER -p $REGISTRY_ADMIN_USER_PASSWORD"
    - sshpass -p "$DEPLOY_HOST_PASSWORD" ssh -o StrictHostKeyChecking=no -tt root@$DEPLOY_HOST_IP "docker run --name xxx -d $REGISTRY_HOST:$REGISTRY_PUBLIC_PORT/xx/xxx"

上述四行命令分别为:

1. 安装sshpass;

2. 根据名称清除已有的正在运行的容器;

3. 登录docker仓库;

4. 部署运行容器。

 

官方使用ssh免密的方法:Using SSH keys with GitLab CI/CD

 

2. kubernetes集群:

需要用户自定义应用的k8s声明文件,配置k8s集群访问,然后在 .gitlab-ci.yml 中实现部署流程:

k8s-deploy:
  image: xxx
  stage: deploy
  script:
    - kubectl create secret docker-registry xxx --docker-server=https://registry.gitlab.com --docker-username=xxx --docker-password=xxx
    - kubectl apply -f deployment.yml

其它详细请参考 k8s集成。

 

7. 完成CI集成并测试

完成 .gitlab-ci.yml 文件的编写后,可通过 GitLab 的 CI Lint 对该文件进行检查,确认语法等是否有问题。

确认无问题后可提交并推送项目至 GitLab 即可触发CI流程。具体过程可通过project -> ci/cd -> pipelines 进行查看:

GitLab 容器化 CI 流程填坑记(一)_第2张图片

 

 

 

 

 

 

相关内容及文章引用:

openssl 工具使用

gitlab-runner官网文档

gitlab ci官网文档

 

结语:

最后感谢 Du Wenkai 小伙伴的技术和环境支持。

 

 

你可能感兴趣的:(spring,boot,gitlab,ci,docker)