Published on

GitLab在Kubernetes上的CI/CD

Authors
  • avatar
    Name
    老杨的博客
    Twitter

GitLab 在 Kubernetes 上的 CI/CD

[TOC]

1. Gitlab 在 Kubernetes 中 CI/CD 流程

下图中,Gitlab 在整个过程中,参与了 60%以上的工作,可以说,开发自从 push 了代码后,就可以直接测试并上线到生产环境。

在 Kubernetes 中,Gitlab Runner,是一个中介的作用,它申请 pod 运行 stage,所以 Runner 并不直接运行 stage。

在开始前,需要详细阅读.gitlab-ci.yml 各名词和用法。

2. 环境

Kubernetes version: 1.12

Gitlab version: 11.4.3

3. Kubernetes 安装

可使用我写的一键安装脚本: https://github.com/ygqygq2/kubernetes/blob/master/kubeadm/kubeadm_install_k8s.sh

4. GitLab 安装

因为已经既然已经用上 Kubernetes,那干脆把 GitLab 也搭建在它上面。 使用 helm 安装。

  1. 添加 gitlab 的 chart 地址到 helm repo;
  2. 下载 gitlab 的 chart;
  3. 设置相关 values.yaml;
  4. helm 安装;

gitlab 的 chart 里,模块很多,使用--set有的并不好写,所以建议先修改 values.yaml(包含各模块的 values.yaml)。

这里如果是不使用自带的 nginx ingress,推荐修改gitlab/values.yaml global.ingress.annotations 参数,下面增加 kubernetes.io/ingress.class: nginx

默认它会安装 prometheus、certmanager、nginx ingress,按自己需求选择。我的环境已经有 nginx ingress、prometheus 了,certmanager 又暂时没用上。所以这几个都设置为false,不安装。如需正式使用,注意持久存储大小。

helm repo add gitlab https://charts.gitlab.io/
helm fetch gitlab/gitlab --untar
cd gitlab
# vim values.yaml
namespace="devops"
helm upgrade --install gitlab --timeout 600 --namespace $namespace . \
--set gitlab.migrations.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-rails-ce \
--set gitlab.sidekiq.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-sidekiq-ce \
--set gitlab.unicorn.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-unicorn-ce \
--set gitlab.unicorn.workhorse.image=registry.gitlab.com/gitlab-org/build/cng/gitlab-workhorse-ce \
--set gitlab.task-runner.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-task-runner-ce \
--set certmanager-issuer.email=my_email@163.com \
--set global.hosts.domain=linuxba.com \
--set global.smtp.enabled=true \
--set global.smtp.address=smtp.163.com \
--set global.smtp.user_name=my_email@163.com \
--set global.smtp.password.key=password \
--set global.smtp.password.secret=ygqmail \
--set global.time_zone="Asia/Shanghai" \
--set gitlab.gitaly.persistence.storageClass=ceph-rbd \
--set gitlab.gitaly.persistence.size=2Gi \
--set gitlab.gitaly.persistence.storageClass=ceph-rbd \
--set postgresql.persistence.size=2Gi \
--set postgresql.persistence.storageClass=ceph-rbd \
--set minio.persistence.size=5Gi \
--set minio.persistence.storageClass=ceph-rbd \
--set redis.persistence.size=1Gi \
--set redis.persistence.storageClass=ceph-rbd \
--set nginx-ingress.enabled=false \
--set prometheus.install=false \
--set certmanager.install=false \
--set gitlab.gitlab-shell.service.externalPort=20022 \
--set gitlab.gitlab-shell.service.internalPort=20022 \
--set gitlab.gitlab-runner.rbac.clusterWideAccess=true \
--set gitlab.gitlab-runner.rbac.create=true \
--set gitlab.gitlab-runner.runners.privileged=true \
--set glabal.initialRootPassword.key="Git@linuxba.com" \
--set gitlab.migrations.initialRootPassword.key="Git@linuxba.com"

# 自定义runner secret,统一管理
# --set gitlab.gitlab-runner.runners.secret=gitlab-runner-custom

# 上面已经不安装prometheus了,则不申请它的pvc
# --set prometheus.server.persistentVolume.storageClass=ceph-rbd \
# --set prometheus.server.persistentVolume.size=2Gi \

安装过程中很容易出现如下提示:

