Red Hat OpenShift on IBM CloudにGitLabをデプロイする（内部Pod編）

# 目的

とある事情でGitLabを使いたかったのですが、IBM CloudのGitLabは少々バージョンが古いか、設定が自由にならないところがあったので、Red Hat OpenShift on IBM Cloud（ROKS）にデプロイしてみましたという話です。GitLabはもともとKubernetesには対応しているのですが、OpenShiftやROKS固有の手順が必要だったので、その点を書きたいと思います。

なお、GitLabの配布版は内部で使用しているPostgreSQLやRedis等をPodで実行することも、外部サービスを利用することもできます。今回はPodでやってみました。

# 手順

本家ガイドはこちらです。

https://docs.gitlab.com/charts/installation/deployment.html

今回はHelmインストールで行います。

## 公開用ドメイン名とTLS証明書の作成

Helmを実行すると、自動的にNginx Ingressがデプロイされ、IBM Cloud VPCのロードバランサーがプロビジョンされます。しかし、ロードバランサーはTLS証明書を持たないため、そのままではHTTPSで通信できません。TLS証明書は自力で注文し入手することもできますが、今回はIBM Cloudが標準で提供するものを使います。

> OpenShiftならRouterを使えばと思われるかもしれませんが、GitLabはgit通信でSSHを使用しますので、HTTP向けのRouterではなく、GitLab付属のNginx Ingressを使いました。

ROKSはデフォルトでパブリック向けのFQDNとロードバランサーが登録されています。

```
$ ibmcloud oc nlb-dns ls -c ${クラスター名}
OK
サブドメイン                                                                        ターゲット                            SSL 証明書の状況   SSL 証明書の秘密名                                秘密の名前 空間
********-********d72d9643e3d07091333056f5-0000.jp-tok.containers.appdomain.cloud   ********-jp-tok.lb.appdomain.cloud   created           ********-********d72d9643e3d07091333056f5-0000   openshift-ingress
```

このときのロードバランサー名を控えます。直接は利用しませんが、一時的に名前を借ります。

GitLabをインストールするネームスペースがまだない場合は事前に作成します。

```
$ oc create ns ${ネームスペース名}
```

下記コマンドを実行して、パブリック向けのドメイン名を追加します。

* ネームスペース名: GitLabをインストールするネームスペース名
* ロードバランサー名: 先ほど控えたロードバランサー名

```
$ ibmcloud oc nlb-dns create vpc-gen2 -c ${クラスター名} --secret-namespace ${ネームスペース名} --type public --lb-host ${ロードバランサー名}
NLB DNS を作成中...
OK
NLB ホスト名が ********-********d72d9643e3d07091333056f5-0001.jp-tok.containers.appdomain.cloud として作成され、public DNS に登録されました
```

証明書の作成状況を確認します。この場合、2行目の``-0001``が先ほど追加したドメイン名です。しばらく待って``SSL証明書の状況``が``created``になればOKです。

> 稀にここが``pending``のままになる場合があります。その場合``ibmcloud ks nlb-dns secret regenerate``コマンドで生成できる場合があります。それでも駄目な場合はサポートに問い合わせてください。

ここで表示された``サブドメイン``（-0001）と``SSL証明書の秘密名``を控えておきます。

```
$ ibmcloud oc nlb-dns ls -c ${クラスター名}
OK
サブドメイン                                                                        ターゲット                            SSL 証明書の状況    SSL 証明書の秘密名                                秘密の名前空間
********-********d72d9643e3d07091333056f5-0000.jp-tok.containers.appdomain.cloud   ********-jp-tok.lb.appdomain.cloud   created            ********-********d72d9643e3d07091333056f5-0000   openshift-ingress
********-********d72d9643e3d07091333056f5-0001.jp-tok.containers.appdomain.cloud   ********-jp-tok.lb.appdomain.cloud   created            ********-********d72d9643e3d07091333056f5-0001   ********
```

## GitLab Helmリポジトリの追加

Helmリポジトリを追加します。

```
$ helm repo add gitlab https://charts.gitlab.io/
$ helm repo update
```

## ServiceAccountの追加

本来ServiceAccountはHelmで自動作成されますが、OpenShift固有のSCCの制約のため、そのままでは使えません。事前作成して、Helmインストール一発で動くようにします。

必要なServiceAccountを作成します。

```
$ oc create sa gitlab-certmanager-issuer
$ oc create sa gitlab-gitlab-runner
$ oc create sa gitlab-nginx-ingress
$ oc create sa gitlab-nginx-ingress-backend
$ oc create sa gitlab-prometheus-server
$ oc create sa gitlab-shared-secrets
```

必要な権限を付与します。

```
$ oc adm policy add-scc-to-user anyuid -z default
$ oc adm policy add-scc-to-user anyuid -z gitlab-certmanager-issuer
$ oc adm policy add-scc-to-user privileged -z gitlab-gitlab-runner
$ oc adm policy add-scc-to-user privileged -z gitlab-nginx-ingress
$ oc adm policy add-scc-to-user anyuid -z gitlab-nginx-ingress-backend
$ oc adm policy add-scc-to-user anyuid -z gitlab-prometheus-server
$ oc adm policy add-scc-to-user anyuid -z gitlab-shared-secrets
```

