はじめに
こんにちは、ACS事業部の吉川です。
先日行われたIgniteで Azure Kubernetes Fleet Manager という新サービスが発表されました。
『Fleet』は「船団」という意味の英単語で、複数のAKSクラスターを束ねる機能のようです。
どんなサービスなのか、さっそく触ってみました。
手順などは以下の公式ドキュメントを参考にしていますが、パラメーターなど一部を変更しています。
検証環境
検証するにあたり以下のような構成を作成します。
まずはAzure Kubernetes Fleet Manager(以下、Fleet Managerと表記します)を作成しましょう。
# サブスクリプションでFleetResourcePreviewを有効化 az feature register --namespace Microsoft.ContainerService --name FleetResourcePreview # Azure CLIのfleet拡張機能をインストール az extension add --name fleet # リソースグループ作成 az group create -l japaneast -n rg-fleetmanager # Fleet Managerを作成 az fleet create -n kfm-sample -g rg-fleetmanager -l japaneast
なお、Fleet Mnager自身もひとつのAKSクラスターで構成されています。
ポータルから確認すると FL_<リソースグループ名>_<リソース名>_<リージョン名>
という名前のリソースグループ内に hub
というAKSクラスターが確認できます。
続いてFleetに所属させるAKSクラスターを作成していきます。
# リソースグループ作成 az group create -l japaneast -n rg-japaneast1 az group create -l japaneast -n rg-japaneast2 az group create -l japanwest -n rg-japanwest1 # VNet/サブネットの作成 az network vnet create -n vnet-japaneast -g rg-japaneast1 -l japaneast \ --address-prefixes 192.168.0.0/16 az network vnet subnet create -n snet-japaneast1 \ --vnet-name vnet-japaneast -g rg-japaneast1 \ --address-prefixes 192.168.0.0/24 az network vnet subnet create -n snet-japaneast2 \ --vnet-name vnet-japaneast -g rg-japaneast1 \ --address-prefixes 192.168.1.0/24 az network vnet create -n vnet-japanwest -g rg-japanwest1 -l japanwest \ --address-prefixes 192.168.0.0/16 az network vnet subnet create -n snet-japanwest1 \ --vnet-name vnet-japanwest -g rg-japanwest1 \ --address-prefixes 192.168.10.0/24 # AKSクラスターを3つ作成 SUBNET_ID1=$(az network vnet subnet show -n snet-japaneast1 \ --vnet-name vnet-japaneast -g rg-japaneast1 --query id -o tsv) az aks create -g rg-japaneast1 -n aks-fleetmember1 -l japaneast \ --node-count 1 --network-plugin azure --vnet-subnet-id $SUBNET_ID1 SUBNET_ID2=$(az network vnet subnet show -n snet-japaneast2 \ --vnet-name vnet-japaneast -g rg-japaneast1 --query id -o tsv) az aks create -g rg-japaneast2 -n aks-fleetmember2 -l japaneast \ --node-count 1 --network-plugin azure --vnet-subnet-id $SUBNET_ID2 SUBNET_ID3=$(az network vnet subnet show -n snet-japanwest1 \ --vnet-name vnet-japanwest -g rg-japanwest1 --query id -o tsv) az aks create -g rg-japanwest1 -n aks-fleetmember3 -l japanwest \ --node-count 1 --network-plugin azure --vnet-subnet-id $SUBNET_ID3 # 認証情報を取得 az aks get-credentials -g rg-japaneast1 -n aks-fleetmember1 az aks get-credentials -g rg-japaneast2 -n aks-fleetmember2 az aks get-credentials -g rg-japanwest1 -n aks-fleetmember3
作成した3つのAKSクラスターを、Fleet Managerのメンバーとして登録していきます。
AKS_ID1=$(az aks show -g rg-japaneast1 -n aks-fleetmember1 --query id -o tsv) az fleet member create --fleet-name kfm-sample -g rg-fleetmanager \ --name aks-fleetmember1 --member-cluster-id $AKS_ID1 AKS_ID2=$(az aks show -g rg-japaneast2 -n aks-fleetmember2 --query id -o tsv) az fleet member create --fleet-name kfm-sample -g rg-fleetmanager \ --name aks-fleetmember2 --member-cluster-id $AKS_ID2 AKS_ID3=$(az aks show -g rg-japanwest1 -n aks-fleetmember3 --query id -o tsv) az fleet member create --fleet-name kfm-sample -g rg-fleetmanager \ --name aks-fleetmember3 --member-cluster-id $AKS_ID3
最後に作成したFleet ManagerにIAMロールを設定します。
ここでは私自身のユーザーを Azure Kubernetes Fleet Manager RBAC Cluster Admin
ロールとして割り当てています。
これで構成の準備は完了です。
以下のようにしてFleetに所属させたメンバーの状態を確認してみましょう。
上記で触れたように、Fleet Manager自身もAKSクラスターで構成されています。そのため、Fleet Managerに対する操作も kubectlで行う というところがポイントですね。
# Fleet Managerの認証情報を取得 az fleet get-credentials -n kfm-sample -g rg-fleetmanager # メンバーの情報を表示 kubectl get memberclusters
NAME JOINED AGE aks-fleetmember1-rg-japaneast1 True 22h aks-fleetmember2-rg-japaneast2 True 22h aks-fleetmember3-rg-japanwest1 True 22h
さて、Fleet Managerの主な機能は以下の2つです。
- リソースの伝達
- L4負荷分散
作成した環境をもとに、それぞれの機能を確認していきましょう。
機能1. リソースの伝達
1つ目の機能 リソースの伝達 では、Fleet ManagerからメンバーのAKSクラスターに対しリソースのデプロイ情報を伝搬することができます。
さっそく試してみましょう。
まずはFleet Managerに対し、以下のマニフェストをデプロイします。
apiVersion: v1 kind: Namespace metadata: name: demo --- apiVersion: apps/v1 kind: Deployment metadata: name: kuard namespace: 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 --- apiVersion: v1 kind: Service metadata: name: kuard namespace: demo labels: app: kuard spec: selector: app: kuard type: LoadBalancer ports: - port: 80 targetPort: 8080
# Fleet Managerのクラスターに対しデプロイ kubectl config use-context hub kubectl apply -f propagate-sample.yaml
Fleet Managerクラスターの状態を見ると、Load BalancerのIPはpendingのまま、Podは起動していません。
Fleet Manager自身はアプリケーションを稼働させるための環境ではないので、これが正常な状態です。
kubectl get all -n demo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kuard LoadBalancer 10.0.130.141 <pending> 80:31202/TCP 35s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/kuard 0/2 0 0 37s
Fleet Managerからメンバークラスターにリソースを伝達させるために、ClusterResourcePlacement というカスタムリソースを作成します。
以下のマニフェストはFleet Managerのdemo
名前空間のリソースをメンバーへ伝達するためのものです。
apiVersion: fleet.azure.com/v1alpha1 kind: ClusterResourcePlacement metadata: name: demo-crp spec: resourceSelectors: - group: "" version: v1 kind: Namespace name: demo
これをFleet Managerクラスターにデプロイします。
kubectl apply -f crp-1.yaml
以下のコマンドで、SCHEDULEDとAPPLIEDの項目が True
となっていることを確認します。
kubectl get clusterresourceplacement demo-crp
NAME GEN SCHEDULED SCHEDULEDGEN APPLIED APPLIEDGEN AGE demo-crp 1 True 1 True 1 105s
これでメンバークラスターに対しリソースが伝達されています。
状態を確認してみましょう。
【aks-fleetmember1】
kubectl config use-context aks-fleetmember1
kubectl get all -n demo
NAME READY STATUS RESTARTS AGE pod/kuard-6fcbf7b5b5-rrvnl 1/1 Running 0 4m24s pod/kuard-6fcbf7b5b5-xsbnk 1/1 Running 0 4m24s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kuard LoadBalancer 10.0.57.103 @@@.@@@.@@@.@@@ 80:31729/TCP 4m24s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/kuard 2/2 2 2 4m24s NAME DESIRED CURRENT READY AGE replicaset.apps/kuard-6fcbf7b5b5 2 2 2 4m24s
【aks-fleetmember2】
kubectl config use-context aks-fleetmember2
kubectl get all -n demo
NAME READY STATUS RESTARTS AGE pod/kuard-6fcbf7b5b5-dw47x 1/1 Running 0 6m pod/kuard-6fcbf7b5b5-lr797 1/1 Running 0 6m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kuard LoadBalancer 10.0.70.168 @@@.@@@.@@@.@@@ 80:30781/TCP 6m1s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/kuard 2/2 2 2 6m1s NAME DESIRED CURRENT READY AGE replicaset.apps/kuard-6fcbf7b5b5 2 2 2 6m1s
【aks-fleetmember3】
kubectl config use-context aks-fleetmember3
kubectl get all -n demo
NAME READY STATUS RESTARTS AGE pod/kuard-6fcbf7b5b5-n8qjw 1/1 Running 0 6m35s pod/kuard-6fcbf7b5b5-vh6dm 1/1 Running 0 6m35s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kuard LoadBalancer 10.0.233.14 @@@.@@@.@@@.@@@ 80:32022/TCP 6m35s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/kuard 2/2 2 2 6m35s NAME DESIRED CURRENT READY AGE replicaset.apps/kuard-6fcbf7b5b5 2 2 2 6m36s
上記のように、Fleet Managerのデプロイ情報が配下のメンバーに対し伝達されていることがわかると思います。
Fleet Manager側に変更を加えるとメンバー側にも変更が伝達されます。
# Fleet Manager側でレプリカ数を2→1へ変更 kubectl config use-context hub kubectl scale deployment --replicas=1 kuard -n demo # aks-fleetmember1でレプリカ数を確認 kubectl config use-context aks-fleetmember1 kubectl get deployment kuard -n demo
NAME READY UP-TO-DATE AVAILABLE AGE kuard 1/1 1 1 18m
また、ClusterResourcePlacementにpolicyの記述を加えることで、リソースの伝達範囲を制限することができます。
以下のように変更することで、東日本リージョンのクラスターのみに限定することができます。
(既に伝達済みの西日本リージョンのリソースは削除されます)
apiVersion: fleet.azure.com/v1alpha1 kind: ClusterResourcePlacement metadata: name: demo-crp spec: resourceSelectors: - group: "" version: v1 kind: Namespace name: demo policy: affinity: clusterAffinity: clusterSelectorTerms: - labelSelector: matchLabels: fleet.azure.com/location: japaneast
# 東日本のみに伝達範囲を制限 kubectl config use-context hub kubectl apply -f crp-2.yaml # 西日本のaks-fleetmember3で状態確認 kubectl config use-context aks-fleetmember3 kubectl get namespaces
伝達されたdemo名前空間がなくなっていることが確認できます。
NAME STATUS AGE default Active 23h fleet-system Active 23h kube-node-lease Active 23h kube-public Active 23h kube-system Active 23h
機能2. L4負荷分散
2つ目の機能 L4負荷分散 ではロードバランサーで複数のクラスターにまたがった負荷分散を実現します。
この機能を利用する条件として以下がありますのでご注意ください。
- Azure CNIを利用すること
- 負荷分散対象のクラスターが同一のVNet or ピアリングされたVNetに配置されていること
今回は同一VNetに配置したaks-fleetmember1, aks-fleetmember2の2つのクラスター間での負荷分散を確認します。
負荷分散を行うためには、まず ServiceExport
という名前のカスタムリソースを作成する必要があります。
apiVersion: networking.fleet.azure.com/v1alpha1 kind: ServiceExport metadata: name: kuard namespace: demo
これをFleet Managerにデプロイします。
前節の伝達設定により、東日本リージョンのメンバーであるaks-fleetmember1, aks-fleetmember2に対しリソースが伝達されます。
kubectl config use-context hub
kubectl apply -f service-export.yaml
続いて MultiClusterService
というカスタムリソースのマニフェストを準備します。
apiVersion: networking.fleet.azure.com/v1alpha1 kind: MultiClusterService metadata: name: kuard namespace: demo spec: serviceImport: name: kuard
これを 負荷分散対象のメンバークラスターのどれか1つ にデプロイします。
今回はaks-fleetmember1を利用します。
kubectl config use-context aks-fleetmember1
kubectl apply -f multi-cluster-service.yaml
以下のコマンドで負荷分散用のIPアドレスを確認します。
kubectl get multiclusterservice -n demo
NAME SERVICE-IMPORT EXTERNAL-IP IS-VALID AGE kuard kuard @@@.@@@.@@@.@@@ True 77s
このIPアドレスに対してリクエストを投げてみましょう。
サンプルでデプロイしたコンテナは自身のホスト名・IPアドレスを返してくれるため、レスポンスからどちらのクラスターで動いているかが判別可能です。
curl @@@.@@@.@@@.@@@ -s | grep addrs
今回の環境では 192.168.0.0/24 であれば aks-fleetmember1、
var pageContext = {"urlBase":"","hostname":"kuard-6fcbf7b5b5-rrvnl","addrs":["192.168.0.13"],~以下略~
192.168.1.0/24 であれば aks-fleetmember2 であると判別できます。
var pageContext = {"urlBase":"","hostname":"kuard-6fcbf7b5b5-lr797","addrs":["192.168.1.29"],~以下略~
これで2つのクラスター上のPodに対し負荷分散できていることが確認できました。
おわりに
複数のAKSクラスターを管理するのに便利に使えそうな Azure Kubernetes Fleet Manager の紹介でした。
特にリソースの伝達機能は、例えばDR環境で複数リージョンに配置したクラスターに同一アプリケーションをデプロイするなどの用途に向いていると思います。
L4負荷分散機能は、Application Gatewayなどの外部のLBサービスを経由しなくても複数クラスタ間での負荷分散ができるのは便利そうですね。
まだプレビューの機能ではありますが、今後のロードマップについてGitHub上で確認することができます。
今後の機能追加が楽しみですね。引き続きウォッチしていきたいと思います。