E1129 15:21:12.482144 2878016 portforward.go:178] lost connection to pod
Error: UPGRADE FAILED: transport is closing

可以等 1 分钟,查看下 pod 是否在生成,如果在生成中,则其实已经安装成功。也可以再次使用上面命令,或者使用helm delete --purge删除再重新安装。

这也是让人讨厌的 helm 缺点之一,这篇文章 恕我直言,对 Helm 大家还是要三思而后用有提到过。

安装成功后,我发现安装设置的 root 密码不生效,可以通过以下命令获取登录的 root 密码: kubectl get secret -n $namespace gitlab-test-gitlab-initial-root-password -ojsonpath={.data.password}|base64 -d

kubectl get ing可以看到,有 3 个 ingress,访问 gitlab.linuxba.com 可以访问到 gitlab 界面。

注意: HTTPS 访问,因为证书 secret 关系,可能需要修改 ing 或者使用事先准备的证书文件生成 ing 中名称对应的 secret。 这些都是 k8s 细节,这里不作详细描述。

5. Auto DevOps

5.1 添加 Kubernetes 集群

管理员通过服务模板添加 Kubernetes 集群,是生效所有项目的。

项目中也可以添加 Kubernetes 集群,优先于管理员添加的全局集群。

  • Active 需要勾上;
  • 添加集群的 API URL 即为 Kubernetes API 地址,因为这里 gitlab 安装在 Kubernetes 内,可以使用地址:https://kubernetes.default
  • CA 证书,即为 Kubernetes 的 ca 证书内容全部复制粘贴;
  • 添加集群使用的 token 和博客《 为 Kubernetes dashboard 访问用户添加权限控制》中 kubeconfig 使用的 token 是一样的,这里不再详细描述;
  • Kubernetes namespace,若添加的 token 的 serviceaccount 对应的权限为某个 namespace,这里需要填写其对应的 namespace。默认为空的话,在 ci/cd 过程中,会自动创建项目的唯一 namespace,且只有此 namespace 的 rbac 权限。

5.2 一个 demo

在看 demo 前,先了解下 gitlab 中.gitlab-ci.yml流水线:

Stage GitLab CI/CD 的执行过程中首先驱动的是 Stage。 每个 GitLab CI/CD 都必须包含至少一个 Stage。多个 Stage 是按照顺序执行的。如果其中任何一个 Stage 失败,则后续的 Stage 不会被执行,整个 CI 过程被认为失败。 默认包含三个 Stage:build、test 和 deploy。 build 被首先执行。如果发生错误,本次 CI 立刻失败; test 在 build 成功执行完毕后执行。如果发生错误,本次 CI 立刻失败; deploy 在 test 成功执行完毕后执行。如果发生错误,本次 CI 失败。

Job Job 包含了真正的执行逻辑,例如调用  mvn  或者  gcc  等命令。

demo 项目地址: https://github.com/ygqygq2/kubernetes-gitlab-autodevops https://github.com/ygqygq2/kubernetes-gitlab-autodevops/tree/master/mytest

demo 是一个 maven 项目,用到了 maven 环境的 docker image。
脚本中,设置了settings.xml以用于上传 image 到 harbor。
.gitlab-ci.yml中,各步骤都有注释,已经算是一个完整的流程。
脚本都是 shell,若有用到数组功能,需要在运行的 stage 的 pod 基础镜像安装 bash,否则出现语法错误,比较误导人。

以下是此 demo 的流水线过程:

分支流水线:

主分支流水线:

build 过程:

deploy 过程:

手动运行流水线:

访问相关环境:

6. 小结

上文没有详细介绍 demo,但从流水线图可以看出.gitlab-ci.yml的 stage,熟悉 gitlab 的 stage 和 job 才能灵活配置 CI/CD。建议先从最简单的开始,所有操作使用 echo 代替,整个流水线跑通了,再细化各 job。

参考资料: [1] https://docs.gitlab.com/ee/install/kubernetes/gitlab_chart.html [2] https://docs.gitlab.com/ee/user/project/clusters/index.html [3] https://docs.gitlab.com/ee/topics/autodevops/index.html [4] https://docs.gitlab.com/ee/ci/variables/ [5] https://docs.gitlab.com/ee/ci/yaml/README.html [6] https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml [7] http://www.ttlsa.com/auto/gitlab-cicd-gitlab-ci-yml-configuration-tasks-detailed/