オンプレミスのKubernetesにNginx-Ingress-Controllerを設定する

この記事は、「[オンプレミス、Kubernetesで、マイクロサービスを意識したWebアプリをデプロイするまでの軌跡](https://qiita.com/soumi/items/2ef65b0d6e3fb562451e)」の一部です。

## はじめに

Kubernetes上に、以下のような構成でWebアプリケーションを構築したいとします。

```
app   ---- /authentication  :  (1)認証用nodejsアプリ (ポート3000)
       |-- /serviceA
       |     |-- /          :  (2)vuejsで作成したサービスAのフロントエンド (ポート8080)
       |     |-- /api       :  (3)expressで作成したサービスAのバックエンド (ポート3001)
       |
       |-- /serviceB
             |-- /          :  (4)vuejsで作成したサービスBのフロントエンド (ポート8081)
             |-- /api       :  (5)expressで作成したサービスBのバックエンド (ポート3101)
```

1～5は全て別のサービスで動いていて、それぞれ重複しない個別のポートで待ち受けています。これを何もせずにこのままでデプロイすると、ドメインが```www.services.com```だったとして、

```url:serviceA
www.services.com:8080
```

```url:serviceB
www.services.com:8081
```

のような形でアクセスする事になり、色々な意味でよろしくない事になります。
これを、

```url:serviceA
www.services.com/serviceA
```

```url:serviceB
www.services.com/serviceB
```

でアクセスできるように設定していきます。

## Ingressを使う

例のごとく詳しく理解しているわけではないですが、以下を見る限りこれを実現するのにはIngressという機能を使うと良さそうです。

https://kubernetes.io/docs/concepts/services-networking/ingress/

早速設定してみます。
*(service-aと、service-bというサービスは既にデプロイしてあるとします。)*

```yaml:ingress-sample.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /serviceA
        backend:
          serviceName: service-a
          servicePort: 8080
      - path: /serviceB
        backend:
          serviceName: service-b
          servicePort: 8081
```

```shell
kubectl apply -f ingress-sample.yaml
```

…動かない…

どうやら、このIngressはただの設定で、実際に動かすためには別途実体を用意する必要があるらしいです。

https://blog.shohhei1126.jp/using_nginx_ingress_controller.html

ということで、今回はNginx-Ingress-Controllerを使用する事にします。

## Nginx-Ingress-Controllerを使う

調べてみると、公式に手順が書いてありました。その通りにやってみます。

https://kubernetes.github.io/ingress-nginx/deploy/

オンプレミス環境での手順は以下の通りで、コマンド2つで済むものになっています。

```shell
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml
```

これでどうだ！

![502.png](https://qiita-image-store.s3.amazonaws.com/0/321330/d9f19bc3-aaf3-57ae-ea7f-fe21e386a721.png)

まだ何か足らないようです…

調べてみると、こんな記事を発見しました。

[kubernetesにNginx Ingress Controllerをセットアップ](https://qiita.com/sheepland/items/37ece5800eb6972ffd91)

この記事によると、

> externalIPsにnodeのIPを指定する

とあります。
先程はネット上に公開されているyamlを直接```kubectl```に食わせましたが、一度ローカルに落としてきて該当箇所を編集する事にします。

```shell
$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml
$ nano service-nodeport.yaml
```

```yaml:service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 80
      protocol: TCP
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  externalIPs:      <-- ここを追加
    - 192.168.0.xxx <-- ここを追加
```

この設定を元に、

```shell
$ kubectl apply -f mandatory.yaml
$ kubectl apply -f  service-nodeport.yaml
```

![200.png](https://qiita-image-store.s3.amazonaws.com/0/321330/97e4d8d8-6e44-49d1-6089-5b49dca8b5ea.png)

動くようになりました！

完全には理解していないまま進めていたので大分手こずってしまいましたが、一度設定動くようになると、冒頭のingress設定ファイルを変更するだけで特定のパスにサービスを割り当てる事が出来、とても便利です。

以上です。
お疲れさまでした！