IKS カスタムドメインを Ingress に設定して、TLS暗号通信を実施する


独自ドメイン名を、ドメインネーム・プロバイダーから取得して、HTTPS暗号通信ができるように、SSL/TLS証明書を取得している状態を想定して、IBM Cloud Kubernetes Service (IKS) の Ingressを使って、Webアプリケーションサーバーに、HTTPSに接続できる環境を設定してみます。

IKSの東京リージョンでは、マルチゾーン または シングルゾーン を選択して利用で来るので、どちらでも利用できるように、進めていきます。そして、マルチゾーン構成時のゾーン障害時の振る舞いについて、考察してみました。

このメモは、次の二つの続きになっています。

* [IKS IBM管理下の LetsEncrypt のTLS証明書を利用してHTTPS通信](https://qiita.com/MahoTakara/items/809bf225d6390dad6316)
* [IKS IBM管理下の LetsEncrypt のTLS証明書を利用してHTTPS通信 part2](https://qiita.com/MahoTakara/items/5b0edae6ecde37f60171)


## 事前準備事項

この作業の前に、必要な事項を列挙しておきます。

* ドメイン名の取得　この例では、www.mahotakara.online を利用します。
* SSL/TLS 証明書 公式認証局から買った証明書を使用します。
* IKS の標準クラスタ　複数DCを利用するマルチゾーン を使用します。
* IBM Cloud CLIをインストールしたPCが必要です。


## ALBのIPアドレスの取得と登録

IKSで標準クラスタを作成すると、各ゾーン（データセンターと同等）に、一つずつ パブリックIPアドレスを取得したALB（Application Load Balancer) が起動します。　シングルゾーンの場合は、一つだけ IPアドレスをもったALBが起動して、マルチゾーンで３つのデータセンターにノードを配置した場合は、３個のALBが活性化して、それぞれパブリックIPアドレスで疎通できる状態になります。

このALBは、Ingressのマニフェストで実行されるIngressコントローラーで、IBMが実装して名付けたもので、各社ごとに実装されています。また、NGINX Ingress Controllerは、OSSとして利用できるものです。　しかし、ALBとNGINX Ingress Contorllerには互換性はありません。

IKSの標準クラスタを構成した場合、次のコマンドで、デフォルトのドメイン名とシークレットを参照できます。しかし、このドメイン名を変更することはできません。

~~~concole
$ bx ks cluster-get iks1
＜中略＞
名前:                           iks1
ID:                             41679d0177fa4f92ab10262fa586956c
状態:                           normal
作成日時:                       2018-10-22T04:40:42+0000
ロケーション:                   tok04
マスター URL:                   https://c1.jp-tok.containers.cloud.ibm.com:31963
マスター・ロケーション:         Tokyo
マスター状況:                   Ready (3 days ago)
入口サブドメイン:               iks1.jp-tok.containers.appdomain.cloud
入口の秘密:                     iks1
ワーカー:                       4
ワーカー・ゾーン:               tok02, tok04, tok05
バージョン:                     1.12.5_1537
~~~

そこで、ALBの各IPアドレスを取得して、ドメインネームプロバイダーのDNSに登録します。ALBのIPアドレスは、次のコマンドで取得できます。この実行結果の３つのIPアドレスをDNSサーバーへ登録すれば良いことになります。

~~~console
$ bx ks albs --cluster iks1
OK
ALB ID                                            有効化   状況       タイプ    ALB IP           ゾーン   ビルド
private-cr41679d0177fa4f92ab10262fa586956c-alb1   false    disabled   private   -                tok04    ingress:350/ingress-auth:192
private-cr41679d0177fa4f92ab10262fa586956c-alb2   false    disabled   private   -                tok05    ingress:350/ingress-auth:192
private-cr41679d0177fa4f92ab10262fa586956c-alb3   false    disabled   private   -                tok02    ingress:350/ingress-auth:192
public-cr41679d0177fa4f92ab10262fa586956c-alb1    true     enabled    public    128.168.73.198   tok04    ingress:406/ingress-auth:301
public-cr41679d0177fa4f92ab10262fa586956c-alb2    true     enabled    public    165.192.71.230   tok05    ingress:406/ingress-auth:301
public-cr41679d0177fa4f92ab10262fa586956c-alb3    true     enabled    public    169.56.27.94     tok02    ingress:406/ingress-auth:301
~~~

DNSサーバーへの登録は、各社ドメインネームプロバイダーの管理画面などから登録しましす。そして、nslookupで次のように参照できるようになれば、準備完了です。 ひとつのドメイン名に対して、３つのアドレスが返る状態です。

~~~console
$ nslookup www.mahotakara.online
Server:         10.0.2.3
Address:        10.0.2.3#53

Non-authoritative answer:
Name:   www.mahotakara.online
Address: 128.168.73.198
Name:   www.mahotakara.online
Address: 165.192.71.230
Name:   www.mahotakara.online
Address: 169.56.27.94
~~~

上記のように安定的に３つのIPアドレスが引ける状態になるまで、数時間を要すると思いますので、その間に、他の作業を進めておきます。


## SSL/TLS証明書をSecretへ登録

IBM Cloud には、[Certfication Manager](https://cloud.ibm.com/catalog/services/certificate-manager) と呼ばれる証明書の管理のシステムがあり、無料で利用することができます。これを利用すると、有効期限が切れる前に、Slackに通知を送るなど、有効期限切れを防止するなどの管理ができます。また、ibmcloud ks の下記の[alb-cert-* サブコマンド](https://cloud.ibm.com/docs/containers?topic=containers-cs_cli_reference#cs_alb_cert_deploy)と連動して、IKSのSecretへの登録などに利用できます。

~~~
  alb-cert-deploy     IBM Cloud Certificate Manager から Ingress ALB に証明書をデプロイまたは更新します。
  alb-cert-get        クラスター内の Ingress ALB 証明書の詳細を表示します。
  alb-cert-rm         クラスターから Ingress ALB 証明書を削除します。
  alb-certs           クラスター内で使用可能な Ingress ALB 証明書をすべてリストします。
~~~

今回は、IBM Cloud Certificate Manager を利用せずに、公的認証局から取得したTLS証明書ファイルと鍵ファイルを、次のコマンドで Secret として登録して、Ingress コントローラー（ALB)からアクセスできるようにします。　公的認証局から証明書を買った場合は、有効期限が近くなると、沢山通知がきますから、更新を忘れるといったことは少ないのではないかと思います。

~~~
$ kubectl create secret tls tls-cert --cert=server.crt --key=server.key
~~~

 
## Ingressのマニフェスト作成

次のマニフェストで、カスタムドメイン名、TLS証明書を利用できるようにします。spec.tls.hostsに、ドメイン名とTLS証明書を指定して、spec.rules.hosts に転送先のサービスと対応づけを実施します。

~~~file:ingress-cd-tls.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingres-dev
  annotations:
     ingress.bluemix.net/redirect-to-https: "True"
     ingress.bluemix.net/rewrite-path: "serviceName=web-svc1 rewrite=/"
spec:
   tls:
   - hosts:
     - www.mahotakara.online
     secretName: tls-cert
   rules:
   - host: www.mahotakara.online
     http:
       paths:
       - path: /
         backend:
           serviceName: web-svc1
           servicePort: 9080
~~~


## 動作確認

このマニフェストを適用することで、各ゾーンに存在するALBへ転送するようになります。

~~~console
$ kubectl apply -f ingress-cd-tls.yml
ingress.extensions/ingres-dev configured

$ kubectl get ing
NAME         HOSTS                                    ADDRESS                                      PORTS     AGE
ingres-dev   www.mahotakara.online                    128.168.73.198,165.192.71.230,169.56.27.94   80, 443   56m
~~~

次は、curlコマンドでアクセスした場合の結果です。

~~~console
$ curl -sI http://www.mahotakara.online/
HTTP/1.1 301 Moved Permanently
Date: Thu, 21 Feb 2019 07:06:37 GMT
Content-Type: text/html
Connection: keep-alive
Location: https://www.mahotakara.online/

$ curl -sI https://www.mahotakara.online/
HTTP/1.1 200 OK
Date: Thu, 21 Feb 2019 07:07:10 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Cache-Control: max-age=604800
~~~


## ゾーン障害の時の動作考察

k8sに自動付与されるドメイン名 「クラスタ名.jp-tok.containers.appdomain.cloud」を利用している場合、
データセンターの一つ、つまり、ゾーンの一つが動作しなくなった場合、障害ゾーンのIPアドレスは自動的に削除され、応答を返せないゾーンのALBへ転送されないという機能を持っていました。つまり、IKSのDNSサーバーは、ゾーンのALBのIPアドレスの活性を監視しておいて、応答が無くなると、DNSのエントリーから自動削除していました。

しかし、今回のように、外部のDNSプロバイダーにDNS名を登録する場合、ゾーンの停止にたいして、その機能が働きません。

次の例では、ALBの一つを無効化して、擬似的な障害状態を作っていますが、nslookupは、停止したALBに対しても、アドレス解決を続けています。

~~~console
$ ibmcloud ks albs --cluster iks1
ALB ID                                            有効化   状況       タイプ    ALB IP           ゾーン   ビルド
public-cr41679d0177fa4f92ab10262fa586956c-alb1    false    disabled   public    -                tok04    ingress:406/ingress-auth:301
public-cr41679d0177fa4f92ab10262fa586956c-alb2    true     enabled    public    165.192.71.230   tok05    ingress:406/ingress-auth:301
public-cr41679d0177fa4f92ab10262fa586956c-alb3    true     enabled    public    169.56.27.94     tok02    ingress:406/ingress-auth:301


$ nslookup www.mahotakara.online
Address:  192.168.1.1

    www.mahotakara.online
Addresses:  169.56.27.94
          165.192.71.230
          128.168.73.198
~~~


## まとめ

マルチゾーン構成で、カスタムドメインを Ingress に設定して、TLS暗号通信を実施することは可能ですが、マルチゾーン構成でゾーン障害に対応するには、不十分であることが解りました。　この対策としては、IBM Cloud Internet Service を利用することになります。 次回以降で対策を確認していきます。