IKS IBM管理下の LetsEncrypt のTLS証明書を利用してHTTPS通信 part2

IBM Cloud Kubernetes Service [IKS IBM管理下の LetsEncrypt のTLS証明書を利用してHTTPS通信](https://qiita.com/MahoTakara/items/809bf225d6390dad6316) の続きで、k8sクラスタ構成時に自動取得されたドメインで、サブドメインを利用するケース、複数のアプリケーションを対応付ける方法について検証したメモです。


## サブドメインの利用

IKSのクラスタ生成時に、自動取得されるドメインには、ユーザーが独自にサブドメインを付与することができます。また、TLS証明書もサブドメインをワイルドカードで作成してあるので、HTTPS通信も同様にりようできます。

ドメイン名とシークレット名を参照するには、「ibmcloud ks cluster-get クラスタ名」をインプットします。

![screen-shot-1.PNG](https://qiita-image-store.s3.amazonaws.com/0/42829/0091fc78-a646-02ec-cfa1-c3c016cc41e0.png)

表示された結果の中で、「入口サブドメイン」が、本クラスタ専用のドメイン名になります。そして、「入口の秘密」となっている項目の値が、k8sのシークレット名です。この中に、サブドメインをワイルドカードにしたTLS証明書と鍵が入っています。

## ユーザー独自のサブドメインの設定

前述のサブドメインに、さらに、子の層を設定したイングレスを作成するためのマニフェストは、次になります。設定するべき項目の部分に、コメントをいれておきました。


~~~file:ingress-tls.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingres-dev
  # アノテーションの設定は、次のURLを参照してきださい。
  # https://cloud.ibm.com/docs/containers/cs_ingress.html#annotations
  annotations:
     ingress.bluemix.net/redirect-to-https: "True"
     ingress.bluemix.net/rewrite-path: "serviceName=web-svc1 rewrite=/;serviceName=web-svc2 rewrite=/;serviceName=web-svc3 rewrite=/"
spec:
   tls:
   # このドメイン名のシークレットは前述と同じものを利用します。
   - hosts:
     - dev.iks1.jp-tok.containers.appdomain.cloud
     secretName: iks1
   rules:
   # 次のhostの値に、devを追加したDNS名をセットします。
   - host: dev.iks1.jp-tok.containers.appdomain.cloud
     http:
       # 複数のサービスをFQDNのパスに対応づけて暗号通信でアクセスできます。
       paths:
       - path: /
         backend:
           serviceName: web-svc1
           servicePort: 9080
       - path: /apl2
         backend:
           serviceName: web-svc2
           servicePort: 80
       - path: /apl3
         backend:
           serviceName: web-svc3
           servicePort: 80
~~~

## イングレスコントローラーへのコマンド

IBMで実装したイングレスコントローラーのことをALBと呼んでいますが、利用法は、NGINX Ingress コントローラーに似ています。しかし、アノテーションで指定できる命令には、互換性がありませんから、IBM Cloudのマニュアル　https://cloud.ibm.com/docs/containers/cs_ingress.html#annotations を参照して、設定する必要があります。

詳しくはリンクを見てほしいのですが、ここで利用した二つについて、コメントしておきます。

### ingress.bluemix.net/redirect-to-https: "True"

クライアントがHTTPでアクセスすると、HTTPSへリダイレクトします。HTTPSを利用する場合は必須の設定と思います。

### ingress.bluemix.net/rewrite-path: "serviceName=web-svc1 rewrite=/"

FQDNのパスに、サービスを対応づける場合に必要な設定です。
例えば、サービスを次のFQDNへ対応づけた場合、

    dev.iks1.jp-tok.containers.appdomain.cloud/apl2 

このリライト設定が無い場合、ディレクトリが無いというエラーを返してしまいます。その様なエラーを防止するために、ALBで、アクセスしてきたURLのパス部分を書き換える設定です。


## サービスとコントローラーのYAML

次のマニフェストは、Javaアプリケーションの実行環境[Open-Liberty](https://openliberty.io/)のコンテナを実行するためのものです。　ALB が受けたリクエストのTLS暗号を終端して、ポート番号9080でサービス名 web-svc1 で待ち受けるポッドへリクエストを分配します。

~~~file:deploy-web1.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: web1
spec:
  replicas: 5
  template:
    metadata:
      labels:
        app: web1
    spec:
      containers:
        - image: openliberty/open-liberty:webProfile8-java8-openj9
          name: openliberty
          ports:
            - containerPort: 9080
---
apiVersion: v1
kind: Service
metadata:
  name: web-svc1
spec:
  selector:
    app: web1
  ports:
    - port: 9080
~~~

次のマニフェストは、Apache2 httpdのウェブサーバーのコンテナです。


~~~file:deploy-web2.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: web2
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: web2
    spec:
      containers:
        - image: 'httpd'
          name: apache2-httpd
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-svc2
spec:
  selector:
    app: web2
  ports:
    - port: 80
~~~

最後に、NGINXのウェブサーバーです。

~~~file:deploy-web3.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: web3
spec:
  replicas: 4
  template:
    metadata:
      labels:
        app: web3
    spec:
      containers:
        - image: nginx
          name: nginx
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-svc3
spec:
  selector:
    app: web3
  ports:
    - port: 80
~~~


## 動作確認

イングレスのマニフェストを適用することで、各ノードで動作しているALBに設定が伝達されることが解ります。そして、dev.iks1.jp-tok... というクラスタ名下のサブドメインで、アクセスできるようになります。

~~~
$ kubectl apply -f ingress-tls.yml
ingress.extensions/ingres-dev created

$ kubectl describe ing ingres-dev
Name:             ingres-dev
Namespace:        default
Address:          128.168.73.198,165.192.71.230,169.56.27.94
Default backend:  default-http-backend:80 (<none>)
TLS:
  iks1 terminates dev.iks1.jp-tok.containers.appdomain.cloud
Rules:
  Host                                        Path  Backends
  ----                                        ----  --------
  dev.iks1.jp-tok.containers.appdomain.cloud
                                              /       web-svc1:9080 (<none>)
                                              /apl2   web-svc2:80 (<none>)
                                              /apl3   web-svc3:80 (<none>)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"ingress.bluemix.net/redirect-to-https":"True","ingress.bluemix.net/rewrite-path":"serviceName=web-svc1 rewrite=/;serviceName=web-svc2 rewrite=/;serviceName=web-svc3 rewrite=/"},"name":"ingres-dev","namespace":"default"},"spec":{"rules":[{"host":"dev.iks1.jp-tok.containers.appdomain.cloud","http":{"paths":[{"backend":{"serviceName":"web-svc1","servicePort":9080},"path":"/"},{"backend":{"serviceName":"web-svc2","servicePort":80},"path":"/apl2"},{"backend":{"serviceName":"web-svc3","servicePort":80},"path":"/apl3"}]}}],"tls":[{"hosts":["dev.iks1.jp-tok.containers.appdomain.cloud"],"secretName":"iks1"}]}}

  ingress.bluemix.net/redirect-to-https:  True
  ingress.bluemix.net/rewrite-path:       serviceName=web-svc1 rewrite=/;serviceName=web-svc2 rewrite=/;serviceName=web-svc3 rewrite=/
