操作系统:CentOS 7.2 1511
GitLab:v11.1.4
GitLab-runner:v11.2.0
Docker:17.03.2 ce
应用框架:Spring boot v2.0.x
项目构建管理:Maven v3.5.x
注:下述 "hostname.com" 请自行替换为GitLab域名
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
可直接通过浏览器导出证书,并将文件存为hostname.com.crt, 存于/etc/gitlab/ssl/(默认)目录下。
完成证书的获取后,可使用:
openssl s_client -connect hostname.com:443 -CAfile hostname.com.crt -state
进行证书的校验。
若返回0则表示无问题,如下图所示:
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部分。
docker-enter
update-ca-certificates
没有 docker-enter 可使用 docker exec -it /bin/bash 进入容器。
docker-enter配置方式请参考这里。
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 下获得,如图所示:
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)的映射(可选)。
.gitlab-ci.yml 是控制整个ci流程的核心配置文件,本文仅针对SpringBoot应用构建的几个要点进行阐述,其它请具体参考 gitlab-ci.yml 指导文档。
在企业内部,实际项目的构建过程大多依赖私有仓库等设置,因此默认的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 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 指导文档 。
目前,部署运行环境主要为两种,传统的宿主机环境(物理机或是虚拟机)以及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集成。
完成 .gitlab-ci.yml 文件的编写后,可通过 GitLab 的 CI Lint 对该文件进行检查,确认语法等是否有问题。
确认无问题后可提交并推送项目至 GitLab 即可触发CI流程。具体过程可通过project -> ci/cd -> pipelines 进行查看:
openssl 工具使用
gitlab-runner官网文档
gitlab ci官网文档