AKO : Avi Kubernetes Operator


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の構成に応じて次のオプションを利用できます。

  1. Podに対して外部から直接ルーティングできない場合 - Static Route
    • 一般的なCNIはクラスター内部で隔離されたCIDRを利用しPod間のネットワークを構成します。CNIはクラスター内の各NodeにPod用CIDRを割り当てます。SEをKubernetesノードと同じネットワークにデプロイする場合、AKOでStatic Routeを設定することで、SEからPod CIDR向けのStatic RouteのネクストホップとしてNodeのIPアドレスが構成されます。
  2. Podに対して外部から直接ルーティングできない場合 - Node Port
    • SEがKubernetesノードと同じネットワークにデプロイされない場合、NodePortサービスをVirtualServiceのプールメンバーのエンドポイントとして使用することが可能です。このオプションではNodePortのServiceを作成し、config.serviceTypeパラメータを利用してNodePortベースのRoute/Ingressを有効にします。nodeSelectorLabels.keyとnodeSelectorLabels.valueパラメーターは、AKOのインストール中に指定し、負荷分散のためにクラスターから必要なノードを選択します。 クラスター内の必要なノードには、構成済みのキーと値のペアでラベルを付ける必要があります。
  3. 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に最低限の設定を行う必要があります。

  1. Controller OVAのデプロイ
  2. IPAM/DNS Profileの作成
  3. DNS Profileの作成
  4. CloudとしてvSphere環境を登録
    1. IPAM/DNS Profileの指定
    2. Management NetworkでSEが利用するポートグループとIP Addressプールを指定
    3. NetworksとしてVIPネットワーク用のポートグループにIP Adressプールを指定

今回はAvi Controllerに2つのネットワークを構成しました。

  • Management Network : SEがAvi Controllerと通信するためのネットワーク

  • VIP用ネットワーク : Service/Ingressリソースが利用するVIPを配置するネットワーク

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
  • Static Routeの確認 : SEはPod向けのLoadBalancerとして機能するため、各ノードCIDRに対するStatic Routeが構成されます。

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を利用するための重要なコンポーネントになっていくと思われます。