K8s 部署 Gitlab CI Runner

LB477發表於2021-08-22
  • K8s 版本:1.20.6
  • GitLab CI 最大的作用是管理各個專案的構建狀態。因此,執行構建任務這種浪費資源的事情交給一個獨立的 Gitlab Runner 來做就會好很多,而且 Gitlab Runner 可以安裝到不同的機器上
  • 只要在專案中新增一個.gitlab-ci.yml檔案,然後新增一個 Runner ,即可進行持續整合
  • 官方文件:Install GitLab Runner | GitLab

1. 介紹

  • Pipeline:相當於一次構建任務,裡面可以包含多個流程,如安裝依賴、執行測試、編譯、部署測試伺服器、部署生產伺服器等。任何提交或者 Merge Request 的合併都可以觸發 Pipeline 構建
  • Stages:表示一個構建階段。一次 Pipeline 中可定義多個 Stages
    • 所有 Stages 會順序執行,即當一個 Stage 完成後,下一個 Stage 才會開始
    • 只有當所有 Stages 完成後,該構建任務才會成功
    • 如果任何一個 Stage 失敗,那麼後面的 Stages 不會執行,該構建任務失敗
  • Jobs:表示構建工作,即某個 Stage 裡面執行的工作。一個 Stage 中可定義多個 Jobs
    • 相同 Stage 中的 Jobs 會並行執行
    • 相同 Stage 中的 Jobs 都執行成功時,該 Stage 才會成功
    • 如果任何一個 Job 失敗,那麼該 Stage 失敗,即該構建任務失敗
  • Runner:執行 Gitlab CI 構建任務

2. Gitlab Runner

  • gitlab-ci-runner-cm:Runner 映象所需環境變數
    • 其他選項可在 Pod 中執行gitlab-ci-multi-runner register --help檢視
  • gitlab-ci-token:存放加密的 Gitlab CI runner token
  • gitlab-ci-runner-scripts:一個用於註冊、執行和取消註冊 Gitlab CI Runner 的指令碼
    • 只有當 Pod 正常通過 Kubernetes(TERM 訊號)終止時,才會觸發取消註冊。如果強制終止 Pod(SIGKILL 訊號),Runner 將不會登出自身,必須手動完成對這種被殺死的 Runner 的清理
  • gitlab-ci-runner:Runner 的 StatefulSet 控制器
    • 通過 K8s 生命週期鉤子:開始執行時取消註冊所有的同名 Runner;節點丟失時(即 NodeLost 事件)重新註冊自己並開始執行;正常停止 Pod 時執行 unregister 命令來取消自己
apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-ci
  namespace: gitlab
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gitlab-ci
  namespace: gitlab
rules:
  - apiGroups: [""]
    resources: ["*"]
    verbs: ["*"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gitlab-ci
  namespace: gitlab
subjects:
  - kind: ServiceAccount
    name: gitlab-ci
    namespace: gitlab
roleRef:
  kind: Role
  name: gitlab-ci
  apiGroup: rbac.authorization.k8s.io

---
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app: gitlab-ci-runner
  name: gitlab-ci-runner-cm
  namespace: gitlab
data:
  REGISTER_NON_INTERACTIVE: "true"
  REGISTER_LOCKED: "false"
  METRICS_SERVER: "0.0.0.0:9100"
  CI_SERVER_URL: "http://gitlab.gitlab.svc.cluster.local/ci"  # *
  RUNNER_REQUEST_CONCURRENCY: "4"
  RUNNER_EXECUTOR: "kubernetes"
  KUBERNETES_NAMESPACE: "gitlab"  # *
  KUBERNETES_PRIVILEGED: "true"
  KUBERNETES_CPU_LIMIT: "1"
  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"
---
apiVersion: v1
kind: Secret
metadata:
  name: gitlab-ci-token
  namespace: gitlab
  labels:
    app: gitlab-ci-runner
data:
  GITLAB_CI_TOKEN: SzlRaGY0U2gxVDdmcXhIU1dTNXMK  # echo K9Qhf4Sh1T7fqxHSWS5s | base64 -w0
---
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app: gitlab-ci-runner
  name: gitlab-ci-runner-scripts
  namespace: gitlab
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

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: gitlab-ci-runner
  namespace: gitlab
  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

建立:

$ kubectl create -f gitlab-runner.yaml
$ kubectl -n gitlab get pod
NAME                        READY   STATUS    RESTARTS   AGE
gitlab-7b894fcff-mnkb4      1/1     Running   0          69m
gitlab-ci-runner-0          1/1     Running   0          2m
gitlab-ci-runner-1          1/1     Running   0          2m
postgresql-6b6b478f-s6nj7   1/1     Running   0          69m
redis-7db89c7d46-fqdr5      1/1     Running   0          69m

結果:

http://gitlab.south.com/admin/runners 即可看到兩個 Runner 例項


參考:在 Kubernetes 上安裝 Gitlab CI Runner-陽明的部落格

相關文章