GitlabCI与Kubernetes实践·部署GitLab-Runner

GitlabCI与Kubernetes实践·部署GitLab-Runner_第1张图片

在Kubernetes里安装GitLab服务

Gitlab的持续集成功能依赖于Gitlab Runner组件完成,gitlab runner作为Gitlab这个中控机的执行者,按照代码仓库里面.gitlab-ci.yaml文件里面预定义的任务job按照指定的顺序或并发的执行完成系列的编译、测试、部署等操作,也就是说只要按照.gitlab-ci.yaml的配置格式[1]将写好的.gitlab-ci.yml文件放在代码仓库内,待下一次代码提交commit的时候就会自动的触发仓库绑定的Gitlab Runner去按照.gitlab-ci.yml里面配置的指定的执行。

总结一下,在Gitlab进行CICD,需要简单的做几步, Gitlab runner运行的架构下图所示:

  1. 安装Gitlab Runner

  2. 把代码仓库与Gitlab Runner进行绑定

  3. 在代码仓库里面配置.gitlab-ci.yml

  4. .gitlab-ci.yml文件里面定义好编译、单元测试、部署等任务(jobs)

GitlabCI与Kubernetes实践·部署GitLab-Runner_第2张图片 触发Gitlab Runner执行自动化操作

上一篇,我们将Gitlab服务安装在我们的ACK(阿里云的kubernetes)里面,下面我们也将在Kubernetes里面安装部署Gitlab Runner[2],给Gitlab增加持续集成的功能,这里有两种方式安装,一种通过helm(省事简单),一种手动安装,第一种方式这里简单的说明一下,我们使用第二种进行部署Gitlab Runner.

Helm安装的GitLab Runner

如果你已经准备好了Helm的话,可以参考此种方式,获取gitlab runner 的helm chat

git clone https://github.com/haoshuwei/gitlab-runner.git
cd gitlab-runner
#修改values.yaml里面的gitlabUrl和runnerRegistrationToken,runnerRegistrationToken可以从Admin Area>Overview>Runner处获取Runner的Token.修改完成之后,通过helm进行打包,然后安装到k8s环境
☸️  ACK???? devops  ~/v1.11.5/Runner-toml/gitlab-runner   master ●  ???? ???? helm package .
Successfully packaged chart and saved it to: /Users/marionxue/v1.11.5/Runner-toml/gitlab-runner/gitlab-runner-0.1.37.tgz
☸️  CKA???? devops  ~/v1.11.5/Runner-toml/gitlab-runner   master ●  ???? ???? helm install gitlab-runner *.tgz #安装到当前的devops空间下

如果你使用的是阿里云的ACK的话,可以参考阿里云的文档:https://www.alibabacloud.com/help/zh/doc-detail/106968.htm

手动安装Gitlab Runner

此部分参考Edenmal[3]的笔记,手动安装Gtilab Runner到K8s集群内,首先声明一个Configmap gitlab-runner.configmap.yaml来为Gitlab Runner提供需要的环境变量以及一些资源约束信息:

