背景

大多数团队都会使用 GitLab 作为代码管理平台,通常采用的都是通过单个安装包(Omnibus)进行安装,安装包内已捆绑了运行 GitLab 所需的所有服务与工具。若是你所在的团队人数比较多或者为了解决单机部署所带来的单点故障问题,那么可用的方案有以下两种:

  • 多台主机安装 Omnibus 包,通过 /etc/gitlab/gitlab.rb 配置文件开启/禁用所需组件,控制组件的数量来达到高可用部署和性能需求
  • 通过 Helm Chart 部署到 Kubernetes 中

现在对比一下各个方案的优劣:

  • 单机部署

    • 优点:维护简单
    • 缺点:存在单点故障、不足以支撑1000+用户使用
      gitlab-single-server.png
  • 多机部署(Omnibus 包)

    • 优点:灵活配置
    • 缺点:配置复杂,官方文档对此部署方式的配置没有很明确的指引
      gitlab-architectures-3k-users.png
  • Helm Chart 部署到 Kubernetes 集群

    • 优点:安装配置简单(其实不简单)、灵活扩容(其中 shell、registry、sidekiq、webservice 支持 HPA 自动扩缩容)
    • 缺点:有一定的局限性,做不到非常灵活的配置;Helm Chart 没有提供的配置项,则要自行修改 Helm Chart 来实现
      代码仓库.drawio.png

    * 不管哪种方案,对 PostgreSQL 的高可用,都是要借助于第三方的 PostgreSQL 高可用方案,GitLab 没有集成。

我的选择

基于以上三种方案的介绍,我的需求是要求有一定的高可用性,仓库(repositories)要存储多份以满足数据的健壮性。

加上我对 Kubernetes 比较熟悉,而且现在部署应用都 All In Kubernetes 了,没有理由不用的。因此我选用 GitLab Helm Chart 的方式部署在 Kubernetes 集群上。

遇到的问题

官方提供的 Helm Chart 安装的过程中可能会遇到各种各样的问题,我这里列一下我所遇到的一些问题:

  • 不支持自定义 GitLab 端口号
  • Helm Chart 自带的对象存储服务 MinIO 安装的是单实例,不满足高可用需求
  • minio 要求要有一个域名,我没有,所以安装完后还要做一定的修改
  • PostgreSQL slave 报错
  • 不会自动创建 praefect 连接 PostgreSQL 的授权账号
  • Helm Chart 貌似没有 SMTP 发送邮件的相关配置

安装前提条件

  • 你得有一个域名,如:git.haxi.cc
  • 你得有一个 Kubernetes 集群,并配备 StorageClass,我用的是 local-path-provisioner
  • 你得用 Helm3
  • 因为用local-path,我定义了3个节点为数据节点,跑 PostgreSQL 和 Redis,因此我给节点打上标签

    • 给一个节点打上标签:gitlab/workerload: db-master
    • 给两个节点打上标签:gitlab/workerload: db-slave

