1. 程式人生 > 其它 >在K8S中部署gitlab-runner

在K8S中部署gitlab-runner

在K8S中部署gilab-runner

目錄

開始寫yml之前的思考:

寫一個gitlab-runner的yaml檔案進行在K8S上執行runner
方案:
1、daemonset 每個node上執行一個runner
缺點: 如果叢集中的node並不都是來做runner時 此路就不通了(註冊了不用 也是可以的)
優點:yaml檔案簡單,操作步驟少
2、deployment
缺點:操作步驟較多,需要對node進行打標籤以及選擇標籤的方式來選擇機器進行部署runner
優點:靈活安排那些node進行執行runner,解決“叢集中並不是所有node都是來進行執行runner的”情況

這兩種方式都是需要進行配合configmap以及serct進行關鍵詞以及配置檔案的傳入


借鑑博主思路:
1、configmap 來儲存runner註冊時的url地址以及限制pod的資源
2、configmap資源型別來定義一個指令碼 “用於註冊、執行和取消註冊”
3、sercet來儲存runner註冊的token
4、rbac的一個授權
5、StatefulSet來執行runner並使用以上定義的configmap以及sercet等資源

最終成品

apiVersion: v1
kind: Namespace
metadata:
  name: gitlab-ci
---
apiVersion: v1
kind: Secret
metadata:
  name: gitlab-ci-token
  namespace: gitlab-ci
  labels:
    app: gitlab-ci-runner
data:
  GITLAB_CI_TOKEN: WmF0Y3JNbUxUbmNncnpKem5CX1UK
---
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}"'/' /etc/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: gitlab-ci
---
apiVersion: v1
data:
  KUBERNETES_NODE_TOLERATIONS: "node-role.kubernetes.io/master:NoSchedule"
  KUBERNETES_IMAGE: "python"
  RUNNER_TAG_LIST: "training"
  REGISTER_NON_INTERACTIVE: "true"
  REGISTER_LOCKED: "false"
  METRICS_SERVER: "0.0.0.0:9100"
  CI_SERVER_URL: "http://git.enflame.cn/"
  RUNNER_REQUEST_CONCURRENCY: "4"
  RUNNER_EXECUTOR: "kubernetes"
  KUBERNETES_NAMESPACE: "gitlab-ci"
  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: gitlab-ci
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-ci
  namespace: gitlab-ci
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gitlab-ci
  namespace: gitlab-ci
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gitlab-ci
  namespace: gitlab-ci
subjects:
  - kind: ServiceAccount
    name: gitlab-ci
    namespace: gitlab-ci
roleRef:
  kind: Role
  name: gitlab-ci
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: gitlab-ci-runner
  namespace: gitlab-ci
  labels:
    app: gitlab-ci-runner
spec:
  updateStrategy:
    type: RollingUpdate
  replicas: 1
  selector:
    matchLabels:
      app: gitlab-ci-runner
  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
      containers:
      - image: gitlab/gitlab-runner:alpine-v14.2.0
        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
      tolerations:
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"

註釋版-StatefulSet(此版本只是參考作用)

#定義namespace
apiVersion: v1 #K8S的api介面版本
kind: Namespace #定義名稱空間
metadata: #屬性
  name: kube-ops #名稱空間的名字
---
#定義註冊的token
apiVersion: v1 #K8S的api介面版本
kind: Secret #資源型別
metadata: #屬性
  name: gitlab-ci-token #secret的名字
  namespace: kube-ops #選擇名稱空間
  labels: #給資源打上標籤
    app: gitlab-ci-runner #標籤內容
data: #定義鍵值對資料 儲存runner註冊時的token
  GITLAB_CI_TOKEN: WURnUG14aUFBZFE0dFRrZ21RSkgK
---
#指令碼用來註冊和取消註冊的命令,會在runner中進行執行
apiVersion: v1 #K8S的api介面版本
kind: ConfigMap #資源型別
data: #定義configmap中的內容 鍵值對方式定義
  run.sh: |
    #!/bin/bash
    unregister() {
        kill %1 #殺死後臺執行程式為1的job
        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} #根據runner的token登出註冊runner
        exit $?
    }
    trap 'unregister' EXIT HUP INT QUIT PIPE TERM #當接收到 關閉的訊號後 進行取消註冊runner 好處就是當pod刪除時 gitlab上自動刪除此runner,不會導致任務分配過來而不執行的情況。
    echo "Registering runner ${RUNNER_NAME} ..."
    /usr/bin/gitlab-ci-multi-runner register -r ${GITLAB_CI_TOKEN}
    sed -i 's/^concurrent.*/concurrent = '"${RUNNER_REQUEST_CONCURRENCY}"'/' /etc/gitlab-runner/config.toml
    echo "Starting runner ${RUNNER_NAME} ..."
    /usr/bin/gitlab-ci-multi-runner run -n ${RUNNER_NAME} & #進行註冊runner
    wait
metadata: #屬性
  labels: #標籤
    app: gitlab-ci-runner #標籤具體內容
  name: gitlab-ci-runner-scripts #configmap的名字
  namespace: kube-ops #選擇名稱空間
