Skip to content

47.GitLab

GitLab 是一个基于 Web 流行开源 Git 仓库管理工具,可以实现代码仓库的管理、代码浏览、问题跟踪、CI/CD 等功能。GitLab 还提供了自己的 CI/CD 工具,可以方便地进行持续集成和持续部署。对于中国地区我们还可以适合国产化的版本:极狐 GitLab,致力于实现一体化 DevOps 平台。

安装

GitLab 官方提供了 Helm 的方式在 Kubernetes 集群中来快速安装,所以我们可以直接使用 Helm 来安装 GitLab。

我们这里的安装环境如下所示:

$ kubectl get nodes
NAME      STATUS   ROLES           AGE    VERSION
master1   Ready    control-plane   183d   v1.26.2
node1     Ready    <none>          164d   v1.26.3
node2     Ready    <none>          183d   v1.26.2

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"27", GitVersion:"v1.27.4", GitCommit:"fa3d7990104d7c1f16943a67f11b154b71f6a132", GitTreeState:"clean", BuildDate:"2023-07-19T12:20:54Z", GoVersion:"go1.20.6", Compiler:"gc", Platform:"darwin/arm64"}
Kustomize Version: v5.0.1
Server Version: version.Info{Major:"1", Minor:"26", GitVersion:"v1.26.2", GitCommit:"fc04e732bb3e7198d2fa44efa5457c7c6f8c0f5b", GitTreeState:"clean", BuildDate:"2023-02-22T13:32:22Z", GoVersion:"go1.19.6", Compiler:"gc", Platform:"linux/amd64"}

$ helm version
version.BuildInfo{Version:"v3.11.1", GitCommit:"293b50c65d4d56187cd4e2f390f0ada46b4c4737", GitTreeState:"clean", GoVersion:"go1.18.10"}

首先要添加极狐 GitLab 的 Helm Chart 仓库:

$ helm repo add jh-gitlab https://charts.gitlab.cn/
"jh-gitlab" has been added to your repositories
$ helm repo update

查看是否添加成功:

$ helm repo list
NAME      URL
jh-gitlab https://charts.gitlab.cn/
$ helm search repo jh-gitlab
NAME                    CHART VERSION   APP VERSION     DESCRIPTION
jh-gitlab/gitlab        7.3.2           v16.3.2         GitLab is the most comprehensive AI-powered Dev...
jh-gitlab/gitlab-runner 0.55.0          16.2.0          GitLab Runner

可以看到极狐 GitLab Chart 的版本是 7.3.2,对应的极狐 GitLab 版本是 16.3.2。

由于极狐 GitLab 包含非常多的组件,包括核心组件(诸如 Registry、Gitaly 等)、可选依赖组件(诸如 PostgreSQL、Redis 等)、可选附件组件(Prometheus、Grafana 等),整体的 Helm Values 文件比较复杂,可以根据自己的需求进行配置。

该 Chart 包是以分布式微服务的方式进行安装的,要搞清楚如何安装,我们需要先了解一下 GitLab 的架构,如下图所示:

img

其中主要涉及到以下几个组件:

  • GitLab Workhorse:轻量级反向代理服务器,可以处理一些大的 HTTP 请求,处理 Git Push/Pull 请求,处理到 Rails 的连接会反向代理给后端的 Puma。
  • Puma:处理 Web 界面和 API 的请求。从 GitLab 13.0 开始,Puma 是默认的 Web 服务器。Puma 是一个 Ruby 应用程序服务器,用于运行核心 Rails 应用程序,该应用程序在 GitLab 中提供面向用户的功能。
  • GitLab Shell:用于 SSH 交互,而不是 HTTP。
  • Redis:缓存每个客户端的 sessions 和后台队列,负责分发任务。
  • Gitaly:后台服务,专门负责访问磁盘以高效处理 gitlab-shellgitlab-workhorse 的 git 操作,并缓存耗时操作。所有的 git 操作都通过 Gitaly 处理,并向 GitLab web 应用程序提供一个 API,以从 git 获取属性,并获取 blob 数据。
  • Sidekiq:后台核心服务,可以从 Redis 队列中提取作业并对其进行处理。后台作业允许 GitLab 通过将工作移至后台来提供更快的请求/响应周期。

当然还有一些其他的组件,比如 MinioKASPrometheus 等,这些都是可选的组件,可以根据自己的需求进行配置。其中 KAS 提供了 GitLab 代理服务器,管理 Kubernetes 的 GitLab 代理。

