IBM Cloud: ROKS(Red Hat OpenShift on IBM Cloud)におけるNLB構成の確認

#1. はじめに

ROKS(Red Hat OpenShift on IBM Cloud)における、VPC Load Balancer(NLB)経由でアクセスする際のアクセス経路の確認を実施した。重要なのは、

- ROKSでService(type=Load Balancer)ではVPC Load BalancerのタイプとしてALBだけではなく、NLBも選択できる。
    - ALBとNLBの違いは[こちら](https://qiita.com/testnin2/items/e97357b875980b95f4aa)を参照。
    - 設定方法: https://cloud.ibm.com/docs/openshift?topic=openshift-vpc-lbaas#setup_vpc_nlb
- VPC LoadBalancer(NLB)は、確かに他のZoneのVSIにはトラフィックを割り振ることができない。ただし、externalTrafficPolicy=Clusterにしておけば、ROKS内のService（実態はiptables）経由で別のZoneにあるPodには接続できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/cc28aa51-7a48-804b-c953-b496636294e0.png)



#2. 環境の作成

```shell:アプリのデプロイ
$ oc new-app -i php https://github.com/nin2yasu/samplephp
$ oc scale --replicas=2 deployment/samplephp
```

```shell:samplephp-nlb.yaml
apiVersion: v1
kind: Service
metadata:
  name: samplephp-vpc-nlb-tokyo1
  annotations:
    service.kubernetes.io/ibm-load-balancer-cloud-provider-enable-features: "nlb"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-ip-type: "private"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-vpc-subnets: "02e7-cc434307-168d-4cb8-bbde-eb45839c8e59"
    service.kubernetes.io/ibm-load-balancer-cloud-provider-zone: "jp-tok-1"
spec:
  type: LoadBalancer
  selector:
    deployment: samplephp
  ports:
   - name: http
     protocol: TCP
     port: 8080
     targetPort: 8080
   - name: https
     protocol: TCP
     port: 8443
     targetPort: 8443
  externalTrafficPolicy: Cluster
```

```shell:NLBのデプロイ
$ oc apply -f samplephp-nlb.yaml
```



#3. 環境の確認

この環境はWorker Nodeが2つしかないが、それで十分動作確認できる。

```shell:WorkerNodeは2つしか存在しないが、Zoneにまたがって配置されている。
$ oc get nodes -L topology.kubernetes.io/zone
NAME        STATUS   ROLES           AGE   VERSION           ZONE
10.0.0.25   Ready    master,worker   27d   v1.20.0+9689d22   jp-tok-1
10.1.0.17   Ready    master,worker   27d   v1.20.0+9689d22   jp-tok-2
```

今回作成されたVPC LoadBalancer(NLB)は同一Zone上のWorker nodeにしか割り振りを行っていない（VSIの数が1つ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/330dd6ed-3af8-80b4-8752-6c22b899c890.png)

```shell:対象のアプリは異なるWorkerNodeにまたがって配置されている（＝Zoneにまたがって配置されている）
$ oc get pods -o wide
NAME                         READY   STATUS      RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
samplephp-1-build            0/1     Completed   0          68m   172.17.34.49   10.0.0.25   <none>           <none>
samplephp-5d89c54548-28t56   1/1     Running     0          58m   172.17.28.90   10.1.0.17   <none>           <none>
samplephp-5d89c54548-csm9n   1/1     Running     0          67m   172.17.34.4    10.0.0.25   <none>           <none>
```

```shell:Endpointにもちゃんと異なるZone上に存在するPodが登録されている。
$ oc describe endpoints samplephp-vpc-nlb-tokyo1
Name:         samplephp-vpc-nlb-tokyo1
Namespace:    syasuda1
Labels:       <none>
Annotations:  endpoints.kubernetes.io/last-change-trigger-time: 2021-10-12T00:29:43Z
Subsets:
  Addresses:          172.17.28.90,172.17.34.4
  NotReadyAddresses:  <none>
  Ports:
    Name   Port  Protocol
    ----   ----  --------
    https  8443  TCP
    http   8080  TCP

Events:  <none>
```

#4. Podを一方のZoneに片寄せしてみてテスト

deploymentに以下のnodeSelectorを設定し、Podが必ずVPC LoadBalancer(NLB)とは別のZoneに配置されるように構成。

```yaml
      nodeSelector:
        topology.kubernetes.io/zone: jp-tok-2
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/c8cedef7-5d7e-0094-c111-b41a8635c682.png)



```
$ oc get pods -o wide
NAME                         READY   STATUS      RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
samplephp-1-build            0/1     Completed   0          84m   172.17.34.49   10.0.0.25   <none>           <none>
samplephp-77f8845999-w9cc7   1/1     Running     0          18s   172.17.28.67   10.1.0.17   <none>           <none>
samplephp-77f8845999-zjr28   1/1     Running     0          15s   172.17.28.73   10.1.0.17   <none>           <none>
```

これでも、Direct Link越しにちゃんとアクセスできることを確認(Power Systems Virtual Server(AIX)から接続確認）。

```
bash-4.3# oslevel -s
7200-04-01-1939

bash-4.3# curl http://eec704cd-jp-tok.lb.appdomain.cloud:8080
Host: eec704cd-jp-tok.lb.appdomain.cloud:8080 <br>
User-Agent: curl/7.52.1 <br>
Accept: */* <br>
```

ただし、当然ながら`externalTrafficPolicy=Local`の場合は、接続対象のPodがないため接続に失敗する

```
$ oc get svc samplephp-vpc-nlb-tokyo1 -o jsonpath={.spec.externalTrafficPolicy}
Local

bash-4.3# oslevel -s
7200-04-01-1939

bash-4.3# curl http://eec704cd-jp-tok.lb.appdomain.cloud:8080
（無応答）
```