背景

大多数团队都会使用 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

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

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

    1. global:
    2. edition: ce
    3. shell:
    4. port: 8000
    5. praefect:
    6. enabled: true
    7. hosts:
    8. domain: haxi.cc
    9. gitlab:
    10. name: git.haxi.cc
    11. port: 8888
    12. ingress:
    13. configureCertmanager: false
    14. minio:
    15. enabled: false
    16. appConfig:
    17. object_store:
    18. enabled: true
    19. connection:
    20. secret: gitlab-rails-storage
    21. certmanager-issuer:
    22. email: a@b.com
    23. gitlab:
    24. webservice:
    25. deployment:
    26. livenessProbe:
    27. initalDelaySeconds: 60
    28. certmanager:
    29. install: false
    30. gitlab-runner:
    31. install: false
    32. postgresql:
    33. replication:
    34. enabled: true
    35. slaveReplicas: 2
    36. master:
    37. nodeSelector:
    38. gitlab/workerload: db-master
    39. slave:
    40. nodeSelector:
    41. gitlab/workerload: db-slave
    42. extraEnv:
    43. - name: POSTGRESQL_REPLICATION_PASSWORD
    44. value: repl_password
    45. redis:
    46. cluster:
    47. enabled: true
    48. slaveCount: 2
    49. master:
    50. nodeSelector:
    51. gitlab/workerload: db-master
    52. slave:
    53. nodeSelector:
    54. gitlab/workerload: db-slave
    55. nginx-ingress:
    56. enabled: false
    57. registry:
    58. storage:
    59. secret: registry-storage
    60. key: config
  4. 部署 MinIO

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

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

    1. apiVersion: apps/v1
    2. kind: DaemonSet
    3. metadata:
    4. labels:
    5. app: minio
    6. name: minio
    7. spec:
    8. selector:
    9. matchLabels:
    10. app: minio
    11. template:
    12. metadata:
    13. labels:
    14. app: minio
    15. spec:
    16. containers:
    17. - name: minio
    18. image: quay.io/minio/minio:RELEASE.2022-05-08T23-50-31Z
    19. imagePullPolicy: IfNotPresent
    20. ports:
    21. - name: api
    22. containerPort: 9000
    23. hostPort: 9000
    24. protocal: TCP
    25. - name: console
    26. containerPort: 9001
    27. hostPort: 9001
    28. protocal: TCP
    29. env:
    30. - name: MINIO_ROOT_USER
    31. value: admin
    32. - name: MINIO_ROOT_PASSWORD
    33. value: pass@1234
    34. args:
    35. - server
    36. - http://192.168.30.{14...17}/data/minio
    37. - http://192.168.30.{18...22}/data/minio
    38. - --address
    39. - :9000
    40. - --console-address
    41. - :9001
    42. volumeMounts:
    43. - name: storage
    44. mountPath: /data/minio
    45. hostNetwork: true
    46. volumes:
    47. - name: storage
    48. hostPath:
    49. path: /data/minio
    50. ---
    51. apiVersion: v1
    52. kind: Service
    53. metadata:
    54. labels:
    55. app: minio
    56. name: minio
    57. spec:
    58. ports:
    59. - name: api
    60. port: 9000
    61. targetPort: 9000
    62. - name: console
    63. port: 9001
    64. targetPort: 9001
    65. selector:
    66. app: minio
    67. type: ClusterIP

    部署 MinIO

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

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

    1. git-lfs
    2. gitlab-artifacts
    3. gitlab-backups
    4. gitlab-ci-secure-files
    5. gitlab-dependency-proxy
    6. gitlab-mr-diffs
    7. gitlab-packages
    8. gitlab-pages
    9. gitlab-pseudo
    10. gitlab-terraform-state
    11. gitlab-uploads, registry
    12. runner-cache
    13. 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:

      1. kubectl create ns gitlab
      2. kubectl -n gitlab create secret generic gitlab-rails-storage --from-file=connection=examples/objectstorage/rails.minio.yaml
      3. 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,新增:

      1. {{- define "gitlab.gitlab.port" -}}
      2. {{- default "" .Values.global.hosts.gitlab.port -}}
      3. {{- 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 下方新增一行,注意空格对齐上一行:

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

      1. cd gitlab-v5.10.2
      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 为新增项:

      1. access_key = minioAccessKey
      2. secret_key = minioSecretKey
      3. host_base = minio.minio.svc.cluster.local:9000
      4. host_bucket = minio.minio.svc.cluster.local:9000/%(bucket)
      5. website_endpoint = http://minio.minio.svc.cluster.local:9000
      6. use_https = False

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

    • 创建praefect数据库及授权

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

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

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

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

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

      使用nginx做反向代理。

      1、安装nginx

      1. yum install nginx -y
      2. systemctl enable --now nginx

      2、配置反向代理

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

      1. ...
      2. server {
      3. listen 8888 ssl http2;
      4. listen [::]:8888 ssl http2;
      5. server_name git.haxi.cc;
      6. root /usr/share/nginx/html;
      7. ssl_certificate "/etc/nginx/ssl/_.haxi.cc.crt"
      8. ssl_certificate_key "/etc/nginx/ssl/_.haxi.cc.key"
      9. ssl_session_cache shared:SSL:1m;
      10. ssl_ciphers HIGN:!aNULL:!MD5
      11. ssl_prefer_server_ciphers on;
      12. client_max_body_size 512m;
      13. include /etc/nginx/default.d/*.conf;
      14. error_page 404 /404.html;
      15. location = /404.html {
      16. }
      17. error_page 500 502 503 504 /50x.html;
      18. location = 50x.html {
      19. }
      20. location / {
      21. proxy_pass http://10.43.125.236:8181;
      22. #10.43.125.236为gitlab webservice的svc ip
      23. proxy_set_header Host $host:$server_port;
      24. proxy_set_header X-Real-IP $remote_addr;
      25. proxy_set_header X-Real-PORT $remote_port;
      26. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      27. proxy_set_header X-Forwarded-Proto $scheme;
      28. }
      29. }
      30. }
      31. stream {
      32. upstream gitlabssh {
      33. server 10.43.17.193:8000 max_fails=3 fail_timeout=10s;
      34. #10.43.17.193为gitlab shell的svc ip
      35. }
      36. server {
      37. listen 8000;
      38. proxy_connect_timeout 20s;
      39. proxy_timeout 5m;
      40. proxy_pass gitlabssh;
      41. }
      42. }

      3、SSL证书

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

      4、重载nginx使配置生效

      1. systemctl reload nginx

      5、SMTP配置

      1. kubectl -n gitlab edit cm gitlab-sidekiq

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

标签: none

添加新评论