了解了基本的架构之后,我们就可以根据我们自身的需求来配置 Helm Values 文件了,我们这里使用的 values.yaml 文件内容如下:

global:
  time_zone: "Asia/Shanghai" # 设置gitlab时区
  edition: ce # 设置gitlab版本 ce:社区版 ee:企业版

  hosts:
    domain: k8s.local # 配置根域名,用于gitlab生成(gitlab.k8s.local, kas.k8s.local, minio.k8s.local)
    https: false # 是否启用https访问,关闭 https

  ingress:
    configureCertmanager: false
    provider: nginx
    class: nginx
    enabled: true
    tls:
      enabled: false # 是否开启tls

  minio:
    enabled: true
    # persistence:
    #   enabled: true
    #   storageClass: cfsauto  # 无效
    #   size: 10Gi

# certmanager-issuer: # 证书生成所使用的邮箱
#   email: ych_1024@163.com

certmanager:
  installCRDs: false
  nameOverride: certmanager
  install: false
  rbac:
    create: true

nginx-ingress: &nginx-ingress
  enabled: false

prometheus:
  install: false

redis:
  install: true
  global:
    storageClass: cfsauto

postgresql:
  install: true
  global:
    storageClass: cfsauto

gitlab-runner:
  install: false

gitlab:
  gitaly:
    persistence:
      enabled: true
      storageClass: cfsauto
      size: 10Gi
  kas:
    minReplicas: 1
  gitlab-shell:
    minReplicas: 1
  webservice:
    minReplicas: 1

registry:
  enabled: false

这里我们不使用 TLS 访问,但是需要注意的是数据库这些组件的存储,一定要做好持久化工作,配置一个可用的存储类即可。然后使用下面的命令即可一键安装:

$ helm upgrade --install jh jh-gitlab/gitlab --namespace kube-ops -f gitlab-values.yaml
Release "jh" does not exist. Installing it now.
NAME: jh
LAST DEPLOYED: Sat Sep  9 15:30:31 2023
NAMESPACE: kube-ops
STATUS: deployed
REVISION: 1
NOTES:
=== NOTICE
The minimum required version of PostgreSQL is now 13. See https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/doc/installation/upgrade.md for more details.

=== WARNING
Automatic TLS certificate generation with cert-manager is disabled.
One or more of the components does not have a TLS certificate Secret configured.
As a result, Self-signed certificates were generated for these components.

You may retrieve the CA root for these certificates from the `jh-wildcard-tls-ca` secret, via the following command. It can then be imported to a web browser or system store.

  kubectl get secret jh-wildcard-tls-ca -ojsonpath='{.data.cfssl_ca}' | base64 --decode > gitlab.k8s.local.ca.pem

If you do not wish to use self-signed certificates, please set the following properties:
- global.ingress.tls.secretName
OR all of:
- global.ingress.tls.enabled (set to `true`)
- gitlab.webservice.ingress.tls.secretName
- minio.ingress.tls.secretName
- gitlab.kas.ingress.tls.secretName

安装后,隔一段时间就可以看到所有的组件都已经正常运行了:

$ kubectl get pods -n kube-ops
NAME                                      READY   STATUS      RESTARTS        AGE
jh-gitaly-0                               1/1     Running     0               2m32s
jh-gitlab-exporter-5cc8fbbdfd-msmk9       1/1     Running     0               2m32s
jh-gitlab-shell-5dc449db95-z5rgb          1/1     Running     0               2m32s
jh-kas-96fc4bbb5-z89z6                    1/1     Running     3 (2m10s ago)   2m32s
jh-migrations-1-vcqkc                     0/1     Completed   0               2m32s
jh-minio-89d5dc58-rqjmc                   1/1     Running     0               2m32s
jh-minio-create-buckets-1-vxz45           0/1     Completed   0               2m32s
jh-postgresql-0                           2/2     Running     0               2m21s
jh-redis-master-0                         2/2     Running     0               2m32s
jh-sidekiq-all-in-1-v2-6fdd868dcb-9zxbz   1/1     Running     0               2m32s
jh-toolbox-67c54d9987-ht8f9               1/1     Running     0               2m32s
jh-webservice-default-6d9986485f-rmsd4    2/2     Running     0               2m32s
$ kubectl get ingress -n kube-ops
NAME                    CLASS   HOSTS                   ADDRESS       PORTS     AGE
jh-kas                  nginx   kas.k8s.local           10.98.12.94   80        31m
jh-minio                nginx   minio.k8s.local         10.98.12.94   80        31m
jh-webservice-default   nginx   gitlab.k8s.local        10.98.12.94   80        31m

