Kubernetes Ingress 実践

# Ingress とは？
※ゲームのほうじゃないです

前回の記事で `Kubernetes Service` について書きました。
`Kubernetes Service` は L4 制御ですが、 `Kubernetes Ingress` は L7 制御です。
そのため、パスベースでのルーティングが制御できるためとても便利なものです。

# 適用する YAML ファイル
上から順番に適用してください。

## Namespace
```yaml:ns.yml
apiVersion: v1
kind: Namespace
metadata:
  name: ing-sample
```

## App
```yaml:deploy_app.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ing-deploy-nginx
  namespace: ing-sample
spec:
  replicas: 8
  selector:
    matchLabels:
      app: ing-deploy-nginx
  template:
    metadata:
      labels:
        app: ing-deploy-nginx
    spec:
      containers:
        - name: ing-deploy-nginx
          image: nginx
          resources:
            limits:
              memory: "50Mi"
              cpu: "100m"
          ports:
            - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ing-deploy-apache
  namespace: ing-sample
spec:
  replicas: 8
  selector:
    matchLabels:
      app: ing-deploy-apache
  template:
    metadata:
      labels:
        app: ing-deploy-apache
    spec:
      containers:
        - name: ing-deploy-apache
          image: httpd
          resources:
            limits:
              memory: "50Mi"
              cpu: "100m"
          ports:
            - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ing-deploy-whoami
  namespace: ing-sample
spec:
  replicas: 8
  selector:
    matchLabels:
      app: ing-deploy-whoami
  template:
    metadata:
      labels:
        app: ing-deploy-whoami
    spec:
      containers:
        - name: ing-deploy-whoami
          image: jwilder/whoami
          resources:
            limits:
              memory: "50Mi"
              cpu: "100m"
          ports:
            - containerPort: 8000
```

```yaml:svc-app.yml
apiVersion: v1
kind: Service
metadata:
  name: ing-svc-nginx
  namespace: ing-sample
spec:
  selector:
    app: ing-deploy-nginx
  ports:
    - port: 80
---
apiVersion: v1
kind: Service
metadata:
  name: ing-svc-apache
  namespace: ing-sample
spec:
  selector:
    app: ing-deploy-apache
  ports:
    - port: 80
---
apiVersion: v1
kind: Service
metadata:
  name: ing-svc-whoami
  namespace: ing-sample
spec:
  selector:
    app: ing-deploy-whoami
  ports:
    - port: 8000
```

## Ingress Service Account
```yaml:sa-ing.yml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ing-sample
  namespace: ing-sample
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: ing-sample-cr
  namespace: ing-sample
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - services
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses/status
    verbs:
      - update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: ing-sample-crb
  namespace: ing-sample
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: ing-sample-cr
subjects:
  - kind: ServiceAccount
    name: ing-sample
    namespace: ing-sample
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: ing-sample-role
  namespace: ing-sample
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - configmaps
      - get
      - update
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: ing-sample-rb
  namespace: ing-sample
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: ing-sample-role
subjects:
  - kind: ServiceAccount
    name: ing-sample
    namespace: ing-sample
```

```yaml:secret-ing.yml
apiVersion: v1
kind: Secret
metadata:
  name: ing-sample-secret
  namespace: ing-sample
data:
  tls.crt: <Base64エンコードした証明書>
  tls.key: <Base64エンコードした鍵>
```

## Ingress
```yaml:cm-ing.yml
kind: ConfigMap
apiVersion: v1
metadata:
  name: ing-sample-cfgmap
  namespace: ing-sample
```

```yaml:deploy-ing.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ing-deploy-controller
  namespace: ing-sample
spec:
  replicas: 3
  selector:
    matchLabels:
      app: ing-deploy-controller
  template:
    metadata:
      labels:
        app: ing-deploy-controller
    spec:
      serviceAccountName: ing-sample
      containers:
        - name: ing-deploy-controller
          image: nginx/nginx-ingress:edge
          resources:
            limits:
              memory: "128Mi"
              cpu: "500m"
          ports:
            - name: http
              containerPort: 80
            - name: https
              containerPort: 443
          env:
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          args:
            - -nginx-configmaps=$(POD_NAMESPACE)/ing-sample-cfgmap
            - -default-server-tls-secret=$(POD_NAMESPACE)/ing-sample-secret
```

```yaml:svc-ing.yml
apiVersion: v1
kind: Service
metadata:
  name: ing-svc-controller
  namespace: ing-sample
spec:
  type: NodePort
  selector:
    app: ing-deploy-controller
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
    - name: https
      protocol: TCP
      port: 443
      targetPort: 443
  externalIPs:
    - 10.0.0.230
  externalTrafficPolicy: Cluster
```

```yaml:ingress-ing.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ing-ing
  namespace: ing-sample
spec:
  rules:
    - host: ing-k8s.local
      http:
        paths:
          - path: /nginx
            backend:
              serviceName: ing-svc-nginx
              servicePort: 80
          - path: /apache
            backend:
              serviceName: ing-svc-apache
              servicePort: 80
  backend:
    serviceName: ing-svc-whoami
    servicePort: 8000
  tls:
    - hosts:
        - ing-k8s.local
      secretName: ing-sample-secret
```

# アクセスしてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204925/c1bb95b3-625d-dde2-cc13-09167bd908f2.png)
`Default` や存在しないパスを指定した場合は `spec.backend` に指定した `Service` に転送されます。
`/nginx` は `Nginx` に、 `/apache` は `Apache` に転送されるように設定したのでしっかり動作していることが確認できました。