在向 ConfigMap 添加新的环境变量,需要删除已有的GitLab CI Runner Pod。因为我们是使用 envFrom来注入上面的这些环境变量而不是直接使用env的(envFrom 通过将环境变量放置到ConfigMapsSecrets来帮助减小清单文件。

apiVersion: v1
data:
  REGISTER_NON_INTERACTIVE: "true"
  REGISTER_LOCKED: "false"
  METRICS_SERVER: "0.0.0.0:9100"
  CI_SERVER_URL: "http://gitlab.devops.svc.cluster.local/ci" # k8s内gitlab服务的通信地址格式:svc.namespace.svc.cluster.local, 同时加上/ci这个prefix,这里也可以使用外网访问地址
  RUNNER_REQUEST_CONCURRENCY: "4"
  RUNNER_EXECUTOR: "kubernetes"
  KUBERNETES_NAMESPACE: "devops" # 服务运行的namespace
  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" # image的拉取策略
  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: devops

同样的,还需要准备一个Configmapgitlab-ci-runner-scripts.configmap.yml存储清理未被正常调度的Gitlab Runner的Pod. 正常来说,Gitlab runner在完成自己的使命之后,Kubernetes就会发送一个TERM signal信号用于正常的注销Gitlab runner, 所以那些被强制终止的Pod是不会自动的被清理的,而这个脚本就是完成这部分Pod的清理工作。

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: devops

我们需要创建一个Secretgitlab-ci-token-secret.yaml来存储Gitlab Runner的Token.以便上面的脚本能正常的运行,在secret内需要存放base64加密后的字符串。

echo YOUR_GITLAB_CI_TOKEN | base64 # YOUR_GITLAB_CI_TOKEN从Gitlab上获取,前面已经说过了.
apiVersion: v1
kind: Secret
metadata:
  name: gitlab-ci-token
  namespace: devops # 指定命名空间
  labels:
    app: gitlab-ci-runner
data:
  GITLAB_CI_TOKEN: SERnMUE3Znh5YVZ4dE1oSkhkQnQK # 这是base64加密Gitlab runner token之后的字符串

我们通过sts(statefulset控制器)gitlab-runner-sts.yaml创建Gitlab Runner。在开始运行的时候,尝试取消注册所有的同名 Runner,当节点丢失时(NodeLost事件)尤其有用。然后再尝试重新注册自己并开始运行。在正常停止 Pod 的时候,Runner 将会运行unregister命令来尝试取消自己,所以 Gitlab 就不能再使用这个 Runner 了,这个是通过 Kubernetes Pod 生命周期中的hooks来完成的,在运行Gitlab Runner的时候,我们通过Envfrom调用之前创建的脚本以及Gitlab runner运行需要的环境变量信息.

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: gitlab-ci-runner
  namespace: devops # gitlab运行的命名空间
  labels:
    app: gitlab-ci-runner
spec:
  updateStrategy:
    type: RollingUpdate # Gitlab Runner的更新模式
  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 # 创建一个serviceAccount,创建pod
      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

从sts配置清单中看到,我们还需要一个ServiceAccount来有足够的权限做一些事情,因此我们创建一个gitlab-ciServiceAccount, 配置清单为:gitlab-runner-rbac.yaml

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

这样,我们就准备好Gitlab Runner运行需要的配置清单,接下来,我们开始创建一下服务:

☸️  ACK???? devops  ~/v1.11.5/gitlab/runner  ???? ???? k apply -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

☸️  ACK???? devops  ~/v1.11.5/gitlab/gitlab-ci-demo   master  ???? ???? k get pods
NAME                            READY   STATUS    RESTARTS   AGE
gitlab-866cc5b84b-6hznk         1/1     Running   0          17h
gitlab-ci-runner-0              1/1     Running   0          34s
gitlab-ci-runner-1              1/1     Running   0          30s
gitlab-redis-5d86f5cf95-g6m7l   1/1     Running   0          17h
postgresql-64d79556cf-xggf8     1/1     Running   0          17h

此时我们在Gitlab平台上即可看到刚才注册的Runner服务

GitlabCI与Kubernetes实践·部署GitLab-Runner_第3张图片 查看注册的Gitlab Runner

这样就完成了Gitlab runner的注册.Gitlab可以对于不同语言的服务进行构建,测试,架构不同、构建环境等一切确定着Gitlab runner的运行环境,所以针对这样的场景,只要Gitlab能与Runner进行通信,就可以通过Tag等进行匹配调度。

完成Gitlab Runner服务的安装之后,下一步就可以开始探索Gitlab Pipeline的实践了。

参考资料

[1]

.gitlab-ci.yaml: https://docs.gitlab.com/ee/ci/quick_start/README.html

[2]

Gitlab Runner: https://docs.gitlab.com/ee/ci/quick_start/README.html

[3]

Edenmal.moe: https://edenmal.moe/

    • ???? Gitlab CICD 与Kubernetes实践·部署GitLab

    • ???? 从GitLabCE CI/CD方法论中探索实践

    • ???? 15 个 Kubectl 现有命令使用技巧 - 拿来即用

    • ???? Jenkins在kubernetes上的初体验

    • ???? 走进Network Namespace学会容器网络调试

    • ???? 实践 | Kubernetes守护进程集之DaemonSet

    • ???? 神奇!如何快速成为一名优秀的YAML工程师?

    • ???? 最流行的五款Kubernetes交互式可视化工具

    • ???? ab压力测试模拟实现kubernetes Pod水平自动伸缩

    • ???? 用Prometheus对业务服务进行监控

    • ???? Prometheus监控系列-监控篇

    • ???? kubernetes炼气期之掌握Kubernetes的背景

    • ???? Prometheus监控系列-部署篇

    • ???? 2020年最高效的10款Kubernetes助力神器

    • ???? 写给孩子看的Kubernetes动画指南 

    • ???? kubernetes的ingress控制器比较(traefik2.0.5安装指南)

    • ???? kubernetes深度探究Node和Pod的亲和性和反亲和性

    • ???? 在kuebernetes上通过nfs-server持久化postgresql

    • ???? kubernetes监控架构核心组件Metrics-server

    • ???? 基于BasicAuth认证的Traefik2.0.5

    • ???? 在Kubernetes上部署Nginx Ingress controller

    • ???? kubernetes安装方案大全

    • ???? kubernetes最常用的资源对象Deployment

    • ???? kubernetes炼气期之掌握kuebernetes背景

    • ???? kubernetes炼气期之k8s平台快速搭建

    • ???? 二进制部署Kubernetes集群1.9版本

你可能还喜欢

点击下方图片即可阅读

GitlabCI与Kubernetes实践·部署GitLab-Runner_第4张图片

你可能感兴趣的:(单元测试,kubernetes,docker,etcd,编程语言)