GitLab Runnerを専有ノードで動かす

現状GitLab RunnerをKubernetes上で稼働させているが、特に稼働するノードなどに制限を設けていない。\
今回、GitLab Runner専用のノードを用意し、他のPodは起動できなくする。
これにより、GitLab Runnerがリソース不足でジョブの実行に失敗するケースを防ぐ。

## 専有ノードの作成
今抱えているノードは以下のようになっている。
```
$ kubectl top node
NAME                              CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
ip-192-168-108-18.ec2.internal    226m         5%     5875Mi          39%
ip-192-168-114-140.ec2.internal   378m         9%     6396Mi          43%
ip-192-168-127-2.ec2.internal     460m         11%    6073Mi          40%
ip-192-168-65-145.ec2.internal    847m         21%    4074Mi          27%
ip-192-168-66-48.ec2.internal     330m         8%     5936Mi          40%
ip-192-168-84-152.ec2.internal    167m         4%     4436Mi          29%
```

`ip-192-168-84-152.ec2.internal`というノードをGitLab Runner専有ノードにする。\
専有ノードはTaintを用いて設定する。
```
kubectl taint nodes ip-192-168-84-152.ec2.internal dedicated=gitlab-runner:NoExecute
```
これにより、`dedicated=gitlab-runner`のTolerationsの設定をしたPodのみこのノードで起動する。
なお、既にそのノードで起動しているPodへの影響を避けたい場合は`NoExecute`ではなく`NoSchedule`を利用する。

EKSの場合はノードグループに対してTaintを割り当てる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/49643e46-2e4a-96cf-8e9a-70d941c2e1d0.png)
こうすることで、ノードが再作成された場合でも自動的にTaintが設定される。

動作確認用にノードにラベルも割り当てて、NodeSelectorで指定したPodがあがらないことを確認する。
```
kubectl label node ip-192-168-84-152.ec2.internal dedicated=gitlab-runner
```

以下のnodeSelectorを指定したPodを作成すると、PendingでPodが作成されない。
```yaml
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx
  name: nginx
spec:
  nodeSelector:
    dedicated: gitlab-runner
  containers:
  - image: nginx
    name: nginx
EOF
```
Tolerationを指定して、当該ノードでPodが起動できることも確認しておく。
```yaml
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
  tolerations:
  - key: "dedicated"
    operator: "Equal"
    value: "gitlab-runner"
    effect: "NoExecute"
EOF
```

### GitLab Runnerのデプロイ
GitLab RunnerでTolerationを設定するには、config.tomlに`node_tolerations`を記載する必要がある。（本家の説明は[こちら](https://docs.gitlab.com/runner/executors/kubernetes.html#other-configtoml-settings))。
ただし、こちらの設定はビルド用Podに関する設定なので、Runner自体のTolerationはconfig.tomlとは別で設定する必要がある。

今回はHelmでRunnerをデプロイする。Helmの設定ファイルを取り出す。
```
helm show values gitlab/gitlab-runner > ./gitlab-runner-sub-values.yaml
```
エディタで設定ファイルを開き、config.tomlにTolerationの設定を追記する。
```
  config: |
    [[runners]]
      [runners.kubernetes]
        namespace = "{{.Release.Namespace}}"
        image = "ubuntu:16.04"
        image_pull_secrets = ["harbor-pull-secret"]
      [runners.kubernetes.node_tolerations]
        "dedicated=gitlab-runner" = "NoExecute"
```
また、Runner本体のTolerationも設定する。
```
## List of node taints to tolerate (requires Kubernetes >= 1.6)
## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
##
tolerations:
 - key: dedicated
   operator: "Equal"
   value: "gitlab-runner"
   effect: "NoExecute"
```
出来上がった設定ファイルからManifest内に設定が反映されていることを確認する。
```
 helm template gitlab-runner-sub gitlab/gitlab-runner -n gitlab -f ./gitlab-runner-sub-values.yaml
```
GitLab Runnerをデプロイする。
```
helm upgrade -i gitlab-runner-sub gitlab/gitlab-runner -n gitlab -f ./gitlab-runner-sub-values.yaml
```

### 動作確認
Runnerデプロイ後、watchコマンドで当該ノードでPodが作成されるのを監視した状態で適当なジョブを実行すると、以下のように当該ノードでRunnerとそのジョブが実行されることが確認できる。
```
$ watch "kubectl get pod -o wide -n gitlab | grep ip-192-168-84-152"
Every 2.0s: kubectl get pod -o wide -n gitlab | grep ip-192-168-84-152                                                                

gitlab-runner-sub-6cffc757b6-c7jnn             1/1     Running   0          4m13s   192.168.71.108   ip-192-168-84-152.ec2.internal    <none>           <none>
runner-eib6xahb-project-3-concurrent-0skrgq    2/2     Running   0          7s      192.168.73.37    ip-192-168-84-152.ec2.internal    <none>           <none>
```