GitLab Operatorを使ってOpenShiftにGitLabを構築する

この記事は[OpenShift Advent Calendar 2022](https://qiita.com/advent-calendar/2022/openshift)の19日目の記事です。

OpenShiftのOperatorHubでは、Red Hatや3rd Party、Communityが提供しているOperatorなど様々なソフトウェアが提供されていますが、最近Community OperatorとしてGitLabが利用できるようになりました。
今回はこのOperatorを使ってOpenShift環境にGitLabを構築していきたいと思います。
環境はROSA(Red Hat OpenShift on AWS)でOpenShiftのバージョンは4.11.17です。

# Operatorのインストール
まずはOperatorをインストールしていきましょう。
OpenShiftコンソールからOperatorHubを選択し、検索ボックスにGitLabと入れます。
そうするとCommunity版のGitLab Operatorが見つかるため、クリックしてインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/e7668550-2839-37f3-7950-093e9afdbd95.png)

この時、インストール先として任意のProjectを選択できます。
今回はデフォルトの`gitlab-system`を使用していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/94fef687-20d9-0277-ec2f-89567c3eca0f.png)


ここから早速カスタムリソースを作成してGitLabを構築していきたいところですが、もう一つOperatorをインストールする必要があります。
それがCert-manager Operatorです。先ほどと同じく検索ボックスにcert-managerと入力し、Operatorをインストールしていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/a74233b6-2ce3-84ef-c034-fc3dc293a8d8.png)
Cert-managerはRed Hatが提供するOperatorがあるためそちらを選択し使用していきましょう。（2022年12月現在Tech Preview）
これで準備が整いました。

# GitLabカスタムリソースの作成
それでは`gitlab-system`Projectに移動し、カスタムリソースを作成していきます。
インストール済みのOperatorからGitLabを選択し、`GitLab`タブを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/f2303776-b339-7bc5-9549-9cfdf77e2ac6.png)

GitLabカスタムリソースを作成する際に、構築するGitLabの証明書をどのように設定するか決めることができます。
今回は以下の3つのパターンを全て試してみます。
* 自己証明書を利用するパターン
* ROSAのワイルドカード証明書を利用するパターン
* Cert-managerを使ってGitLab用の証明書を発行するパターン

## 自己証明書を利用するパターン
まずは自己証明書を利用するパターンです。
GitLabカスタムリソースは以下の通りとなります。
```
kind: GitLab
apiVersion: apps.gitlab.com/v1beta1
metadata:
  name: gitlab
  namespace: gitlab-system
spec:
  chart:
    values:
      certmanager:
        install: false
      nginx-ingress:
        enabled: false
      global:
        hosts:
          domain: apps.${CLUSTER_NAME}.${YOUR_DOMAIN} #自クラスタのドメインに置き換えて下さい
          hostSuffix: null
        ingress:
          configureCertmanager: false
          tls:
            secretName: null
          class: none
          annotations:
            route.openshift.io/termination: "edge"
    version: '6.6.0'

```
`.spec.chart.values`以下で[HelmでGitLabをインストールする](https://docs.gitlab.com/charts/charts/globals.html)のと同様のパラメータを設定することができます。（ただし、Helmで有効な設定項目でもOperatorで全て有効になっているわけではなさそうです。）
このパターンではCert-managerを利用した証明書発行は行わないため、Cert-managerのインストールや設定に関する項目は`false`と設定しています。
またGitLabのデフォルトIngressであるNginx-ingressは使用せず、OpenShiftのRouteを使用するためannotationの付与などがされています。

`.spec.version`はHelm Chartのバージョンです。利用可能なバージョンは[こちら](https://docs.gitlab.com/charts/installation/version_mappings.html)で確認しましょう。
Helmの最新は`6.6.2`ですが、Operatorでは`6.6.0`が最新の利用可能バージョンとなっているなど若干の違いがあるようです。

あとはこのyamlファイルを適用するとGitLabの構築がスタートします。
利用可能になるまでしばし待ちましょう。

GitLabのStatusがRunningになったらRouteからGitLabのURLにアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/cc5f64ea-7d3d-1056-e729-b1710342e3f7.png)
無事ログイン画面を開くことができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/e520f0ef-7b08-83eb-45dc-1ece56ca7044.png)