---
#定義runner執行時的環境變數(這些變數runner部分是藉助/usr/bin/gitlab-ci-multi-runner進行使用的,檢視有哪些變數 /usr/bin/gitlab-ci-multi-runner   register  --help)
apiVersion: v1
kind: ConfigMap
data:
  REGISTER_NON_INTERACTIVE: "true" #非互動式註冊
  REGISTER_LOCKED: "false" #暫存器鎖定
  METRICS_SERVER: "0.0.0.0:9100" #度量伺服器
  CI_SERVER_URL: "http://10.0.0.6/" #gitlab的url 註冊地址
  RUNNER_REQUEST_CONCURRENCY: "4" #請求併發數量
  RUNNER_EXECUTOR: "kubernetes" #runner的執行器型別
  KUBERNETES_NAMESPACE: "kube-ops" #指定名稱空間
  KUBERNETES_PRIVILEGED: "true" #有特權的
  KUBERNETES_CPU_LIMIT: "1" #限制CPU資源為 1
  KUBERNETES_CPU_REQUEST: "500m"  #要求500m
  KUBERNETES_MEMORY_LIMIT: "1Gi" #記憶體限制為1G
  KUBERNETES_SERVICE_CPU_LIMIT: "1" #限制CPU為1
  KUBERNETES_SERVICE_MEMORY_LIMIT: "1Gi" #記憶體為1G
  KUBERNETES_HELPER_CPU_LIMIT: "500m" #輔助程式CPU限制
  KUBERNETES_HELPER_MEMORY_LIMIT: "100Mi" #
  KUBERNETES_PULL_POLICY: "if-not-present"
  KUBERNETES_TERMINATIONGRACEPERIODSECONDS: "10"
  KUBERNETES_POLL_INTERVAL: "5"
  KUBERNETES_POLL_TIMEOUT: "360"
metadata:
  labels:
    app: gitlab-ci-runner
  name: gitlab-ci-runner-cm
  namespace: kube-ops
---
#進行rbac授權
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: ["*"]
---
apiVersion: v1
kind: RoleBinding
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

---
#執行runner
apiVersion: apps/v1 #api版本
kind: StatefulSet #資源型別
metadata: 元資料
  name: gitlab-ci-runner 指定資源的名稱
  namespace: kube-ops 指定名稱空間
  labels: 標籤
    app: gitlab-ci-runner 標籤具體內容
spec: 屬性
  updateStrategy: #指定更新策略 
    type: RollingUpdate
  replicas: 1 指定副本數
  selector: 指定選擇
    matchLabels:
      app: gitlab-ci-runner
  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 #引用configmap中定義的那個指令碼
              items: #引用key
              - key: run.sh
                path: run.sh
                mode: 0755
      serviceAccountName: gitlab-ci #指定serviceaccount 進行繫結
      containers: #容器資訊
      - image: gitlab/gitlab-runner:alpine-v12.10.1 #指定容器執行時的映象
        name: gitlab-ci-runner #容器名字
        command: #執行的命令
        - /scripts/run.sh
        envFrom:
        - configMapRef:
            name: gitlab-ci-runner-cm #引入環境變數
        - secretRef:
            name: gitlab-ci-token #引入token
        env: #環境變數
        - name: RUNNER_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name #runner-name的名稱 pod的
        ports: #容器埠
        - containerPort: 9100
          name: http-metrics
          protocol: TCP
        volumeMounts:
        - name: gitlab-ci-runner-scripts
          mountPath: "/scripts"
          readOnly: true #只讀的方式掛載
      restartPolicy: Always

daemonset

#定義runner工作的namespace
apiVersion: v1
kind: Namespace
metadata:
  name: kube-ops
---
#定義runner註冊時用到的token
apiVersion: v1
kind: Secret
metadata:
  name: gitlab-ci-token
  namespace: kube-ops
  labels:
    app: gitlab-ci-runner
data:
  GITLAB_CI_TOKEN: WURnUG14aUFBZFE0dFRrZ21RSkgK
---
#定義一個指令碼(暫時不明白博主為何這麼操作)
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
---
#定義runner執行時的環境變數
apiVersion: v1
data:
  REGISTER_NON_INTERACTIVE: "true"
  REGISTER_LOCKED: "false"
  METRICS_SERVER: "0.0.0.0:9100"
  CI_SERVER_URL: "http://10.0.0.6/"
  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
---
#定義RBAC授權
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
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: gitlab-ci-runner
  namespace: kube-ops
  labels:
    app: gitlab-ci-runner
spec:
  updateStrategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: 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
      containers:
      - image: gitlab/gitlab-runner:alpine-v12.10.1
        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

遇到的問題

問題一:指令碼中註冊runner的是什麼方式進行註冊的?

問題描述:當我嘗試以手動的方式執行指令碼的內容時,發現指令碼中用到了runner的token 並不是gitlab-server的註冊runner時的token從而產生了疑惑:難道註冊gitlab-runner還能用自己的token(gitlab-runner的token)

