kubernetes(k8s)Gitlab CI Runner 的安裝

簡介

從 Gitlab 8.0 開始,Gitlab CI 就已經(jīng)集成在 Gitlab 中,只要在項(xiàng)目中添加一個.gitlab-ci.yml文件,然后添加一個Runner,即可進(jìn)行持續(xù)集成。在介紹 Gitlab CI 之前,先看看一些 Gitlab CI 的一些相關(guān)概念。

流程邏輯如下:

Jobs->Stages->Pipeline

Pipeline

一次 Pipeline 其實(shí)相當(dāng)于一次構(gòu)建任務(wù),里面可以包含很多個流程,如安裝依賴、運(yùn)行測試、編譯、部署測試服務(wù)器、部署生產(chǎn)服務(wù)器等流程。任何提交或者 Merge Request 的合并都可以觸發(fā) Pipeline 構(gòu)建,如下圖所示:

+------------------+           +----------------+
|                  |  trigger  |                |
|   Commit / MR    +---------->+    Pipeline    |
|                  |           |                |
+------------------+           +----------------+

Stages

Stages 表示一個構(gòu)建階段,也就是上面提到的一個流程??梢栽谝淮?Pipeline 中定義多個 Stages,這些 Stages 會有以下特點(diǎn):

  • 所有 Stages 會按照順序運(yùn)行,即當(dāng)一個 Stage 完成后,下一個 Stage 才會開始
  • 只有當(dāng)所有 Stages 完成后,該構(gòu)建任務(wù) (Pipeline) 才會成功
  • 如果任何一個 Stage 失敗,那么后面的 Stages 不會執(zhí)行,該構(gòu)建任務(wù) (Pipeline) 失敗

Stages 和 Pipeline 的關(guān)系如下所示:

|                                                        |
|  Pipeline                                              |
|                                                        |
|  +-----------+     +------------+      +------------+  |
|  |  Stage 1  |---->|   Stage 2  |----->|   Stage 3  |  |
|  +-----------+     +------------+      +------------+  |
|                                                        |
+--------------------------------------------------------+

Jobs

Jobs 表示構(gòu)建工作,表示某個 Stage 里面執(zhí)行的工作??梢栽?Stages 里面定義多個 Jobs,這些 Jobs 會有以下特點(diǎn):

  • 相同 Stage 中的 Jobs 會并行執(zhí)行
  • 相同 Stage 中的 Jobs 都執(zhí)行成功時,該 Stage 才會成功
  • 如果任何一個 Job 失敗,那么該 Stage 失敗,即該構(gòu)建任務(wù) (Pipeline) 失敗

Jobs 和 Stage 的關(guān)系如下所示:

|                                          |
|  Stage 1                                 |
|                                          |
|  +---------+  +---------+  +---------+   |
|  |  Job 1  |  |  Job 2  |  |  Job 3  |   |
|  +---------+  +---------+  +---------+   |
|                                          |
+------------------------------------------+

Gitlab Runner

如果理解了上面的基本概念之后,可能我們就會發(fā)現(xiàn)一個問題,我們的構(gòu)建任務(wù)在什么地方來執(zhí)行呢,以前用 Jenkins 在 Master 和 Slave 節(jié)點(diǎn)都可以用來運(yùn)行構(gòu)建任務(wù),而來執(zhí)行我們的 Gitlab CI 構(gòu)建任務(wù)的就是 Gitlab Runner。

我們知道大多數(shù)情況下構(gòu)建任務(wù)都是會占用大量的系統(tǒng)資源的,如果直接讓 Gitlab 本身來運(yùn)行構(gòu)建任務(wù)的話,顯然 Gitlab 的性能會大幅度下降的。GitLab CI 最大的作用是管理各個項(xiàng)目的構(gòu)建狀態(tài),因此,運(yùn)行構(gòu)建任務(wù)這種浪費(fèi)資源的事情交給一個獨(dú)立的 Gitlab Runner 來做就會好很多,更重要的是 Gitlab Runner 可以安裝到不同的機(jī)器上,甚至是我們本機(jī),這樣完全就不會影響到 Gitlab 本身了。

安裝

安裝 Gitlab Runner 非常簡單,我們可以完全安裝官方文檔:https://docs.gitlab.com/runner/install/即可,比如可以直接使用二進(jìn)制、Docker 等來安裝。同樣的,我們這里還是將 Gitlab Runner 安裝到 Kubernetes 集群中來,讓我們的集群來統(tǒng)一管理 Gitlab 相關(guān)的服務(wù)。

1.驗(yàn)證 Kubernetes 集群

執(zhí)行下面的命令驗(yàn)證 Kubernetes 集群:

$ kubectl cluster-info
Kubernetes master is running at https://10.8.13.81:6443
CoreDNS is running at https://10.8.13.81:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
kubernetes-dashboard is running at https://10.8.13.81:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy
Metrics-server is running at https://10.8.13.81:6443/api/v1/namespaces/kube-system/services/https:metrics-server:/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