安装完成后我们就可以通过 gitlab.k8s.local 来访问 GitLab 了,但是要注意的是,我们这里是通过 Ingress 的方式来暴露服务的,所以我们需要修改本地的 hosts 文件,将 gitlab.k8s.local 指向到 Ingress 的 IP 地址。

img

初始用户名为 root,密码是以 Secret 的形式存放的:

$ kubectl -n kube-ops get secret | grep root
jh-gitlab-initial-root-password   Opaque               1      58m

$ kubectl -n kube-ops get secret jh-gitlab-initial-root-password -o=jsonpath='{.data.password}' | base64 -d
1TkQrZQFMiqhvpgZR5E96ncnbOBQcDboXFwQ05PExuFDYwwc5x0cyjAyRSzIPeFd

使用上述密码以及 root 用户名即可登录极狐 GitLab 实例:

img

然后可以前往 https://gitlab.k8s.local/-/profile/password/edit 页面修改密码,需要至少 8 位(比如 root@321),还可以修改用户名、语言等信息。

img

然后我们可以创建一个实例仓库来测试下:

img

创建完成后,我们可以添加本地用户的一个 SSH-KEY,这样我们就可以通过 SSH 来拉取或者推送代码了。SSH 公钥通常包含在 ~/.ssh/id_rsa.pub文件中,并以 ssh-rsa 开头。如果没有的话可以使用 ssh-keygen 命令来生成,id_rsa.pub 里面的内容就是我们需要的 SSH 公钥,然后添加到 Gitlab 中。

如果我们通过 SSH 方式去获取代码,这里需要注意我们服务的暴露方式,我们这里是通过 ingress-nginx 来暴露的服务,属于 7 层服务,而且我们这里本地是通过 LoadBalancer 去接入的 Ingress 流量,要通过 SSH 方式去获取代码,实际上是通过 gitlab-shell 组件来实现的,所以我们需要通过 ingress-nginx 去暴露 gitlab-shell 组件的 TCP 服务,这样我们才能通过 SSH 方式去获取代码。

$ kubectl get svc jh-gitlab-shell -n kube-ops
jh-gitlab-shell          ClusterIP   10.108.128.219   <none>        22/TCP                                27m

可以看到 gitlab-shell 的端口是 22,所以我们需要在 ingress-nginx 中添加一个 TCP 的暴露规则,上面使用 Helm Chart 方式安装后会自动创建:

$ kubectl get cm -n kube-ops jh-nginx-ingress-tcp -oyaml
apiVersion: v1
data:
  "22": 'kube-ops/jh-gitlab-shell:22::'
kind: ConfigMap
metadata:
  annotations:
    meta.helm.sh/release-name: jh
    meta.helm.sh/release-namespace: kube-ops
  creationTimestamp: "2023-09-09T08:56:37Z"
  labels:
    app: gitlab-shell
    app.kubernetes.io/managed-by: Helm
    chart: gitlab-shell-7.3.2
    heritage: Helm
    release: jh
  name: jh-nginx-ingress-tcp
  namespace: kube-ops

而且该配置文件是不能被你自己的 ingress-nginx 识别的,所以上面这个 ConfigMap 其实并没有生效,而且如果你使用的是 hostNetwork 模式则可能会和宿主机的 22 端口冲突,这里我们可以修改一下端口,比如修改为 2222,比如我们这里的 ingress-nginx 监听的 tcp 配置的 ConfigMap 名为 ingress-nginx-tcp,则修改为如下内容:

# tcp-ingress.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: ingress-nginx-tcp
  namespace: ingress-nginx
data:
  "2222": "kube-ops/jh-gitlab-shell:22::"

然后在本地的 ~/.ssh/config 文件中添加如下配置:

Host gitlab.k8s.local
  HostName gitlab.k8s.local
  User cnych
  Port 2222
  IdentityFile ~/.ssh/id_rsa

现在我们就可以通过 SSH 方式去获取代码了:

