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

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