NSX Advanced Load Balancer アプリケーションのモダナイゼーション ネットワーク

NSX-ALB による Kubernetes Ingress サービスの高度化 – Part 2

本稿は NSX-ALBAKO による Kubernetes L4/L7 Ingress サービス機能についてご紹介するブログの Part 2 となります。今回は主に AKO を介した L7 Ingress の実現および AKO Custom Resource についてご紹介したいと思います。

なお Part 1 では AKO の概要や主な機能、ネットワーク構成オプション、LB 構成例についてご紹介しております。本稿の前に Part 1 をご一読いただけると幸いです。

NSX-ALB Controller, Service Engine, AKO と K8s クラスタの全体像

 

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) を無償でご提供しています。本ブログでご紹介したソリューションについては、以下のラボで体験していただけます。