简介

从 Gitlab 8.0 开始,Gitlab CI 就已经集成在 Gitlab 中,我们只要在项目中添加一个.gitlab-ci.yml文件,然后添加一个Runner,即可进行持续集成。在介绍 Gitlab CI 之前,我们先看看一些 Gitlab CI 的一些相关概念。

Pipeline

一次 Pipeline 其实相当于一次构建任务,里面可以包含很多个流程,如安装依赖、运行测试、编译、部署测试服务器、部署生产服务器等流程。任何提交或者 Merge Request 的合并都可以触发 Pipeline 构建,如下图所示:

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

Stages

Stages 表示一个构建阶段,也就是上面提到的一个流程。我们可以在一次 Pipeline 中定义多个 Stages,这些 Stages 会有以下特点:

  • 所有 Stages 会按照顺序运行,即当一个 Stage 完成后,下一个 Stage 才会开始
  • 只有当所有 Stages 完成后,该构建任务 (Pipeline) 才会成功
  • 如果任何一个 Stage 失败,那么后面的 Stages 不会执行,该构建任务 (Pipeline) 失败

Stages 和 Pipeline 的关系如下所示:

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

Jobs

Jobs 表示构建工作,表示某个 Stage 里面执行的工作。我们可以在 Stages 里面定义多个 Jobs,这些 Jobs 会有以下特点:

  • 相同 Stage 中的 Jobs 会并行执行
  • 相同 Stage 中的 Jobs 都执行成功时,该 Stage 才会成功
  • 如果任何一个 Job 失败,那么该 Stage 失败,即该构建任务 (Pipeline) 失败

Jobs 和 Stage 的关系如下所示:

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

Gitlab Runner

如果理解了上面的基本概念之后,可能我们就会发现一个问题,我们的构建任务在什么地方来执行呢,以前用 Jenkins 在 Master 和 Slave 节点都可以用来运行构建任务,而来执行我们的 Gitlab CI 构建任务的就是 Gitlab Runner。

我们知道大多数情况下构建任务都是会占用大量的系统资源的,如果直接让 Gitlab 本身来运行构建任务的话,显然 Gitlab 的性能会大幅度下降的。GitLab CI 最大的作用是管理各个项目的构建状态,因此,运行构建任务这种浪费资源的事情交给一个独立的 Gitlab Runner 来做就会好很多,更重要的是 Gitlab Runner 可以安装到不同的机器上,甚至是我们本机,这样完全就不会影响到 Gitlab 本身了。

安装

安装 Gitlab Runner 非常简单,我们可以完全安装官方文档:https://docs.gitlab.com/runner/install/即可,比如可以直接使用二进制、Docker 等来安装。同样的,我们这里还是将 Gitlab Runner 安装到 Kubernetes 集群中来,让我们的集群来统一管理 Gitlab 相关的服务。

1.验证 Kubernetes 集群

执行下面的命令验证 Kubernetes 集群:

$ kubectl cluster-info
Kubernetes master is running at https://10.151.30.11:6443
KubeDNS is running at https://10.151.30.11:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

cluster-info这个命令会显示当前链接的集群状态和可用的集群服务列表。

2.获取 Gitlab CI Register Token

前面的章节中我们已经成功安装了 Gitlab,在浏览器中打开git.qikqiak.com页面,然后登录后进入到管理页面http://git.qikqiak.com/admin,然后点击导航栏中的Runner,可以看到该页面中有两个总要的参数,一个是 URL,另外一个就是 Register Token,下面的步骤中需要用到这两个参数值。

gitlab runner

注意:不要随便泄露 Token

3.编写 Gitlab CI Runner 资源清单文件