Events:
  Type    Reason   Age   From                                                             Message
  ----    ------   ----  ----                                                             -------
  Normal  Success  4s    public-cr41679d0177fa4f92ab10262fa586956c-alb1-7fc8d4d4c9-hqcm7  Successfully applied ingress resource.
  Normal  Success  4s    public-cr41679d0177fa4f92ab10262fa586956c-alb2-64478db6dc-kkp52  Successfully applied ingress resource.
  Normal  Success  4s    public-cr41679d0177fa4f92ab10262fa586956c-alb3-b9df97448-jm5rz   Successfully applied ingress resource.
  Normal  Success  4s    public-cr41679d0177fa4f92ab10262fa586956c-alb1-7fc8d4d4c9-xq2bc  Successfully applied ingress resource.
~~~


* https://dev.iks1.jp-tok.containers.appdomain.cloud/ のアクセス結果
![web-1.PNG](https://qiita-image-store.s3.amazonaws.com/0/42829/33581c35-b4b2-1669-f36b-a5f95b415e8d.png)

* https://dev.iks1.jp-tok.containers.appdomain.cloud/apl2 のアクセス結果

![web-3.PNG](https://qiita-image-store.s3.amazonaws.com/0/42829/f649a5c9-c41d-11b0-4b5d-1cf83526a6a2.png)

* https://dev.iks1.jp-tok.containers.appdomain.cloud/apl3 のアクセス結果

![web-2.PNG](https://qiita-image-store.s3.amazonaws.com/0/42829/08910502-6b3d-ace7-4330-3de56c35b62d.png)


## まとめ

今回の検証を簡潔にまとめると、以下のような知見が得られたことになると思います。

* k8sクラスタ生成時に割り当てされるサブドメインの下に、ユーザーがドメインを設定できる。
* ユーザー設定のサブドメインは、イングレスのマニフェストで設定する。
* TLS証明書は、ワイルドカードで設定されているため、HTTPS通信に利用できる。
* ALBのアノテーションは、NGINXイングレスコントローラーと互換性が無いため、IBM Cloud のドキュメントを参照して、設定を実施する必要がある。


## 参考資料

* アノテーションを使用した Ingress のカスタマイズ、https://console.bluemix.net/docs/containers/cs_annotations.html#ingress_annotation
* Ingress を使用してアプリを公開する､https://console.bluemix.net/docs/containers/cs_ingress.html#ingress
* NGINX Ingress Controlle、https://kubernetes.github.io/ingress-nginx/