本稿は NSX-ALB と AKO による Kubernetes L4/L7 Ingress サービス機能についてご紹介するブログの Part 2 となります。今回は主に AKO を介した L7 Ingress の実現および AKO Custom Resource についてご紹介したいと思います。
なお Part 1 では AKO の概要や主な機能、ネットワーク構成オプション、LB 構成例についてご紹介しております。本稿の前に Part 1 をご一読いただけると幸いです。
AKO による高度な K8s Ingress 機能
Part 1 でご紹介したように、NSX-ALB と AKO は L4/L7 LB 機能を K8s に提供できますが、特に Ingress を利用した L7LB の実現に関して多様な拡張機能をサポートしています。以下は AKO が Ingress においてサポートする機能の一部です。
- セキュア/インセキュア対応
- Sharded Virtual Service – 複数の仮想ホストによる Virtual Service の共有を制御
- SNI と EVH – 単一の Virtual Service で複数の FQDN とパスに対応
- CRD による仮想ホストへのポリシーやプロファイルの割り当て、ネットワーク設定などのサポート
- パススルー Ingress のサポート
まずは IngressClass を用いた NSX-ALB の利用方法から見ていきます。
IngressClass
AKO は networking.k8s.io/v1 Ingress を部分的にサポートしています。AKO の初期構成時に IngressClass “avi-lb” を自動的に作成し、これを利用して K8s 上で作成される Ingress を NSX-ALB の L7LB として実現します。通常は “avi-lb” がデフォルトの IngressClass に設定されています。
apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: annotations: ingressclass.kubernetes.io/is-default-class: "true" meta.helm.sh/release-name: ako-1643099082 meta.helm.sh/release-namespace: avi-system creationTimestamp: "2022-01-25T08:24:47Z" generation: 1 labels: app.kubernetes.io/managed-by: Helm name: avi-lb resourceVersion: "2683" uid: fe4ed16d-eb97-4353-a815-4bab0be6c458 spec: controller: ako.vmware.com/avi-lb
デフォルト以外の IngressClass を作成して使う場合は “.spec.controller” に ”ako.vmware.com/avi-lb” を指定します。
Ingress
AKO の IngressClass “avi-lb” がデフォルト指定されている場合は Ingress を作成すると自動的に AKO が使用されます。Ingress を作成する際にデフォルトでない IngressClass を指定する場合は ingressClassName で指定します。
AKO を利用して Ingress を作成した場合、バックエンドプールメンバーは Ingress の “.service.name” から Service リソースが導き出されます。”.service.port” は影響を与えません。AKO が ClusterIP モードの場合はプールは Pod IP アドレスとポート番号が指定され、NodePort モードの場合は ノードの IP アドレスと NodePort のポート番号が指定されます。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: ingressClassName: avi-lb rules: - host: host1.avi.internal http: paths: - backend: service: name: service1 port: number: 80 path: / pathType: Prefix
Ingress Sharded Virtual Service
Sharded Virtual Service とは、複数の仮想ホストを単一もしくは一定数の Virtual Service で実行するための仕組みです。NSX-ALB Service Engine の上で消費される仮想 IP アドレス (VIP) やサブネット、vNIC を削減できるため、すべての Ingress 仮想ホストに対して専用の VIP を割り当てるモデルに比べ、より少ないリソースで多くの仮想ホストを提供することが可能となります。
Sharded Virtual Service のサイズ設定として LARGE, MEDIUM, SMALL, DEDICATED の4種類を指定できます。SMALL の場合は1個、MEDIUM では4個、LARGE では8個の Virtual Service に仮想ホストが配置されます。DEDICATED を選択した場合は、Ingress 仮想ホスト各々に専用の Virtual Service が割り当てられるようになります。
AKO Custom Resource Definition (CRD)
NSX ALB が提供する高度なロードバランサー機能を K8s 側から利用できるようにするために、AKO はいくつかの Custom Resource を利用できます。現在提供されている CRD は以下の2種類に大別されます。
- L7 CRD
- L7 トラフィック (Ingress) に様々なルーティングルールを指定できる
- HostRule と HTTPRule の2種類の CRD
- インフラストラクチャ CRD
- Service Engine Group や Sharding など NSX ALB のカスタムインフラ設定を作成し、LB や Ingress に関連付ける
- AviInfraSetting CRD – IngressClass、GatewayClass への紐付け、もしくは annotation での指定
HostRule
HostRule CRD は Ingress や OpenShift Route に拡張的な仮想ホスト設定を追加するために使用します。利用できる主な設定としては以下のようなものがあります:
- 仮想ホスト設定の有効化・無効化
- 各種ポリシーの指定 – HTTP Policy, WAF Policy, Analytics Policy
- 各種プロファイルの指定 – Application Profile, Analytics Profile, Error Page Profile
- TLS キーと証明書の指定
- DataScript の指定
- GSLB FQDN の指定
- TCP 設定(ポート、IPアドレスの指定)
- Alias 設定
HostRule CRD で利用するポリシーやプロファイルは、事前に NSX-ALB で作成済みのものを指定します。以下は HostRule CRD の例です。
apiVersion: ako.vmware.com/v1alpha1 kind: HostRule metadata: name: my-host-rule namespace: red spec: virtualhost: fqdn: foo.region1.com # mandatory fqdnType: Exact enableVirtualHost: true tls: # optional sslKeyCertificate: name: avi-ssl-key-cert type: ref alternateCertificate: name: avi-ssl-key-cert2 type: ref sslProfile: avi-ssl-profile termination: edge gslb: fqdn: foo.com includeAliases: false httpPolicy: policySets: - avi-secure-policy-ref overwrite: false datascripts: - avi-datascript-redirect-app1 wafPolicy: avi-waf-policy applicationProfile: avi-app-ref analyticsProfile: avi-analytics-ref errorPageProfile: avi-errorpage-ref analyticsPolicy: # optional fullClientLogs: enabled: true throttle: HIGH logAllHeaders: true tcpSettings: listeners: - port: 6443 enableSSL: true loadBalancerIP: 10.10.10.10 aliases: # optional - bar.com - baz.com
HTTPRule
HTTPRule CRD は Ingress や Route で指定したパスターゲットに対するトラフィックルーティング設定を行います。利用できる主な設定は以下の通りです:
- ロードバランサアルゴリズム
- ヘルスモニターの指定
- バックエンドへのエンクリプションの有効化・無効化
以下は HTTPRule CRD の例です。
apiVersion: ako.vmware.com/v1alpha1 kind: HTTPRule metadata: name: my-http-rule namespace: purple-l7 spec: fqdn: foo.avi.internal paths: - target: /foo healthMonitors: - my-health-monitor-1 - my-health-monitor-2 loadBalancerPolicy: algorithm: LB_ALGORITHM_CONSISTENT_HASH hash: LB_ALGORITHM_CONSISTENT_HASH_SOURCE_IP_ADDRESS tls: ## This is a re-encrypt to pool type: reencrypt # Mandatory [re-encrypt] sslProfile: avi-ssl-profile destinationCA: |- -----BEGIN CERTIFICATE----- [...] -----END CERTIFICATE-----
AviInfraSetting
AviInfraSetting CRD は、AKO が作成する L4/L7 Virtual Service が利用する NSX-ALB のインフラ設定を定義するためのものです。AKO 初期構築時にインフラ設定を行いますが、この CRD を利用すれば、個々の Virtual Service 毎にカスタマイズしたインフラを利用することが可能になります。AviInfraSetting CRD で実施できる主な設定は以下となります:
- SE Group の指定 – どの Service Engine を利用して Virtual Service を実現するか
- VIP やノード(サーバプール)ネットワークの指定
- BGP RHI (BGPを利用したスケーリング) の有効化・無効化、BGP ピアのラベル設定
- VIP の Shard の設定
apiVersion: ako.vmware.com/v1alpha1 kind: AviInfraSetting metadata: name: my-infra-setting spec: seGroup: name: compact-se-group network: vipNetworks: - networkName: vip-network-10-10-10-0-24 cidr: 10.10.10.0/24 nodeNetworks: - networkName: node-network-10-10-20-0-24 cidrs: - 10.10.20.0/24 enableRhi: true bgpPeerLabels: - peer1 - peer2 l7Settings: shardSize: MEDIUM
AviInfraSetting で作成した設定を実際に VirtualService に適用する方法はいくつかあります。現状は、以下の図のように IngressClass の利用、GatewayClass の利用、annotation の3種類となっています。
以下は IngressClass を利用して AviInfraSetting を指定している例です。
apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: avi-ingress-class spec: controller: ako.vmware.com/avi-lb parameters: apiGroup: ako.vmware.com kind: AviInfraSetting name: my-infra-setting
実際にやってみた
それでは、実際に IngressClass と CRD を使って L7 Virtual Service を展開してみたいと思います。K8s 環境は Part 1 と同じものを利用しますので、初期設定は省略します。前回 ConfigMap “avi-k8s-config” で確認したように、この環境の Shard サイズは SMALL に設定されています。これは、Ingressで仮想ホストを複数作成してもすべて同じ Virtual Service で実現されることを意味します。
> kubectl get configmap avi-k8s-config -n avi-system -o yaml
apiVersion: v1
data:
(snip...)
shardVSSize: SMALL
(snip...)
最初の Ingress のデプロイ
ではまず Ingress を作成してみます。前回と同じくデモ用の Pod と Service (lb-demo) を展開した状態で、適用済みの Service を以下のコマンドで編集し、“type: LoadBalancer” から “type: ClusterIP” に変更します。
> kubectl edit service lb-demo
次に以下のような Ingress マニフェストを作成して適用します。host FQDN は “lb-demo2.netlab.com”、バックエンドサービス名は “lb-demo” です。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: lb-demo-ingress spec: ingressClassName: avi-lb rules: - host: lb-demo1.netlab.com http: paths: - backend: service: name: lb-demo port: number: 33333 # fake port path: / pathType: Prefix
> kubectl apply -f lb-demo-ingress1.yaml ingress.networking.k8s.io/lb-demo-ingress created > > kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 79d lb-demo ClusterIP 10.103.109.197 <none> 80/TCP 46h > > kubectl get ingress NAME CLASS HOSTS ADDRESS PORTS AGE lb-demo-ingress avi-lb lb-demo1.netlab.com 172.19.0.211 80 14m
NSX-ALB UI で アプリケーション>仮想サービス と移動すると、“kubeadm-cluster–Shared-L7-0” という名前で L7 Virtual Service が作成されており、“172.19.0.211” というアドレスと “80” と “443” のサービスポートが割り当てられていることが分かります。
またこの Virtual Service に対応するプールも作成されます。前回同様、AKO は ClusterIP モードで動作しているので、Pod のアドレスが直接プールに追加されます。
ブラウザで http://lb-demo1.netlab.com/ にアクセスして httpd コンテナが正常に動作していることを確認しておきます。
2番目の Ingress のデプロイ
次に以下のような別の Ingress マニフェストを作成して適用します。このマニフェストでは host FQDN を “lb-demo2.netlab.com” に変更しています。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: lb-demo2-ingress spec: ingressClassName: avi-lb rules: - host: lb-demo2.netlab.com http: paths: - backend: service: name: lb-demo port: number: 33333 # fake port path: / pathType: Prefix
> kubectl apply -f lb-demo-ingress2.yaml
ingress.networking.k8s.io/lb-demo2-ingress created
>
> kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 79d
lb-demo ClusterIP 10.103.109.197 <none> 80/TCP 46h
>
> kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
lb-demo-ingress avi-lb lb-demo1.netlab.com 172.19.0.211 80 133m
lb-demo2-ingress avi-lb lb-demo2.netlab.com 172.19.0.211 80 17m
新しく作成された Ingress “lb-demo2-ingress” が最初に作った Ingress と同じアドレスを割り当てられていることが分かります。
NSX-ALB UI で仮想サービスを表示すると、最初に作られた “kubeadm-cluster–Shared-L7-0” に新しく作った Ingress の FQDN “lb-demo2.netlab.com” が割り当てられていることが確認できます。これはこのクラスタの AKO で shardVSSize が SMALL に設定されており、1つの L7 VirtualService ですべての Ingress 仮想ホストを動作させようとするためです。
ブラウザで http://lb-demo2.netlab.com/ にもアクセスして httpd コンテナの動作を確認します。
HTTPRule を使って負荷分散アルゴリズムをカスタマイズ
次に、CRD を使った L7 LB の制御を行ってみます。ここでは、HTTPRule を使って仮想ホストに割り当てられている負荷分散アルゴリズムを変更してみます。
現状、デフォルトでは Least Connections アルゴリズムが自動的に割り当てられます。上で作成した “lb-demo1.netlab.com” のプール設定を見ると、以下のようにロードバランシング(負荷分散アルゴリズム)が Least Connections になっていることが確認できます。
ここで以下のような HTTPRule マニフェストを作成し、適用します。fqdn として上で最初に作成した Ingress の host FQDN を指定し、algorithm に LB_ALGORITHM_ROUND_ROBIN を指定しています。負荷分散アルゴリズムなど、HTTPRule CRD で利用可能なパラメータの説明はこちらもご参照下さい。
apiVersion: ako.vmware.com/v1alpha1 kind: HTTPRule metadata: name: http-rule-roundrobin spec: fqdn: lb-demo1.netlab.com paths: - target: / loadBalancerPolicy: algorithm: LB_ALGORITHM_ROUND_ROBIN
> kubectl apply -f httprule-rr.yaml httprule.ako.vmware.com/http-rule-roundrobin created
設定後、もう一度プールの設定を確認すると、以下のようにロードバランシング(負荷分散アルゴリズム)が Round Robin に変わっています。
“http://lb-demo1.netlab.com” に何度かアクセスすると、Round Robin アルゴリズムに変わっていることが確認できます。
AviInfraSetting を使って ShardVS 設定をカスタマイズ
今度は、AviInfraSetting CRD を使って指定した Ingress 仮想ホストが使用するインフラ設定をカスタマイズしてみます。まず、以下のような AviInfraSetting マニフェストを準備し、適用します。
apiVersion: ako.vmware.com/v1alpha1 kind: AviInfraSetting metadata: name: infra-setting-dedicated spec: seGroup: name: Default-Group network: vipNetworks: - networkName: "VLAN 2900" cidr: 172.19.0.0/24 enableRhi: false shardSize: DEDICATED
> kubectl apply -f aviinfra-dedicated.yaml aviinfrasetting.ako.vmware.com/infra-setting-dedicated created
Service Engine Group やネットワーク設定は同じのままで、shardSize 設定を DEDICATED に変更します。AKO の設定では SMALL でしたが、この設定を使う仮想ホストでは、作成される度に新たな VS を作成するようになるはずです。
次に、この infra-setting-dedicated を使用する IngressClass を作成します。以下のようなマニフェストを作成して適用します。
apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: annotations: ingressclass.kubernetes.io/is-default-class: "false" meta.helm.sh/release-name: ako-1643099082 meta.helm.sh/release-namespace: avi-system name: avi-lb-dedicated spec: controller: ako.vmware.com/avi-lb parameters: apiGroup: ako.vmware.com kind: AviInfraSetting name: infra-setting-dedicated
> kubectl apply -f ingressclass-dedicated.yaml ingressclass.networking.k8s.io/avi-lb-dedicated created
最後に、この IngressClass avi-lb-dedicated を使用する Ingress マニフェストを作成して適用します。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: lb-dedicated-ingress spec: ingressClassName: avi-lb-dedicated rules: - host: lb-dedicated.netlab.com http: paths: - backend: service: name: lb-demo port: number: 30 # fake port path: / pathType: Prefix
> kubectl apply -f lb-demo-ingress-dedicated.yaml
ingress.networking.k8s.io/lb-dedicated-ingress created
>
> kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
lb-dedicated-ingress avi-lb-dedicated lb-dedicated.netlab.com 172.19.0.212 80 59s
lb-demo-ingress avi-lb lb-demo1.netlab.com 172.19.0.211 80 1d3h
lb-demo2-ingress avi-lb lb-demo2.netlab.com 172.19.0.211 80 1d
作成された新しい仮想ホスト lb-dedicated.netlab.com には、このように新しいアドレスが割り当てられました。NSX-ALB UI 上でも L7 Virtual Service として作成されていることを確認しておきます。
最後に
いかがでしょうか。本稿では K8s で AKO の IngressClass や CRD を介した NSX-ALB の高度な利用についてお話しました。今後も AKO の追加機能についてご紹介していきたいと思います。
〜お知らせ〜
※VMwareでは、各種製品をクラウド上でご評価いただける Hands-on Labs (HOL) を無償でご提供しています。本ブログでご紹介したソリューションについては、以下のラボで体験していただけます。