cluster-info這個命令會顯示當(dāng)前鏈接的集群狀態(tài)和可用的集群服務(wù)列表。

2.獲取 Gitlab CI Register Token

上節(jié)已經(jīng)成功安裝了 Gitlab,在瀏覽器中打開hwzxgit.sinoing.net頁面,然后登錄后進(jìn)入到管理頁面http://hwzxgit.sinoing.net/admin,然后點(diǎn)擊導(dǎo)航欄中的Runner,可以看到該頁面中有兩個總要的參數(shù),一個是 URL,另外一個就是 Register Token,下面的步驟中需要用到這兩個參數(shù)值。
圖一、

image.png

圖二、
image.png

注意:不要隨便泄露 Token
3.編寫 Gitlab CI Runner 資源清單文件

同樣將 Runner 相關(guān)的資源對象都安裝到kube-ops這個 namespace 下面,首先,通過 ConfigMap 資源來傳遞 Runner 鏡像所需的環(huán)境變量(runner-cm.yaml):

$ cd /gitlab/
$ mkdir runner
apiVersion: v1
data:
  REGISTER_NON_INTERACTIVE: "true"
  REGISTER_LOCKED: "false"
  METRICS_SERVER: "0.0.0.0:9100"
  CI_SERVER_URL: "http://gitlab.kube-ops.svc.cluster.local/ci"
  RUNNER_REQUEST_CONCURRENCY: "4"
  RUNNER_EXECUTOR: "kubernetes"
  KUBERNETES_NAMESPACE: "kube-ops"
  KUBERNETES_PRIVILEGED: "true"
  KUBERNETES_CPU_LIMIT: "1"
  KUBERNETES_CPU_REQUEST: "500m"
  KUBERNETES_MEMORY_LIMIT: "1Gi"
  KUBERNETES_SERVICE_CPU_LIMIT: "1"
  KUBERNETES_SERVICE_MEMORY_LIMIT: "1Gi"
  KUBERNETES_HELPER_CPU_LIMIT: "500m"
  KUBERNETES_HELPER_MEMORY_LIMIT: "100Mi"
  KUBERNETES_PULL_POLICY: "if-not-present"
  KUBERNETES_TERMINATIONGRACEPERIODSECONDS: "10"
  KUBERNETES_POLL_INTERVAL: "5"
  KUBERNETES_POLL_TIMEOUT: "360"
kind: ConfigMap
metadata:
  labels:
    app: gitlab-ci-runner
  name: gitlab-ci-runner-cm
  namespace: kube-ops

要注意CI_SERVER_URL對應(yīng)的值需要指向 Gitlab 實(shí)例的 URL(可以是外網(wǎng)地址,也可以是 Kubernetes 集群內(nèi)部的 Service DNS 地址,因?yàn)?Runner 也是運(yùn)行在 Kubernetes 集群中的),并加上/cihttp://gitlab.kube-ops.svc.cluster.local/ci ),也可以是CI_SERVER_URL: "http://hwzxgit.sinoing.net/ci"此外還添加了一些構(gòu)建容器運(yùn)行的資源限制,可以自己根據(jù)需要進(jìn)行更改即可。
除了上面的一些環(huán)境變量相關(guān)的配置外,還需要一個用于注冊、運(yùn)行和取消注冊 Gitlab CI Runner 的小腳本。只有當(dāng) Pod 正常通過 Kubernetes(TERM信號)終止時,才會觸發(fā)轉(zhuǎn)輪取消注冊。 如果強(qiáng)制終止 Pod(SIGKILL信號),Runner 將不會注銷自身。必須手動完成對這種被殺死的 Runner 的清理,配置清單文件如下:(runner-scripts-cm.yaml)

apiVersion: v1
data:
  run.sh: |
    #!/bin/bash
    unregister() {
        kill %1
        echo "Unregistering runner ${RUNNER_NAME} ..."
        /usr/bin/gitlab-ci-multi-runner unregister -t "$(/usr/bin/gitlab-ci-multi-runner list 2>&1 | tail -n1 | awk '{print $4}' | cut -d'=' -f2)" -n ${RUNNER_NAME}
        exit $?
    }
    trap 'unregister' EXIT HUP INT QUIT PIPE TERM
    echo "Registering runner ${RUNNER_NAME} ..."
    /usr/bin/gitlab-ci-multi-runner register -r ${GITLAB_CI_TOKEN}
    sed -i 's/^concurrent.*/concurrent = '"${RUNNER_REQUEST_CONCURRENCY}"'/' /home/gitlab-runner/.gitlab-runner/config.toml
    echo "Starting runner ${RUNNER_NAME} ..."
    /usr/bin/gitlab-ci-multi-runner run -n ${RUNNER_NAME} &
    wait
kind: ConfigMap
metadata:
  labels:
    app: gitlab-ci-runner
  name: gitlab-ci-runner-scripts
  namespace: kube-ops

可以看到需要一個 GITLAB_CI_TOKEN,然后復(fù)制下圖中的Gitlab CI runner token 來創(chuàng)建一個 Kubernetes secret 對象。將 token 進(jìn)行 base64 編碼:


