概述
GitLab CI / CD是GitLab的一部分,gitlab 8.0版本开始新增的功能,是用Ruby和Go语言编写的。根我们通常的CI系统不一样通常的是一个master-slave架构,即使没有slave,master一样可以做CI,slave只是做为一个压力分担功能,gitlab是gitlab-server本身是不执行的,是通过api与GitLab Runner交互让gitlab-runner去执行CI。
GitLab Runner是一个go语言编写程序,它可以运行在任何可以运行go环境的平台上(二进制包、docker、k8s)
易用性方面
同样也是Everything as docker
Gitlab CI 整个流程和 Drone 以及流行的 Travis CI 都是比较类似的,通过在项目中添加一个 .gitlab-ci.yml 的配置文件,配置文件中描述构建流水线来执行任务,对不同编程语言的编译通过不同的docker image实现。
让CI工作所需的步骤可归纳为
添加.gitlab-ci.yml到存储库的根目录
配置一个Runner
Runner分两种类型
Specific Runners (独享的runner)
Shared Runners(共享的runner)
软件版本
gitlab:GitLab Community Edition 13.7.0
Kubernetes:1.17.4
部署gitlab-runner
创建测试项目代码和Dockerfile
在gitlab上创建一个项目名为go-server,编写个应用
server.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package main import ( "fmt" "log" "net/http" ) func hello(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World") } func main() { http.HandleFunc("/", hello) if err := http.ListenAndServe(":8080", nil); err != nil { log.Fatal(err) } }
|
创建Dockerfile
Dockerfile
1 2 3 4
| FROM golang WORKDIR /go ADD server /go CMD ["./server"]
|
deployment.yaml
部署到Kubernetes的yaml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| apiVersion: apps/v1 kind: Deployment metadata: name: go-demo labels: app: go-demo spec: replicas: 1 selector: matchLabels: app: go-demo template: metadata: labels: app: go-demo spec: containers: - name: go-demo image: 172.16.1.31/library/go-server-demo:IMAGE_TAG ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: go-demo spec: type: NodePort selector: app: go-demo ports: - port: 8080 targetPort: 8080 nodePort: 30007
|
在Kubernetes集群中部署gitlab-runner
整体流程

- 先执行代码构建,构建出制品
- 基于制品构建应用的容器镜像
- 部署到Kubernetes集群中
在gitlab项目页申请runner连接gitlab的地址和token,注意保存

git clone部署runner到Kubernetes中的helm文件
1
| git clone https://gitlab.com/gitlab-org/charts/gitlab-runner.git
|
修改values.yaml 以下几个地方:
1 2 3 4 5 6
| gitlabUrl: //填写在项目页申请的gitlab地址和token runnerRegistrationToken: rbac: create: true //启用RBAC runners: tags: "k8s-runner" //执行CI任务时可以通过tags匹配对应的runner,这里指定为k8s-runner
|
通过helm部署runner到Kubernetes中
1
| helm install --namespace default gitlab-runner gitlab-runner/
|
查看是否部署成功,主要是看POD是否正常启动
1 2 3
| kubectl get pod NAME READY STATUS RESTARTS AGE gitlab-runner-gitlab-runner-b5744f77c-jwnjk 1/1 Running 0 5d
|
默认是部署一个副本,如果需要多个runner实例,扩容对应的Deployment副本数即可。
同样是刚刚项目CI/CD设置页可以看见已经可用的runner了

在gitlab-ci中创建环境变量用于存放一些连接认证信息环境变量

将对应的信息填写到的对应的环境变量中,包括连接镜像仓库的帐号和密码和连接Kubernetes集群的config文件

KUBECONFIG文件进行base64编码存入,为了防止重定向后格式损坏
1
| base64 /root/.kube/config -w0
|
测试案例
编写gitlab—ci.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| stages: - package - docker_build - deploy_k8s build_job: image: golang:alpine stage: package tags: - k8s-runner script: - go build server.go artifacts: paths: - /builds/root/go-server docker_build_job: image: docker:19.03.0 services: - name: docker:19.03.0-dind command: ["--insecure-registry=0.0.0.0/0","--registry-mirror=https://vqgjby9l.mirror.aliyuncs.com"] variables: DOCKER_HOST: tcp://127.0.0.1:2375 DOCKER_TLS_CERTDIR: "" stage: docker_build tags: - k8s-runner script: - docker info - docker login -u $REGISTRY_USERNAME -p $REGISTRY_PASSWORD 172.16.1.31 - docker build -t 172.16.1.31/library/go-server-demo:$CI_PIPELINE_ID . - docker push 172.16.1.31/library/go-server-demo:$CI_PIPELINE_ID deploy_k8s_job: image: bitnami/kubectl:1.17 stage: deploy_k8s tags: - k8s-runner script: - echo $KUBECONFIG |base64 -d > config - sed -i "s/IMAGE_TAG/$CI_PIPELINE_ID/g" deployment.yaml - cat deployment.yaml - kubectl apply -f deployment.yaml --kubeconfig config
|
注:
1、因为Docker这边我们需要配置insecure-Registry需要这里通过Service的方式配置,所以这里在stage启用的是安装docker-cli的镜像,然后在server里面启用的是docker-dind的镜像,连接通过tcp连接使用
这里需要注意新版docker需要使用DOCKER_TLS_CERTDIR参数设置为空,不然无法连接。
2、kubeconfig文件使用base64编码主要为了重定向后格式不会造成损坏。
3、因为gitlab-ci每个阶段都是启动一个容器去执行构建任务,所以在每个阶段产生的制品如何给下个阶段使用是一个很大问题,这里可以配置artifacts参数将对应需要保留的制品保存到下个阶段。
4、构建的缓存配置,可以参考以下链接
https://docs.gitlab.com/runner/configuration/advanced-configuration.html
5、Docker镜像构建这里使用的是docker-dind的方式,实际上也可以直接透传主机的docker.sock文件到POD内使用,但不是特别安全,也可以使用一些其他解决方案如kaniko
上传后gitlab-ci会自动执行cicd部署到Kubernetes集群中

自动部署完成,查看Kubernetes集群中部署对象
1 2 3 4
| kubectl get pod NAME READY STATUS RESTARTS AGE go-demo-7f697958d4-7fbcd 1/1 Running 0 32h
|
访问节点30007端口
1 2
| curl 192.168.0.6:30007 Hello World
|
总结:
优点:
- 与gitlab集成度非常高
- 不需要单独部署有gitlab>=8.0 就能直接使用
- runner支持Autoscale
- UI可视化,可操作性强,可针对但个流程进行重复执行及报表展示
- CI完全对应你这个代码库,每个项目对应自己CI
缺点:
- 没有插件,对接第三方系统需要自己实现
- 只能支持gitlab代码仓库