そろそろ真面目にGitLabをクラウドネイティブする

## 何するの？

みなさんクラウドネイティブしていますか？
Serverlessアプリケーションをkubernetesクラスタにデプロイできる[GitLab 11.6](https://about.gitlab.com/2018/12/22/gitlab-11-6-released/)がリリースされましたね。


進化著しいGitLabですが、インストール方法も変わりつつあります。
従来から提供されている[Omnibus GitLab package](https://docs.gitlab.com/ee/install/docker.html#omnibus-gitlab-based-images)( Docker image )だけでなく、
GitLab自体をkubernetesクラスタにHelmでデプロイするための[Cloud native images](https://docs.gitlab.com/ee/install/docker.html#cloud-native-images)( Helm Chart )が登場しています( しかも[stable/gitlab](https://github.com/helm/charts/tree/master/stable)のChartより`APP VERSION`が新しい！ )。

さっそくGitLabをクラウドネイティブな手順でkubernetesクラスタにデプロイしてみたいと思います。Serverlessの機能も試してみたいですね。

CPU/メモリリソースをそこそこ要求されます(後述)ので、今回はGKEのようなパブリッククラウドでなく、お金のかからないminikube上にデプロイしたいと思います。
minikubeならではの仕様による課題(`LoadBalancer`に`EXTERNAL-IP`が付与されない)がありましたのでその対策もご紹介します。

クラウドネイティブなデプロイにはHelmを使用します、Helmについては[Helmのすゝめ](https://qiita.com/loftkun/items/853bbaabd4bf0fa96e9c)をご参照下さい。


## 環境

自宅の実機(`core i7 8700K`, `64GB`)。OSは`Ubuntu 17.10`です。
以下をインストールしています。

- `minikube v0.28.2`
  - クラスタバージョンは`v1.10.0`
  - [CPUコア割り当て](https://qiita.com/loftkun/items/41ecde082778254de79a)を12コアにしています
  - [メモリ割り当て](https://qiita.com/loftkun/items/7400d5ae0e7b1fb7d26e)を20GBにしています
- `kuberctl v1.9.2`
- `helm v2.11.0`

```bash
$ uname -a
Linux hoge 4.13.0-46-generic #51-Ubuntu SMP Tue Jun 12 12:36:29 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=17.10
DISTRIB_CODENAME=artful
DISTRIB_DESCRIPTION="Ubuntu 17.10"
$ cat /proc/cpuinfo | grep "model name"
model name      : Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
( 略。12コア )
$ free -h
              total        used        free      shared  buff/cache   available
Mem:            62G         18G         34G         42M         10G         43G
Swap:          2.0G          0B        2.0G

$ minikube version
minikube version: v0.28.2
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.2", GitCommit:"5fa2db2bd46ac79e5e00a4e6ed24191080aa463b", GitTreeState:"clean", BuildDate:"2018-01-18T10:09:24Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.0", GitCommit:"fc32d2f3698e36b93322a3465f63a14e9f0eaead", GitTreeState:"clean", BuildDate:"2018-03-26T16:44:10Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
$ helm version
Client: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b146b", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b146b", GitTreeState:"clean"}
$
```

## 必要なリソース
[CPU and RAM Resource Requirements](https://gitlab.com/charts/gitlab/blob/master/doc/installation/deployment.md#cpu-and-ram-resource-requirements)に以下のように記載されています。
デフォルト構成では8コア・30GB、最小構成では2コア・4GBのようですね。
( minikubeのメモリ割り当ては20GBでなく30GBにしておけばよかったと後から気付く。今のところ害はなし。 )

- ` by default to be adequate for a small production`
  - `at least 8vCPU and 30gb of RAM`
-  `non-production `
  - `minimal GKE example values file` は `3vCPU 12gb`
  - `minimal minikube example values file` は`2vCPU, 4gb`

## 参考ドキュメント

ここからの手順は以下ドキュメントを参考にしています。

- gitlab.com
  - [Installing GitLab using Helm](https://gitlab.com/charts/gitlab/blob/master/doc/installation/index.md)
  - [Deployment Guide](https://gitlab.com/charts/gitlab/blob/master/doc/installation/deployment.md)
  - [Installation command line options](https://gitlab.com/charts/gitlab/blob/master/doc/installation/command-line-options.md)
  - [Releases](https://gitlab.com/charts/gitlab/blob/master/doc/development/release.md#chart-versioning)

- docs.gitlab.com
  - [GitLab Helm Chart](https://docs.gitlab.com/ee/install/kubernetes/gitlab_chart.html)

## デプロイ

さっそくデプロイしてみましょう。

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

追加前

```bash
$ helm repo list
NAME            URL
stable          https://kubernetes-charts.storage.googleapis.com
local           http://127.0.0.1:8879/charts
incubator       https://kubernetes-charts-incubator.storage.googleapis.com/
$
```

追加

```bash
$ helm repo add gitlab https://charts.gitlab.io/
"gitlab" has been added to your repositories
$
```

追加後
`gitlab`という名前で追加できています。

```bash
$ helm repo list
NAME            URL
stable          https://kubernetes-charts.storage.googleapis.com
local           http://127.0.0.1:8879/charts
incubator       https://kubernetes-charts-incubator.storage.googleapis.com/
gitlab          https://charts.gitlab.io/
$
```

update

```bash
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "incubator" chart repository
...Successfully got an update from the "stable" chart repository
...Successfully got an update from the "gitlab" chart repository
Update Complete. ⎈ Happy Helming!⎈
$
```

search
使用するのは`gitlab/gitlab`です。
`stable/gitlab`のchartは`APP VERSION`が古いことが分かります。
そう、使うなら[Cloud native images](https://docs.gitlab.com/ee/install/docker.html#cloud-native-images)なのです！

```bash
$ helm search gitlab
NAME                            CHART VERSION   APP VERSION     DESCRIPTION
gitlab/gitlab                   1.4.2           11.6.3          Web-based Git-repository manager with wiki and issue-trac...
gitlab/gitlab-omnibus           0.1.37                          GitLab Omnibus all-in-one bundle
gitlab/gitlab-runner            0.1.44                          GitLab Runner
gitlab/kubernetes-gitlab-demo   0.1.29                          GitLab running on Kubernetes suitable for demos
stable/gitlab-ce                0.2.2           9.4.1           GitLab Community Edition
stable/gitlab-ee                0.2.2           9.4.1           GitLab Enterprise Edition
gitlab/auto-deploy-app          0.2.6                           GitLab's Auto-deploy Helm Chart
$
```

### デプロイする

Helmコマンドでデプロイします。
環境に応じたパラメタを適宜指定する必要があります。

- Chart名は`gitlab/gitlab`です。
- `global.hosts.externalIP`
  - GKEならばstatic-ipを取得しておいてここに指定したいところですね。
  - 今回はminikubeです。後の作業でexternalIPが決定してからでないと指定できないため指定していません。
- `global.hosts.domain`
  - static-ipにひもづくドメイン名を取得しておいてここに指定したいところですね。
  - 今回はminikubです。仮に`test.com`としています。
  - 後ほどhostsの設定などを行いこのドメイン名でアクセスできるようにします。
- `namespace`は`gitlab`としました。
- CE(Community Edition)を指定しています。

```bash
helm install gitlab/gitlab \
  --name gitlab \
  --namespace gitlab \
  --set global.hosts.domain=test.com \
  --set global.edition=ce \
  --set gitlab.migrations.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-rails-ce \
  --set gitlab.sidekiq.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-sidekiq-ce \
  --set gitlab.unicorn.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-unicorn-ce \
  --set gitlab.unicorn.workhorse.image=registry.gitlab.com/gitlab-org/build/cng/gitlab-workhorse-ce \
  --set gitlab.task-runner.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-task-runner-ce \
  --set certmanager-issuer.email=あなたのメールアドレス
```

実行ログ
Chartの使い方などが記載されていることの多い`NOTES:`は空でした、今後の整備に期待します。

```bash
$ helm install gitlab/gitlab \
>   --name gitlab \
>   --namespace gitlab \
>   --set global.hosts.domain=test.com \
>   --set global.edition=ce \
>   --set gitlab.migrations.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-rails-ce \
>   --set gitlab.sidekiq.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-sidekiq-ce \
>   --set gitlab.unicorn.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-unicorn-ce \
>   --set gitlab.unicorn.workhorse.image=registry.gitlab.com/gitlab-org/build/cng/gitlab-workhorse-ce \
>   --set gitlab.task-runner.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-task-runner-ce \
>   --set certmanager-issuer.email=あなたのメールアドレス
NAME:   gitlab
LAST DEPLOYED: Mon Jan 14 22:03:15 2019
NAMESPACE: gitlab
STATUS: DEPLOYED

RESOURCES:
==> v1/RoleBinding
NAME                       AGE
gitlab-certmanager-issuer  1s
gitlab-nginx-ingress       1s

==> v1beta1/Ingress
gitlab-unicorn   1s
gitlab-minio     1s
gitlab-registry  1s

==> v1/Pod(related)

NAME                                                  READY  STATUS             RESTARTS  AGE
gitlab-certmanager-684998874-prjkk                    0/1    ContainerCreating  0         1s
gitlab-gitlab-runner-544fd9dcb5-92lxf                 0/1    Init:0/1           0         1s
gitlab-gitlab-shell-77499546cb-ztw4g                  0/1    Init:0/2           0         1s
gitlab-sidekiq-all-in-1-7bb9d95f9d-cp2l7              0/1    Init:0/3           0         1s
gitlab-task-runner-db8556848-l5gkc                    0/1    Init:0/2           0         1s
gitlab-unicorn-67f6d9d66b-jhlkw                       0/2    Pending            0         1s
gitlab-minio-7d5dbcccb6-9b49d                         0/1    Pending            0         1s
gitlab-nginx-ingress-controller-7565f874b9-t9qht      0/1    Pending            0         0s
gitlab-nginx-ingress-default-backend-fd5bb5468-j9f8p  0/1    Pending            0         0s
gitlab-gitaly-0                                       0/1    Pending            0         1s
gitlab-issuer.1-kjb4b                                 0/1    Pending            0         1s
gitlab-migrations.1-298sx                             0/1    Pending            0         1s
gitlab-minio-create-buckets.1-bxpbl                   0/1    Pending            0         1s

==> v1beta1/CustomResourceDefinition

NAME                               AGE
certificates.certmanager.k8s.io    1s
clusterissuers.certmanager.k8s.io  1s
issuers.certmanager.k8s.io         1s

==> v1beta1/ClusterRoleBinding
gitlab-certmanager                    1s
gitlab-prometheus-alertmanager        1s
gitlab-prometheus-kube-state-metrics  1s
gitlab-prometheus-node-exporter       1s
gitlab-prometheus-server              1s

==> v1beta1/RoleBinding
gitlab-gitlab-runner  1s

==> v1/Job
gitlab-issuer.1                1s
gitlab-migrations.1            1s
gitlab-minio-create-buckets.1  1s

==> v1/ConfigMap
gitlab-certmanager-issuer-certmanager  1s
gitlab-gitlab-runner                   1s
gitlab-gitaly                          1s
gitlab-gitlab-shell                    1s
gitlab-nginx-ingress-tcp               1s
gitlab-migrations                      1s
gitlab-sidekiq-all-in-1                1s
gitlab-sidekiq                         1s
gitlab-task-runner                     1s
gitlab-unicorn                         1s
gitlab-workhorse-config                1s
gitlab-unicorn-tests                   1s
gitlab-minio-config-cm                 1s
gitlab-nginx-ingress-controller        1s
gitlab-postgresql                      1s
gitlab-prometheus-server               1s
gitlab-redis                           1s
gitlab-registry                        1s

==> v1/PersistentVolumeClaim
gitlab-minio              1s
gitlab-postgresql         1s
gitlab-prometheus-server  1s
gitlab-redis              1s

==> v1/ServiceAccount
gitlab-certmanager-issuer             1s
gitlab-certmanager                    1s
gitlab-gitlab-runner                  1s
gitlab-nginx-ingress                  1s
gitlab-prometheus-alertmanager        1s
gitlab-prometheus-kube-state-metrics  1s
gitlab-prometheus-node-exporter       1s
gitlab-prometheus-server              1s

==> v1beta1/Role
gitlab-gitlab-runner  1s

==> v1beta2/StatefulSet
gitlab-gitaly  1s

==> v1beta1/PodDisruptionBudget
gitlab-gitaly                         0s
gitlab-gitlab-shell                   0s
gitlab-sidekiq                        0s
gitlab-unicorn                        0s
gitlab-minio-v1                       0s
gitlab-nginx-ingress-controller       0s
gitlab-nginx-ingress-default-backend  0s
gitlab-redis-v1                       0s
gitlab-registry-v1                    0s

==> v1beta1/ClusterRole
gitlab-certmanager                    1s
gitlab-prometheus-kube-state-metrics  1s
gitlab-prometheus-server              1s

==> v1/Role
gitlab-certmanager-issuer  1s
gitlab-nginx-ingress       1s

==> v1/Service
gitlab-gitaly                            1s
gitlab-gitlab-shell                      1s
gitlab-unicorn                           1s
gitlab-minio-svc                         1s
gitlab-nginx-ingress-controller-metrics  1s
gitlab-nginx-ingress-controller          1s
gitlab-nginx-ingress-controller-stats    1s
gitlab-nginx-ingress-default-backend     1s
gitlab-postgresql                        1s
gitlab-prometheus-server                 1s
gitlab-redis                             1s
gitlab-registry                          1s

==> v1beta1/Deployment
gitlab-certmanager        1s
gitlab-gitlab-runner      1s
gitlab-postgresql         1s
gitlab-prometheus-server  1s

==> v1beta2/Deployment
gitlab-gitlab-shell                   1s
gitlab-sidekiq-all-in-1               1s
gitlab-task-runner                    1s
gitlab-unicorn                        1s
gitlab-minio                          1s
gitlab-nginx-ingress-controller       1s
gitlab-nginx-ingress-default-backend  1s
gitlab-redis                          1s
gitlab-registry                       1s

==> v2beta1/HorizontalPodAutoscaler
gitlab-gitlab-shell      0s
gitlab-sidekiq-all-in-1  0s
gitlab-unicorn           0s
gitlab-registry          0s


NOTES:

$
```

### デプロイ結果

pod, service, ingressの構成を見てみます。

#### pod

gitlab-runnerが`CrashLoopBackOff`となりました。後述します。

```bash
$ kubectl get po --all-namespaces
NAMESPACE     NAME                                                   READY     STATUS             RESTARTS   AGE
gitlab        cm-acme-http-solver-bg79m                              1/1       Running            0          8m
gitlab        cm-acme-http-solver-hns5v                              1/1       Running            0          8m
gitlab        cm-acme-http-solver-srbq2                              1/1       Running            0          8m
gitlab        gitlab-certmanager-684998874-prjkk                     1/1       Running            0          8m
gitlab        gitlab-gitaly-0                                        1/1       Running            0          8m
gitlab        gitlab-gitlab-runner-544fd9dcb5-92lxf                  0/1       CrashLoopBackOff   5          8m
gitlab        gitlab-gitlab-shell-77499546cb-pmmkr                   1/1       Running            0          8m
gitlab        gitlab-gitlab-shell-77499546cb-ztw4g                   1/1       Running            0          8m
gitlab        gitlab-minio-7d5dbcccb6-9b49d                          1/1       Running            0          8m
gitlab        gitlab-nginx-ingress-controller-7565f874b9-t9qht       1/1       Running            0          8m
gitlab        gitlab-nginx-ingress-controller-7565f874b9-xz2k8       1/1       Running            0          8m
gitlab        gitlab-nginx-ingress-controller-7565f874b9-zxcjg       1/1       Running            0          8m
gitlab        gitlab-nginx-ingress-default-backend-fd5bb5468-fmsh4   1/1       Running            0          8m
gitlab        gitlab-nginx-ingress-default-backend-fd5bb5468-j9f8p   1/1       Running            0          8m
gitlab        gitlab-postgresql-5578b89f58-rswv2                     2/2       Running            0          8m
gitlab        gitlab-prometheus-server-847c8bb76-8s7nm               2/2       Running            0          8m
gitlab        gitlab-redis-7855c75bc9-ns8bc                          2/2       Running            0          8m
gitlab        gitlab-registry-f5cc79958-pg5j5                        1/1       Running            0          8m
gitlab        gitlab-registry-f5cc79958-zb5vj                        1/1       Running            0          8m
gitlab        gitlab-sidekiq-all-in-1-7bb9d95f9d-cp2l7               1/1       Running            0          8m
gitlab        gitlab-task-runner-db8556848-l5gkc                     1/1       Running            0          8m
gitlab        gitlab-unicorn-67f6d9d66b-4k4dl                        2/2       Running            0          8m
gitlab        gitlab-unicorn-67f6d9d66b-jhlkw                        2/2       Running            0          8m
kube-system   etcd-minikube                                          1/1       Running            0          9m
kube-system   heapster-fwjds                                         1/1       Running            0          10m
kube-system   influxdb-grafana-fqnvd                                 2/2       Running            0          10m
kube-system   kube-addon-manager-minikube                            1/1       Running            0          9m
kube-system   kube-apiserver-minikube                                1/1       Running            0          9m
kube-system   kube-controller-manager-minikube                       1/1       Running            0          9m
kube-system   kube-dns-86f4d74b45-nlzjv                              3/3       Running            0          10m
kube-system   kube-proxy-9pzlq                                       1/1       Running            0          10m
kube-system   kube-scheduler-minikube                                1/1       Running            0          9m
kube-system   kubernetes-dashboard-5498ccf677-j4clg                  1/1       Running            0          10m
kube-system   storage-provisioner                                    1/1       Running            0          10m
kube-system   tiller-deploy-6fd8d857bc-m6zsf                         1/1       Running            0          9m
```

#### service

minikubeなので、LoadBalancerの`EXTERNAL-IP`が`<pending>`です。
クラスタ外部から`EXTERNAL-IP`経由でアクセスできるようにする必要があります、手順を後述します。

```bash
$ kubectl get svc --all-namespaces
NAMESPACE     NAME                                      TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                                   AGE
default       kubernetes                                ClusterIP      10.96.0.1        <none>        443/TCP                                   10m
gitlab        cm-acme-http-solver-5jnrt                 NodePort       10.99.22.181     <none>        8089:31912/TCP                            8m
gitlab        cm-acme-http-solver-rlgx9                 NodePort       10.98.39.181     <none>        8089:32089/TCP                            8m
gitlab        cm-acme-http-solver-t5wlx                 NodePort       10.104.21.86     <none>        8089:32554/TCP                            8m
gitlab        gitlab-gitaly                             ClusterIP      None             <none>        8075/TCP,9236/TCP                         8m
gitlab        gitlab-gitlab-shell                       ClusterIP      10.105.108.223   <none>        22/TCP                                    8m
gitlab        gitlab-minio-svc                          ClusterIP      10.96.20.212     <none>        9000/TCP                                  8m
gitlab        gitlab-nginx-ingress-controller           LoadBalancer   10.106.203.63    <pending>     80:32693/TCP,443:31602/TCP,22:32479/TCP   8m
gitlab        gitlab-nginx-ingress-controller-metrics   ClusterIP      10.100.78.127    <none>        9913/TCP                                  8m
gitlab        gitlab-nginx-ingress-controller-stats     ClusterIP      10.102.76.134    <none>        18080/TCP                                 8m
gitlab        gitlab-nginx-ingress-default-backend      ClusterIP      10.106.104.56    <none>        80/TCP                                    8m
gitlab        gitlab-postgresql                         ClusterIP      10.106.171.116   <none>        5432/TCP                                  8m
gitlab        gitlab-prometheus-server                  ClusterIP      10.101.56.39     <none>        80/TCP                                    8m
gitlab        gitlab-redis                              ClusterIP      10.104.57.149    <none>        6379/TCP,9121/TCP                         8m
gitlab        gitlab-registry                           ClusterIP      10.102.70.88     <none>        5000/TCP                                  8m
gitlab        gitlab-unicorn                            ClusterIP      10.103.23.54     <none>        8080/TCP,8181/TCP                         8m
kube-system   heapster                                  ClusterIP      10.110.17.167    <none>        80/TCP                                    10m
kube-system   kube-dns                                  ClusterIP      10.96.0.10       <none>        53/UDP,53/TCP                             10m
kube-system   kubernetes-dashboard                      NodePort       10.110.36.209    <none>        80:30000/TCP                              10m
kube-system   monitoring-grafana                        NodePort       10.96.206.158    <none>        80:30002/TCP                              10m
kube-system   monitoring-influxdb                       ClusterIP      10.100.26.192    <none>        8083/TCP,8086/TCP                         10m
kube-system   tiller-deploy                             ClusterIP      10.98.2.151      <none>        44134/TCP                                 9m
$
```

#### ingress

クラスタ外部からホスト名`gitlab.test.com`でアクセスして使って欲しいことが分かりました。手順を後述します。

```bash
$ kubectl get ing --all-namespaces
NAMESPACE   NAME                        HOSTS               ADDRESS   PORTS     AGE
gitlab      cm-acme-http-solver-khlqr   gitlab.test.com               80        10m
gitlab      cm-acme-http-solver-mvq5r   minio.test.com                80        10m
gitlab      cm-acme-http-solver-vjft9   registry.test.com             80        10m
gitlab      gitlab-minio                minio.test.com                80, 443   11m
gitlab      gitlab-registry             registry.test.com             80, 443   11m
gitlab      gitlab-unicorn              gitlab.test.com               80, 443   11m
$
```

#### gitlab-runner の podはとりあえず保留

logを見るとgitlab本体(`gitlab.test.com`)にアクセスしようとしていました。
gitlab-runnerのpodから見た`gitlab.test.com`を解決できるようにしてあげれば良さそうですが、
まだrunnerは使わないのでレプリカ数を0にしてpodを0個にしておきます。

```bash
$ kubectl logs -f gitlab-gitlab-runner-544fd9dcb5-92lxf -n gitlab
Runtime platform                                    arch=amd64 os=linux pid=15 revision=3afdaba6 version=11.5.0
WARNING: Running in user-mode.
WARNING: The user-mode requires you to manually start builds processing:
WARNING: $ gitlab-runner run
WARNING: Use sudo for system-mode:
WARNING: $ sudo gitlab-runner...

ERROR: Registering runner... failed                 runner=Ixy5TRFT status=couldn't execute POST against https://gitlab.test.com/api/v4/runners: Post https://gitlab.test.com/api/v4/runners: dial tcp 10.107.221.8:443: i/o timeout
PANIC: Failed to register this runner. Perhaps you are having network problems
$
```

```
$ kubectl get deployment gitlab-gitlab-runner -n gitlab
NAME                   DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
gitlab-gitlab-runner   1         1         1            0           2h
$
$ kubectl edit deployment gitlab-gitlab-runner -n gitlab
deployment "gitlab-gitlab-runner" edited
$ kubectl get deployment gitlab-gitlab-runner -n gitlab
NAME                   DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
gitlab-gitlab-runner   0         0         0            0           2h
$
```


## LoadBalancerにEXTERNAL-IPを付与する

以下のように`<pending>`になっています。
GKE等にデプロイすれば付与されるのですが、minikubeなので付与されません。

```bash
$ kubectl get svc gitlab-nginx-ingress-controller -n gitlab
NAME                              TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                                   AGE
gitlab-nginx-ingress-controller   LoadBalancer   10.106.203.63   <pending>        80:32693/TCP,443:31602/TCP,22:32479/TCP   44m
$
```

ここで全minikube使いに朗報があります。
LoadBalancerのEXTERNAL-IPとしてCLUSTER-IPを設定してくれるpodのimageが公開されています。
これをデプロイしてみましょう。
[elsonrodriguez/minikube-lb-patch](https://github.com/elsonrodriguez/minikube-lb-patch)


デプロイ前
LoadBalancerのstatus/loadBalancer/配下に何もありません。

```bash
$ kubectl get svc gitlab-nginx-ingress-controller -n gitlab -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: 2019-01-14T13:03:34Z
  labels:
    app: nginx-ingress
    chart: nginx-ingress-0.30.0-1
    component: controller
    heritage: Tiller
    release: gitlab
  name: gitlab-nginx-ingress-controller
  namespace: gitlab
  resourceVersion: "756"
  selfLink: /api/v1/namespaces/gitlab/services/gitlab-nginx-ingress-controller
  uid: ccd6c290-17fc-11e9-8bab-080027a0645f
spec:
  clusterIP: 10.106.203.63
  externalTrafficPolicy: Local
  healthCheckNodePort: 30556
  ports:
  - name: http
    nodePort: 32693
    port: 80
    protocol: TCP
    targetPort: http
  - name: https
    nodePort: 31602
    port: 443
    protocol: TCP
    targetPort: https
  - name: gitlab-shell
    nodePort: 32479
    port: 22
    protocol: TCP
    targetPort: gitlab-shell
  selector:
    app: nginx-ingress
    component: controller
    release: gitlab
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer: {}
$
```

デプロイ

```bash
$ kubectl run minikube-lb-patch --replicas=1 --image=elsonrodriguez/minikube-lb-patch:0.1 --namespace=kube-system
deployment "minikube-lb-patch" created
$
```

デプロイ後
LoadBalancerの`status/loadBalancer/` 配下に ingressのipが`clusterIP`で設定されました。

```bash
$ kubectl get svc gitlab-nginx-ingress-controller -n gitlab -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: 2019-01-14T13:03:34Z
  labels:
    app: nginx-ingress
    chart: nginx-ingress-0.30.0-1
    component: controller
    heritage: Tiller
    release: gitlab
  name: gitlab-nginx-ingress-controller
  namespace: gitlab
  resourceVersion: "3591"
  selfLink: /api/v1/namespaces/gitlab/services/gitlab-nginx-ingress-controller
  uid: ccd6c290-17fc-11e9-8bab-080027a0645f
spec:
  clusterIP: 10.106.203.63
  externalTrafficPolicy: Local
  healthCheckNodePort: 30556
  ports:
  - name: http
    nodePort: 32693
    port: 80
    protocol: TCP
    targetPort: http
  - name: https
    nodePort: 31602
    port: 443
    protocol: TCP
    targetPort: https
  - name: gitlab-shell
    nodePort: 32479
    port: 22
    protocol: TCP
    targetPort: gitlab-shell
  selector:
    app: nginx-ingress
    component: controller
    release: gitlab
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 10.106.203.63
$
```

`EXTERNAL-IP`として`CLUSTER-IP`の値が付与されたことが分かります。

```bash
$ kubectl get svc gitlab-nginx-ingress-controller -n gitlab
NAME                                      TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                   AGE
gitlab-nginx-ingress-controller           LoadBalancer   10.106.203.63    10.106.203.63   80:32693/TCP,443:31602/TCP,22:32479/TCP   17m
$
```

ingressにも`ADDRESS`が付きました。

```
$ kubectl get ing -n gitlab
NAME                        HOSTS               ADDRESS         PORTS     AGE
cm-acme-http-solver-khlqr   gitlab.test.com     10.106.203.63   80        16m
cm-acme-http-solver-mvq5r   minio.test.com      10.106.203.63   80        16m
cm-acme-http-solver-vjft9   registry.test.com   10.106.203.63   80        16m
gitlab-minio                minio.test.com      10.106.203.63   80, 443   17m
gitlab-registry             registry.test.com   10.106.203.63   80, 443   17m
gitlab-unicorn              gitlab.test.com     10.106.203.63   80, 443   17m
$
```

## EXTERNAL-IPへの経路を作成する
`EXTERNAL-IP`が付与されたとは言っても値は`CLUSTER-IP`ですので、
クラスタ外からクラスタ内の`EXTERNAL-IP`への経路を作成します。
また、ホスト名`gitlab.test.com`でアクセスできるようにもします。

### hostsファイルへの追加

`/etc/hosts`ファイルを編集し、`EXTERNAL-IP`を以下hostのIPアドレスとして設定します。

- gitlab.test.com
- minio.test.com
- registry.test.com

```bash
$ sudo vim /etc/hosts
$ cat /etc/hosts
( 略 )
10.106.203.63   gitlab.test.com
10.106.203.63   minio.test.com
10.106.203.63   registry.test.com
( 略 )
$
```

### ルーティングテーブルへの追加

`EXTERNAL-IP`への経路をルーティングテーブルに追加します。

追加前

```bash
$ sudo route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    20100  0        0 enp0s31f6
link-local      0.0.0.0         255.255.0.0     U     1000   0        0 enp0s31f6
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-dd3ae712d9ae
192.168.3.0     0.0.0.0         255.255.255.0   U     100    0        0 enp0s31f6
192.168.99.0    0.0.0.0         255.255.255.0   U     0      0        0 vboxnet0
```

追加コマンド
[elsonrodriguez/minikube-lb-patch](https://github.com/elsonrodriguez/minikube-lb-patch)を参考にしています。

```bash
$ ServiceCIDR=$(cat ~/.minikube/profiles/minikube/config.json | jq -r ".KubernetesConfig.ServiceCIDR")
$ echo ${ServiceCIDR}
10.96.0.0/12
$ sudo route -n add -net ${ServiceCIDR} gw $(minikube ip)
```

追加後

`minikube`をGatewayとする経路が追加できました。

```bash
$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    20100  0        0 enp0s31f6
10.96.0.0       minikube        255.240.0.0     UG    0      0        0 vboxnet0
link-local      0.0.0.0         255.255.0.0     U     1000   0        0 enp0s31f6
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-dd3ae712d9ae
192.168.3.0     0.0.0.0         255.255.255.0   U     100    0        0 enp0s31f6
192.168.99.0    0.0.0.0         255.255.255.0   U     0      0        0 vboxnet0
$
```

## ブラウザでLoadBalancerにアクセスする

ubuntuマシンでgoogle-chromeを起動します。

```
$ google-chrome
```

以降、ubuntuで起動しているgoogle-chromeからminikubeのクラスタにアクセスしている画面のスクリーンショットを貼り付けます。
( google-chromeの画面をubuntu(minikubeが起動しているマシン)からWindows(ただの作業用マシン)にX11 Forwardingで転送しているため、スクリーンショットの見た目はWindowsアプリに見えますがご了承下さい。 )

ブラウザで`https://gitlab.${global.hosts.domain}`を開きます。
`ADVNACED`をクリックします。
![01.png](https://qiita-image-store.s3.amazonaws.com/0/21106/48475f4d-7b91-51ab-f9ea-c8ef88245f61.png)

`Proceed to gitlab.test.com`をクリックします。
![02.png](https://qiita-image-store.s3.amazonaws.com/0/21106/11ca46aa-3d66-87dd-93e3-87041fbbf97b.png)


ログイン画面です。Usernameは`root`とします。`Password`は以下コマンドで取得できます。
( Helmコマンドに指定したデプロイ名がgitlab以外の場合、secret名も以下と異なりますのでご注意下さい )

```bash
$ kubectl get secret gitlab-gitlab-initial-root-password -ojsonpath={.data.password} -n gitlab | base64 --decode ; echo
xxxxxxxxxxxxxxxxxxxxxxxxxxxx
$
```
![03.png](https://qiita-image-store.s3.amazonaws.com/0/21106/e8209765-0c4f-9041-5c90-edf8397a6993.png)

## 動作確認

`Create a project`をクリックします
![04.png](https://qiita-image-store.s3.amazonaws.com/0/21106/1427b9c8-062d-18bb-593b-90787d53ab51.png)

プロジェクト名は`test`としました。
![06.png](https://qiita-image-store.s3.amazonaws.com/0/21106/ad25ff49-fa72-8945-231b-ef40b6c5bb32.png)

空の状態で`test`プロジェクトが作成できました。
![07.png](https://qiita-image-store.s3.amazonaws.com/0/21106/23a4a3ec-21f9-8e04-b3c0-118f03b34b7b.png)

リポジトリのclone、ファイル(README.md)のadd、commit & pushができることを確認します。

```bash
$ # 怒られる
$ git clone https://gitlab.test.com/root/test.git
Cloning into 'test'...
fatal: unable to access 'https://gitlab.test.com/root/test.git/': server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
$ # 非推奨
$ git config --global http.sslverify false
$ # clone できる
$ git clone https://gitlab.test.com/root/test.git
Cloning into 'test'...
Username for 'https://gitlab.test.com': root
Password for 'https://root@gitlab.test.com':
warning: You appear to have cloned an empty repository.
$ cd ./test/
$ vim README.md
$ cat README.md
# test

GitLab test
$ git add README.md
$ git commit -m "add"
[master (root-commit) ca0f2bd] add
 1 file changed, 3 insertions(+)
 create mode 100644 README.md
$ git push
Username for 'https://gitlab.test.com': root
Password for 'https://root@gitlab.test.com':
Counting objects: 3, done.
Writing objects: 100% (3/3), 217 bytes | 217.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://gitlab.test.com/root/test.git
 * [new branch]      master -> master
$
```

確かにpushできています。
![08.png](https://qiita-image-store.s3.amazonaws.com/0/21106/502c0432-b85c-d09c-77db-4ef53f7dd5eb.png)

`Operations`配下に目玉機能のServerlessがありました。是非とも試したいです。
![09.png](https://qiita-image-store.s3.amazonaws.com/0/21106/09c36134-1b69-fad5-0577-e9ede24261e4.png)

Container Registoryもあります、嬉しいですね。
![10.png](https://qiita-image-store.s3.amazonaws.com/0/21106/90cc14ed-c7d4-5bb9-712b-38bc6f1bc0b2.png)

バージョンはヘルプで確認できます。`11.6.3`です。
![11.png](https://qiita-image-store.s3.amazonaws.com/0/21106/95ee38fd-25fa-53f9-93c3-6f211dcfb823.png)


## まとめ

クラウドネイティブの潮流を感じられる方法でGitLabをデプロイしてみました。
最新のGitLabデプロイ方法の参考になりましたら幸いです。

minikubeはEXTERNAL-IPが付与されない扱いづらさはありますが、課金の心配がないところが良いですね。
構成も自由に変更できるので特に学習・実験用途に適していると思います。
引き続き、Serverlessの機能も試してみたいと思っています。