思考:應該不是使用token的方式 因為命令列方式獲取得到的token和gitlab-ci獲取的token值是不一樣的

解決

此yaml中 使用runner的token進行的登出操作
註冊runner是根據Secret中的token進行註冊的(也就是gitlab-server中的token)
提問問題時沒搞明白指令碼的具體含義,指令碼中是 藉助gitlab-runner的token來進行登出runner的一個操作 而註冊的操作還是使用gitlab-server提供的token
問題二:configmap中的變數從哪裡可以看到?

在configmap中gitlab-ci-runner-cm的其他變數怎麼沒看到使用?

這些變數是藉助/usr/bin/gitlab-ci-multi-runner進行使用的,自帶的內建變數引數
檢視有哪些變數 /usr/bin/gitlab-ci-multi-runner   register  --help
問題四:RUNNER_NAME這個變數是自帶的嗎?
根據K8S中的pod自帶獲取名稱方式獲取的
metadata.name
問題五:kill %1 是什麼意思?
kill %1這條命令表示殺死一個後臺程式,這個後臺程式的“工作號碼(jobnumber)”是1號。job命令的作用就是將放在後臺執行的程式(& nohup等方式執行的程序)給顯示出來,kill %1 則是將後臺程式的job號碼為1的給殺掉。
問題六:設定容忍度

問題描述:將K8S自動設定的系統汙點誤認為是人為設定的,導致找不到對應的key:value值,陷入不知道該如何設定容忍度的問題

正常情況下 kubectl describe node work1 |grep Taint 命令是可以看到人為設定的key:value的汙點的。

我誤認為 磁碟故障而導致K8S系統自動給node節點打的汙點 是人為設定的汙點,導致使用kubectl describe node work1|grep Taint 而沒有找到key:value,從而陷入不知道該如何設定容忍的困境

解決: 如果是人為設定的汙點,kubectl describe node work1 其實是可以看到設定的汙點的key:value的

work1因為磁碟的故障而自動打汙點

Warning  Evicted    1s    kubelet            The node had condition: [DiskPressure].
問題七:gitlab-runner建立的容器需要設定容忍度

問題描述:gitlab-runner在接收到任務時 自動建立執行具體內容的容器 無法容忍汙點 一直處於pending的狀態

因為在yml檔案中可以設定gitlab-runner的容忍,但是不清楚gitlab-runner執行後自動建立的容器是怎麼設定汙點容忍的。

解決

須知:①gitlab-runner建立的容器 是從configmap中定義的環境變數中來獲取資訊的;②configmap中設定的gitlab-runner的環境變數獲取方式為:/usr/bin/gitlab-ci-multi-runner register --help|grep kubernetes-node-tolerations

root@c75cacba4598:/# /usr/bin/gitlab-ci-multi-runner  register --help|grep kubernetes-node-tolerations
Runtime platform                                    arch=amd64 os=linux pid=50 revision=8925d9a0 version=14.1.0
   --kubernetes-node-tolerations value                                         A toml table/json object of key=value:effect. Value and effect are expected to be strings. When set, pods will tolerate the given taints. Only one toleration is supported through environment variable configuration. (default: "{}") [$KUBERNETES_NODE_TOLERATIONS]

具體解決方法:在yml中的configmap中設定 gitlab-runner建立容器時的特性

KUBERNETES_NODE_TOLERATIONS: "node-role.kubernetes.io/master:NoSchedule"

補充gitlab-ci-multi-runner命令解釋

NAME:
   gitlab-ci-multi-runner - a GitLab Runner

USAGE:
   gitlab-ci-multi-runner [global options] command [command options] [arguments...]

VERSION:
   14.1.0 (8925d9a0)

AUTHOR:
   GitLab Inc. <[email protected]>

COMMANDS:
     exec                  在本地執行構建
     list                  列出所有配置的執行程式
     run                   執行多執行程式服務
     register              登記新的runner
     install               安裝服務
     uninstall             解除安裝服務
     start                 開始服務
     stop                  停止服務
     restart               重啟服務
     status                獲取服務狀態
     run-single            啟動單執行緒runner
     unregister            取消註冊特定的執行程式
     verify                驗證所有已註冊的runner
     artifacts-downloader  下載並提取構建工件(內部)
     artifacts-uploader    建立和上載構建工件(內部)
     cache-archiver        建立和上載快取工件(內部)
     cache-extractor       下載並提取快取工件(內部)
     cache-init            已更改快取路徑的許可權(內部)
     health-check          檢查特定地址的執行狀況
     read-logs             從kubernetes executor(內部)使用的檔案讀取作業日誌
     help, h               Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --cpuprofile value           write cpu profile to file [$CPU_PROFILE]
   --debug                      debug mode [$DEBUG]
   --log-format value           Choose log format (options: runner, text, json) [$LOG_FORMAT]
   --log-level value, -l value  Log level (options: debug, info, warn, error, fatal, panic) [$LOG_LEVEL]
   --help, -h                   show help
   --version, -v                print the version
因為你不會,所以你才會---大司馬