適用対象: ✔️ ハブ クラスターを含む Fleet Manager
Azure Kubernetes Fleet Manager の段階的更新実行は、ステージごとのプロセスを使用して、複数のメンバークラスターに Kubernetes ワークロードをデプロイするための制御されたアプローチを提供します。 リスクを最小限に抑えるために、このアプローチは、オプションの待機時間とステージ間の承認ゲートを使用して、対象となるクラスターに順番にデプロイされます。
この記事では、段階的な更新実行を作成して実行し、ワークロードを段階的にデプロイし、必要に応じて以前のバージョンにロールバックする方法について説明します。
Azure Kubernetes Fleet Manager では、段階的な更新の 2 つのスコープがサポートされています。
-
クラスター全体への適用: インフラストラクチャ レベルの変更を管理するフリート管理者は、
ClusterStagedUpdateRunとClusterResourcePlacementを併用します。 -
名前空間スコープ:
StagedUpdateRunは、特定の名前空間内でのロールアウトを管理するアプリケーションチームのResourcePlacementと併用してください。
Important
ResourcePlacement では、 placement.kubernetes-fleet.io/v1beta1 API バージョンが使用され、現在プレビュー段階です。
ResourceSnapshotなど、この記事で示されている一部の機能も v1beta1 API の一部であり、v1 API では使用できません。
この記事の例では、タブを使用する両方の方法を示します。 デプロイ スコープに一致するタブを選択します。
開始する前に
Prerequisites
アクティブなサブスクリプションを持つAzure アカウントが必要です。 無料でアカウントを作成できます。
この記事で使用される概念と用語を理解するには、 段階的なロールアウト戦略の概念の概要を参照してください。
この記事Azure CLI完了するには、バージョン 2.58.0 以降がインストールされている必要があります。 インストールまたはアップグレードするには、Azure CLI のインストールを参照してください。
Kubernetes CLI (kubectl) がまだインストールされていない場合は、次のコマンドを使用してインストールしてください。
az aks install-clifleetAzure CLI 拡張子が必要です。 これは、次のコマンドを実行してインストールできます。az extension add --name fleet最新バージョンの拡張機能に更新するには、
az extension updateコマンドを実行します。az extension update --name fleet
デモ環境を構成する
このデモは、ハブ クラスターと 3 つのメンバー クラスターを持つ Fleet Manager で実行されます。 お持ちでない場合は、 クイックスタート に従って、ハブ クラスターを使用して Fleet Manager を作成します。 次に、Azure Kubernetes Service (AKS) クラスターをメンバーとして参加させます。
このチュートリアルでは、次のラベルを持つ 3 つのメンバー クラスターを含むデモフリート環境を使用して、段階的な更新実行を示します。
| メンバー名 | labels |
|---|---|
| member1 | environment=canary, order=2 |
| member2 | environment=staging |
| member3 | environment=canary,order=1 |
これらのラベルを使用すると、ステージを作成し、各ステージ内の配置順序を制御できます。
表示されたコマンドを使用して、メンバー クラスターにラベルを適用します。
az fleet member update \
--resource-group $GROUP \
--fleet-name $FLEET_NAME \
--name member2 \
--labels environment=staging
配置用に Kubernetes ワークロードを準備する
Kubernetes ワークロードをハブ クラスターに発行して、メンバー クラスターに配置できるようにします。
ハブ クラスターでワークロードの名前空間と ConfigMap を作成します。
kubectl create namespace test-namespace
kubectl create configmap test-cm --from-literal=key=value1 -n test-namespace
リソースをデプロイするには、 ClusterResourcePlacementを作成します。
Note
spec.strategy.typeはExternalに設定され、ClusterStagedUpdateRunでロールアウトがトリガーされます。
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterResourcePlacement
metadata:
name: example-placement
spec:
resourceSelectors:
- group: ""
kind: Namespace
name: test-namespace
version: v1
policy:
placementType: PickAll
strategy:
type: External
PickAll ポリシーを使用するため、3 つのクラスターはすべてスケジュールする必要がありますが、ClusterStagedUpdateRunを作成していないため、まだメンバー クラスターにリソースをデプロイする必要はありません。
配置がスケジュールされていることを確認します。
kubectl get clusterresourceplacement example-placement
出力は次の例のようになります。
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 51s
段階的な更新戦略を作成する
ClusterStagedUpdateStrategyは、クラスターをステージにグループ化するオーケストレーション パターンを定義し、ロールアウト シーケンスを指定します。 ラベルによってメンバー クラスターが選択されます。 デモでは、ステージングとカナリアの 2 段階 から成るものを作成します:
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateStrategy
metadata:
name: example-strategy
spec:
stages:
- name: staging
labelSelector:
matchLabels:
environment: staging
afterStageTasks:
- type: TimedWait
waitTime: 1m
maxConcurrency: 1
- name: canary
labelSelector:
matchLabels:
environment: canary
sortingLabelKey: order
beforeStageTasks:
- type: Approval
maxConcurrency: 50%
リソース スナップショットの操作
フリートマネージャーは、配置に RollingUpdateのロールアウト戦略がある場合、リソースが変更されたときにリソーススナップショットを作成します。 各スナップショットには、リソースの特定のバージョンを参照するために使用できる一意のインデックスがあります。
配置で External ロールアウト戦略が使用されている場合、リソース スナップショットは自動的に作成されません。 代わりに、段階的な更新プログラムの実行を実行するときに作成されます。 つまり、 External ロールアウト戦略を使用して配置を最初に作成した場合、最初の段階的な更新プログラムの実行を実行するまでリソース スナップショットは存在しません。
Note
配置が以前に RollingUpdate 戦略を使用していて、 Externalに変更された場合、既存のリソース スナップショットは引き続き使用できます。 ステージング更新実行を作成するときに、これらの既存のスナップショットを参照できます。
Tip
リソース スナップショットとその動作の詳細については、 リソース スナップショットを参照してください。
現在のリソース スナップショットを確認する
ClusterResourcePlacementはExternal戦略を使用するため、リソース スナップショットはまだ存在しません。 次のことを確認しましょう。
kubectl get clusterresourcesnapshots --show-labels
出力にはリソースが表示されないはずです。
No resources found
最初のリソース スナップショットを作成する
最初のリソース スナップショットを作成するには、ClusterStagedUpdateRun フィールドを省略してresourceSnapshotIndexを作成する必要があります。 更新実行コントローラーは、スナップショットが存在しないことを検出し、スナップショットを自動的に作成します。
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-initial-run
spec:
placementName: example-placement
stagedRolloutStrategyName: example-strategy
state: Run
更新プログラムの実行が完了したら、リソース スナップショットを確認します。
kubectl get clusterresourcesnapshots --show-labels
出力は次の例のようになります。
NAME GEN AGE LABELS
example-placement-0-snapshot 1 60s kubernetes-fleet.io/is-latest-snapshot=true,kubernetes-fleet.io/parent-CRP=example-placement,kubernetes-fleet.io/resource-index=0
これで、スナップショットのバージョンが 1 つになりました。 最新の (kubernetes-fleet.io/is-latest-snapshot=true) であり、リソース インデックス 0 (kubernetes-fleet.io/resource-index=0) を持ちます。
新しいリソース スナップショットを作成する
次に、ConfigMap を新しい値で変更します。
kubectl edit configmap test-cm -n test-namespace
値を value1 から value2 に更新します。
kubectl get configmap test-cm -n test-namespace -o yaml
出力は次の例のようになります。
apiVersion: v1
data:
key: value2 # value updated here, old value: value1
kind: ConfigMap
metadata:
creationTimestamp: ...
name: test-cm
namespace: test-namespace
resourceVersion: ...
uid: ...
配置では External 戦略が使用されるため、新しいリソース スナップショットは自動的に作成されません。 新しいスナップショットの作成をトリガーするために、ClusterStagedUpdateRun フィールドを省略して別のresourceSnapshotIndexを作成します。
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-snapshot-run
spec:
placementName: example-placement
stagedRolloutStrategyName: example-strategy
state: Run
更新プログラムの実行が完了すると、それぞれインデックス 0 と 1 の 2 つのバージョンのリソース スナップショットが表示されます。最新のバージョンはインデックス 1 です。
kubectl get clusterresourcesnapshots --show-labels
出力は次の例のようになります。
NAME GEN AGE LABELS
example-placement-0-snapshot 1 2m6s kubernetes-fleet.io/is-latest-snapshot=false,kubernetes-fleet.io/parent-CRP=example-placement,kubernetes-fleet.io/resource-index=0
example-placement-1-snapshot 1 10s kubernetes-fleet.io/is-latest-snapshot=true,kubernetes-fleet.io/parent-CRP=example-placement,kubernetes-fleet.io/resource-index=1
最新のラベルは、最新の ConfigMap データを含む example-placement-1-snapshot に設定されます。
kubectl get clusterresourcesnapshots example-placement-1-snapshot -o yaml
出力は次の例のようになります。
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterResourceSnapshot
metadata:
annotations:
kubernetes-fleet.io/number-of-enveloped-object: "0"
kubernetes-fleet.io/number-of-resource-snapshots: "1"
kubernetes-fleet.io/resource-hash: 10dd7a3d1e5f9849afe956cfbac080a60671ad771e9bda7dd34415f867c75648
creationTimestamp: "2025-07-22T21:26:54Z"
generation: 1
labels:
kubernetes-fleet.io/is-latest-snapshot: "true"
kubernetes-fleet.io/parent-CRP: example-placement
kubernetes-fleet.io/resource-index: "1"
name: example-placement-1-snapshot
ownerReferences:
- apiVersion: placement.kubernetes-fleet.io/v1
blockOwnerDeletion: true
controller: true
kind: ClusterResourcePlacement
name: example-placement
uid: e7d59513-b3b6-4904-864a-c70678fd6f65
resourceVersion: "19994"
uid: 79ca0bdc-0b0a-4c40-b136-7f701e85cdb6
spec:
selectedResources:
- apiVersion: v1
kind: Namespace
metadata:
labels:
kubernetes.io/metadata.name: test-namespace
name: test-namespace
spec:
finalizers:
- kubernetes
- apiVersion: v1
data:
key: value2 # latest value: value2, old value: value1
kind: ConfigMap
metadata:
name: test-cm
namespace: test-namespace
ロールアウトの変更に合わせて段階的な更新プログラムの実行を準備する
ClusterStagedUpdateRunは、ClusterResourcePlacementに従ってClusterStagedUpdateStrategyのロールアウトを実行します。 ClusterResourcePlacement (CRP) のステージング更新実行をトリガーするために、CRP 名、updateRun 戦略名、最新のリソース スナップショット インデックス ("1")、状態を "Initialize" として指定する ClusterStagedUpdateRun を作成します。
Note
Externalロールアウト戦略を使用する場合は、最新のリソースをデプロイする場合は、resourceSnapshotIndex フィールドを省略できます。 更新実行コントローラーでは、 resourceSnapshotIndex を省略すると、新しいリソース スナップショットが自動的に作成されます。
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-run
spec:
placementName: example-placement
resourceSnapshotIndex: "1"
stagedRolloutStrategyName: example-strategy
state: Initialize
ステージングされた更新プログラムの実行は初期化されますが、実行されていません。
kubectl get clusterstagedupdaterrun example-run
出力は次の例のようになります。
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
段階的な更新プログラムの実行を開始する
段階的な更新プログラムの実行を開始するには、仕様の state フィールドに修正プログラムを適用して Runする必要があります。
kubectl patch clusterstagedupdaterrun example-run --type merge -p '{"spec":{"state":"Run"}}'
Note
最初にstateに設定されたRun フィールドを使用して更新プログラムの実行を作成することもできます。このフィールドは、更新プログラムの実行を 1 回の手順で初期化して開始します。
ステージングされた更新プログラムの実行が初期化され、実行されます。
kubectl get clusterstagedupdaterrun example-run
出力は次の例のようになります。
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
1 分間の TimedWait が経過した後の状態の詳細を次に示します。
kubectl get clusterstagedupdaterrun example-run -o yaml
出力は次の例のようになります。
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
...
name: example-run
...
spec:
placementName: example-placement
resourceSnapshotIndex: "1"
stagedRolloutStrategyName: example-strategy
state: Run
status:
conditions:
- lastTransitionTime: "2025-07-22T21:28:08Z"
message: ClusterStagedUpdateRun initialized successfully
observedGeneration: 2
reason: UpdateRunInitializedSuccessfully
status: "True" # the updateRun is initialized successfully
type: Initialized
- lastTransitionTime: "2025-07-22T21:29:53Z"
message: The updateRun is waiting for after-stage tasks in stage canary to complete
observedGeneration: 2
reason: UpdateRunWaiting
status: "False" # the updateRun is still progressing and waiting for approval
type: Progressing
deletionStageStatus:
clusters: [] # no clusters need to be cleaned up
stageName: kubernetes-fleet.io/deleteStage
policyObservedClusterCount: 3 # number of clusters to be updated
policySnapshotIndexUsed: "0"
resourceSnapshotIndexUsed: "1"
stagedUpdateStrategySnapshot: # snapshot of the strategy used for this update run
stages:
- afterStageTasks:
- type: TimedWait
waitTime: 1m0s
labelSelector:
matchLabels:
environment: staging
maxConcurrency: 1
name: staging
- beforeStageTasks:
- type: Approval
labelSelector:
matchLabels:
environment: canary
maxConcurrency: 50%
name: canary
sortingLabelKey: order
stagesStatus: # detailed status for each stage
- afterStageTaskStatus:
- conditions:
- lastTransitionTime: "2025-07-22T21:29:23Z"
message: Wait time elapsed
observedGeneration: 2
reason: StageTaskWaitTimeElapsed
status: "True" # the wait after-stage task has completed
type: WaitTimeElapsed
type: TimedWait
clusters:
- clusterName: member2 # stage staging contains member2 cluster only
conditions:
- lastTransitionTime: "2025-07-22T21:28:08Z"
message: Cluster update started
observedGeneration: 2
reason: ClusterUpdatingStarted
status: "True"
type: Started
- lastTransitionTime: "2025-07-22T21:28:23Z"
message: Cluster update completed successfully
observedGeneration: 2
reason: ClusterUpdatingSucceeded
status: "True" # member2 is updated successfully
type: Succeeded
conditions:
- lastTransitionTime: "2025-07-22T21:28:23Z"
message: All clusters in the stage are updated and after-stage tasks are completed
observedGeneration: 2
reason: StageUpdatingSucceeded
status: "False"
type: Progressing
- lastTransitionTime: "2025-07-22T21:29:23Z"
message: Stage update completed successfully
observedGeneration: 2
reason: StageUpdatingSucceeded
status: "True" # stage staging has completed successfully
type: Succeeded
endTime: "2025-07-22T21:29:23Z"
stageName: staging
startTime: "2025-07-22T21:28:08Z"
- beforeStageTaskStatus:
- approvalRequestName: example-run-before-canary # ClusterApprovalRequest name for this stage for before stage task
conditions:
- lastTransitionTime: "2025-07-22T21:29:53Z"
message: ClusterApprovalRequest is created
observedGeneration: 2
reason: StageTaskApprovalRequestCreated
status: "True"
type: ApprovalRequestCreated
type: Approval
conditions:
- lastTransitionTime: "2025-07-22T21:29:53Z"
message: Not all before-stage tasks are completed, waiting for approval
observedGeneration: 2
reason: StageUpdatingWaiting
status: "False" # stage canary is waiting for approval task completion
type: Progressing
stageName: canary
startTime: "2025-07-22T21:29:23Z"
ステージング ステージの TimedWait 期間が経過し、カナリア ステージの承認タスクの ClusterApprovalRequest オブジェクトが作成されたことがわかります。 生成された ClusterApprovalRequest を確認し、まだ誰も承認していないことがわかります
kubectl get clusterapprovalrequest
出力は次の例のようになります。
NAME UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary 2m39s
段階的な更新プログラムの実行を承認する
json パッチ ファイルを作成して適用することで、 ClusterApprovalRequest を承認できます。
cat << EOF > approval.json
"status": {
"conditions": [
{
"lastTransitionTime": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"message": "lgtm",
"observedGeneration": 1,
"reason": "testPassed",
"status": "True",
"type": "Approved"
}
]
}
EOF
注:
observedGenerationが承認オブジェクトの生成と一致していることを確認してください。
作成された JSON ファイルを使用して、承認するパッチ要求を送信します。
kubectl patch clusterapprovalrequests example-run-before-canary --type='merge' --subresource=status --patch-file approval.json
次に、要求が承認されたことを確認します。
kubectl get clusterapprovalrequest
出力は次の例のようになります。
NAME UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary True True 3m35s
現在、ClusterStagedUpdateRun は処理を進めて完了できます。
kubectl get clusterstagedupdaterrun example-run
出力は次の例のようになります。
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True True 5m28s
ロールアウトの完了を確認する
ClusterResourcePlacementには、ロールアウトが完了し、リソースがすべてのメンバー クラスターで使用できることも示されています。
kubectl get clusterresourceplacement example-placement
出力は次の例のようになります。
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 True 1 8m55s
ConfigMap test-cm は、最新のデータを使用して、3 つのメンバー クラスターすべてにデプロイする必要があります。
apiVersion: v1
data:
key: value2
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
段階的な更新プログラムの実行を停止する
実行中のクラスター ステージング更新実行の実行を停止するには、仕様の state フィールドに修正プログラムを適用して Stopする必要があります。 このアクションにより、更新プログラムの実行が正常に停止され、進行中のクラスターはロールアウト プロセス全体を停止する前に更新を完了できます。
kubectl patch clusterstagedupdaterun example-run --type merge -p '{"spec":{"state":"Stop"}}'
ステージングされた更新プログラムの実行が初期化され、実行されなくなりました。
kubectl get clusterstagedupdaterun example-run
出力は次の例のようになります。
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
更新プログラムの実行が停止した後の状態の詳細を次に示します。
kubectl get clusterstagedupdaterun example-run -o yaml
出力は次の例のようになります。
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
...
name: example-run
...
spec:
placementName: example-placement
resourceSnapshotIndex: "1"
stagedRolloutStrategyName: example-strategy
state: Stop
status:
conditions:
- lastTransitionTime: "2025-07-22T21:28:08Z"
message: ClusterStagedUpdateRun initialized successfully
observedGeneration: 3
reason: UpdateRunInitializedSuccessfully
status: "True" # the updateRun is initialized successfully
type: Initialized
- lastTransitionTime: "2025-07-22T21:28:23Z"
message: The update run has been stopped
observedGeneration: 3
reason: UpdateRunStopped
status: "False" # the updateRun has stopped progressing
type: Progressing
deletionStageStatus:
clusters: [] # no clusters need to be cleaned up
stageName: kubernetes-fleet.io/deleteStage
policyObservedClusterCount: 3 # number of clusters to be updated
policySnapshotIndexUsed: "0"
resourceSnapshotIndexUsed: "1"
stagedUpdateStrategySnapshot: # snapshot of the strategy used for this update run
stages:
- afterStageTasks:
- type: TimedWait
waitTime: 1m0s
labelSelector:
matchLabels:
environment: staging
maxConcurrency: 1
name: staging
- beforeStageTasks:
- type: Approval
labelSelector:
matchLabels:
environment: canary
maxConcurrency: 50%
name: canary
sortingLabelKey: order
stagesStatus: # detailed status for each stage
- clusters:
- clusterName: member2 # stage staging contains member2 cluster only
conditions:
- lastTransitionTime: "2025-07-22T21:28:08Z"
message: Cluster update started
observedGeneration: 3
reason: ClusterUpdatingStarted
status: "True"
type: Started
- lastTransitionTime: "2025-07-22T21:28:23Z"
message: Cluster update completed successfully
observedGeneration: 3
reason: ClusterUpdatingSucceeded
status: "True" # member2 is updated successfully
type: Succeeded
conditions:
- lastTransitionTime: "2025-07-22T21:28:23Z"
message: All the updating clusters have finished updating, the stage is now stopped, waiting to be resumed
observedGeneration: 3
reason: StageUpdatingStopped
status: "False"
type: Progressing
stageName: staging
startTime: "2025-07-22T21:28:08Z"
以前のバージョンにロールバックする 2 番目の段階的な更新プログラムの実行をデプロイする
ワークロード管理者が ConfigMap の変更をロールバックし、 value2 値を value1に戻したいとします。 ハブから ConfigMap を手動で更新する代わりに、コンテキストで以前のリソース スナップショット インデックス "0" を使用して新しい ClusterStagedUpdateRun を作成し、同じ戦略を再利用できます。
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-run-2
spec:
placementName: example-placement
resourceSnapshotIndex: "0"
stagedRolloutStrategyName: example-strategy
state: Run
新しい ClusterStagedUpdateRunを確認してみましょう。
kubectl get clusterstagedupdaterun
出力は次の例のようになります。
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True True 13m
example-run-2 example-placement 0 0 True 9s
1 分間のTimedWaitが経過すると、新しいClusterApprovalRequest用に作成されたClusterStagedUpdateRun オブジェクトが表示されます。
kubectl get clusterapprovalrequest
出力は次の例のようになります。
NAME UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-2-before-canary example-run-2 canary 75s
example-run-before-canary example-run canary True True 14m
新しい ClusterApprovalRequest オブジェクトを承認するには、同じ approval.json ファイルを再利用して修正プログラムを適用しましょう。
kubectl patch clusterapprovalrequests example-run-2-before-canary --type='merge' --subresource=status --patch-file approval.json
新しいオブジェクトが承認されているかどうかを確認します。
kubectl get clusterapprovalrequest
出力は次の例のようになります。
NAME UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-2-before-canary example-run-2 canary True True 2m7s
example-run-before-canary example-run canary True True 15m
ConfigMap test-cm は、次の 3 つのメンバー クラスターすべてにデプロイされ、データは value1に戻されます。
apiVersion: v1
data:
key: value1
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
リソースをクリーンアップする
このチュートリアルが完了したら、作成したリソースをクリーンアップできます。
kubectl delete clusterstagedupdaterun example-run example-run-2
kubectl delete clusterstagedupdatestrategy example-strategy
kubectl delete clusterresourceplacement example-placement
kubectl delete namespace test-namespace
配置用に Kubernetes ワークロードを準備する
Kubernetes ワークロードをハブ クラスターに発行して、メンバー クラスターに配置できるようにします。
ハブ クラスターでワークロードの名前空間と ConfigMap を作成します。
kubectl create namespace test-namespace
kubectl create configmap test-cm --from-literal=key=value1 -n test-namespace
ResourcePlacementは名前空間スコープであるため、まず、選択スコープのClusterResourcePlacementを指定して、NamespaceOnlyを使用して名前空間をすべてのメンバー クラスターにデプロイします。
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterResourcePlacement
metadata:
name: test-namespace-placement
spec:
resourceSelectors:
- group: ""
kind: Namespace
name: test-namespace
version: v1
selectionScope: NamespaceOnly
policy:
placementType: PickAll
名前空間がすべてのメンバー クラスターにデプロイされていることを確認します。
kubectl get clusterresourceplacement test-namespace-placement
出力は次の例のようになります。
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
test-namespace-placement 1 True 1 True 1 30s
ConfigMap をデプロイするには、名前空間スコープの ResourcePlacementを作成します。
Note
spec.strategy.typeはExternalに設定され、StagedUpdateRunでロールアウトがトリガーされます。
apiVersion: placement.kubernetes-fleet.io/v1beta1
kind: ResourcePlacement
metadata:
name: example-placement
namespace: test-namespace
spec:
resourceSelectors:
- group: ""
kind: ConfigMap
name: test-cm
version: v1
policy:
placementType: PickAll
strategy:
type: External
PickAll ポリシーを使用するため、3 つのクラスターはすべてスケジュールする必要がありますが、StagedUpdateRunを作成していないため、ConfigMap をメンバー クラスターにまだデプロイしないでください。
配置がスケジュールされていることを確認します。
kubectl get resourceplacement example-placement -n test-namespace
出力は次の例のようになります。
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 51s
段階的な更新戦略を作成する
StagedUpdateStrategyは、クラスターをステージにグループ化するオーケストレーション パターンを定義し、ロールアウト シーケンスを指定します。 ラベルによってメンバー クラスターが選択されます。 デモでは、ステージングとカナリアの 2 段階 から成るものを作成します:
apiVersion: placement.kubernetes-fleet.io/v1
kind: StagedUpdateStrategy
metadata:
name: example-strategy
namespace: test-namespace
spec:
stages:
- name: staging
labelSelector:
matchLabels:
environment: staging
afterStageTasks:
- type: TimedWait
waitTime: 1m
maxConcurrency: 1
- name: canary
labelSelector:
matchLabels:
environment: canary
sortingLabelKey: order
beforeStageTasks:
- type: Approval
maxConcurrency: 50%
リソース スナップショットの操作
フリートマネージャーは、配置に RollingUpdateのロールアウト戦略がある場合、リソースが変更されたときにリソーススナップショットを作成します。 各スナップショットには、リソースの特定のバージョンを参照するために使用できる一意のインデックスがあります。
配置で External ロールアウト戦略が使用されている場合、リソース スナップショットは自動的に作成されません。 代わりに、段階的な更新プログラムの実行を実行するときに作成されます。 つまり、 External ロールアウト戦略を使用して配置を最初に作成した場合、最初の段階的な更新プログラムの実行を実行するまでリソース スナップショットは存在しません。
Note
配置が以前に RollingUpdate 戦略を使用していて、 Externalに変更された場合、既存のリソース スナップショットは引き続き使用できます。 ステージング更新実行を作成するときに、これらの既存のスナップショットを参照できます。
Tip
リソース スナップショットとその動作の詳細については、 リソース スナップショットを参照してください。
現在のリソース スナップショットを確認する
ResourcePlacementはExternal戦略を使用するため、リソース スナップショットはまだ存在しません。 次のことを確認しましょう。
kubectl get resourcesnapshots -n test-namespace --show-labels
出力にはリソースが表示されないはずです。
No resources found in test-namespace namespace.
最初のリソース スナップショットを作成する
最初のリソース スナップショットを作成するには、StagedUpdateRun フィールドを省略してresourceSnapshotIndexを作成する必要があります。 更新実行コントローラーは、スナップショットが存在しないことを検出し、スナップショットを自動的に作成します。
apiVersion: placement.kubernetes-fleet.io/v1
kind: StagedUpdateRun
metadata:
name: example-initial-run
namespace: test-namespace
spec:
placementName: example-placement
stagedRolloutStrategyName: example-strategy
state: Run
更新プログラムの実行が完了したら、リソース スナップショットを確認します。
kubectl get resourcesnapshots -n test-namespace --show-labels
出力は次の例のようになります。
NAME GEN AGE LABELS
example-placement-0-snapshot 1 60s kubernetes-fleet.io/is-latest-snapshot=true,kubernetes-fleet.io/parent-CRP=example-placement,kubernetes-fleet.io/resource-index=0
これで、スナップショットのバージョンが 1 つになりました。 最新の (kubernetes-fleet.io/is-latest-snapshot=true) であり、リソース インデックス 0 (kubernetes-fleet.io/resource-index=0) を持ちます。
新しいリソース スナップショットを作成する
次に、ConfigMap を新しい値で変更します。
kubectl edit configmap test-cm -n test-namespace
値を value1 から value2 に更新します。
kubectl get configmap test-cm -n test-namespace -o yaml
出力は次の例のようになります。
apiVersion: v1
data:
key: value2 # value updated here, old value: value1
kind: ConfigMap
metadata:
creationTimestamp: ...
name: test-cm
namespace: test-namespace
resourceVersion: ...
uid: ...
配置では External 戦略が使用されるため、新しいリソース スナップショットは自動的に作成されません。 新しいスナップショットの作成をトリガーするために、StagedUpdateRun フィールドを省略して別のresourceSnapshotIndexを作成します。
apiVersion: placement.kubernetes-fleet.io/v1
kind: StagedUpdateRun
metadata:
name: example-snapshot-run
namespace: test-namespace
spec:
placementName: example-placement
stagedRolloutStrategyName: example-strategy
state: Run
更新プログラムの実行が完了すると、それぞれインデックス 0 と 1 の 2 つのバージョンのリソース スナップショットが表示されます。
kubectl get resourcesnapshots -n test-namespace --show-labels
出力は次の例のようになります。
NAME GEN AGE LABELS
example-placement-0-snapshot 1 2m6s kubernetes-fleet.io/is-latest-snapshot=false,kubernetes-fleet.io/parent-CRP=example-placement,kubernetes-fleet.io/resource-index=0
example-placement-1-snapshot 1 10s kubernetes-fleet.io/is-latest-snapshot=true,kubernetes-fleet.io/parent-CRP=example-placement,kubernetes-fleet.io/resource-index=1
最新のラベルは、最新の ConfigMap データを含む example-placement-1-snapshot に設定されます。
kubectl get resourcesnapshots example-placement-1-snapshot -n test-namespace -o yaml
出力は次の例のようになります。
apiVersion: placement.kubernetes-fleet.io/v1beta1
kind: ResourceSnapshot
metadata:
annotations:
kubernetes-fleet.io/number-of-enveloped-object: "0"
kubernetes-fleet.io/number-of-resource-snapshots: "1"
kubernetes-fleet.io/resource-hash: 10dd7a3d1e5f9849afe956cfbac080a60671ad771e9bda7dd34415f867c75648
creationTimestamp: "2025-07-22T21:26:54Z"
generation: 1
labels:
kubernetes-fleet.io/is-latest-snapshot: "true"
kubernetes-fleet.io/parent-CRP: example-placement
kubernetes-fleet.io/resource-index: "1"
name: example-placement-1-snapshot
namespace: test-namespace
ownerReferences:
- apiVersion: placement.kubernetes-fleet.io/v1beta1
blockOwnerDeletion: true
controller: true
kind: ResourcePlacement
name: example-placement
uid: e7d59513-b3b6-4904-864a-c70678fd6f65
resourceVersion: "19994"
uid: 79ca0bdc-0b0a-4c40-b136-7f701e85cdb6
spec:
selectedResources:
- apiVersion: v1
data:
key: value2 # latest value: value2, old value: value1
kind: ConfigMap
metadata:
name: test-cm
namespace: test-namespace
ロールアウトの変更に合わせて段階的な更新プログラムの実行を準備する
StagedUpdateRunは、ResourcePlacementに従ってStagedUpdateStrategyのロールアウトを実行します。 ResourcePlacement (RP) の段階的な更新実行をトリガーするために、RP 名、updateRun 戦略名、最新のリソース スナップショット インデックス ("1")、状態を "Initialize" として指定する StagedUpdateRun を作成します。
Note
Externalロールアウト戦略を使用する場合は、最新のリソースをデプロイする場合は、resourceSnapshotIndex フィールドを省略できます。 更新実行コントローラーでは、 resourceSnapshotIndex を省略すると、新しいリソース スナップショットが自動的に作成されます。
apiVersion: placement.kubernetes-fleet.io/v1
kind: StagedUpdateRun
metadata:
name: example-run
namespace: test-namespace
spec:
placementName: example-placement
resourceSnapshotIndex: "1"
stagedRolloutStrategyName: example-strategy
state: Initialize
ステージングされた更新プログラムの実行は初期化されますが、実行されていません。
kubectl get stagedupdaterrun example-run -n test-namespace
出力は次の例のようになります。
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
段階的な更新プログラムの実行を開始する
段階的な更新プログラムの実行を開始するには、仕様の state フィールドに修正プログラムを適用して Runする必要があります。
kubectl patch stagedupdaterrun example-run -n test-namespace --type merge -p '{"spec":{"state":"Run"}}'
Note
最初にstateに設定されたRun フィールドを使用して更新プログラムの実行を作成することもできます。このフィールドは、更新プログラムの実行を 1 回の手順で初期化して開始します。
ステージングされた更新プログラムの実行が初期化され、実行されます。
kubectl get stagedupdaterrun example-run -n test-namespace
出力は次の例のようになります。
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
1 分間の TimedWait が経過したら、承認要求を確認します。
kubectl get approvalrequests -n test-namespace
出力は次の例のようになります。
NAME STAGED-UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary 2m39s
段階的な更新プログラムの実行を承認する
json パッチ ファイルを作成して適用することで、 ApprovalRequest を承認できます。
cat << EOF > approval.json
"status": {
"conditions": [
{
"lastTransitionTime": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"message": "lgtm",
"observedGeneration": 1,
"reason": "testPassed",
"status": "True",
"type": "Approved"
}
]
}
EOF
Note
observedGenerationが承認オブジェクトの生成と同じであることを確認します。
作成された JSON ファイルを使用して、承認するパッチ要求を送信します。
kubectl patch approvalrequests example-run-before-canary -n test-namespace --type='merge' --subresource=status --patch-file approval.json
次に、要求が承認されたことを確認します。
kubectl get approvalrequests -n test-namespace
出力は次の例のようになります。
NAME STAGED-UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary True True 3m35s
現在、StagedUpdateRun は処理を進めて完了できます。
kubectl get stagedupdaterrun example-run -n test-namespace
出力は次の例のようになります。
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True True 5m28s
ロールアウトの完了を確認する
ResourcePlacementには、ロールアウトが完了し、リソースがすべてのメンバー クラスターで使用できることも示されています。
kubectl get resourceplacement example-placement -n test-namespace
出力は次の例のようになります。
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 True 1 8m55s
ConfigMap test-cm は、最新のデータを使用して、3 つのメンバー クラスターすべてにデプロイする必要があります。
apiVersion: v1
data:
key: value2
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
段階的な更新プログラムの実行を停止する
実行中のステージング更新実行の実行を停止するには、仕様の state フィールドに修正プログラムを適用して Stopする必要があります。 このアクションにより、更新プログラムの実行が正常に停止され、進行中のクラスターはロールアウト プロセス全体を停止する前に更新を完了できます。
kubectl patch stagedupdaterun example-run -n test-namespace --type merge -p '{"spec":{"state":"Stop"}}'
ステージングされた更新プログラムの実行が初期化され、実行されなくなりました。
kubectl get stagedupdaterun example-run -n test-namespace
出力は次の例のようになります。
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
更新プログラムの実行が停止した後の状態の詳細を次に示します。
kubectl get stagedupdaterun example-run -n test-namespace -o yaml
出力は次の例のようになります。
apiVersion: placement.kubernetes-fleet.io/v1
kind: StagedUpdateRun
metadata:
...
name: example-run
namespace: test-namespace
...
spec:
placementName: example-placement
resourceSnapshotIndex: "1"
stagedRolloutStrategyName: example-strategy
state: Stop
status:
conditions:
- lastTransitionTime: "2025-07-22T21:28:08Z"
message: StagedUpdateRun initialized successfully
observedGeneration: 3
reason: UpdateRunInitializedSuccessfully
status: "True" # the updateRun is initialized successfully
type: Initialized
- lastTransitionTime: "2025-07-22T21:28:23Z"
message: The update run has been stopped
observedGeneration: 3
reason: UpdateRunStopped
status: "False" # the updateRun has stopped progressing
type: Progressing
deletionStageStatus:
clusters: [] # no clusters need to be cleaned up
stageName: kubernetes-fleet.io/deleteStage
policyObservedClusterCount: 3 # number of clusters to be updated
policySnapshotIndexUsed: "0"
resourceSnapshotIndexUsed: "1"
stagedUpdateStrategySnapshot: # snapshot of the strategy used for this update run
stages:
- afterStageTasks:
- type: TimedWait
waitTime: 1m0s
labelSelector:
matchLabels:
environment: staging
maxConcurrency: 1
name: staging
- beforeStageTasks:
- type: Approval
labelSelector:
matchLabels:
environment: canary
maxConcurrency: 50%
name: canary
sortingLabelKey: order
stagesStatus: # detailed status for each stage
- clusters:
- clusterName: member2 # stage staging contains member2 cluster only
conditions:
- lastTransitionTime: "2025-07-22T21:28:08Z"
message: Cluster update started
observedGeneration: 3
reason: ClusterUpdatingStarted
status: "True"
type: Started
- lastTransitionTime: "2025-07-22T21:28:23Z"
message: Cluster update completed successfully
observedGeneration: 3
reason: ClusterUpdatingSucceeded
status: "True" # member2 is updated successfully
type: Succeeded
conditions:
- lastTransitionTime: "2025-07-22T21:28:23Z"
message: All the updating clusters have finished updating, the stage is now stopped, waiting to be resumed
observedGeneration: 3
reason: StageUpdatingStopped
status: "False"
type: Progressing
stageName: staging
startTime: "2025-07-22T21:28:08Z"
以前のバージョンにロールバックする 2 番目の段階的な更新プログラムの実行をデプロイする
ワークロード管理者が ConfigMap の変更をロールバックし、 value2 値を value1に戻したいとします。 ハブから configmap を手動で更新する代わりに、コンテキストで以前のリソース スナップショット インデックス "0" を使用して新しい StagedUpdateRun を作成し、同じ戦略を再利用できます。
apiVersion: placement.kubernetes-fleet.io/v1
kind: StagedUpdateRun
metadata:
name: example-run-2
namespace: test-namespace
spec:
placementName: example-placement
resourceSnapshotIndex: "0"
stagedRolloutStrategyName: example-strategy
state: Run
新しい StagedUpdateRunを確認してみましょう。
kubectl get stagedupdaterun -n test-namespace
出力は次の例のようになります。
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True True 13m
example-run-2 example-placement 0 0 True 9s
1 分間のTimedWaitが経過すると、新しいApprovalRequest用に作成されたStagedUpdateRun オブジェクトが表示されます。
kubectl get approvalrequests -n test-namespace
出力は次の例のようになります。
NAME STAGED-UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-2-before-canary example-run-2 canary 75s
example-run-before-canary example-run canary True True 14m
新しい ApprovalRequest オブジェクトを承認するには、同じ approval.json ファイルを再利用して修正プログラムを適用しましょう。
kubectl patch approvalrequests example-run-2-before-canary -n test-namespace --type='merge' --subresource=status --patch-file approval.json
新しいオブジェクトが承認されているかどうかを確認します。
kubectl get approvalrequests -n test-namespace
出力は次の例のようになります。
NAME STAGED-UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-2-before-canary example-run-2 canary True True 2m7s
example-run-before-canary example-run canary True True 15m
ConfigMap test-cm は、次の 3 つのメンバー クラスターすべてにデプロイされ、データは value1に戻されます。
apiVersion: v1
data:
key: value1
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
リソースをクリーンアップする
このチュートリアルが完了したら、作成したリソースをクリーンアップできます。
kubectl delete stagedupdaterun example-run example-run-2 -n test-namespace
kubectl delete stagedupdatestrategy example-strategy -n test-namespace
kubectl delete resourceplacement example-placement -n test-namespace
kubectl delete clusterresourceplacement test-namespace-placement
kubectl delete namespace test-namespace
アプローチの主な違い
| 特徴 | Cluster-Scoped | Namespace-Scoped |
|---|---|---|
| 戦略リソース |
ClusterStagedUpdateStrategy (短い名前: csus) |
StagedUpdateStrategy (短い名前: sus) |
| 実行リソースの更新 |
ClusterStagedUpdateRun (短い名前: csur) |
StagedUpdateRun (短い名前: sur) |
| ターゲットの配置 |
ClusterResourcePlacement (短い名前: crp) |
ResourcePlacement (短い名前: rp) |
| 承認リソース |
ClusterApprovalRequest (短い名前: careq) |
ApprovalRequest (短い名前: areq) |
| スナップショット リソース | ClusterResourceSnapshot |
ResourceSnapshot |
| Scope | クラスター全体 | 名前空間バインド |
| ユースケース(事例) | インフラストラクチャのロールアウト | アプリケーションのロールアウト |
| アクセス許可 | クラスター管理者レベル | 名前空間レベル |
次のステップ
この記事では、段階的な更新実行を使用して、メンバー クラスター間のロールアウトを調整する方法について説明しました。 クラスター スコープデプロイと名前空間スコープデプロイの両方に対して段階的な更新戦略を作成し、プログレッシブ ロールアウトを実行し、以前のバージョンへのロールバックを実行しました。
段階的な更新プログラムの実行と関連する概念の詳細については、次のリソースを参照してください。