Gitlab-CI使用

概述

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代码仓库