AKO (Avi Kubernetes Operator)とは
KubernetesやOpenShift環境でAvi Kubernetes Operator (AKO)を利用することにより、Kubernetes/OpenShiftのリソースをAvi Controller APIに変換し、NSX ALBによりLoadBalancerとIngressリソースを提供することが可能になります。NSX ALBが持つアプリケーショントラフィック可視化機能を利用することも可能です。
2021年2月現在、対応しているKubernetesは 1.16〜1.19、OpenShift 4.3〜4.5、CNIはAntrea, Calico, OpenShift SDNです。(Compatibility Guide for AKO)
NSX Advanced Load Balancer (NSX ALB)について
NSX ALBは(旧Avi Vantage Platform)はロードバランサーを制御するAvi Controllerと、実際のロードバランサー機能を提供するService Engine(SE)と呼ばれるデータプレーンで構成されます。vSphereやAWS等の環境で利用可能で、性能要件に応じてSEを増やすことでLoad Balancerの性能をスケールアウトすることが可能です。また、ロードバランサー上で様々な情報を収集し、Controller上でアプリケーションの情報を可視化することが可能です。
アーキテクチャ
Kubernetes/OpenShift環境のAKOは以下の3つのコンポーネントで構成されます。
- Avi Controller
- Service Engines (SE)
- Avi Kubernetes Operator (AKO)
AKO Networkの構成方法
SEはKubernetesクラスター外部に仮想マシンとしてデプロイされます。SEがLoad Balancer/Ingress Controllerとして受信したリクエストはPodに負荷分散するためPod CIDRに対してSEからルーティングされる必要があります。クラスターで使用されるCNIの構成に応じて次のオプションを利用できます。
- Podに対して外部から直接ルーティングできない場合 - Static Route
- 一般的なCNIはクラスター内部で隔離されたCIDRを利用しPod間のネットワークを構成します。CNIはクラスター内の各NodeにPod用CIDRを割り当てます。SEをKubernetesノードと同じネットワークにデプロイする場合、AKOでStatic Routeを設定することで、SEからPod CIDR向けのStatic RouteのネクストホップとしてNodeのIPアドレスが構成されます。
- Podに対して外部から直接ルーティングできない場合 - Node Port
- SEがKubernetesノードと同じネットワークにデプロイされない場合、NodePortサービスをVirtualServiceのプールメンバーのエンドポイントとして使用することが可能です。このオプションではNodePortのServiceを作成し、config.serviceTypeパラメータを利用してNodePortベースのRoute/Ingressを有効にします。nodeSelectorLabels.keyとnodeSelectorLabels.valueパラメーターは、AKOのインストール中に指定し、負荷分散のためにクラスターから必要なノードを選択します。 クラスター内の必要なノードには、構成済みのキーと値のペアでラベルを付ける必要があります。
- Podサブネットが外部から直接ルーティング可能
- NSX-T CNI、AWS CNI、Azure CNIなどPodのサブネットが外部に対してルーティング可能な場合に利用することができます。これらのCNIを利用している場合、SEがPodのIPアドレスに到達するために特別な設定は不要です。AKOの設定で「Static Route Programming」を無効化することができます。SEはPodに対してルーティング可能なネットワークであればどこにでもデプロイすることが可能です。
AKOを使ってみる
以下のような環境でAKOを利用してみます。上記3つのオプションの中で「Podに対して外部から直接ルーティングできない場合 - Static Route」の構成に該当します。
ネットワーク構成
今回は、以下のような構成でKubernetes環境でAKOを利用してみます。各NodeはvSphere上の仮想マシンとして構成しており、Avi Controllerと各Nodeは同じセグメント(ポートグループ)に接続されています。
Kubernetesクラスター
Master x3、Node x 3のKubernetesクラスターでCNIとしはAntreaを利用しています。
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
avi-master1 Ready control-plane,master 13d v1.20.2 172.16.250.11 <none> Ubuntu 20.04.1 LTS 5.4.0-65-generic containerd://1.3.3-0ubuntu2.2
avi-master2 Ready control-plane,master 13d v1.20.2 172.16.250.12 <none> Ubuntu 20.04.1 LTS 5.4.0-65-generic containerd://1.3.3-0ubuntu2.2
avi-master3 Ready control-plane,master 13d v1.20.2 172.16.250.13 <none> Ubuntu 20.04.1 LTS 5.4.0-65-generic containerd://1.3.3-0ubuntu2.2
avi-node1 Ready <none> 13d v1.20.2 172.16.250.21 <none> Ubuntu 20.04.1 LTS 5.4.0-65-generic containerd://1.3.3-0ubuntu2.2
avi-node2 Ready <none> 13d v1.20.2 172.16.250.22 <none> Ubuntu 20.04.1 LTS 5.4.0-65-generic containerd://1.3.3-0ubuntu2.2
avi-node3 Ready <none> 13d v1.20.2 172.16.250.23 <none> Ubuntu 20.04.1 LTS 5.4.0-65-generic containerd://1.3.3-0ubuntu2.2
AKO(Avi Kubernetes Operator)構成方法
Avi Controllerの準備
vSphere環境上のKubernetesクラスターでAKOを利用するにはAvi Controllerに最低限の設定を行う必要があります。
- Controller OVAのデプロイ
- IPAM/DNS Profileの作成
- DNS Profileの作成
- CloudとしてvSphere環境を登録
- IPAM/DNS Profileの指定
- Management NetworkでSEが利用するポートグループとIP Addressプールを指定
- NetworksとしてVIPネットワーク用のポートグループにIP Adressプールを指定
今回はAvi Controllerに2つのネットワークを構成しました。
AKOの構成
AKOはhelmによりインストールします。
- helmレポジトリの追加
$ helm repo add ako https://avinetworks.github.io/avi-helm-charts/charts/stable/ako
"ako" has been added to your repositories
$ helm repo list
NAME URL
ako https://avinetworks.github.io/avi-helm-charts/charts/stable/ako
- AKO用ネームスペースの作成
$ kubectl create ns avi-system
namespace/avi-system created
- AKOをインストールする際のパラメータを設定するvalues.yamlのテンプレート作成
$ helm show values ako/ako > values.yaml
- values.yamlのパラメータ指定
values.yaml
ではAvi Controllerのアドレスやクレデンシャルの他、IngressやServiceリソース作成時に作成されるVirtual Serivce(VIP)をどのサブネット、ポートグループで利用するかを指定します。Service Engineはここで指定したポートグループに接続され、VIPが払い出されます。以下はvaleus.yamlの設定箇所の抜粋です。
AKOSettings:
clusterName: "avi-cluster" # A unique identifier for the kubernetes cluster
NetworkSettings:
subnetIP: "172.16.251.0" # Subnet IP of the vip network
subnetPrefix: "255.255.255.0" # Subnet Prefix of the vip network
networkName: "alb-vip" # Network Name of the vip network
L7Settings:
shardVSSize: "SMALL" # Use this to control the layer 7 VS numbers. ENUMs: LARGE, MEDIUM, SMALL
ControllerSettings:
controllerVersion: "20.1.3" # The controller API version
controllerIP: "172.16.250.1" # Controller IP Address
avicredentials:
username: "<USER>" # Controller Username
password: "<PASSWORD>" # Controller Password
- helm chartのインストール
helm install ako/ako --generate-name --version 1.3.1 -f values.yaml -n avi-system
NAME: ako-1612391086
LAST DEPLOYED: Wed Feb 3 22:24:47 2021
NAMESPACE: avi-system
STATUS: deployed
REVISION: 1
- 作成の確認 : avi-systemネームスペースにako-0 podが作成されます。
$ helm list -n avi-system
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
ako-1612391086 avi-system 1 2021-02-03 22:24:47.131176283 +0000 UTC deployed ako-1.3.1 1.3.1
$ kubectl get pod -n avi-system
NAME READY STATUS RESTARTS AGE
ako-0 1/1 Running 0 3m6s
Service type=LoadBalancerの作成
nginx podを作成してService type=LoadBalancerを指定してPodを公開してみます。以下の例ではAvi Controllerで指定したalb-vipのネットワークプール(172.16.251.1-172.16.251.100)から172.16.251.1
がLoadBalancerのアドレスとして払い出されました。
$ kubectl create deploy nginx1 --image=nginxhellos/demo
deployment.apps/nginx1 created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx1-6754b74cdd-9csrs 1/1 Running 0 4m45s 10.244.3.23 avi-node1 <none> <none>
$ kubectl expose deploy nginx1 --type=LoadBalancer --port=80
service/nginx1 exposed
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d23h
nginx1 LoadBalancer 10.103.97.178 172.16.251.1 80:30664/TCP 5m27s
最初にVirtual Serviceを必要とするリソース(Service/Ingress)が作成されると、akoによりSEのプロビジョニングが開始されます。SEをOVAからデプロイするため、Serviceにアクセスできるようになるまでしばらく時間がかかります。
デプロイされたSEは、管理用IPとしてAvi Controllerで設定したManagement Network(alb-mgmt
)に接続され、values.yamlで指定したnetworkNameポートグループ(alb-vip
)に接続してVIPが構成されます。今回の例ではKubernetes環境では、SEの管理用ネットワークとKubernetesノード通信用ネットワークとしてalb-mgmt
が利用されています。
Avi Controllerを確認すると、Virtual Serviceとして「k8s--default-nginx1」(クラスター名--ネームスペース名-サービス名という命名規則)が作成され、しばらくするとLoadBalancerが処理した各種メトリックが表示されます。
Virtual Serviceに関連付けられているPoolのServerにはPodのIPアドレスが構成されています。
Pod数を1→5に変更してみます。
$ kubectl scale deploy nginx1 --replicas=5
deployment.apps/nginx1 scaled
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx1-6754b74cdd-2t8zb 1/1 Running 0 2s 10.244.5.19 avi-node3 <none> <none>
nginx1-6754b74cdd-9csrs 1/1 Running 0 9m17s 10.244.3.23 avi-node1 <none> <none>
nginx1-6754b74cdd-fh72t 1/1 Running 0 2s 10.244.5.18 avi-node3 <none> <none>
nginx1-6754b74cdd-qkpnt 1/1 Running 0 2s 10.244.4.10 avi-node2 <none> <none>
nginx1-6754b74cdd-t464l 1/1 Running 0 2s 10.244.3.24 avi-node1 <none> <none>
PoolのServerもPodの増加に追従して負荷分散対象を修正しています。
Ingressとしての利用
AKOはIngressリソースにも対応しています。Ingress利用時はDNS Virtual Serviceを併用することでIngressリソース向けの名前解決を提供することも可能です。
DNS Virtual Serviceの作成と設定
本環境のDNSサーバーをexample.comゾーンの権威サーバーとして構成し、サブドメイン
ako.example.com
の委譲先としてDNS Virtual Serviceで指定するIPアドレス(172.16.251.253)を指定しています。
Virtual Service作成画面で、Application Profileとして「System-DNS」を選択してDNS Virtual Serviceを作成します。VIPとして手動で172.16.251.253を割り当てています。
Administration > Settings > DNS Serviceを開き、作成したDNS Virtual Serviceを選択します。
Infrastructure > Cloudで、「State Based DNS Registration」が有効になっていることを確認します。
Ingressリソースの作成
Ingressリソースを作成します。
$ cat << EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx1-ingress
spec:
rules:
- host: nginx1.ako.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx1
port:
number: 80
EOF
Ingressリソースを確認するとAvi Controllerで指定したalb-vipのネットワークプール(172.16.251.1-172.16.251.100)から172.16.251.4がIngressリソースとして払い出されています。
# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx1-ingress avi-lb nginx1.ako.example.com 172.16.251.4 80 3s
Ingressとして作成されるVirtual Serviceは複数のIngressリソースで共有されるため、Virtual Serviceの「Application Domain Name」には複数のIngressリソースのFQDNが構成されます。
# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
httpd1-ingress avi-lb httpd1.ako.example.com 172.16.251.4 80 4s
nginx1-ingress avi-lb nginx1.ako.example.com 172.16.251.4 80 14m
nginx1.ako.example.comやhttpd1.ako.example.comのAレコードはDNS Virtual Serviceに登録されるため、FQDNでアクセスすることが可能です。
アプリケーショントラフィックの可視化
Ingressで作成したVirtual ServiceはL7ロードバランサーとして構成される(Application Profile = System-HTTP)ためアプリケーションレベルの可視化が可能です。
まとめ
Kubernetes環境でNSX-ALBを利用してServiceやIngressリソースを提供することが可能です。NSX ALBを利用することで、ControllerのGUIからトラフィックを詳細に可視化することが可能です。
VMware TanzuのStandard Edition以上にはNSX Advanced LoadBalancerがバンドルされるため、Tanzuの中でLoadBalancerを利用するための重要なコンポーネントになっていくと思われます。