$ git clone git@gitlab.k8s.local:cnych/gitlab-demo.git
Cloning into 'gitlab-demo'...
The authenticity of host '[gitlab.k8s.local]:2222 ([43.137.15.212]:2222)' can't be established.
ED25519 key fingerprint is SHA256:X/LdrDCX1kxg/jqye2LJEHZfxONPm6iFUX2rwyUjuaY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[gitlab.k8s.local]:2222' (ED25519) to the list of known hosts.
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.

同样现在我们也可以提交代码到 GitLab 了:

$ cd gitlab-demo/
$ echo "Hello GitLab Helm Chart" > README.md
$ git add .
$ git commit -m "add README.md"
[main 9deb0d5] add README.md
 1 file changed, 1 insertion(+), 92 deletions(-)
$ git push origin main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 10 threads
Compressing objects: 100% (1/1), done.
Writing objects: 100% (3/3), 268 bytes | 268.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To gitlab.k8s.local:cnych/gitlab-demo.git
   36c0acb..9deb0d5  main -> main

我们可以在 GitLab 的 Web 界面上看到提交的代码了:

img

到这里我们就完成了 GitLab 的安装。如果你想要了解更多的 GitLab 的使用,可以参考 GitLab 官方文档

触发 Jenkins 构建

到这里我们完成了 GitLab 和 Jenkins 的安装,其实我们还可以将 GitLab 和 Jenkins 结合起来使用,这样当我们提交代码到 GitLab 时,就可以触发 Jenkins 的构建了。

我们可以通过 GitLab 的 Web 界面来触发 Jenkins 的构建,首先我们需要在 Jenkins 中创建一个 Pipeline 项目,然后在 GitLab 中配置 Webhook,这样当我们提交代码到 GitLab 时,就会触发 Jenkins 的构建。

首先需要在 Jenkins 中安装插件 Generic Webhook Trigger

img

安装完成后,我们重新创建一个新的 Pipeline 任务,然后就可以选择这个触发器了。

img

勾选 Generic Webhook Trigger 后, 相当于给 Jenkins 加了一个新的接口 http://JENKINS_URL/generic-webhook-trigger/invoke

img

在使用的时候我们需要把 JENKINS_URL 换成自己真实的 Jenkins 服务器地址,有端口就加上端口,是域名就写域名。比如我们这里就是 http://jenkins.k8s.local/generic-webhook-trigger/invoke

此外我们还可以为该触发器添加一个 Token,这样可以增加安全性,比如我们这里的 Token 是 youdianzhishi

img

一共有 3 种方式可以使用这个 Token:

  • 在 URL 中使用 token 参数,比如 http://jenkins.k8s.local/generic-webhook-trigger/invoke?token=youdianzhishi
  • 在 HTTP Header 中使用 token 参数,比如 token: youdianzhishi
  • 通过 HTTP Header 的 Bearer Token 传递,比如 Authorization: Bearer youdianzhishi

此外还可以配置触发条件等等。然后定义流水线代码后保存即可。

这样 Jenkins 就开启 trigger 了,开启后,就可以实现其他系统通过一个指定的 URL 进行自动触发构建了。

就比如我们这里还是使用上面的 gitlab-demo 这个仓库。进入 GitLab 项目设置, 进入 Webhook 配置页面;

添加新的 webhook,配置要触发的 URL,即 Jenkins 触发器接口 URL:http://jenkins.k8s.local/generic-webhook-trigger/invoke?token=youdianzhishi。然后选择发生哪种 GitLab 事件后触发此 Webhook,例如:Push 提交代码、Tag 创建标签等等;

img

添加后如果出现 Url is blocked: Requests to the local network are not allowed 这样的错误信息,则需要进入管理中心 -> 网络页面,路径 http://gitlab.k8s.local/admin/application_settings/network,z 找到出站请求,勾选允许来自 webhooks 和集成对本地网络的请求

img

保存后重新再去添加 webhook,就可以成功了,然后我们可以通过测试按钮来测试下是否可以触发 Jenkins 的构建。

img

正常情况下,我们可以看到 Jenkins 的构建已经触发了:

img

在 GitLab Webhook 这边我们也可以查看到请求日志,如果出现了错误,可以根据日志来进行排查:

img

到这里我们就完成了 GitLab 和 Jenkins 的集成,当我们提交代码到 GitLab 时,就可以触发 Jenkins 的构建了,当然还有很多地方是可以优化的,我们将在后面的内容中进行介绍。