本記事はvExperts Advent Calendar 2021の12月18日分の投稿です。
はじめに
NSX-Tで構成されるvSphere環境のTanzu Kubernetes GridのワークロードクラスターではAntrea CNIを利用して、Podに対してルーティング可能なIPアドレスを構成し、NATを利用せずにPodにアクセスする(Routable Pod)ことが可能になります。Tanzu Kubernetes Grid環境、vSphere with Tanzu環境ともRoutable Podを利用することが可能です。以下のドキュメント設定方法が記載されています。
- Tanzu Kubernetes Grid
- vSphere with Tanzu
Tanzu Kubernetes Gridで構成してみる
マニュアルの「Deploy Pods with Routable, No-NAT IP Addresses (NSX-T)」を参考にTanzu Kubernetes Grid環境のワークロードクラスターでRoutable Podを利用してみます。
NSX-Tの要件
NSX-T側では予めワークロードクラスターを接続するネットワーク(NSX-Tのセグメント)を作成し、Tier1 Gateway配下にぶら下げておく必要があります。
- Tier0 Gatewayを既存ネットワークに対して接続
- Tanzu Kubernetes Clusterを接続するTier1 Gatewayの作成
- Tier0 Gatewayに接続
- ルートアドバタイズとして「すべてのスタティックルート」と「接続されている全てのセグメントおよびサービスポート」を有効化する
- Tanzu Kubernetes Gridを接続するセグメントの作成
- ゲートウェイアドレスの指定
- 上記で作成したTier1 Gatewayに接続
- Tanzu Kubernernets Clusterのノードが利用するDHCPサーバーの構成
ネットワーク構成
Routable Podを有効化すると、NSX-TのTier1 Gateway配下にワークロードクラスターが作成され、Tier1 GatewayにPod CIDR向けのStatic Routeが追加されます。T1 Gatewayに追加されたStatic Routeは上位のTier0 Gatewayにアドバタイズされ、外部のネットワークからPodのIPアドレスに対して直接通信することが可能になります。
マネジメントクラスターの作成
今回はロードバランサーとしてNSX-ALBを利用するため、以下のようにAVI_
パラメータを指定してマネジメントクラスターを作成します。マネジメントクラスターはRoutable Podを利用しないため、CLUSTER_CIDR
として100.96.0.0/11
を指定しています。
AVI_CA_DATA_B64: XXXXXXXX...
AVI_CLOUD_NAME: Default-Cloud
AVI_CONTROL_PLANE_HA_PROVIDER: "false"
AVI_CONTROLLER: 192.168.30.250
AVI_DATA_NETWORK: tanzu-overlay
AVI_DATA_NETWORK_CIDR: 172.16.128.0/21
AVI_ENABLE: "true"
AVI_LABELS: ""
AVI_PASSWORD: <encoded:XXXXXXXXXXXX>
AVI_SERVICE_ENGINE_GROUP: Default-Group
AVI_USERNAME: admin
CLUSTER_CIDR: 100.96.0.0/11
CLUSTER_NAME: mgmt
CLUSTER_PLAN: dev
ENABLE_CEIP_PARTICIPATION: "true"
ENABLE_MHC: "true"
IDENTITY_MANAGEMENT_TYPE: none
INFRASTRUCTURE_PROVIDER: vsphere
SERVICE_CIDR: 100.64.0.0/13
TKG_HTTP_PROXY_ENABLED: "false"
VSPHERE_CONTROL_PLANE_ENDPOINT: 172.16.135.240
VSPHERE_DATACENTER: /DC
VSPHERE_DATASTORE: /DC/datastore/NFS
VSPHERE_FOLDER: /DC/vm
VSPHERE_NETWORK: tanzu-overlay
VSPHERE_PASSWORD: <encoded:XXXXXXXXXXXX>
VSPHERE_RESOURCE_POOL: /DC/host/CL/Resources/Tanzu
VSPHERE_SERVER: 10.44.55.100
VSPHERE_SSH_AUTHORIZED_KEY: ssh-rsa AAAAB...
VSPHERE_INSECURE: true
VSPHERE_USERNAME: administrator@vsphere.local
以下のコマンドでマネジメントクラスターを作成します。
$ tanzu management-cluster create -f management.yaml
ワークロードクラスターの作成
マネジメントクラスターの作成が完了したら、マネジメントクラスターを利用してRoutable Podが利用可能なワークロードクラスターを作成します。ワークロードクラスターの作成には以下の構成ファイルを利用します。
CLUSTER_NAME: cl1
CLUSTER_PLAN: dev
INFRASTRUCTURE_PROVIDER: vsphere
ENABLE_CEIP_PARTICIPATION: true
ENABLE_AUDIT_LOGGING: true
SERVICE_CIDR: 100.64.0.0/13
AVI_CONTROL_PLANE_HA_PROVIDER: false
DEPLOY_TKG_ON_VSPHERE7: true
ENABLE_TKGS_ON_VSPHERE7: false
VSPHERE_CONTROL_PLANE_ENDPOINT: 172.16.135.250
VSPHERE_DATACENTER: /DC
VSPHERE_DATASTORE: /DC/datastore/NFS
VSPHERE_FOLDER: /DC/vm
VSPHERE_NETWORK: tanzu-overlay
VSPHERE_PASSWORD: <encoded:xxxxxxxxxxxx>
VSPHERE_RESOURCE_POOL: /DC/host/CL/Resources/Tanzu
VSPHERE_SERVER: 10.44.55.100
VSPHERE_SSH_AUTHORIZED_KEY: ssh-rsa AAAA...
VSPHERE_INSECURE: true
VSPHERE_USERNAME: administrator@vsphere.local
VSPHERE_STORAGE_POLICY_ID: "tkg"
CONTROLPLANE_SIZE: large
WORKER_SIZE: large
WORKER_MACHINE_COUNT: 2
OS_NAME: "photon"
ENABLE_MHC: true
MHC_UNKNOWN_STATUS_TIMEOUT: 5m
MHC_FALSE_STATUS_TIMEOUT: 12m
CLUSTER_CIDR: 172.16.136.0/21
NSXT_POD_ROUTING_ENABLED: "true"
NSXT_MANAGER_HOST: 10.44.55.101
NSXT_ROUTER_PATH: /infra/tier-1s/tanzu-cl1
NSXT_USERNAME: admin
NSXT_PASSWORD: NSXTPASSWORD
NSXT_ALLOW_UNVERIFIED_SSL: "true"
ポイントは、NSXT_
パラメータの指定とCLUSTER_CIDR
の指定です。CLUSTER_CIDR
には/24
以上のCIDRを指定します。作成するクラスターの各ノードにはCLUSTER_CIDR
から/24
単位でpodCIDRが割り当てられます。作成するノード数に注意してCLUSTER_CIDR
を指定する必要があります。
以下のコマンドでマネジメントクラスターを作成します。
$ tanzu cluster create cl1 -f clsuter01.yaml
Podの作成と動作確認
作成されたクラスターに接続して確認するとノードのIPアドレスはDHCPから払い出されています。
$ tanzu cluster kubeconfig get cl1 --admin
$ kubectl config use-context cl1-admin@cl1
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
cl1-control-plane-nh9n7 Ready control-plane,master 20m v1.21.2+vmware.1 172.16.128.63 172.16.128.63 VMware Photon OS/Linux 4.19.198-1.ph3 containerd://1.4.6
cl1-md-0-5789bbcb76-hbnqz Ready <none> 17m v1.21.2+vmware.1 172.16.128.126 172.16.128.126 VMware Photon OS/Linux 4.19.198-1.ph3 containerd://1.4.6
cl1-md-0-5789bbcb76-vvrjv Ready <none> 14m v1.21.2+vmware.1 172.16.128.35 172.16.128.35 VMware Photon OS/Linux 4.19.198-1.ph3 containerd://1.4.6
各ノードのpodCIDRを確認すると、クラスター作成時に指定したCLUSTER_CIDR: 172.16.136.0/21
から各ノードに対して/24
単位で割り当てられています。
$ kubectl get node -o=jsonpath='{range .items[*]}{.spec.podCIDR}{"\n"}{end}'
172.16.136.0/24
172.16.137.0/24
172.16.138.0/24
T1 GatewayのStatic Routeを確認すると、各podCIDRのNextHopとしてワークロードクラスターのノードが追加されています。複数のワークロードクラスターを構成する場合、各ワークロードクラスターのCLUSTER_CIDR
として重複しないアドレス範囲を指定する必要があります。以下の例はワークロードクラスターとしてcl1とcl2を作成し、それぞれのCLUSTER_CIDR
として172.16.136.0/21
と172.16.144.0/21
を割り当てた場合の状態です。
Podを作成し、確認すると各PodのIPアドレスはpodCIDRから払い出されています。
$ kubectl create deploy nginx --image=nginxdemos/hello:plain-text
$ kubectl scale deploy nginx --replicas=4
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6bbf47444b-9p4lx 1/1 Running 0 24s 172.16.138.5 cl1-md-0-5789bbcb76-vvrjv <none> <none>
nginx-6bbf47444b-j2wsf 1/1 Running 0 20s 172.16.137.9 cl1-md-0-5789bbcb76-hbnqz <none> <none>
nginx-6bbf47444b-ws4z7 1/1 Running 0 20s 172.16.138.6 cl1-md-0-5789bbcb76-vvrjv <none> <none>
nginx-6bbf47444b-x5mkc 1/1 Running 0 20s 172.16.137.10 cl1-md-0-5789bbcb76-hbnqz <none> <none>
各PodのIPアドレスに直接curlを実行すると、Podに対してアクセスすることができました。
$ for i in $(kubectl get pod -o=jsonpath='{.items[*].status.podIP}'); do curl -s $i; done | grep 'Server address'
Server address: 172.16.139.5:80
Server address: 172.16.137.9:80
Server address: 172.16.139.6:80
Server address: 172.16.137.10:80
Antrea CNIの設定確認
ワークロードクラスターのantreaの設定を確認してみます。kube-systemネームスペースにConfigMapとしてantrea-configが作成されています。内容を確認すると、antrea-agent.conf
でtrafficEncapMode: noEncap
、noSNAT: true
が指定されています。
$ kubectl get configmap -n kube-system antrea-config-ctb8mftc58
NAME DATA AGE
antrea-config-ctb8mftc58 3 73m
$ kubectl get configmap antrea-config-ctb8mftc58 -oyaml
apiVersion: v1
data:
antrea-agent.conf: |
featureGates:
AntreaProxy: true
EndpointSlice: false
Traceflow: true
NodePortLocal: false
AntreaPolicy: true
FlowExporter: false
NetworkPolicyStats: false
trafficEncapMode: noEncap
noSNAT: true
LoadBalancerの利用
LoadBalancer Serviceを作成し、NSX-ALBにVirtual Serviceが構成されてアクセスできることを確認します。
$ kubectl expose deploy nginx --port=80 --type=LoadBalancer
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 5h15m
nginx LoadBalancer 100.69.231.126 172.16.129.2 80:30858/TCP 15s
$ while true; do curl -s 172.16.129.2|grep address; sleep 1; done
Server address: 172.16.138.6:80
Server address: 172.16.137.9:80
Server address: 172.16.138.5:80
Server address: 172.16.137.9:80
Server address: 172.16.137.10:80
NSX-ALB Controllerを確認すると、Service用のVirtual Serivceの負荷分散対象はワークロードクラスターのNodePortが構成されていました。AKO自体はRoutable Podを負荷分散対象として利用することが可能ですが、TKGのオプションとして設定する方法を見つけることができませんでした。
ノードの追加・削除
TKGではクラスターのノードを簡単にスケールアウト・スケールインすることが可能です。ノードの追加と削除の際に、T1 GatewayのStatic Routeが追加・削除される様子を確認してみました。Static Routeの追加削除は、各ワークロードクラスターのvsphere-cloud-controller-manager
が行っており、以下のログが出力されていました。なお、クラスター削除時は各ノードのStatic Routeは削除されないため手動でStatic Routeエントリを削除する必要があります。
- ノード追加時
I1216 05:40:06.080046 1 route_controller.go:193] Creating route for node cl1-md-0-5789bbcb76-vvrjv 172.16.139.0/24 with hint 1455b87f-8fbe-4cfd-b43c-fdfb822acfc7, throttled 564ns
I1216 05:40:10.107407 1 route_controller.go:213] Created route for node cl1-md-0-5789bbcb76-vvrjv 172.16.139.0/24 with hint 1455b87f-8fbe-4cfd-b43c-fdfb822acfc7 after 4.027359885s
I1216 05:40:10.107480 1 route_controller.go:303] Patching node status cl1-md-0-5789bbcb76-vvrjv with true previous condition was:nil
hintとして表示されているIDはNSX上に作成されるStatic RouteリソースのIDのPrefixとして利用されるため、IDにより追加されたリソースを検索することが可能です。
- ノード削除時
ノードの削除は古いものが優先して削除されるようです。
I1216 05:44:46.046675 1 route_controller.go:246] Deleting route a57a555e-e4eb-49ad-af74-e11a7d7a8ad8_172.16.138.0_24 172.16.138.0/24
I1216 05:44:46.485056 1 route_controller.go:250] Deleted route a57a555e-e4eb-49ad-af74-e11a7d7a8ad8_172.16.138.0_24 172.16.138.0/24 after 438.418613ms
vSpehre with Tanzuで構成してみる
vSphere with Tanzu環境では、Supervisor Cluster有効時にNSX-T側の構成が完了しているため、TKGと比べるとシンプルにRoutable Podクラスターを構成することができます。ネームスペースのオプションで「クラスターネットワーク設定のオーバーライド」を有効にし、NATモードを無効化し、「名前空間ネットワーク」と「名前空間サブネットプリフィックス」を指定します。「名前空間ネットワーク」はワークロードクラスターとそのPod CIDRとして利用されるネットワークとして利用されます。「名前空間サブネットプリフィックス」はワークロードクラスターのノードに割り当てるIPアドレスのプリフィックスとして利用されますが、各ノードのPod CIDRはTKGと同じように/24で割り当てられます。
以下のようなマニフェストを利用してワークロードクラスターを作成することで、Routable Podを利用することが可能になります。
apiVersion: run.tanzu.vmware.com/v1alpha2
kind: TanzuKubernetesCluster
metadata:
name: routablepods
spec:
topology:
controlPlane:
replicas: 3
vmClass: best-effort-medium
storageClass: k8s-policy
tkr:
reference:
name: v1.21.2---vmware.1-tkg.1.ee25d55
nodePools:
- name: worker-nodepool-a1
replicas: 3
vmClass: best-effort-medium
storageClass: k8s-policy
tkr:
reference:
name: v1.21.2---vmware.1-tkg.1.ee25d55
settings:
storage:
defaultClass: k8s-policy
network:
# antrea-nsx-routed is the required CNI for routable pods
cni:
name: antrea-nsx-routed
services:
cidrBlocks: ["10.97.0.0/24"]
serviceDomain: tanzukubernetescluster.local
# pods.cidrBlocks value must be empty when antrea-nsx-routed is the CNI
pods:
cidrBlocks:
作成したワークロードクラスターの動作を確認すると、ワークロードクラスターのAPI用のロードバランサーや、LoadBalancer Serivceは入力方向(Ingress)から払い出されています。
$ kubectl config get-clusters
NAME
10.44.186.2
172.16.90.2
supervisor-10.44.186.2
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
routablepods-control-plane-87fvv Ready control-plane,master 32h v1.21.2+vmware.1 172.16.96.38 <none> VMware Photon OS/Linux 4.19.191-4.ph3-esx containerd://1.4.6
routablepods-control-plane-s8wq4 Ready control-plane,master 32h v1.21.2+vmware.1 172.16.96.34 <none> VMware Photon OS/Linux 4.19.191-4.ph3-esx containerd://1.4.6
routablepods-control-plane-t6htb Ready control-plane,master 32h v1.21.2+vmware.1 172.16.96.39 <none> VMware Photon OS/Linux 4.19.191-4.ph3-esx containerd://1.4.6
routablepods-worker-nodepool-a1-s6bsw-b89cf564b-jbs56 Ready <none> 32h v1.21.2+vmware.1 172.16.96.36 <none> VMware Photon OS/Linux 4.19.191-4.ph3-esx containerd://1.4.6
routablepods-worker-nodepool-a1-s6bsw-b89cf564b-n5jh4 Ready <none> 32h v1.21.2+vmware.1 172.16.96.35 <none> VMware Photon OS/Linux 4.19.191-4.ph3-esx containerd://1.4.6
routablepods-worker-nodepool-a1-s6bsw-b89cf564b-zs2nw Ready <none> 32h v1.21.2+vmware.1 172.16.96.37 <none> VMware Photon OS/Linux 4.19.191-4.ph3-esx containerd://1.4.6
$ kubectl get node -o=jsonpath='{range .items[*]}{.spec.podCIDR}{"\n"}{end}'
172.16.101.0/24
172.16.97.0/24
172.16.102.0/24
172.16.98.0/24
172.16.99.0/24
172.16.100.0/24
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6bbf47444b-2b7gx 1/1 Running 0 54s 172.16.98.6 routablepods-worker-nodepool-a1-s6bsw-b89cf564b-jbs56 <none> <none>
nginx-6bbf47444b-dhbxn 1/1 Running 0 54s 172.16.100.8 routablepods-worker-nodepool-a1-s6bsw-b89cf564b-zs2nw <none> <none>
nginx-6bbf47444b-lj2pb 1/1 Running 0 54s 172.16.100.9 routablepods-worker-nodepool-a1-s6bsw-b89cf564b-zs2nw <none> <none>
nginx-6bbf47444b-mtg7z 1/1 Running 0 58s 172.16.99.7 routablepods-worker-nodepool-a1-s6bsw-b89cf564b-n5jh4 <none> <none>
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.97.0.1 <none> 443/TCP 32h
nginx LoadBalancer 10.97.0.31 172.16.90.3 80:30966/TCP 15s
supervisor ClusterIP None <none> 6443/TCP 32h
まとめ
vSphere環境でNSX-Tを利用すると、vSphere with TanzuやTanzu Kubernetes GridのワークロードクラスターでRoutable Podを利用することが可能になります。Routable Podを利用すると従来のVMと同じようにPodに対して直接通信することが可能になり、NATのオーバーヘッドを削減し、多様なアプリケーションの要件に対応することが可能になります。