安装步骤

  1. 我的一些配置

    • 不安装 ingress,另外安装 Nginx 做反代
    • GitLab 端口:8888
    • shell 端口(SSH 协议):8000
    • 不安装 runner,我貌似在官方文档看过 helm 部署的 runner 有问题来着,但是我已经找不到链接了
  2. 下载 GitLab Helm Chart

    helm add repo gitlab https://charts.gitlab.io
    helm pull gitlab/gitlab --version 5.10.2
  3. 配置 GitLab Helm Chart

    编写 Helm Chart 配置文件,保存为 myvalues.yaml,文件内容如下:

    global:
      edition: ce
      shell:
        port: 8000
      praefect:
        enabled: true
      hosts:
        domain: haxi.cc
        gitlab:
          name: git.haxi.cc
          port: 8888
      ingress:
        configureCertmanager: false
      minio:
        enabled: false
      appConfig:
        object_store:
          enabled: true
          connection:
            secret: gitlab-rails-storage
    certmanager-issuer:
      email: [email protected]
    gitlab:
      webservice:
        deployment:
          livenessProbe:
            initalDelaySeconds: 60
    certmanager:
      install: false
    gitlab-runner:
      install: false
    postgresql:
      replication:
        enabled: true
        slaveReplicas: 2
      master:
        nodeSelector:
          gitlab/workerload: db-master
      slave:
        nodeSelector:
          gitlab/workerload: db-slave
      extraEnv:
      - name: POSTGRESQL_REPLICATION_PASSWORD
        value: repl_password
    redis:
      cluster:
        enabled: true
        slaveCount: 2
      master:
        nodeSelector:
          gitlab/workerload: db-master
      slave:
        nodeSelector:
          gitlab/workerload: db-slave
    nginx-ingress:
      enabled: false
    registry:
      storage:
        secret: registry-storage
        key: config
  4. 部署 MinIO

    MinIO 是一款高性能、分布式的对象存储系统。Gitlab使用它存储部分数据。

    编写minio部署清单,保存为minio.yaml,内容如下:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      labels:
        app: minio
      name: minio
    spec:
      selector:
        matchLabels:
          app: minio
      template:
        metadata:
          labels:
            app: minio
        spec:
          containers:
          - name: minio
            image: quay.io/minio/minio:RELEASE.2022-05-08T23-50-31Z
            imagePullPolicy: IfNotPresent
            ports:
            - name: api
              containerPort: 9000
              hostPort: 9000
              protocal: TCP
            - name: console
              containerPort: 9001
              hostPort: 9001
              protocal: TCP
            env:
            - name: MINIO_ROOT_USER
              value: admin
            - name: MINIO_ROOT_PASSWORD
              value: pass@1234
            args:
            - server
            - http://192.168.30.{14...17}/data/minio
            - http://192.168.30.{18...22}/data/minio
            - --address
            - :9000
            - --console-address
            - :9001
            volumeMounts:
            - name: storage
              mountPath: /data/minio
          hostNetwork: true
          volumes:
          - name: storage
            hostPath:
              path: /data/minio
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: minio
      name: minio
    spec:
      ports:
      - name: api
        port: 9000
        targetPort: 9000
      - name: console
        port: 9001
        targetPort: 9001
      selector:
        app: minio
      type: ClusterIP

    部署 MinIO

    kubectl create ns minio
    kubectl -n minio apply -f minio.yaml

    创建buckets,登录minio webui,依次创建以下bucket:

    git-lfs
    gitlab-artifacts
    gitlab-backups
    gitlab-ci-secure-files
    gitlab-dependency-proxy
    gitlab-mr-diffs
    gitlab-packages
    gitlab-pages
    gitlab-pseudo
    gitlab-terraform-state
    gitlab-uploads, registry
    runner-cache
    tmp

    在Minio上创建一个ServiceAccount,并记录下来,等会配置gitlab连接到对象存储要用到。

  5. 部署 GitLab

    • 配置minio连接信息

      部署 GitLab 前,需要先配置 MinIO 的连接信息。在 examples/objectstorage 目录下有配置模板,本次部署用到的模板是rails.minio.yaml和registry.minio.yaml。

      修改rails.minio.yaml模板中的aws_access_key_id、aws_secret_access_key为刚才在minio上创建的ServiceAccount对应的AccessKey和SecretKey,host为minio.minio.svc.cluster.local,endpoint为http://minio.minio.svc.cluster.local:9000

      修改registry.minio.yaml模板中的accesskey、secretkey为刚才在minio上创建的ServiceAccount对应的AccessKey和SecretKey,regionendpoint为http://minio.minio.svc.cluster.local:9000

      创建secret:

      kubectl create ns gitlab
      kubectl -n gitlab create secret generic gitlab-rails-storage --from-file=connection=examples/objectstorage/rails.minio.yaml
      kubectl -n gitlab create secret generic registry-storage --from-file=config=examples/objectstorage/registry.minio.yaml
    • 编辑gitlab helm chart模板

      由于官方提供的helm charts不支持自定义gitlab的端口号,所以要对gitlab helm charts做一定的定制化修改,添加自定义端口的支持。

      编辑templates/_helpers/tpl,新增:

      {{- define "gitlab.gitlab.port" -}}
      {{- default "" .Values.global.hosts.gitlab.port -}}
      {{- end -}}

      编辑 charts/gitlab/charts/geo-logcursor/templates/configmap.yml, charts/gitlab/charts/toolbox/templates/configmap.yaml, charts/gitlab/charts/webservice/templates/configmap.yml, charts/gitlab/charts/sidekiq/templates/configmap.yaml, charts/gitlab/charts/migrations/templates/configmap.yaml,在 gitlab.yml.erbhost 下方新增一行,注意空格对齐上一行:

          port: {{ default "" (include "gitlab.gitlab.port" .) }}
    • 部署gitlab

      cd gitlab-v5.10.2
      helm -n gitlab install gitlab -f values.yaml -f myvalues.yaml .
    • 修复postgresql slave启动失败

      postgresql slave启动会报错:The POSTGRESQL_REPLICATION_PASSWORD variable is empty or not set. Set the envirable ALLOW_EMPTY_PASSWORD=yes to allow container to be started with blank passwords.,需要修改secret gitlab-postgresql-password,新增一个键值对:postgresql-replication-password: cmVwbF9wYXNzd29yZA==

      其中cmVwbF9wYXNzd29yZA==repl_password的 base64 编码后的值。

    • 修复toolbox连接minio报错

      编辑 configmap gitlab-toolbox,修改 cat <<EOF > "/${secret_dir}/.s3cfg" 下方的几个配置项的值,其中 use_https 为新增项:

      access_key = minio的AccessKey
      secret_key = minio的SecretKey
      host_base = minio.minio.svc.cluster.local:9000
      host_bucket = minio.minio.svc.cluster.local:9000/%(bucket)
      website_endpoint = http://minio.minio.svc.cluster.local:9000
      use_https = False

      配置完成后,重启 toolbox 使其加载正确的配置项。

    • 创建praefect数据库及授权

      GitLab Helm Chart 部署后,并不会自动创建 preafect 数据库及其授权,需要手动创建。

      1、查询praefect的配置的数据库连接密码:

      kubectl -n gitlab get secret gitlab-praefect-dbsecret -o jsonpath="{.data.secret}" | base64 -d; echo

      2、进入postgresql master容器内执行命令创建数据库及授权:

      kubectl -n gitlab exec -it gitlab-postgresql-master-0 -- /bin/bash
      postgresql> PGPASSWORD=$(cat $POSTGRES_POSTGRES_PASSWORD_FILE) psql -U postgres
      postgresql> CREATE ROLE praefect WITH LOGIN;
      postgresql> \password praefect
      postgresql> 输入步骤1查询到的密码
      postgresql> CREATE DATABASE praefect WITH OWNER praefect;
    • 配置反向代理

      使用nginx做反向代理。

      1、安装nginx

      yum install nginx -y
      systemctl enable --now nginx

      2、配置反向代理

      修改/etc/nginx/nginx.conf,内容如下:

      ...
          server {
              listen        8888 ssl http2;
              listen        [::]:8888 ssl http2;
              server_name   git.haxi.cc;
              root          /usr/share/nginx/html;
              
              ssl_certificate "/etc/nginx/ssl/_.haxi.cc.crt"
              ssl_certificate_key "/etc/nginx/ssl/_.haxi.cc.key"
              ssl_session_cache shared:SSL:1m;
              ssl_ciphers HIGN:!aNULL:!MD5
              ssl_prefer_server_ciphers on;
              
              client_max_body_size 512m;
              
              include /etc/nginx/default.d/*.conf;
              
              error_page 404 /404.html;
              location = /404.html {
              }
        
              error_page 500 502 503 504 /50x.html;
              location = 50x.html {
              }
              
              location / {
                  proxy_pass http://10.43.125.236:8181;
                  #10.43.125.236为gitlab webservice的svc ip
                  proxy_set_header Host $host:$server_port;
                  proxy_set_header X-Real-IP $remote_addr;
                  proxy_set_header X-Real-PORT $remote_port;
                  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                  proxy_set_header X-Forwarded-Proto $scheme;
              }
          }
      }
      
      stream {
          upstream gitlabssh {
              server 10.43.17.193:8000 max_fails=3 fail_timeout=10s;
              #10.43.17.193为gitlab shell的svc ip
          }
          server {
              listen 8000;
              proxy_connect_timeout 20s;
              proxy_timeout 5m;
              proxy_pass gitlabssh;
          }
      }

      3、SSL证书

      证书放这里:
      /etc/nginx/ssl/_.haxi.cc.crt
      /etc/nginx/ssl/_.haxi.cc.key

      4、重载nginx使配置生效

      systemctl reload nginx

      5、SMTP配置

      kubectl -n gitlab edit cm gitlab-sidekiq

      修改email_from, smtp_setting.rb(address, user_name, password)

标签: none

添加新评论