概述
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
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
FROM golang
WORKDIR /go
ADD server /go
CMD ["./server"]
deployment.yaml
部署到Kubernetes的yaml文件
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文件
git clone https://gitlab.com/gitlab-org/charts/gitlab-runner.git
修改values.yaml 以下几个地方:
gitlabUrl: //填写在项目页申请的gitlab地址和token
runnerRegistrationToken:
rbac:
create: true //启用RBAC
runners:
# runner configuration, where the multi line strings is evaluated as
# template so you can specify helm values inside of it.
#
# tpl: https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function
# runner configuration: https://docs.gitlab.com/runner/configuration/advanced-configuration.html
config: |
[[runners]]
[runners.kubernetes]
namespace = "{{.Release.Namespace}}"
image = "ubuntu:20.04"
privileged = true
tags: "k8s-runner"//执行CI任务时可以通过tags匹配对应的runner,这里指定为k8s-runner
通过helm部署runner到Kubernetes中
1 | helm install --namespace default gitlab-runner gitlab-runner/ |
查看是否部署成功,主要是看POD是否正常启动
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编码存入,为了防止重定向后格式损坏
base64 /root/.kube/config -w0
测试案例
编写.gitlab-ci.yaml
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集群中部署对象
kubectl get pod
NAME READY STATUS RESTARTS AGE
go-demo-7f697958d4-7fbcd 1/1 Running 0 32h
访问节点30007端口
curl 192.168.0.6:30007
Hello World
总结:
优点:
- 与gitlab集成度非常高
- 不需要单独部署有gitlab>=8.0 就能直接使用
- runner支持Autoscale
- UI可视化,可操作性强,可针对但个流程进行重复执行及报表展示
- CI完全对应你这个代码库,每个项目对应自己CI
缺点:
- 没有插件,对接第三方系统需要自己实现
- 只能支持gitlab代码仓库