ラベルを付与します。これをしないと、Helmインストール時にServiceAccountが重複したとみなされ、失敗します。

```
$ oc label sa gitlab-certmanager-issuer app.kubernetes.io/managed-by=Helm
$ oc label sa gitlab-gitlab-runner app.kubernetes.io/managed-by=Helm
$ oc label sa gitlab-nginx-ingress app.kubernetes.io/managed-by=Helm
$ oc label sa gitlab-nginx-ingress-backend app.kubernetes.io/managed-by=Helm
$ oc label sa gitlab-prometheus-server app.kubernetes.io/managed-by=Helm
$ oc label sa gitlab-shared-secrets app.kubernetes.io/managed-by=Helm
```

同様の利用で、アノテーションを付与します。

```
$ oc annotate sa gitlab-certmanager-issuer meta.helm.sh/release-name=gitlab meta.helm.sh/release-namespace=${ネームスペース名}
$ oc annotate sa gitlab-gitlab-runner meta.helm.sh/release-name=gitlab meta.helm.sh/release-namespace=${ネームスペース名}
$ oc annotate sa gitlab-nginx-ingress meta.helm.sh/release-name=gitlab meta.helm.sh/release-namespace=${ネームスペース名}
$ oc annotate sa gitlab-nginx-ingress-backend meta.helm.sh/release-name=gitlab meta.helm.sh/release-namespace=${ネームスペース名}
$ oc annotate sa gitlab-prometheus-server meta.helm.sh/release-name=gitlab meta.helm.sh/release-namespace=${ネームスペース名}
$ oc annotate sa gitlab-shared-secrets meta.helm.sh/release-name=gitlab meta.helm.sh/release-namespace=${ネームスペース名}
```

## GitLabのインストール

いよいよGitLabをインストールします。

* インストール名: 任意
* ドメイン名: 先ほど控えた``サブドメイン``（-0001）
* シークレット名: 先ほど控えた``SSL証明書の秘密名``

```
$ helm upgrade --install ${インストール名} gitlab/gitlab --timeout 300s \
  --set certmanager-issuer.email=me@example.com \
  --set global.hosts.domain=${ドメイン名} \
  --set global.ingress.tls.secretName=${シークレット名}
```

もしGitLab Pagesを使いたい場合は、次のパラメータも追加してください。

```
  --set global.pages.enabled=true \
  --set global.pages.host=${ドメイン名}
```

ここまでの設定に問題ない場合、順調にPodが起動してきますが、唯一``gitlab-runner``だけは起動に失敗するはずです。理由ですが、先ほど設定したドメイン名を使った通信がまだできないからです。

## ドメイン名の宛先変更

GitLabをデプロイすると、自動的にNginx Ingress用のロードバランサーがプロビジョンされています。その名前を控えます。

```
$ oc get svc | grep LoadBalancer
gitlab-nginx-ingress-controller           LoadBalancer   172.21.161.208   ********-jp-tok.lb.appdomain.cloud   80:31150/TCP,443:30340/TCP,22:30119/TCP   4m37s
```

先ほど登録したドメイン名の宛先を上記の名前に変更します。

```
$ ibmcloud oc nlb-dns replace -c ${クラスター名} --lb-host ********-jp-tok.lb.appdomain.cloud --nlb-subdomain ********-********d72d9643e3d07091333056f5-0001.jp-tok.containers.appdomain.cloud
NLB DNS を更新中...
注: 変更が適用されるまで数分かかる場合があります。
OK
```

しばらく待つと、``gitlab-runner``がRunningになります。

> DNSのレコード伝搬の都合により数十分程度かかる場合があります。

## rootパスワードの確認

管理者ユーザーであるrootの初期パスワードは下記コマンドで確認することができます。

```
$ oc get secret ${インストール名}-gitlab-initial-root-password -o jsonpath='{.data.password}' | base64 -d; echo
********
```

## GitLabへのアクセス

> https://gitlab.********-********d72d9643e3d07091333056f5-0001.jp-tok.containers.appdomain.cloud/

# 注意点

デフォルトで下記のストレージが使用されています。有料ですのでご注意ください。

```
$ oc get pvc
NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                 AGE
data-gitlab-postgresql-0           Bound    pvc-817fe266-d46e-4ce8-aa37-1e48ce42a1e3   10Gi       RWO            ibmc-vpc-block-10iops-tier   44h
gitlab-minio                       Bound    pvc-fa24be28-5c07-4111-8e3b-1d8134fe081e   10Gi       RWO            ibmc-vpc-block-10iops-tier   44h
gitlab-prometheus-server           Bound    pvc-2ade9e01-a65f-43b9-ac0c-178377e819dd   10Gi       RWO            ibmc-vpc-block-10iops-tier   44h
redis-data-gitlab-redis-master-0   Bound    pvc-93ea63c4-9e4c-41ad-81a1-31a6fdee5d88   10Gi       RWO            ibmc-vpc-block-10iops-tier   44h
repo-data-gitlab-gitaly-0          Bound    pvc-8172fd76-5ceb-468d-ab9d-91f43dcfdd63   50Gi       RWO            ibmc-vpc-block-10iops-tier   44h
```