IKS-LB2.0 と CIS-GLB 併用のマルチゾーン・クラスタの検証

IKS (IBM Cloud Kubernetes Service) の Load Balancer と CIS (IBM Cloud Internet Service)の Global Load Balancer との組み合わせで、マルチゾーン環境のカスタムドメイン使用について、構築を確認していきます。

IKSでは、ここで取り上げる以外にも様々な選択肢があります。これらからの選択については、[IKS MZ構成時のIngressとLoadBalancer+GLBの方式選択の考察](https://qiita.com/MahoTakara/items/832febb0273e54fb9333) に書いておきましたので、参照をお願いします。　


## 前提条件

この検証を開始するにあたり、必要な条件を、以下にリストしました。簡単ですが、準備を整える方法についてメモを残しておきます。

* IBM Cloudのアカウントがあること
* カスタムドメインを持ち、そのDNSサービスプロバイダーは、ドメイン管理を委任できること
* CISのサービスを申し込んでいること
* IKSクラスタを作成できること バージョン 1.12以上
* IBM Cloud CLI をパソコンにインストールしていること


#### IBM Cloudのアカウント

本件ではIKSの標準クラスタを作成する必要がありますから、フリーアカウントではなく、クレジットカード、または、契約書によるアカウントを持っている必要があります。　[クレジットカードでアカウント作成](https://cloud.ibm.com/login)から申し込みができます。契約書ベースのアカウント作成は、日本アイ・ビー・エムの担当営業に連絡頂ければと思います。


#### カスタムドメイン

今回の検証では、[IBM Cloud DNSサービス](https://console.bluemix.net/catalog/infrastructure/domain_registration)からドメイン名 takara9.com を取得しました。 このサービスでは、次の[ドメイン管理画面](https://control.bluemix.net/services/domains) から　CISのネームサーバーを登録、すなわち、ドメイン管理の委任の設定ができます。


#### CISの利用申し込み

この [Cloud Internet Service](https://cloud.ibm.com/login) は、IBM Cloudのアカウントがあることで、使用を開始できます。[CISの詳細なドキュメント](https://cloud.ibm.com/docs/infrastructure/cis?topic=cis-about-ibm-cloud-internet-services-cis-&locale=ja#about-ibm-cloud-internet-services) および、Qiitaに[CIS関連記事](https://qiita.com/y_tama/items/a3c409aa58933c5bbbe4) が登録されていますので機能の全容や、使い方は簡単に把握できると思います。

今回は沢山ある機能のなかから、Global Load Balancer （GLB) の機能を使用します。


#### IBM Cloud CLIのインストール

[IBM Cloud CLI の概説](https://console.bluemix.net/docs/cli/index.html#overview) に、インストールや設定方法の解説があります。　インストールしてログインしておくと、すぐに開始できます。



## マルチゾーンクラスタの作成

IBM Cloud の東京リージョンにある３か所のゾーン TOK02,TOK04,TOK05 を利用するマルチゾーンの IKS クラスタを作成します。　IBM Cloud のウェブ画面のカタログから、[Kubernetes Service](https://console.bluemix.net/containers-kubernetes/catalog/cluster) を選択することで、IKSのマルチゾーンのクラスタを作成できます。

ロケーションに「AP北」を選択して、可用性で「複数ゾーン」を選択、tok02,tok04,tok05のチェックボックスを設定することで、東京／埼玉／神奈川の３箇所の独立したデータセンター（ゾーン）にワーカーノードを配置できます。　

ワーカー・ノード数のデフォルト値が、３になっているので、各ゾーンに３個づつ作られることがデフォルトなので、値段をみてビックリするかもしれませんが、1に減らすことで、料金は下がります。

IKSクラスタをオーダーして、通常は30分程度で、稼働を開始します。


### 必要な情報の収集

IKSクラスタを作成すると、自動的に、ゾーンのVLAN、Ingress のドメイン名、Ingress用ALBのIPアドレス、ゾーンのポータブル・サブネットが自動で取得されます。 これらの情報は、つぎのような表にまとめておくと良いでしょう。

| ゾーン |VLAN-ID | ポータブルサブネット　| ALBｰIPアドレス | LBｰIPアドレス候補 |
|:------|:-------|:---------------------|:------------|:-----------:|
|tok02  |978113  | 169.56.27.80/28　　  |169.56.27.94 |      -      |
|tok04  |2445697 | 128.168.73.192/29    |128.168.73.198 |   -        |
|tok05  |2445837 | 165.192.71.224/29    |165.192.71.230 |    -       |


情報を所得するためのコマンドを列挙しておきます。

* bx ks cluster-get CLUSTER_NAME : IKSクラスタ用のGLBドメイン名、ゾーンなどのリスト
* bx ks vlans --zone ZONE_NAME : VLANーIDのリストが得られ、Public と Private がリストされる
* bx ks albs --cluster CLUSTER_NAME : ALBのIPアドレスのリスト
* bx ks subnets |grep VLAN-ID : VLAN-ID にアサインされたサブネット

各ゾーンのロードバランサーのIPアドレスは、マニフェストに指定しなければ自動取得されますので、アサインはシステムに任せて、アサインされたIPアドレスを前述のテーブルで管理するのも一つの方法です。マニフェストにロードバランサーのIPアドレスを記述して、自ら決める方法も取れます。

マニフェストに設定可能なホストアドレスを求めるには、ipcalcコマンドが便利です。次は、tok04のケースでホストアドレスを求めた結果です。　この出力から、HostMax: のIPアドレスは、ALBのIPアドレスに割り当てられていることが読み取れます。

~~~
$ bx ks subnets |grep 2445697
1871255   128.168.73.192/29   128.168.73.193   2445697   public    41679d0177fa4f92ab10262fa586956c

$ ipcalc 128.168.73.192/29
Address:   128.168.73.192       10000000.10101000.01001001.11000 000
Netmask:   255.255.255.248 = 29 11111111.11111111.11111111.11111 000
Wildcard:  0.0.0.7              00000000.00000000.00000000.00000 111
=>
Network:   128.168.73.192/29    10000000.10101000.01001001.11000 000
HostMin:   128.168.73.193       10000000.10101000.01001001.11000 001
HostMax:   128.168.73.198       10000000.10101000.01001001.11000 110
Broadcast: 128.168.73.199       10000000.10101000.01001001.11000 111
Hosts/Net: 6                     Class B
~~~


## LoadBalancer 2.0 の利用申請

[LoadBalancer 2.0 を使用するためのサポートへの申し込み方法](https://cloud.ibm.com/docs/containers?topic=containers-loadbalancer#ipvs_provision)が案内されています。

ZONE、VLAN-ID、Subnetsは、前述で整理したものに置き換えて、提出します。　それから、一番最後の部分で、リファレンスのチケット番号を添えています。　これは、この必要性を確認して対策を決めた記録です。一般のユーザーが、このチケットを参照することはできませんが、このコメントにより、サポート担当者は実施するべきことを、迅速に正確に理解することができるので、必ず加えておきます。

~~~
Support Type: Technical
Category: infrastructure
Subject: Public Network Question
Body:

Please set up the network to allow capacity aggregation on the public VLANs associated with my account.

IKS Cluster Name: IKS_CLUSTER_NAME
ZONE    VLAN-ID             Subnet
tok02   VLAN_ID_for_tok02   Portable_Subnet/mask_for_tok02
tok04   VLAN_ID_for_tok04   Portable_Subnet/mask_for_tok02
tok05   VLAN_ID_for_tok05   Portable_Subnet/mask_for_tok02

The reference ticket for this request is: https://control.softlayer.com/support/tickets/63859145」
~~~

ポストが完了して、しばらくすると、設定が完了したことが通知されます。設定情報の伝搬に少し時間が必要ですから、安定までに数時間必要なこともあるようです。筆者で安定したと思えるまでに、６時間程度かかりました。



## カスタムドメインの作成

今回は、[IBM Cloud のドメイン・ネーム・サービス](https://console.bluemix.net/catalog/infrastructure/domain_registration)から、ドメイン名の注文しました。.comドメインで 年間 $9.94 ですから、以外と国内業者よりも、お得かもしてませんね。

欲しいドメイン名をインプットして、「Check Availability」をクリックして、他で使われていないか確認できます。未使用であれば、「Continue」をクリックして先へ進めます。

CISのGLBを利用するにあたり、ドメイン管理の委任、すなわち、NSレコードのドメインネームサーバーを IBM Cloud Internet Seriveのネームサーバーに、置き換える必要があります。そのことを承諾いただけるプロバイダーを選んでおく必要があります。　もちろん、自営のDNSサーバーがある場合は、ドメイン管理者と事前の合意が必要ですね。


## CISの申し込み

ドメインが取得して、ドメイン管理の委任の合意ができれば、[Cloud Internet Service](https://console.bluemix.net/catalog/services/internet-services)の利用を開始していきます。お試し用のフリープランがあますから、無料で試すことができます。標準プランで１ドメインあたり、月額 $275で、DDoS対策、コンテンツキャッシュ、WAF、GLBなどサービスが利用できますから、お得なサービスなんだと思います。

#### ドメイン管理の委任方法

CISの利用を開始すると、移管するドメイン名の登録の画面が表示されます。　これらの登録方法は、Qiita [IBM Cloud Internet Services (CIS)を使ってみた（オーダー・初期設定）](https://qiita.com/y_tama/items/9151b4c981abbb65c53d) 解りやすい解説がありますので、参考にされると良いです。

IBM Cloud のドメイン・ネーム・サービスでは、NSレコードの変更画面が用意されているので、こちらを利用することで、ドメイン管理の委任作業が完了します。


## LoadBalancer 2.0 のマニフェスト作成

LoadBalancer 2.0 の[設定方法](https://cloud.ibm.com/docs/containers?topic=containers-loadbalancer#ipvs_multi_zone_config)の解説を参考に進めると良いでしょう。筆者が利用した LB 2.0 のマニフェストを以下に挙げておきます。

これは、Kubernetesのサービス・オブブジェクトで、アノテーションにLB2.0への命令をセットしてデプロイします。loadBalancerIPを省略すると、ポータブルサブネットの範囲から自動取得します。しかし、CISに設定も必要なので、自己管理することにしましたが、ダブって失敗することもあるので、お任せでも良いと思います。

各ゾーンごとに、一つサービスを作成します。今回は tok02, tok04, tok05 の三か所にワーカーノードを配置したので、３本のYAMLを連結してデプロイしました。

LBには、セッション・パーシステンス または、セッション・アフィニティの機能はありません。一方、GLBは、これらの機能を利用して、同じサーバーにリクエストを転送する機能があります。しかし、LB2.0のスケジューリングには、ソース・ハッシュ sh という、送信元のIPアドレスによって、一定のポッドに送信する機能がありますので、必要におうじて、適用を検討すると良いでしょう。[3]


~~~file:lb2-mz.yml
apiVersion: v1
kind: Service
metadata:
  name: lb2-tok02
  annotations:
    service.kubernetes.io/ibm-load-balancer-cloud-provider-ip-type: public
    service.kubernetes.io/ibm-load-balancer-cloud-provider-zone: "tok02"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-vlan: "978113"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-enable-features: "ipvs"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-scheduler: "rr"
spec:
   type: LoadBalancer
   selector:
     app: web-lb2
   ports:
   - protocol: TCP
     port: 80
   loadBalancerIP: 169.56.27.93
   externalTrafficPolicy: Local
---
apiVersion: v1
kind: Service
metadata:
  name: lb2-tok04
  annotations:
    service.kubernetes.io/ibm-load-balancer-cloud-provider-ip-type: public
    service.kubernetes.io/ibm-load-balancer-cloud-provider-zone: "tok04"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-vlan: "2445697"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-enable-features: "ipvs"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-scheduler: "rr"
spec:
   type: LoadBalancer
   selector:
     app: web-lb2
   ports:
   - protocol: TCP
     port: 80
   loadBalancerIP: 128.168.73.196
   externalTrafficPolicy: Local
---
apiVersion: v1
kind: Service
metadata:
  name: lb2-tok05
  annotations:
    service.kubernetes.io/ibm-load-balancer-cloud-provider-ip-type: public
    service.kubernetes.io/ibm-load-balancer-cloud-provider-zone: "tok05"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-vlan: "2445837"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-enable-features: "ipvs"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-scheduler: "rr"
spec:
   type: LoadBalancer
   selector:
     app: web-lb2
   ports:
   - protocol: TCP
     port: 80
   loadBalancerIP: 165.192.71.226
   externalTrafficPolicy: Local
~~~

## GLBの設定

ダッシュボード -> サービス -> Internet Service-XX の順にメニューを進め、左サイドのメニューの信頼性の下のグローバル・ロード・バランサーを選択します。そして、画面のガイドに従って、GLBのサブドメイン名、起点プールを設定します。

GLBの名前が、そのまま、GLBでアクセスできるサブドメインになります。そして、起点プールのIKS-LBにリクエストが分配されるようになります。

GLBは、DNSを利用するので、nslookupの応答が安定するまでに、やはり少し時間を必要とします。


## 動作検証

GLBのDNS名を確認します。GLBの起点プールに設定したIPアドレスは、nslookupを利用したIPアドレス解決で取得できます。ヘルスチェックの間隔は60秒で、応答がなくなると、IPアドレスの提示が無くなります。

~~~
$ nslookup lb2.takara9.com
Server:         10.0.2.3
Address:        10.0.2.3#53

Non-authoritative answer:
Name:   lb2.takara9.com
Address: 165.192.71.226
Name:   lb2.takara9.com
Address: 169.56.27.93
Name:   lb2.takara9.com
Address: 128.168.73.196
~~~

165.192.71.226　lb2-tok05 のシャットダウンして、DNSのアドレス解決を確認します。
60秒以上経過して、確認すると、lb2-tok05 が消えていることが確認できました。

~~~
$ bx sl vs power-off 71618325
This will power off virtual server instance: 71618325. Continue?> yes
OK

<120秒待機>

$ nslookup lb2.takara9.com
Server:         10.0.2.3
Address:        10.0.2.3#53

Non-authoritative answer:
Name:   lb2.takara9.com
Address: 169.56.27.93
Name:   lb2.takara9.com
Address: 128.168.73.19
~~~

CISウェブ画面の起点プールのスタータスの更新間隔は、60秒よりも長く、DNSのIPアドレスからエントリーが落ちた後でも、しばらくの間、グリーンの状態になっていました。混乱しないように、緩慢なステータス変更であることを覚えておかなければなりませんね。


次に繰り返しGLBのDNSをアクセスして、負荷分散の動作を確認します。REMOTE_ADDは、クライアントのIPアドレスが表示されており、IPIPでカプセル化されたパケットがノードに振分けられた後、DSRで応答が返されていることが読み取れます。

~~~
$ while true; do date;curl --connect-timeout 1 http://lb2.takara9.com ;echo; sleep 5; done
Mon Feb 25 06:14:10 UTC 2019
Hostname: web-lb2-6fb896b566-62r6r<br>
1th time access.
<br>
REMOTE_ADDR = 126.77.***.60<br>

Mon Feb 25 06:14:15 UTC 2019
Hostname: web-lb2-6fb896b566-t5xk5<br>
1th time access.
<br>
REMOTE_ADDR = 126.77.***.60<br>

Mon Feb 25 06:14:20 UTC 2019
Hostname: web-lb2-6fb896b566-jhpnx<br>
1th time access.
<br>
REMOTE_ADDR = 126.77.***.60<br>
~~~

それぞれのゾーンのノード数の増減にたいしても、LBのIPアドレスは維持されますから、GLBの起点プールを変更する必要はありません。


## まとめ

IKS-LB2.0 + CIS-GLB の組み合わせによる、マルチゾーンの可用性についての動作検証ができました。
ゾーンの一つが障害になっても、DNSのIPアドレス解決から障害ゾーンが落とされ、ポッドの応答はを継続できることになります。

もちろん、データベースの障害に対する考慮も必要ですが、この検証からアプリケーションサーバーのレベルではサービスが維持できることになります。



## 参考資料

[1] IKS MZ構成時のIngressとLoadBalancer+GLBの方式選択の考察, https://qiita.com/MahoTakara/items/832febb0273e54fb9333
[2] IBM Cloud Internet Services (CIS)を使ってみた（Global Load Balancer）, https://qiita.com/y_tama/items/7e1ddd5dc94990835311
[3] サポートされるスケジューリング・アルゴリズム､ https://cloud.ibm.com/docs/containers?topic=containers-loadbalancer#scheduling_supported