image.png
$ echo VhSA7XiDmU65LoHxN-Gs | base64 -w0
VmhTQTdYaURtVTY1TG9IeE4tR3MK

base64 命令在大部分 Linux 發(fā)行版中都是可用的。
然后使用上面的 token 創(chuàng)建一個 Secret 對象:(gitlab-ci-token-secret.yaml)

apiVersion: v1
kind: Secret
metadata:
  name: gitlab-ci-token
  namespace: kube-ops
  labels:
    app: gitlab-ci-runner
data:
  GITLAB_CI_TOKEN: VmhTQTdYaURtVTY1TG9IeE4tR3MK

然后接下來就可以來編寫一個用于真正運(yùn)行 Runner 的控制器對象,這里使用 Statefulset。首先,在開始運(yùn)行的時候,嘗試取消注冊所有的同名 Runner,當(dāng)節(jié)點(diǎn)丟失時(即NodeLost事件),這尤其有用。然后再嘗試重新注冊自己并開始運(yùn)行。在正常停止 Pod 的時候,Runner 將會運(yùn)行unregister命令來嘗試取消自己,所以 Gitlab 就不能再使用這個 Runner 了,這個是通過 Kubernetes Pod 生命周期中的hooks來完成的。

另外通過使用envFrom來指定Secrets和ConfigMaps來用作環(huán)境變量,對應(yīng)的資源清單文件如下:(runner-statefulset.yaml)

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: gitlab-ci-runner
  namespace: kube-ops
  labels:
    app: gitlab-ci-runner
spec:
  updateStrategy:
    type: RollingUpdate
  replicas: 2
  serviceName: gitlab-ci-runner
  template:
    metadata:
      labels:
        app: gitlab-ci-runner
    spec:
      volumes:
      - name: gitlab-ci-runner-scripts
        projected:
          sources:
          - configMap:
              name: gitlab-ci-runner-scripts
              items:
              - key: run.sh
                path: run.sh
                mode: 0755
      serviceAccountName: gitlab-ci
      securityContext:
        runAsNonRoot: true
        runAsUser: 999
        supplementalGroups: [999]
      containers:
      - image: gitlab/gitlab-runner:latest
        name: gitlab-ci-runner
        command:
        - /scripts/run.sh
        envFrom:
        - configMapRef:
            name: gitlab-ci-runner-cm
        - secretRef:
            name: gitlab-ci-token
        env:
        - name: RUNNER_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        ports:
        - containerPort: 9100
          name: http-metrics
          protocol: TCP
        volumeMounts:
        - name: gitlab-ci-runner-scripts
          mountPath: "/scripts"
          readOnly: true
      restartPolicy: Always

可以看到上面我們使用了一個名為 gitlab-ci 的 serviceAccount,新建一個 rbac 資源清單文件:(runner-rbac.yaml)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-ci
  namespace: kube-ops
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gitlab-ci
  namespace: kube-ops
rules:
  - apiGroups: [""]
    resources: ["*"]
    verbs: ["*"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gitlab-ci
  namespace: kube-ops
subjects:
  - kind: ServiceAccount
    name: gitlab-ci
    namespace: kube-ops
roleRef:
  kind: Role
  name: gitlab-ci
  apiGroup: rbac.authorization.k8s.io

4.創(chuàng)建 Runner 資源對象

資源清單文件準(zhǔn)備好后,直接創(chuàng)建上面的資源對象:

$ ls
gitlab-ci-token-secret.yaml  runner-cm.yaml  runner-rbac.yaml  runner-scripts-cm.yaml  runner-statefulset.yaml
$ kubectl create -f .
secret "gitlab-ci-token" created
configmap "gitlab-ci-runner-cm" created
serviceaccount "gitlab-ci" created
role.rbac.authorization.k8s.io "gitlab-ci" created
rolebinding.rbac.authorization.k8s.io "gitlab-ci" created
configmap "gitlab-ci-runner-scripts" created
statefulset.apps "gitlab-ci-runner" created

創(chuàng)建完成后,可以通過查看 Pod 狀態(tài)判斷 Runner 是否運(yùn)行成功:

$ kubectl get pods -n kube-ops
NAME                        READY   STATUS    RESTARTS   AGE
gitlab-0                    1/1     Running   0          4d
gitlab-ci-runner-0          1/1     Running   0          17m
gitlab-ci-runner-1          1/1     Running   0          16m
jenkins2-7cc9df89dd-bwqwd   1/1     Running   9          6d3h
postgresql-0                1/1     Running   0          4d1h
redis-0                     1/1     Running   0          4d1h

可以看到已經(jīng)成功運(yùn)行了兩個(具體取決于StatefulSet清單中的副本數(shù)) Runner 實(shí)例,然后切換到 Gitlab Admin 頁面下面的 Runner 頁面:


image.png

至此,在kubernetes中安裝Gitlab CI Runner結(jié)束,當(dāng)然也可以根據(jù)需要更改 Runner 的一些配置,比如添加 tag 標(biāo)簽等。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容