同样我们将 Runner 相关的资源对象都安装到kube-ops这个 namespace 下面,首先,我们通过 ConfigMap 资源来传递 Runner 镜像所需的环境变量(runner-cm.yaml):

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_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对应的值需要指向我们的 Gitlab 实例的 URL(可以是外网地址,也可以是 Kubernetes 集群内部的 Service DNS 地址,因为 Runner 也是运行在 Kubernetes 集群中的),并加上/ci( http://gitlab.kube-ops.svc.cluster.local/ci )。此外还添加了一些构建容器运行的资源限制,我们可以自己根据需要进行更改即可。

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

另外如果要添加其他选项的话,我们可以在 Pod 中运行gitlab-ci-multi-runner register --help命令来查看所有可使用的选项,只需为要配置的标志添加 env 变量即可,如下所示:

gitlab-runner@gitlab-ci-runner-0:/$ gitlab-ci-multi-runner --help
[...]
--kubernetes-cpu-limit value The CPU allocation given to build containers (default: "1") [$KUBERNETES_CPU_LIMIT]
--kubernetes-memory-limit value The amount of memory allocated to build containers (default: "4Gi") [$KUBERNETES_MEMORY_LIMIT]
--kubernetes-service-cpu-limit value The CPU allocation given to build service containers (default: "1") [$KUBERNETES_SERVICE_CPU_LIMIT]
--kubernetes-service-memory-limit value The amount of memory allocated to build service containers (default: "1Gi") [$KUBERNETES_SERVICE_MEMORY_LIMIT]
--kubernetes-helper-cpu-limit value The CPU allocation given to build helper containers (default: "500m") [$KUBERNETES_HELPER_CPU_LIMIT]
--kubernetes-helper-memory-limit value The amount of memory allocated to build helper containers (default: "3Gi") [$KUBERNETES_HELPER_MEMORY_LIMIT]
--kubernetes-cpu-request value The CPU allocation requested for build containers [$KUBERNETES_CPU_REQUEST]
[...]

除了上面的一些环境变量相关的配置外,还需要一个用于注册、运行和取消注册 Gitlab CI Runner 的小脚本。只有当 Pod 正常通过 Kubernetes(TERM信号)终止时,才会触发转轮取消注册。 如果强制终止 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,然后我们用 Gitlab CI runner token 来创建一个 Kubernetes secret 对象。将 token 进行 base64 编码:

$ echo rcVZF-mdHt9qCyyrCDgS | base64 -w0
cmNWWkYtbWRIdDlxQ3l5ckNEZ1MK

base64 命令在大部分 Linux 发行版中都是可用的。

然后使用上面的 token 创建一个 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: cmNWWkYtbWRIdDlxQ3l5ckNEZ1MK

然后接下来我们就可以来编写一个用于真正运行 Runner 的控制器对象,我们这里使用 Statefulset。首先,在开始运行的时候,尝试取消注册所有的同名 Runner,当节点丢失时(即NodeLost事件),这尤其有用。然后再尝试重新注册自己并开始运行。在正常停止 Pod 的时候,Runner 将会运行unregister命令来尝试取消自己,所以 Gitlab 就不能再使用这个 Runner 了,这个是通过 Kubernetes Pod 生命周期中的hooks来完成的。

另外我们通过使用envFrom来指定SecretsConfigMaps来用作环境变量,对应的资源清单文件如下:(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.创建 Runner 资源对象

资源清单文件准备好后,我们直接创建上面的资源对象:

$ 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

创建完成后,可以通过查看 Pod 状态判断 Runner 是否运行成功:

$ kubectl get pods -n kube-ops
NAME READY STATUS RESTARTS AGE
gitlab-7bff969fbc-k5zl4 1/1 Running 0 4d
gitlab-ci-runner-0 1/1 Running 0 3m
gitlab-ci-runner-1 1/1 Running 0 3m
......

可以看到已经成功运行了两个(具体取决于StatefulSet清单中的副本数) Runner 实例,然后切换到 Gitlab Admin 页面下面的 Runner 页面:

gitlab runner list

当然我们也可以根据需要更改 Runner 的一些配置,比如添加 tag 标签等。

参考链接: https://edenmal.moe/post/2017/GitLab-Kubernetes-Running-CI-Runners-in-Kubernetes/

在 Kubernetes 上安装 Gitlab CI Runner Gitlab CI 基本概念以及 Runner 的安装的更多相关文章

  1. 实例演示:如何在Kubernetes上大规模运行CI/CD

    本周四晚上8:30,第二期k3s在线培训如约开播!本期课程将介绍k3s的核心架构,如高可用架构以及containerd.一起来进阶探索k3s吧! 报名及观看链接:http://z-mz.cn/PmwZ ...

  2. 3.在 Kubernetes 上安装 Gitlab CI Runner

    结合文章:1. 在 Kubernetes 上安装 Gitlab ,地址:https://www.cnblogs.com/sanduzxcvbnm/p/13852854.html 总结: 结合开头的文章 ...

  3. 使用gitlab runner 进行CI(二):gitlab runner的安装与配置

    参考 https://docs.gitlab.com/runner/install/index.html,可以选择与gitlab相同的版本. gitlab runner可以通过安装binary包或do ...

  4. 2. 在 Kubernetes 上安装 Gitlab

    总结: 所需要的三个yaml文件的下载地址:https://files.cnblogs.com/files/sanduzxcvbnm/k8s-gitlab.zip Gitlab官方提供了 Helm 的 ...

  5. 使用gitlab runner进行CI(三):使用sonarqube做c++的静态检查

    目录 1. gitlab-ci.yml的配置 1.1 几个基本概念 1.2 使用CI进行代码检查demo 2. Sonarqube安装和配置 2.1 Sonarqube安装 2.2 数据库配置 2.3 ...

  6. Linux上安装git并在gitlab上建立对应的项目

    1.CentOS上面安装git我所用的CentOS为CentOS6.5,其他版本没有测试. yum install git 安装之后查看git版本信息 git --version 2.配置git信息g ...

  7. 使用gitlab自带的ci/cd实现.net core应用程序的部署

    这两天在折腾持续集成和交付,公司考虑使用gitlab自带的ci/cd来处理,特此记下来整个流程步骤. 好记性不如一支烂笔头---尼古拉斯-古人言 第一步: 安装gitlab,这个自然不用多说 第二步: ...

  8. Docker+Vagrant+Gitlab 构建自动化的 CI/CD

    如果你的开发流程是下面这个样子的, 那么你一定很好奇, 为什么我提交到仓库的代码可以自动部署并访问到最新的提交内容 这就是近年来兴起的 DevOps 文化, 很方便的解决了开发人员和运维人员每次发布版 ...

  9. docker搭建gitlab,设置邮件提醒,并运行runner

    接着http://www.cnblogs.com/wsy1030/p/8431837.html 在另一台机子运行gitlab: docker run --name='gitlab' -d -p 222 ...

  10. Jenkins+Gitlab搭建持续集成(CI)环境

    利用Jenkins+Gitlab搭建持续集成(CI)环境 Permalink: 2013-09-08 22:04:00 by hyhx2008in intern tags: jenkins gitla ...

随机推荐

  1. 踩坑系列《二》NewProxyResultSet.isClosed()Z is abstract 报错踩坑

    在运行测试类的时候莫名其妙的报了个 NewProxyResultSet.isClosed()Z is abstract 这个错误,之前出现过这个错误,以为是版本出现了问题 就将版本 0.9.1.2 改 ...

  2. NOIP模拟73

    T1 小L的疑惑 解题思路 第一眼不是正解,又是 bitset 优化可以得到的 60pts 的部分分. 打着打着突然发现这个东西好像和之前做过的某个题有一些相似,试着打了一下. 然后样例过了,然后对拍 ...

  3. null与undefined到底有啥区别?

    话不多说,直接先上结论: null 和 undefined 基本相同,只有细微差别 null 是表示缺少的标识,指示变量未指向任何对象,转为数值为 0 undefined 表示 "缺少值&q ...

  4. FastAPI 学习之路(十四)响应模型

    系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) FastAPI 学习之路(三) FastAPI 学习之路(四) FastAPI 学习之 ...

  5. DL4J实战之五:矩阵操作基本功

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. 用NXOpen.CAM.CAMSetup.CopyObjects复制刻字操作

    复制刻字操作 手动时,报粘贴对象失败: 用代码执行,报内部错误: Dim destinationObject As NXOpen.CAM.CAMObject = CType(NXOpen.Utilit ...

  7. Less-(26~28) preg_replace3

    Less-26: 核心语句:  各种回显均存在. 本题相比Less-25,多屏蔽了很多符号: 首先是各种注释符 --+,#,/**/  . /[]/表示字符集合:任何出现在里面的字符均会被替换. 屏蔽 ...

  8. 为什么阿里巴巴开发手册中强制要求 POJO 类使用包装类型?NPE问题防范

    封面:学校内的秋天 背景:写这个的原因,也是我这两天凑巧看到的,虽然我一直有 alibaba Java 开发手册,也看过不少次,但是一直没有注意过这个问题 属于那种看过,但又没完全看过 一起来看看吧冲 ...

  9. [软工顶级理解组] Alpha阶段测试报告

    [软工顶级理解组] Alpha阶段测试报告 在测试过程中发现了多少Bug? 测试阶段发现并已修复的bug: 尚且存在,但是难以解决或者不影响使用的bug: 计算重修课程的时候,如果重修课程的课程号和原 ...

  10. [Beta]the Agiles Scrum Meeting 1

    会议时间:2020.5.9 21:00 1.每个人的工作 今天已完成的工作 讨论转会事项 经过组内成员的讨论,我们做出了非常艰难的决定:我们的组员老c将作为转会成员,离开我们的团队.感谢老c在Alph ...