Kubernetes - Ingressを使ってサービスを公開する

## 概要
Ingressとは、Serviceの一つ上にロードバランサとして設置するものである。
L7の情報を使ってLoadBalancingができる。
VirtualHostの設定をすることができる。また、SSLの設定もできる。

Ingressを利用しなくても、Serviceの機能でアプリケーションを公開することはできるが、SSLの設定や、その他メリットも多いので、基本的には利用したほうがよいと思う。

参考: [Kubernetes NodePort と LoadBalancer と Ingress のどれを使うべきか](https://sff8.hatenablog.com/entry/2018/10/27/234757)

## 目次
- [Kubernetesハンズオン目次](https://qiita.com/Esfahan/items/4fcf51622fed20dffb88)

## 事前準備
minikubeを利用している場合は、以下のコマンドでingressを有効にする。

```console
$ sudo minikube addons enable ingress
✅  ingress was successfully enabled
```

## nginx-ingress-controller
`namespace: kube-system`に、`nginx-ingress-controller-xxxx`というPodが起動している。
これは、minikubeを起動しIngressのaddonを有効にしていれば、Ingressを作成せずとも起動している。
このnginxのPodがIngressのロードバランサの役割をする。

```console
$ sudo kubectl get pods -n kube-system | grep ingress
kube-system   nginx-ingress-controller-xxxxxxxxxxxxxxxx   1/1     Running   0          24h
```

[Kubernetes NodePort と LoadBalancer と Ingress のどれを使うべきか](http://chidakiyo.hatenablog.com/entry/2018/09/10/Kubernetes_NodePort_vs_LoadBalancer_vs_Ingress%3F_When_should_I_use_what%3F_%28Kubernetes_NodePort_%E3%81%A8_LoadBalancer_%E3%81%A8_Ingress_%E3%81%AE%E3%81%A9%E3%82%8C%E3%82%92%E4%BD%BF%E3%81%86)

>  Ingressコントローラーの種類は、GCLB、Nginx、Contour、istioなどあがります

らしい。

## ハンズオン
nginxを使ったwebアプリでページを表示してみる。
以下の2つのページが表示されるようにする。

- http://example.com/app1/
- http://example.com/app2/

### Deployment

```yaml:deployment
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: sample-http-app
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: sample-http-app
    spec:
      containers:
      - name: nginx-container
        image: nginx:alpine
        ports:
        - name: http-port
          containerPort: 80
        volumeMounts:
        - name: documentroot
          mountPath: /usr/share/nginx/html/
      volumes:
        - name: documentroot
          hostPath:
            path: /home/username/containers/web/html
```

### Service

```yaml:service.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: http-service
  labels:
    app: sample-http-app
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: http-port
  selector:
    app: sample-http-app
```

### Ingress

```yaml:ingress.yaml
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: sample-ingress
spec:
  rules:
  # VirtualHostのホスト名
  - host: example.com
    http:
      paths:
      # {DocumentRoot}/app1がトップディレクトリになる
      - path: /app1
        backend:
          # bindするService名
          # service.yamlのmetadata.nameと合わせる
          serviceName: http-service
          # Serviceが公開しているPort
          servicePort: 80
  # 複数設定可能
  - host: example.com
    http:
      paths:
      # {DocumentRoot}/app2がトップディレクトリになる
      - path: /app2
        backend:
          # service.yamlのmetadata.nameと合わせる
          serviceName: http-service
          # Serviceが公開しているPort
          servicePort: 80
```

### WEB用テストファイルを作成
ブラウザで表示するテストページ用のファイルを作成する。
/home/username/containers/web/htmlをDocumentRootとしてマウントするので、その下にファイルを置く。
/app1, /app2の2つのディレクトリを作成する。

```console
$ mkdir /home/username/containers/web/html/{app1,app2}
```

```html:/home/username/containers/web/html/app1/index.html
This is a app 1.
```

```html:/home/username/containers/web/html/app2/index.html
This is a app 2.
```

### 作成

```console
$ sudo kubectl apply -f deployment.yaml -f service.yaml -f ingress.yaml
deployment.extensions/sample-http-app created
service/http-service created
ingress.extensions/sample-ingress created
```

## 確認
ingressが作成されていることを確認。

```console
$ sudo kubectl get ingress
NAME             HOSTS              ADDRESS   PORTS   AGE
sample-ingress   example.com             80      20s
```

ブラウザでページが表示されることを確認。

- http://example.com/app1/
    - `This is a app 1.`
- http://example.com/app2/
    - `This is a app 2.`

## Ingressのログを確認する方法
Ingressのログを確認する場合は、nginx-ingress-controllerのPodを確認すればよい。

```console
$ sudo kubectl logs nginx-ingress-controller-xxxxxxxxxxxxxxxx -n kube-system
-------------------------------------------------------------------------------
NGINX Ingress controller
  Release:    0.23.0
  Build:      git-be1329b22
  Repository: https://github.com/kubernetes/ingress-nginx
-------------------------------------------------------------------------------
# **omitted**
```

## 参考
- [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
- [Kubernetes道場 22日目 - Ingressについて](https://cstoku.dev/posts/2018/k8sdojo-22/)
- [ingress-nginx/troubleshooting](https://kubernetes.github.io/ingress-nginx/troubleshooting/)
- [Kubernetes Ingressを触ってみた](https://tech.virtualtech.jp/entry/2019/01/11/190811)
- [Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what? (Kubernetes NodePort と LoadBalancer と Ingress のどれを使うべきか) を訳した](http://chidakiyo.hatenablog.com/entry/2018/09/10/Kubernetes_NodePort_vs_LoadBalancer_vs_Ingress%3F_When_should_I_use_what%3F_%28Kubernetes_NodePort_%E3%81%A8_LoadBalancer_%E3%81%A8_Ingress_%E3%81%AE%E3%81%A9%E3%82%8C%E3%82%92%E4%BD%BF%E3%81%86)
- [GKE Kubernetes で Ingress が 503 を返す](https://unching-star.hatenablog.jp/entry/2019/02/23/233314)