在阿里云 ACK 中部署 GitLab

常见 GitLab 安装方式

Omnibus GitLab 和官方 Docker 镜像

你可以通过 GitLab 的 Linux 安装包(即 Omnibus GitLab)可以在机器上直接安装,或者可以通过 官方的 GitLab 镜像 在 Docker 中部署 GitLab,官方 GitLab Docker 镜像本质上是在 Docker 环境中安装了 Omnibus GitLab,所以二者使用和配置方式几乎接近。安装 Omnibus GitLab 包会一起安装 GitLab 所需的依赖,例如 Redis,PostgreSQL,sidekiq 等组件,这也就意味着用官方 GitLab Docker 镜像启动时,容器内已经运行了所有你需要的或者需要的组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
export GITLAB_HOME=$HOME/gitlab-vol
docker run --detach \
--hostname example.com \
--env GITLAB_OMNIBUS_CONFIG="external_url 'http://example.com'" \
--name gitlab \
--restart always \
--volume $GITLAB_HOME/config:/etc/gitlab \
--volume $GITLAB_HOME/logs:/var/log/gitlab \
--volume $GITLAB_HOME/data:/var/opt/gitlab \
--shm-size 256m \
gitlab/gitlab-ce:16.10.2-ce.0

docker logs -f gitlab

成功启动后,通过 docker stats 查看 GitLab 容器的大概资源占用情况。

1
2
3
docker stats gitlab --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
4e1fd9c7b6f1 gitlab 1.06% 3.506GiB / 7.251GiB 48.34% 2.48kB / 1.91kB 507MB / 650MB 292

Helm chart 和 Operator

官方提供了 Helm chartOperator 两种在 K8s 部署 GitLab 的方式。

Helm chart 和 Docker 镜像不同的是 GitLab 服务不再集中在一个容器中,你可以仅修改几个配置来快速部署 GitLab,也可以按需对 GitLab chart 定制,例如无需创建 PostgreSQL 和 Redis,而是直接连接生产环境中的服务,来满足更复杂的使用需求。

Helm 添加 GitLab chart repo:

1
2
helm repo add gitlab https://charts.gitlab.io/
helm repo update

创建必要的初始配置后,执行命令(来自文档)来快速部署一个 GitLab chart 的 PoC

1
2
3
4
5
6
helm upgrade --install --version 7.10.2 gitlab gitlab/gitlab \
--timeout 600s \
--set global.hosts.domain=example.com \
--set global.hosts.externalIP=10.10.10.10 \
--set certmanager-issuer.email=me@example.com \
--set postgresql.image.tag=13.6.0

NOTE: 如果域名不正确,GitLab Runner 自动注册会失败。

版本 7.10.2 对应 GitLab 16.10.2,如果不确定版本,可以通过命令搜索:

1
helm search repo -l gitlab/gitlab

Operator 方式则是先在集群中部署 GitLab Operator,通过 CR(Custom Resource) 维护 GitLab chart 配置,GitLab Operator 会把根据 CR 创建和调整 GitLab 服务。

sameersbn/gitlab

sameersbn/gitlab 也是一个非常流行的 GitLab Docker 镜像,它从源码构建 GitLab CE,附带了 Nginx、Sidekiq 等必备的依赖组件,但不包含 Redis 和 PostgreSQL。它的最大优点是通过环境变量就能配置 GitLab,这样不论你是通过 Docker、Docker-Compose、或是直接在 K8s 环境中部署和管理它都很方便。

在 ACK 中部署 GitLab

我的部署方式就是使用 sameersbn/gitlab 镜像,因为它没有预装 PostgreSQL 和 Redis,所以我使用了 bitnami/postgresqlbitnami/redis 自建 PostgreSQL 和 Redis。也可以直接购买阿里云的相关产品代替自建。运行 GitLab 容器还是需要比较大的内存,考虑到 K8s Worker 上本来就会跑一些服务,机器最好是 4C8G 以上的配置。

NAS 存储类

部署中需要的持久卷都通过 StorageClass 动态卷制备,所以先在 NAS 控制台创建一个 NAS 文件系统,然后在 ACK 集群 - 存醋 - 存储类 中创建 StorageClass,你可以使用 GUI 创建,或者参考 gitlab-nas-sc.yaml 通过 YAML 创建一个 StorageClass。

