はじめに
今回は要素が盛り沢山なので、関連するソフトウェアをはじめに紹介します。
VMware NSX Advanced Load Balancer (NSX ALB)
NSX ALB は、クラウドネイティブ時代にピッタリなソフトウェアベースのロードバランサーです。旧 Avi Networks の技術を活用しており、マルチクラウド環境においても、柔軟にスケールし、かつ WAF (Web Application Firewall) や GSLB (Global Server Load Balancing) など、豊富な機能を備えていることが特徴です。
また、トラヒックの可視化や分析の機能が非常に優れており、個人的に、とても好きなソリューションです。
VMware Tanzu Kubernetes Grid (TKG)
TKG は、vSphere with Tanzu との区別のため、Tanzu Kubernetes Grid multicloud (TKGm) と呼称されることもありますが、マルチクラウド環境において、OSS Kubernetes 準拠で、かつ、シンプルな操作でライフサイクル管理できる Kubernetes ソリューションです。
非常に省リソースな環境でも動作しますし、コンテナ レジストリやユーザー認証の連携など、豊富な拡張機能を提供しています。
NSX ALB + TKG のデプロイ方法
NSX ALB と TKG を組合せた際のデプロイ方法については、VMware Japan Blog でも紹介されています。
スクリーンショットを含めて、分かりやすく紹介されているので、一見、ボリュームがあるように感じられますが、プロダクションレディで、複数の Kubernetes クラスタを運用管理できるにも関わらず、これだけのステップで Kubernetes 環境が展開できるのは、なかなかシンプルで良いんじゃないかな、と思っています。
Avi Kubernetes Operator (AKO)
NSX ALB を使って Kubernetes のコンテナネットワークを実現する際、NSX ALB と Kubernetes の橋渡しを実現しているのが、AKO というオープンソース ソフトウェア (OSS) です。
AKO 自体は、Kubernetes クラスタ上において Pod として動作しており、Kubernetes 上で各種リソースの制御情報の更新を検知して、NSX ALB Controller に更新を連携し、コンテナ向けに様々なロードバランシング機能を提供します。
L4 ロードバランシングはもちろん、L7 ロードバランシング (Ingress) や、WAF (Web Application Firewall) などのセキュリティも、Kubernetes API を通じて制御することが可能です。
今回は、この仕組みを使い込んでいくための入り口として、NSX ALB と TKG の組合せにおいて、Ingress を構成してみようと思います。
前提
前述の VMware Japan Blog の記事を参考にしていただきつつ、基本は TKG の公式ドキュメントに従って、vSphere 環境に TKG の Management Cluster がデプロイされていることを想定しています。
また、NSX ALB では、Ingress リソースの DNS 名前解決に、NSX ALB の DNS Provider (DNS サーバー) を利用することが可能です。クライアント端末は、NSX ALB を DNS サーバーとして利用することで、Ingress の払出しに合わせて、自動で名前解決できるようになりますので、事前に構成しておくと非常に便利です。
この NSX ALB の DNS Provider の構成に関しては、下記の記事で紹介しています。
なお、利用している製品のバージョンは、下記の通りです。
- NSX Advanced Load Balancer 21.1.4-2p3 (Build 9210)
- Tanzu Kubernetes Grid 1.6
- vCenter 7.0 Update 3h (Build 20395099)
- ESXi 7.0 Update 3g (Build 20328353)
手順
Management Cluster に対する AKODeploymentConfig の設定
まず、Management Cluster に Admin 権限でアクセスできるコンテキストでの操作が必要となります。
kubectl config use-context management-admin@management
この状態で、AKODeploymentConfig
と呼ばれるリソースを用いて、実際に Ingress を利用する Workload Cluster を展開する際の事前設定を入れ込んで置きます。
apiVersion: networking.tkg.tanzu.vmware.com/v1alpha1
kind: AKODeploymentConfig
metadata:
name: npl-enabled
spec:
adminCredentialRef:
name: avi-controller-credentials
namespace: tkg-system-networking
certificateAuthorityRef:
name: avi-controller-ca
namespace: tkg-system-networking
cloudName: Default-Cloud
clusterSelector:
matchLabels:
npl-enabled: "true"
controlPlaneNetwork:
cidr: xxx.xxx.xxx.xxx/xx
name: XXXX-Network
controller: xxx.xxx.xxx.xxx
dataNetwork:
cidr: xxx.xxx.xxx.xxx/xx
name: XXXX-Network
extraConfigs:
cniPlugin: antrea
disableStaticRouteSync: false
ingress:
disableIngressClass: false
nodeNetworkList:
- cidrs:
- xxx.xxx.xxx.xxx/xx
networkName: XXXX-Network
serviceType: NodePortLocal
shardVSSize: MEDIUM
serviceEngineGroup: Default-Group
-
spec.cloudName
およびspec.serviceEngineGroup
- TKG の Management Cluster を展開する際、
tanzu
CLI から起動したウィザードの中で指定した NSX ALB のクラウド名と、Service Engine Group 名です。
- TKG の Management Cluster を展開する際、
-
spec.clusterSelector
- Workload Cluster を作成した後、この設定を有効化する対象のクラスタを指定するためのラベルセレクタを定義しています。
- 今回の例では
npl-enabled="true"
でラベル付けされたクラスタに対して、この設定が有効化されます。
-
spec.controlPlaneNetwork
- 名前の通りですが、Kubernetes のコントロールプレーンのネットワークが接続する IP アドレス帯と、実際に Node VM が接続すべき Port Group 名を指定します。
-
spec.controller
- NSX ALB Controller の IP (Controller クラスタの VIP) を指定します。
-
spec.dataNetwork
- こちらも名前の通りですが、Kubernetes のデータプレーンのネットワークを指定します。
- TKG 1.6 の構成に依存しますが、
spec.controlPlaneNetwork
と同じ設定になる場合があります。
-
spec.extraConfigs.cniPlugin
およびspec.extraConfigs.ingress.serviceType
- 後述しますが、今回の構成オプションの場合には、CNI として Antrea が必須であり、Ingress のタイプとして
NodePortLocal
を選択しています。
- 後述しますが、今回の構成オプションの場合には、CNI として Antrea が必須であり、Ingress のタイプとして
-
spec.extraConfigs.ingress.nodeNetworkList
- Ingress として利用するネットワークを指定します。
- こちらも、TKG 1.6 の構成に依存しますが、
spec.controlPlaneNetwork
と同じ設定になる場合があります。
マニフェストが作成できたら、これを Management Cluster に適用します。
kubectl apply -f npl-enabled.yaml
Workload Cluster の展開
Management Cluster をデプロイする際に使用した Cluster Config ファイルをベースに Workload Cluster を展開していきます。
この Cluster Config ファイルは tanzu
CLI からウィザードを起動して Managemet Cluster をデプロイした場合、下記のディレクトリに配置されています。
$ ls .config/tanzu/tkg/clusterconfigs/
xxxxxxxxxx.yaml # 10桁のランダムなファイル名前
このファイルをコピーし、いくつかのパラメータの修正をします。
...(snip)...
# TKG 1.6 での不具合を回避するため、下記をコメントアウト。
#AVI_LABELS: |
# '': ''
...(snip)...
# ファイル内でクラスタ名を指定すると、コマンド実行時に引数が少なくて済む。
CLUSTER_NAME: tkc01
...(snip)...
# 特に K8s クラスタのコントロールプレーンの IP に指定が無ければ、コメントアウト。
#VSPHERE_CONTROL_PLANE_ENDPOINT: xxx.xxx.xxx.xxx
...(snip)...
# 今回の構成オプションの場合、下記の設定の追記が必要。
ANTREA_NODEPORTLOCAL: "true"
作成した Cluster Config を使って、Workload Cluster をデプロイします。
tanzu cluster create -f tkc01.yaml
Workload Cluster がデプロイできたら、AKODeploymentConfig
の中で設定したラベル定義に合うように、クラスタにラベル付けしておきます。これによって、事前に構成した AKODeploymentConfig
の設定が、クラスタに対して反映されます。
kubectl label cluster tkc01 npl-enabled="true"
Workload Cluster へのアクセス
まず、下記のコマンドで、作成した Workload Cluster にアクセスするための kubeconfig を取得します。
tanzu cluster kubeconfig get tkc01 --admin
これによって、~/.kube/config
に、作成した Workload Cluster へのコンテキスト情報が格納されたので、kubectl
コマンドを使って、コンテキストを切り替えます。
kubectl config use-context tkc01-admin@tkc01
Workload Cluster の展開の最後の手順で、ラベル付けをしたことを契機に、設定が伝搬される仕組みですが、迅速に設定を反映させるための Tips として、AKO の Pod を手動で削除し、強制的に Pod を再作成させるという方法があります。あるいは、確実に設定を反映させるための手段として、念押しで実施しても良いかも知れません。
kubectl delete pod ako-0 -n avi-system
ここまでの手順によって、Ingress Class に avi-lb
が登録されていることが確認できます。
$ kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
avi-lb ako.vmware.com/avi-lb <none> 1h
動作確認
実際にサンプルのアプリをデプロイして、Ingress の動作を確認してみます。
面白みがあるマニフェストではないですが、下記のような内容を用意しました。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
spec:
ingressClassName: avi-lb
rules:
- host: nginx.ako.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
imagePullSecrets:
- name: docker-hub
- Ingress
-
spec.ingressClassName
でavi-lb
を指定しています。
-
- Service
-
spec.type
としてClusterIP
を指定している点に注意してください。 -
LoadBalancer
を指定した場合、Ingress 用の NSX ALB の Virtual Service (VS) と、L4 LB 用の VS を二重で通過する設定となってしまい、Ingress 用の VS が上手く構成されません。
-
- Deployment
- 参考までに、
spec.template.spec.imagePullSecrets
を指定していますが、Docker Hub の Rate Limit を回避するために入れてあります。 - 手元の端末で Docker Hub にログインした後、Secret を作成してください。
# Docker Hub にログイン docker login # Secret の作成 kubectl create secret generic docker-hub \ --from-file=.dockerconfigjson=${HOME}/.docker/config.json \ --type=kubernetes.io/dockerconfigjson
- 参考までに、
作成したマニフェストを使って nginx をデプロイします。
$ kubectl apply -f nginx-with-ingress.yaml
ingress.networking.k8s.io/nginx created
service/nginx created
deployment.apps/nginx created
NSX ALB Controller の UI で [Applications] > [Dashborad] のページに進み、表示形式を [View VS Tree] とすると、下記のようなイメージで Ingress が構成されていることが分かります。
もし、NSX ALB で DNS Provider を構成し、クライアントがその DNS を使っていれば、nginx.ako.test
が自動で名前解決されますので、クライアントからブラウザアクセスすれば、それが確認できます。
参考
今回の記事では、詳細には触れませんでしたが、NSX ALB と TKG 1.6 の組合せで、Ingress を構成する場合には、下記の 4つの構成オプションがあります。
After you install NSX Advanced Load Balancer using the steps in Install NSX Advanced Load Balancer, you can configure L7 ingress for your workload clusters using one of the following options:
- L7 ingress in ClusterIP mode
- L7 ingress in NodePortLocal mode
- L7 ingress in NodePort mode
- NSX ALB L4 ingress with Contour L7 ingress
このうち、今回の記事で利用したのは、L7 ingress in NodePortLocal mode の手順を実践しています。この構成オプションの場合、CNI が Antrea (TKG のデフォルト) が必要ですが、NodePortLocal を用いることで、コンテナネットワーク内でのトラヒックが最適化され、余計なトラヒックの発生を防ぐことができます。
他のオプションを含めて、NSX ALB が提供するコンテナネットワークに関しては、VMware Japan Blog の記事で、分かりやすく解説されていますので、ぜひご参考にしていただければと思います。