Usernameは`root`、Passwordは以下のコマンドで取得できます。
```
oc get secret gitlab-gitlab-initial-root-password -o "jsonpath={.data.password}" | base64 -d -
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/df1c6d1b-8dbb-4848-10ad-c18c75da7948.png)
ということで、無事ログインすることができました。
しかし、自己証明書を使用しているため次は別の方法でのデプロイを試してみたいと思います。

## ROSAのワイルドカード証明書を利用するパターン
ROSAではクラスタ構築時にLet's Encryptによる有効な証明書を取得し設定しているため、これをGitLabにも適用していきます。

まず、必要な証明書チェーンと暗号鍵をローカルに保存します。
```
oc extract secret/${YOUR_CLUSTER}-primary-cert-bundle-secret --keys=tls.crt -n openshift-ingress
oc extract secret/${YOUR_CLUSTER}-primary-cert-bundle-secret --keys=tls.key -n openshift-ingress
```
これらを一つのSecretにまとめ、`gitlab-system`Projectに作成します。
```
oc create secret tls gitlab-tls --cert=tls.crt --key=tls.key -n gitlab-system
```
あとは作成したこのSecretを利用するよう、GitLabのCRを修正します。
```
kind: GitLab
apiVersion: apps.gitlab.com/v1beta1
metadata:
  name: gitlab
  namespace: gitlab-system
spec:
  chart:
    values:
      certmanager:
        install: false
      nginx-ingress:
        enabled: false
      global:
        hosts:
          domain: apps.${CLUSTER_NAME}.${YOUR_DOMAIN} #自クラスタのドメインに置き換えて下さい
          hostSuffix: null
        ingress:
          configureCertmanager: false
          tls:
            secretName: gitlab-tls # 作成したSecretを指定
          class: none
          annotations:
            route.openshift.io/termination: "edge"
    version: '6.6.0'
```
`.spec.chart.values.global.ingress.tls.secretName`に先ほど作成したSecretを指定します。

カスタムリソースを更新し、しばらく待つとGitLabのURLにアクセスすると有効な証明書が設定されていることが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/015f5d5c-ac60-079e-d433-5e20742d4540.png)

これで有効な証明書の設定ができましたが、手動でSecretの作成を行なっているため証明書のローテーションを考えるとやや面倒ですね。
この点をケアすべく、最後にCert-managerを利用するパターンを試してみましょう。

## Cert-managerを使ってGitLab用の証明書を発行するパターン
```
apiVersion: apps.gitlab.com/v1beta1
kind: GitLab
metadata:
  name: gitlab
  namespace: gitlab-system
spec:
  chart:
    values:
      certmanager:
        install: false
      certmanager-issuer:
        email: ${YOUR_EMAIL} # 証明書取得用のメールアドレス
      global:
        hosts:
          domain: apps.${CLUSTER_NAME}.${YOUR_DOMAIN} #自クラスタのドメインに置き換えて下さい
          hostSuffix: null
        ingress:
          annotations:
            route.openshift.io/termination: edge
            kubernetes.io/tls-acme: true
          class: none
      nginx-ingress:
        enabled: false
    version: 6.6.0