部署 bitnami/postgresql 和 bitnami/redis

这两个镜像部署流程接近:

  1. 创建 PVC,这一步会从 StorageClass 创建 PV,并且和 PVC 绑定
  2. 通过环境变量配置,我偷懒把所有配置都写在了 ConfigMap 里,在 Pod 启动时,会从 ConfigMap 加载环境变量
  3. 在 ACK 里创建 StatefulSet,StatefulSet 的启动策略可以避免正在启动的 Pod 和即将退出的 Pod 同时挂载一个 PV
  4. 配置相应的网络 Service,这里我用了 Headless Service,毕竟都是只有一个实例,没有负载均衡的场景。

权限问题

bitnami 容器不运行在 root 用户,而 NAS 挂载的目录默认是 root 的,所以在挂载后访问会出现 Permission Denied 的情况。参考阿里云的文档,需要配置 securityContext:

1
2
3
4
securityContext:
runAsUser: 1001
fsGroup: 1001
fsGroupChangePolicy: "OnRootMismatch"

runAsUserfsGroup 一致,配置为 bitnami 镜像默认的用户 1001fsGroupChangePolicy 可以在持久卷重新挂载(比如 Pod 重启)时避免不需要的 chown 操作。

runAsGroup 不能配置,bitnami 容器运行时很多目录是通过 root 组权限访问的。

具体原因参考文档

完整 YAML 文件参考 gitlab-redis.yamlgitlab-pgsql.yaml

部署 sameersbn/gitlab

部署 sameersbn/gitlab 流程和 bitnami 的差不多,参考文档调整配置,然后创建 StatefulSet 就可以了,不过没有什么权限需要特殊处理。就是镜像比较大,初次启动比较慢。

有几个配置需要注意:

  • GITLAB_HTTPS 设为了 true,这种情况下 GitLab 容器会额外监听 443 端口。这个配置会影响 GitLab UI 中展示链接时是否带上 https,而我们 https 是通过 Ingress 来实现的,所以在 Service 里还是只暴露 80。
  • GITLAB_SSH_HOST 设置了一个不同的主机名,GITLAB_HOST 关联了 Ingress 端点,需要设置 GITLAB_SSH_HOST 来关联 External Service 端点。

参考文件 gitlab-app.yaml

ALB Ingress 和 NLB Service

简单聊聊在 ACK 中用 ALB、CLB、NLB 三款负载均衡产品。

ALB 和 ACK 结合最好,可以通过 CRD 管理,配置 Ingress 时,只要指定 Class 就行。但是最近有一个恶心人的操作,就是把基础版的功能 HTTPS 证书支持强行削了,手动可以配置 ALB 基础版的证书,但是没办法通过 CRD 匹配到证书了,你必须使用 3 倍价格的标准版才行。

CLB 用在 Nginx Ingress 上,如果用这套机制,ACK 会给一个集群域名,自动绑定到 CLB 端点上。

NLB 和 CLB 都是 4 层的,但是用法上不太一样。ACK 支持在 Service 的 annotations 里创建或者指定 NLB 实例,阿里云推荐使用这种方式把 Service 对外暴露。我试过创建一个 Nginx Ingress,然后通过修改 nginx-ingress-controller 的方式,让 Nginx Ingress 通过 NLB 对外暴露,不过这样会让 Ingress 处于非托管的状态,算是一种尝试性用法。

结尾

去年年初搭完 GitLab 后本想整理一下发篇博客的,结果一拖就拖到了现在。今年正好负责新集群搭建,迁移了 GitLab 后又想起这事,趁我还没忘记细节,赶紧整理出来。

这篇文章目的是聊聊用阿里云全家桶在 ACK 部署简单部署一个 GitLab,以及我的各种不靠谱操作,但从整体观感看,更像是 GitLab 场景下阿里云 ACK 全家桶使用。我在 ACK 中部署 GitLab 单纯是为了管理统一,如果考虑经济实惠,建议直接用 Omnibus 安装包方式,或者看看 gitea