0.はじめに
Microsoft Ignite 2022 でも取り上げられ、先日パブリックプレビューとなりました、Azure Kubernetes Fleet Manager を試します。
Fleet Manager は複数の Kubernetes クラスターの一元管理や、複数クラスタをまたいだワークロードの実行等がおこなえるサービスです。
実行結果等を含めて本記事は、執筆時点(2022/11/30〜12/12)での内容となります
1. 前提条件
今回 Fleet のメンバーとなる、AKS クラスタは、後述する MultiClusterService
を利用するため、Azure CNI の利用と同一 VNet 上にクラスターサブネットを別にした形で以下の通り、既に作成済みとします。
AKS名 | リソースグループ | CNI | VNet | クラスターサブネット | K8s version |
ノードプール | ノードサイズ | リージョン |
---|---|---|---|---|---|---|---|---|
demo-aks01 | demo_aks01 | Azure CNI | 10.224.0.0/12 | 10.224.0.0/16 | 1.23.12 | 手動: 1台 | Standard_DS2_v2 | eastus |
demo-aks02 | 同上 | 同上 | 同上 (同一のVNet) |
10.225.0.0/16 | 1.23.12 | 同上 | 同上 | 同上 |
2. 事前準備
こちらのクイックスタートのドキュメントを参考に進めます。
- 機能の有効化と extension のインストール
- Fleet の作成 と メンバーの追加
-
hub
AKS への Kubectl 接続用に ロールをアサイン
2.1 機能の有効化と extension のインストール
以下の az コマンドで Fleet を作成するサブスクリプション、メンバーとなる AKS クラスターが配置されているサブスクリプションごとに、機能を有効にします。(今回は単一のサブスクリプションを利用)
また、つづいて Fleet 用の Azure CLI の extension をインストールします。
$ az feature register --namespace Microsoft.ContainerService --name FleetResourcePreview
Once the feature 'FleetResourcePreview' is registered, invoking 'az provider register -n Microsoft.ContainerService' is required to get the change propagated
{
"id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX/providers/Microsoft.Features/providers/Microsoft.ContainerService/features/FleetResourcePreview",
"name": "Microsoft.ContainerService/FleetResourcePreview",
"properties": {
"state": "Registering"
},
"type": "Microsoft.Features/providers/features"
}
$ az extension add --name fleet
The installed extension 'fleet' is in preview.
2.2. Fleet の作成 と メンバーの追加
今回は、Azure Portal から Fleet の作成と、メンバーとなる AKS 追加します。
以下設定で作成します。
- リソースグループ: demo_aks_fleetmng
- Fleet 名: aks-fleet01
- デプロイするリージョン: eastus
- リージョンは Japan east / west ともに選択可能
- メンバー
- demo-aks-01
- demo-aks-02
- なお、メンバーは、Fleet 作成時には指定せずに、作成後に、追加、削除も可能
作成後の Portal 画面はとてもシンプルです。
fleet メンバー([リソースグループ名]-[ AKS 名])を確認
Tips1: Fleet( hub
) の AKS について
Fleet の作成が終わると、FL_[Fleetリソースグループ名]_[Fleet名]_[リージョン]
というリソースグループが自動的に作成され、その中に hub
とよばれる特殊な AKS クラスタが作成されていることが確認できます。
なお、AKS リソースの実態はMC_FL_[Fleetリソースグループ名]_[Fleet名]_[リージョン]
リソースグループの中に作成されます。
また、ノードプールは Standard_D4s_v4 (1 個のインスタンス)となっています。
後ほど説明しますが、こちらのhub
AKS へ K8s の namespace
を作成し、deployment
などをメンバーへ 伝搬させることができます。
ただし、こちらは Fleet メンバーへの 伝搬と管理が目的の特殊な AKS のため、例えば、 deployment
を apply しても pod
等は起動されず、CPU やメモリ等のリソースを無駄に消費することが無いようになっています。
2.3. hub
AKS への Kubectl 接続用に ロールをアサイン
kubectl より、Fleet manager の Kubernetes API(hub
AKS) へアクセスするためにロールを割り当てます。
サブスクリプションとリソースグループ、作成した Fleet 名を環境変数として設定し
組み込みロール(Azure Kubernetes Fleet Manager RBAC クラスター管理者)を azure ログインアカウントへ割り当てます。
$ SUBSCRIPTION_ID=XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX
$ GROUP=demo_aks_fleetmng
$ FLEET=aks-fleet01
$ export FLEET_ID=/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${GROUP}/providers/Microsoft.ContainerService/fleets/${FLEET}
$ echo $ FLEET_ID
/subscriptions/XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/demo_aks_fleetmng/providers/Microsoft.ContainerService/fleets/aks-fleet01
$ export IDENTITY=$ (az ad signed-in-user show --query "id" --output tsv)
export ROLE="Azure Kubernetes Fleet Manager RBAC Cluster Admin"
az role assignment create --role "${ROLE}" --assignee ${IDENTITY} --scope ${FLEET_ID}
{
"canDelegate": null,
"condition": null,
"conditionVersion": null,
"description": null,
"id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/demo_aks_fleetmng/providers/Microsoft.ContainerService/fleets/aks-fleet01/providers/Microsoft.Authorization/roleAssignments/857ce606-0ea2-4350-8f7b-fff99dfeb325",
"name": “YYYYYYYYYYYYYYYYYYY”,
"principalId": “ZZZZZZZZZZZZZZZZZ”,
"principalType": "User",
"resourceGroup": "demo_aks_fleetmng",
"roleDefinitionId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX/providers/Microsoft.Authorization/roleDefinitions/YYYYYYYYYYYYYYYYYYY",
"scope": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/demo_aks_fleetmng/providers/Microsoft.ContainerService/fleets/aks-fleet01",
"type": "Microsoft.Authorization/roleAssignments"
}
az コマンドで fleet メンバー([AKS リソースグループ名]-[AKS 名])を確認
$ az fleet member list --resource-group demo_aks_fleetmng --fleet-name aks-fleet01 -o table
ClusterResourceId Name ProvisioningState ResourceGroup
---------------------------------------------------------------------------------------------------------------------------------------- --------------------- ------------------- -----------------
/subscriptions/XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/demo_aks01/providers/Microsoft.ContainerService/managedClusters/demo-aks01 demo-aks01-demo-aks01 Succeeded demo_aks_fleetmng
/subscriptions/XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/demo_aks01/providers/Microsoft.ContainerService/managedClusters/demo-aks02 demo-aks02-demo-aks01 Succeeded demo_aks_fleetmng
az fleet get-credentials
コマンドで、fleet ( hub
AKS )のクレデンシャルを取得し
kubectl get memberclusters
コマンドでも、fleet メンバー([AKS リソースグループ名]-[AKS 名])を確認をします。
$ az fleet get-credentials --resource-group demo_aks_fleetmng --name aks-fleet01
Merged "hub" as current context in /Users/XXXX/.kube/config
$ kubectl config current-context
hub
$ kubectl get memberclusters
NAME JOINED AGE
demo-aks01-demo-aks01 True 7h14m
demo-aks02-demo-aks01 True 5h42m
Tips2: kubelogin
について
hub
AKS への kubectl 接続には、ロールをアサインしたアカウントでの Azure ログイン認証が必要となります。
$ kubectl get memberclusters
Unable to connect to the server: getting credentials: exec: executable kubelogin not found
It looks like you are trying to use a client-go credential plugin that is not installed.
To learn more about this feature, consult the documentation available at:
https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins
$
ただし上記の通り、kubelogin not found
とエラーが出てしまう場合は
https://github.com/Azure/kubeloginを参考にkubelogin
をインストールします。
なお、Azure CloudShell を利用する場合は既にインストール済みなので不要です。
以下は Mac の場合に brew でインストールする例
$ brew install Azure/kubelogin/kubelogin
Running `brew update --auto-update`...
==> Auto-updated Homebrew!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(中略)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$
無事にインストールできると、以下のような感じで、ブラウザでのデバイスログインを求められますのでロールをアサインしたユーザーでログインします。
$ kubectl version
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXXX to authenticate.
〜 ブラウザでログイン後のつづき 〜
WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short. Use --output=yaml|json to get the full version.
Client Version: version.Info{Major:"1", Minor:"25", GitVersion:"v1.25.2", GitCommit:"5835544ca568b757a8ecae5c153f317e5736700e", GitTreeState:"clean", BuildDate:"2022-09-21T14:33:49Z", GoVersion:"go1.19.1", Compiler:"gc", Platform:"darwin/amd64"}
Kustomize Version: v4.5.7
Unable to connect to the server: context deadline exceeded (Client.Timeout exceeded while awaiting headers)
$
3. 複数 AKS クラスタを跨ぐ MultiClusterService
の L4 負荷分散を試す
準備ができたので、以下を参考に、kuard ( Kuberentes up and running demo )のデモアプリを使った、複数の AKS クラスタを跨ぐマルチクラスター間での L4 負荷分散を以下の流れでためしていきます。
-
MultiClusterService
の前提条件 -
hub
AKS へデモアプリをデプロイする -
ClusterResourcePlacement
により、Fleet メンバーへ伝搬させる -
MultiClusterService
の適用 -
MultiClusterService
による L4 負荷分散の検証
3.1. MultiClusterService
の前提条件
MultiClusterService
による L4 負荷分散の前提条件は以下の通り(詳細はこちら)です。
- 対象 AKS クラスタが 同一の Fleet Manager のメンバーとなっている
- 対象 AKS クラスタが Azure CNI を利用している
- 対象 AKS クラスタが同一 VNet または、VNet ピアリング接続されている
また、Kubectl コマンドにて各 AKS クラスタへの操作ができることを前提とします。
-
hub
およびメンバーの AKS クラスタのクレデンシャル(kubeconfig)が取得できている -
kubectl
コマンドおよび、kubelogin
プラグイン( Tips2 参照)がインストールされている
3.2. hub
AKS へデモアプリをデプロイする
まずは、kubeconfig の接続先( current-context )を hub
AKS に設定し、
kubectl config use-context hub
デモアプリをデプロイする k8s namespace
を作成します
kubectl create ns kuard-demo
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
demo-aks01 demo-aks01 clusterUser_demo_aks01_demo-aks01
demo-aks02 demo-aks02 clusterUser_demo_aks01_demo-aks02
* hub hub clusterUser_FL_demo_aks_fleetmng_aks-fleet01_eastus_hub
$ kubectl config use-context hub
Switched to context "hub".
$
$ kubectl create ns kuard-demo
namespace/kuard-demo created
$ kubectl get ns
NAME STATUS AGE
default Active 22d
fleet-member-demo-aks01-demo-aks01 Active 21d
fleet-member-demo-aks02-demo-aks01 Active 21d
hello-world Active 21d
kuard-demo Active 1m33s
kube-node-lease Active 22d
kube-public Active 22d
kube-system Active 22d
$
つづいて、kuard のデモアプリを hub
aks へデプロイします。
kubectl apply -f https://raw.githubusercontent.com/Azure/AKS/master/examples/fleet/kuard/kuard-export-service.yaml
apply するマニフェストファイルの内容は以下の通り
apiVersion: apps/v1
kind: Deployment
metadata:
name: kuard
namespace: kuard-demo
spec:
replicas: 2
selector:
matchLabels:
app: kuard
template:
metadata:
labels:
app: kuard
spec:
containers:
- name: kuard
image: gcr.io/kuar-demo/kuard-amd64:blue
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: kuard
namespace: kuard-demo
labels:
app: kuard
spec:
ports:
- port: 8080
selector:
app: kuard
---
apiVersion: networking.fleet.azure.com/v1alpha1
kind: ServiceExport
metadata:
name: kuard
namespace: kuard-demo
実行結果の例は以下の通りです。
- 特徴的なのは、
deployment
でreplicas: 2
と設定されているのにも関わらず READY 状態が0/2
とpod
が起動していないことがわかります。また、serviceexport
も機能していません。 - これは Tips1 にも記載の通り、
hub
AKS ノードの CPU やメモリのリソースを無駄に消費させないためのものとなります。
$ kubectl apply -f https://raw.githubusercontent.com/Azure/AKS/master/examples/fleet/kuard/kuard-export-service.yaml
deployment.apps/kuard created
service/kuard created
serviceexport.networking.fleet.azure.com/kuard created
$ kubectl get all -n kuard-demo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kuard ClusterIP 10.0.148.120 <none> 8080/TCP 4m13s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kuard 0/2 0 0 4m13s
$ kubectl get serviceexport kuard -n kuard-demo
NAME IS-VALID IS-CONFLICTED AGE
kuard 21d
3.3. ClusterResourcePlacement
により、Fleet メンバーへ伝搬させる
つづいて、hub
AKS 内のデモアプリのリソースを、メンバーの AKS クラスタへ 伝搬させるために
Kind: ClusterResourcePlacement
の以下のマニフェストファイルkuard-crp.yaml
を作成し hub
AKS へ apply します。
こちらは hub
AKS 内の K8s namespace kuard-demo
の内容を Fleet メンバーの AKS クラスタのうち、条件として clusterSelectorTerms
で指定した eastus
にデプロイされている AKS にへ 伝搬します。
apiVersion: fleet.azure.com/v1alpha1
kind: ClusterResourcePlacement
metadata:
name: kuard-demo
spec:
resourceSelectors:
- group: ""
version: v1
kind: Namespace
name: kuard-demo
policy:
affinity:
clusterAffinity:
clusterSelectorTerms:
- labelSelector:
matchLabels:
fleet.azure.com/location: eastus
apply 結果の例
$ kubectl apply -f kuard-crp.yaml
clusterresourceplacement.fleet.azure.com/kuard-demo created
$ kubectl get clusterresourceplacements.fleet.azure.com
NAME GEN SCHEDULED SCHEDULEDGEN APPLIED APPLIEDGEN AGE
kuard-demo 1 True 1 True 1 3m10s
$
つづいて、Fleet メンバーの AKS へ 伝搬されていることを確認します。
kubeconfig の接続先( current-context
)をdemo-aks01
,demo-aks02
にそれぞれ切り替えて確認します。
以下確認結果
hub
AKS でKind: ClusterResourcePlacement
で設定したとおり、k8s namespace
kuard-demo
内のリソース含めてメンバーへ伝搬されていることが確認できます。また、pod
やserviceexport
も正常に機能しています。
$ kubectl config use-context demo-aks01
Switched to context "demo-aks01".
$ kubectl get all -n kuard-demo
NAME READY STATUS RESTARTS AGE
pod/kuard-7788d9bc5-8f8fz 1/1 Running 0 9d
pod/kuard-7788d9bc5-nqztl 1/1 Running 0 9d
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kuard ClusterIP 10.0.171.245 <none> 8080/TCP 21d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kuard 2/2 2 2 9d
NAME DESIRED CURRENT READY AGE
replicaset.apps/kuard-7788d9bc5 2 2 2 9d
$ kubectl get serviceexport kuard -n kuard-demo
NAME IS-VALID IS-CONFLICTED AGE
kuard True False 9d
$
$ kubectl config use-context demo-aks02
Switched to context "demo-aks02".
$ kubectl get all -n kuard-demo
NAME READY STATUS RESTARTS AGE
pod/kuard-7788d9bc5-bzsnb 1/1 Running 0 9d
pod/kuard-7788d9bc5-hcdzp 1/1 Running 0 9d
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kuard ClusterIP 10.0.153.57 <none> 8080/TCP 21d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kuard 2/2 2 2 9d
NAME DESIRED CURRENT READY AGE
replicaset.apps/kuard-7788d9bc5 2 2 2 9d
$ kubectl get serviceexport kuard -n kuard-demo
NAME IS-VALID IS-CONFLICTED AGE
kuard True False 9d
$
Tips3: kubeconfig context の切り替えについて
複数の Kubernets クラスタへの接続 context を切り替えたい場合
kubectx を利用すると便利です。
kubectl config get-contexts
や kubectl config use-context
のコマンドをそれぞれ、kubectx
とkubectx [context名]
に置き換えられます
色が異なっているのがcurrent context
です。
3.4. MultiClusterService
の適用
Fleet メンバーのいずれにか(今回は demo-aks01
)に、MultiClusterService
を適用し、事前にservicexport
されているエンドポイント間を L4 負荷分散します。
kubectl apply -f https://raw.githubusercontent.com/Azure/AKS/master/examples/fleet/kuard/kuard-mcs.yaml
apiVersion: networking.fleet.azure.com/v1alpha1
kind: MultiClusterService
metadata:
name: kuard
namespace: kuard-demo
spec:
serviceImport:
name: kuard
以下、実行結果の例
$ kubectl config use-context demo-aks01
Switched to context "demo-aks01".
$ kubectl apply -f https://raw.githubusercontent.com/Azure/AKS/master/examples/fleet/kuard/kuard-mcs.yaml
multiclusterservice.networking.fleet.azure.com/kuard created
$ kubectl get MultiClusterService -n kuard-demo
NAME SERVICE-IMPORT EXTERNAL-IP IS-VALID AGE
kuard kuard XXX.XXX.XXX.XXX True 9d
$ kubectl get all -n fleet-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kuard-demo-kuard LoadBalancer 10.0.20.159 XXX.XXX.XXX.XXX 8080:31125/TCP 9d
$
*:上記でEXTERNAL-IP
はXXX.XXX.XXX.XXX
へマスクしています
MultiClusterService
の EXTERNAL-IP
:8080 へブラウザよりアクセスし kuard デモアプリが表示されることを確認します。
また、デモアプリでは、pod名
とpodのIPアドレス
が確認できます。
3.5. MultiClusterService
による L4 負荷分散の検証
つづいて、複数クラスタを跨いで L4 負荷分散されることを確認します。
それぞれの AKS クラスタ上で動作しているデモアプリのpod 名
とpod の IP アドレス
を確認します。
$ kubectl config use-context demo-aks01
Switched to context "demo-aks01".
$ kubectl get po -o wide -n kuard-demo
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kuard-7788d9bc5-8f8fz 1/1 Running 0 9d 10.224.0.104 aks-agentpool-35471025-vmss000003 <none> <none>
kuard-7788d9bc5-nqztl 1/1 Running 0 9d 10.224.0.43 aks-agentpool-35471025-vmss000003 <none> <none>
$ kubectl config use-context demo-aks02
Switched to context "demo-aks02".
$ kubectl get po -o wide -n kuard-demo
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kuard-7788d9bc5-bzsnb 1/1 Running 0 9d 10.225.0.60 aks-agentpool-33918313-vmss000003 <none> <none>
kuard-7788d9bc5-hcdzp 1/1 Running 0 9d 10.225.0.29 aks-agentpool-33918313-vmss000003 <none> <none>
$
上記を表にまとめると
AKS 名 | pod 名 | pod の IP アドレス |
IP アドレスの 2オクテット目 |
---|---|---|---|
demo-aks01 |
kuard-7788d9bc5-8f8fz | 10.224.0.104 | 224 |
demo-aks01 |
kuard-7788d9bc5-nqztl | 10.224.0.43 | 224 |
demo-aks02 |
kuard-7788d9bc5-bzsnb | 10.225.0.60 | 225 |
demo-aks02 |
kuard-7788d9bc5-hcdzp | 10.225.0.29 | 225 |
IP アドレスの2オクテット目に注目すると、どちらの AKS クラスタで動いているか簡易に判別できることがわかります。
-
demo-aks01
のpodのIPアドレス
: 10.224.0.XXX- 2オクテット目が 224
-
demo-aks02
のpodのIPアドレス
: 10.225.0.XXX- 2オクテット目が 225
そこで、1秒毎にcurl
コマンドを発行し、pod 名
とpod の IP アドレス
を確認します。
確認用のcurl
コマンドは以下
watch -n 1 "curl -s XXX.XXX.XXX.XXX:8080 | grep hostname | sed 's/var pageContext = //g' | jq | sed 's/XXX.XXX.XXX.XXX/xxx.xxx.xxx.xxx/g'"
*:上記でEXTERNAL-IP
はXXX.XXX.XXX.XXX
へマスクしています。
以下の通り、複数クラスタを跨いで L4 負荷分散されること確認できました。
curl
リクエスト毎に上記 json 出力結果の
-
pod 名
(=hostname
)とpod の IP アドレス
(=addrs
)が変化している- 複数
pod
間で L4 負荷分散されている
- 複数
-
pod の IP アドレス
(=addrs
)の2オクテット目が、224, 225 と変化している- 複数の AKS クラスタを跨いで L4 負荷分散されている
4. ロードマップ
ロードマップの最新状況については以下 Github 上で公開されています
5. さいごに
今回、Azure Kubernetes Fleet Manager を試してみた感想ですが、
特に複雑な部分はないと思いますので、普段 AKS を触っている方達は特に抵抗なく利用できるのではと思います。
パブリックプレビュー直後ということもあり、現在提供されている機能の多くは、例えば同一のリポジトリを複数クラスタから参照する GitOps の活用や、Azure の各種負荷分散機能の組み合わせにて代替可能な部分も多いと思いますが、個人的にはとても興味深いサービスだと思いますので、今後のロードマップによる機能拡充にも期待しています。
6. 参考URL