```
`.spec.chart.values.certmanager-issuer.email`に証明書発行時に利用するメールアドレスを設定します。
また先ほどまでのパターンでは`ingress`の`configureCertmanager: false`という設定がありましたがこちらを削ったり、annotationを追加したりしています。
こちらを適用するとCert-managerにより発行された証明書を使ってGitLabを構築できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/8f66a8e4-8b9b-2c42-e696-2e910b6cd061.png)
証明書の発行先が、このGitLab用のURLに変わっていることが確認できました。
本格的に運用していくことを考えるとこの方法が良さそうかなと思います。

# GitLabのメトリクスの取得
さて無事構築できたGitLabですが、実はインストールした時点でPrometheusでメトリクスを取得するためのExporterやServiceMonitorが自動的に作成されます。
```
oc get pod | grep exporter
---
gitlab-gitlab-exporter-65c8bb6888-hc6qj      1/1     Running     0          29m
```
```
oc get servicemonitor
---
NAME                     AGE
gitlab-gitaly            93m
gitlab-gitlab-exporter   93m
gitlab-postgresql        93m
gitlab-redis             93m
gitlab-webservice        93m
```
そのため、OpenShiftでは[ユーザー定義プロジェクトのモニタリングを有効化](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.11/html-single/monitoring/index#enabling-monitoring-for-user-defined-projects)するだけでGitLabのメトリクスを取得することができます。ROSAの場合こちらはデフォルトで有効化されています。（クラスタ作成時の設定に依ります）

Self-managedでクラスタを構築している場合は、以下のyamlファイルを適用してあげましょう。
```
apiVersion: v1
kind: ConfigMap
metadata:
  name: cluster-monitoring-config
  namespace: openshift-monitoring
data:
  config.yaml: |
    enableUserWorkload: true
```

OpenShiftコンソールのメトリクスからGitLabのメトリクス名を指定することで情報を得ることができます。
取得できるPrometheusのメトリクスについては[こちら](https://docs.gitlab.com/ee/administration/monitoring/prometheus/gitlab_metrics.html)を参照しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/0c1cf273-a60c-a9cd-190c-fafd25a69b8b.png)

# GitLab Runnerのインストール
せっかくなのでGitLabでCI/CDを実行する際に必要となるGitLab RunnerについてもOperatorでインストールしたいと思います。

再びOperatorHubに移り、GitLab Runnerを探します。
この時、Community版とCertified版という二つのバージョンがありますが、Community版の方がバージョンが新しそうなのでそちらをインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/18b0d90e-c053-e611-6394-0988a928fe7f.png)
インストールするProjectを選択することができますが、今回はGitLab Operatorと同じ`gitlab-system`にインストールします。

ここからまずGitLab Runnerを登録するためのTokenを払い出しSecretとして登録するのですが、GitLab Operatorを使ってGitLabを構築している場合は、`gitlab-gitlab-runner-secret`という名前で必要なSecretが既に作成されています。便利ですね。

一応外部のGitLabを使用する場合を踏まえ、手動でTokenを登録する方法も書いておきましょう。
まずGitLabのAdmin画面から`Runners`を選択し、登録用のTokenをコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/acf2306f-398f-7932-17f4-57450199f50d.png)

コピーしたTokenを元にGitLab Runnerの登録用Secretを作成します。
```
apiVersion: v1
kind: Secret
metadata:
  name: gitlab-runner-secret
type: Opaque
stringData:
  runner-registration-token: NdX... # ここにコピーしたTokenを貼る
```

あとはGitLab Runnerを登録するため、TokenのSecretを使用するよう`Runner`カスタムリソースを作成すれば完了です。
```
apiVersion: apps.gitlab.com/v1beta2
kind: Runner
metadata:
 generateName: gitlab-runner-
spec:
 gitlabUrl: https://gitlab.apps.xxx.yyy.com # GitLabのURL
 buildImage: registry.access.redhat.com/ubi8/ubi
 token: gitlab-runner-secret # TokenのSecret
 tags: openshift
```
GitLabのAdmin画面から無事Runnerが登録できたことが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969075/4240961b-e42e-6f20-2100-b6fe96eab02d.png)

Runnerを増やしたい場合はDeploymentのPod数を変更するのではなく、Runnerカスタムリソースを新たに追加すればOKです。(RunnerカスタムリソースでgenerateNameを使っていたのはこの理由からです。)

# まとめ
今回はOpenShiftにGitLabをインストールしてみました。Operatorで気軽にGitリポジトリを立てれるのは有難いですね。みなさんも是非試してみて下さい。