Gitaly ClusterでGitLabのGitalyを冗長化させる

## はじめに

GitLabは複数のコンポーネントから構成されていますが、その中でもGitalyはGitリポジトリへのアクセス処理を担っています。GitLab 13からは[Gitaly Cluster](https://docs.gitlab.com/ee/administration/gitaly/praefect.html)が提供されるようになり、Gitリポジトリの冗長化が可能となりました。

それ以前もNFSをストレージとして使用して可用性を上げることはできていましたが、[公式ページ](https://docs.gitlab.com/ee/administration/nfs.html)によるとGitLab 13からNFSは非推奨となり、GitLab 14からはサポート外となるようです。

今回はGitaly ClusterをKubernetes上に構築する手順を説明します。

## Gitaly Clusterについて

Gitaly ClusterはGitalyのクラスタ化を実現させたもので、PraefectというGitalyへのルーティングとトランザクション処理を行うコンポーネントを利用します。また、PraefectにはロードバランサとDBをデプロイする必要があります。Kubernetesの場合、ロードバランサはServiceになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/d6687b87-138c-571c-798a-aa29cedd35fc.png)

Gitaly Clusterは以下の機能があります。

* レプリカごとの高い整合性
* 自動フェイルオーバー
* データロス検知後のリポジトリへのready only設定

## 構築

環境はEKS 1.16を使用し、Helm 3.4.0でデプロイします。GitLab Helm Chart 4.5.3、ALB Ingress Controller Helm Chart 0.1.11を利用しています。

### GitLabのデプロイ

GitLab Helm Chartのvaluesは以下のようにします。RDSのPostgreSQL DBを事前にPraefectのために作成しておき`global.praefect.psql.host`に設定します。バージョンは11以上でないといけないことに注意しましょう。

```yaml:my-values.yaml
global:
  edition: ce
  hosts:
    https: false
    gitlab:
      name: XXXXXXXXXX.ap-northeast-1.elb.amazonaws.com
      https: false
  ingress:
    configureCertmanager: false
    enabled: false
    tls:
      enabled: false
  praefect:
    enabled: true
    gitalyReplicas: 3
    psql:
      host: YYYYYYYYYY.ap-northeast-1.rds.amazonaws.com
      port: 5432
      user: praefect
      dbName: praefect
      sslMode: "disable"
upgradeCheck:
  enabled: false
certmanager:
  install: false
nginx-ingress:
  enabled: false
prometheus:
  install: false
registry:
  enabled: false
gitlab-runner:
  install: false
gitlab:
  gitlab-exporter:
    enabled: false
  gitlab-shell:
    enabled: false
  praefect:
    replicas: 3
  sidekiq:
    registry:
      enabled: false
  task-runner:
    enabled: false
    registry:
      enabled: false
  webservice:
    registry:
      enabled: false
    service:
      type: NodePort
    ingress:
      enabled: false
```

```console
$ helm install --name test-gitlab \
  -f my-values.yaml \
  gitlab/gitlab --version 4.5.3
```

`global.hosts.gitlab.name`にはALBのエンドポイントを設定しています。ALB Ingress Controllerをデプロイしておき、以下のIngressでALBを自動作成します。`gitlab.webservice.service.type`が`NodePort`になっているのもそのためです。

```yaml:ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    kubernetes.io/ingress.class: alb
  name: alb-ingress
spec:
  rules:
  - http:
      paths:
       - backend:
           serviceName: test-gitlab-webservice
           servicePort: 8181
       - backend:
           serviceName: test-gitlab-webservice 
           servicePort: 8080
         path: /admin/sidekiq
```

```console
$ kubectl apply -f ingress.yaml
```

以上を行うだけではPraefect PodはRunningになりません。Praefect DBの設定を手動で行う必要があります。

### Praefect DBの設定

HelmでGitLabをデプロイした際、Praefect DBのパスワードがSecretとして作成されるので以下のコマンドで確認します。

```console
$ kubectl get secret test-gitlab-praefect-dbsecret \
  -o jsonpath='{.data.secret}' \
  | base64 --decode
```

確認したパスワードを用いて、事前に作成したRDSのPostgreSQL DBに以下の設定を入れます。

```console
$ psql -h YYYYYYYYYY.ap-northeast-1.rds.amazonaws.com \
  -p 5432 \
  -U postgres \
  -d template1
> CREATE ROLE praefect WITH LOGIN;
> \password praefect
Enter new password:
Enter it again:
> GRANT praefect TO postgres;
> CREATE DATABASE praefect WITH OWNER praefect;
```

### Podの確認

実際にPodを確認します。PraefectとGitalyが複数存在していることが分かります。

```console
$ kubectl get pod
NAME                                               READY   STATUS      RESTARTS   AGE
test-gitlab-gitaly-0                               1/1     Running     0          3h24m
test-gitlab-gitaly-1                               1/1     Running     0          3h24m
test-gitlab-gitaly-2                               1/1     Running     0          3h24m
test-gitlab-migrations-2-kn8sj                     0/1     Completed   0          3h18m
test-gitlab-minio-666d6596c-kpfzx                  1/1     Running     0          3h24m
test-gitlab-minio-create-buckets-2-psqds           0/1     Completed   0          3h18m
test-gitlab-postgresql-0                           2/2     Running     0          3h24m
test-gitlab-praefect-0                             1/1     Running     0          3h20m
test-gitlab-praefect-1                             1/1     Running     0          3h20m
test-gitlab-praefect-2                             1/1     Running     0          3h20m
test-gitlab-redis-master-0                         2/2     Running     0          3h24m
test-gitlab-sidekiq-all-in-1-v1-76489f4f45-4ql2m   1/1     Running     0          3h18m
test-gitlab-webservice-6db7f4bcd8-jgh57            2/2     Running     0          3h18m
test-gitlab-webservice-6db7f4bcd8-qrcrr            2/2     Running     0          3h18m
```

## 動作確認

実際にアクセスして動作を確認していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/9a16c653-b29f-d6ba-f016-35709e96cd81.png)

rootでログインしてプロジェクトを作成してみます。

![screencapture-d7f12bb1-updatetest-albing-6622-1463059363-ap-northeast-1-elb-amazonaws-2020-12-06-19_09_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/a4a9bfdf-8639-7e01-8aa7-a6f66ed4dcb6.png)

`test`という名前でプロジェクトを作成することにします。

![screencapture-d7f12bb1-updatetest-albing-6622-1463059363-ap-northeast-1-elb-amazonaws-projects-new-2020-12-06-19_13_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/998a969f-9f9e-24d1-fdaa-9ec5e7d38b09.png)

実際に作成されました。これでGitaly Clusterの動作確認は完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/1d8d4e86-e12c-906e-53d7-d9ee1953c641.png)

## まとめ

GitLabのGitリポジトリへのアクセス処理を行うGitalyを冗長化させるためのGitaly ClusterをEKS上に構築する方法を説明しました。

今回はGitalyにフォーカスしていたため別コンポーネントには特に触れていませんが、可用性をさらに上げる場合にはminioをS3、アプリ用のpostgresql DBをRDS、redisをElastiCache等で代替すると良いです。