RedHat OpenShift on IBM Cloud VPC gen2マルチゾーンクラスターを作成する

IBM CloudのVPC gen2環境にIBM Cloud CLIを利用してマルチゾーンクラスターを作成する手順メモです。

## 事前準備
事前に以下の準備が必要になりますが、この記事では割愛します。

1) IBM Cloud CLIおよびVPC gen2プラグインの導入
2) VPCのオーダーおよびサブネットの作成
3) OpenShiftの構成情報バックアップ用のIBM Cloud Object Storage(ICOS)インスタンスの準備

## オーダー
GUIからオーダーする場合はマルチゾーンの指定ができますが、CLIを利用する場合は一度単一のゾーンに作成して、その後ワーカープールに別ゾーンを追加するというステップが必要になります。  

この例ではjp-tok-1にまずクラスターを作成します。VPC ID、Subnet ID、オブジェクトストレージのCRNが必要となりますので、控えます。

```bash
## VPC IDの確認
$ ibmcloud is vpcs
## Subnet IDの確認
$ ibmcloud is subnets
## オブジェクトストレージのCRN
$ ibmcloud resource service-instance <オブジェクトストレージ名>
```
   
上記で控えたIDを利用してオーダーを行います。

```bash
$ ibmcloud oc cluster create vpc-gen2 --name roks-test --zone jp-tok-1 --version 4.5_openshift --flavor bx2.4x16 --workers 2 --vpc-id <VPC ID> --subnet-id <Subnet ID> --cos-instance <オブジェクトストレージのCRN>
クラスターを作成中...
OK
ID xxxxxxxxxxxx で作成されたクラスター
```

クラスターのステータスがReadyになってから、ゾーンの追加を行います。今回はjp-tok-2を追加します。

```bash
$ ibmcloud oc zone add vpc-gen2 --zone jp-tok-2 --subnet-id <追加したいjp-tok-2のSubnet ID> --cluster roks-test --worker-pool <ワーカープール名>
OK
```

しばらくしてからワーカープールの状態を確認すると、ノードの数が当初の2台から倍の4台になっています。

```bash
$ ibmcloud oc worker-pool ls --cluster roks-test
OK
名前      ID                             フレーバー   ワーカー   
default   xxxxxxxxxxxxxxxxxxxxxxxxxx   bx2.4x16     4   
```

## セキュリティーグループの設定

クラスターをオーダーした時点で、ワーカーノード用のSG(kube-から始まる名前のもの)が自動作成されています。

```bash
$ ibmcloud is sgs
ID                                          名前                        ルール   ネットワーク・インターフェース   VPC            リソース・グループ   
rxxxxxxxxxxxxxxx   kube-xxxxxxxxxxxxxx   4        4                                <VPC名>   <リソースグループ名>   
:
```

先程の手順で追加したワーカーノードには自動的にこのSGがアタッチされるようです。Classicのクラスターでは手動でアタッチする必要がありましたが、進化していますね。
注意が必要なのが、この自動的に作成されるSGだけでなく、VPCのデフォルトSGもアタッチされます。そして、デフォルトSGにもOpenShift向けのルールを追加する必要があります。以下を実行します。

```bash
$ ibmcloud is security-group-rule-add <VPCのデフォルトSGのID> inbound tcp --port-min 30000 --port-max 32767
$ ibmcloud is security-group-rule-add <VPCのデフォルトSGのID> inbound udp --port-min 30000 --port-max 32767
```


## Ingress Controllerの再作成

イケてないのが、ゾーンを追加しても、そのままではIngress Controllerが当初オーダーした際に指定したゾーン(今回の例ではjp-tok-1)のみにデプロイされた状態となっています。手動で再作成して、DNSレコードを更新する必要があります。
ocコマンドでクラスターの操作を行えるようにした上で、以下を実行します。

```bash
## Ingress Controllerの削除
$ oc delete ingresscontroller default -n openshift-ingress-operator
ingresscontroller.operator.openshift.io "default" deleted

## 暫く待つと自動的に再作成される
$ oc get ingresscontroller -n openshift-ingress-operator
NAME      AGE
default   6s
```

バックグラウンドで、VPC LoadBalancerが再作成されています(kube-yyyyyyy)。サブネット欄が、tok1とtok2に変わっていることがわかります。

```bash
$ ibmcloud is load-balancers
ID                                          名前                                                         ファミリー    サブネット                                             パブリックです   プロビジョン状況   作動状況   リソース・グループ   
rxxxxxxxxxxxxxxxxxxx   kube-xxxxxxxx   Application   subnet-tok1               true             active             online     <RG名>   
ryyyyyyyyyyyyyyyyyyy   kube-yyyyyyyy   Application   subnet-tok2, subnet-tok1   true             create_pending     offline    <RG名>   
```

次に、NLB DNSのレコードをこの新しいVPC LoadBlancerのものに変更します。

```bash
## RouterのSVCの外部IP欄を確認
$ oc get svc -n openshift-ingress
NAME                      TYPE           CLUSTER-IP      EXTERNAL-IP                          PORT(S)                      AGE
router-default            LoadBalancer   172.21.98.170   xxxxxxxx-jp-tok.lb.appdomain.cloud   80:31989/TCP,443:31857/TCP   7m13s
router-internal-default   ClusterIP      172.21.82.113   <none>                               80/TCP,443/TCP,1936/TCP      7m13s

## クラスターのIngressサブドメインを確認
$ LANG=C ibmcloud oc cluster get -c roks-test | grep 'Ingress Subdomain'
Ingress Subdomain:              roks-test-xxxxxxxxxxxxxxxxx-0000.jp-tok.containers.appdomain.cloud  

## レコード更新
$ ibmcloud oc nlb-dns replace --cluster roks-test --nlb-subdomain roks-test-xxxxxxxxxxxxxxxxxxx-0000.jp-tok.containers.appdomain.cloud --lb-host xxxxxxx-jp-tok.lb.appdomain.cloud
NLB DNS を更新中...
OK
```

Ingress Contorollerを再作成すると、Routerが持つTLS証明書が、IBMが提供する証明書ではなく、OpenShiftが自動生成する自己証明書に変わってしまっています。この状態でOpenShiftのWebコンソール等にアクセスすると警告が出ることと思います。
以下の記事が参考になります。

https://qiita.com/teruq/items/1df488a2edccc4da1b99

以下のように、Ingress Contorollerにデフォルト証明書の項目を追加してあげると解消します。

```bash
$ oc patch ingresscontroller/default -n openshift-ingress-operator --type merge -p '{"spec":{"defaultCertificate":{"name":"roks-test-xxxxxxxxxxxxxxxxxxxxxxxxxx-0000"}}}'

```