ProgressivePerGroupとPlacementのdecision groupを組み合わせると、add-on configの変更をdev → stg → prodの順に配信できます。この記事ではcluster-proxyを例に、必要な設定と実際の動きを説明します。
全体像
黄色はHub上ですぐに進む更新、青はProgressivePerGroupで制御される更新、緑はspoke上の処理です。破線はspokeからHubへ戻るstatusを表します。
設定手順
1. ManagedClusterに環境ラベルを付ける
ManagedClusterをdev、stg、prodに分けます。
apiVersion: cluster.open-cluster-management.io/v1
kind: ManagedCluster
metadata:
name: dev-cluster
labels:
cluster-proxy: enabled
environment: dev
spec:
hubAcceptsClient: true
leaseDurationSeconds: 60
---
apiVersion: cluster.open-cluster-management.io/v1
kind: ManagedCluster
metadata:
name: stg-cluster
labels:
cluster-proxy: enabled
environment: stg
spec:
hubAcceptsClient: true
leaseDurationSeconds: 60
---
apiVersion: cluster.open-cluster-management.io/v1
kind: ManagedCluster
metadata:
name: prod-cluster
labels:
cluster-proxy: enabled
environment: prod
spec:
hubAcceptsClient: true
leaseDurationSeconds: 60
2. Placementに更新順を書く
Placementが選ぶのは、cluster-proxy: enabledが付いたクラスタのうちenvironmentがdev、stg、prodのものだけ。選択結果は環境ごとのdecision groupに分けます。
apiVersion: cluster.open-cluster-management.io/v1beta1
kind: Placement
metadata:
name: cluster-proxy-placement
namespace: open-cluster-management
spec:
predicates:
- requiredClusterSelector:
labelSelector:
matchLabels:
cluster-proxy: enabled
matchExpressions:
- key: environment
operator: In
values:
- dev
- stg
- prod
decisionStrategy:
groupStrategy:
clustersPerDecisionGroup: "100%"
decisionGroups:
- groupName: dev
groupClusterSelector:
labelSelector:
matchLabels:
environment: dev
- groupName: stg
groupClusterSelector:
labelSelector:
matchLabels:
environment: stg
- groupName: prod
groupClusterSelector:
labelSelector:
matchLabels:
environment: prod
リリース順を決めるのは、decisionGroupsの記述順です。Placementコントローラーがdevにgroup index 0、stgに1、prodに2を付け、ProgressivePerGroupがその順番でconfigを配ります。
3. ClusterManagementAddOnにrolloutを設定する
cluster-proxyのClusterManagementAddOnにProgressivePerGroupを設定します。
apiVersion: addon.open-cluster-management.io/v1beta1
kind: ClusterManagementAddOn
metadata:
name: cluster-proxy
annotations:
addon.open-cluster-management.io/lifecycle: addon-manager
spec:
addOnMeta:
displayName: cluster-proxy
description: cluster-proxy
defaultConfigs:
- group: proxy.open-cluster-management.io
resource: managedproxyconfigurations
name: cluster-proxy
installStrategy:
type: Placements
placements:
- name: cluster-proxy-placement
namespace: open-cluster-management
rolloutStrategy:
type: ProgressivePerGroup
progressivePerGroup:
minSuccessTime: 5m
progressDeadline: 15m
maxFailures: 0
4. add-on configを更新する
spec.defaultConfigsから参照しているManagedProxyConfigurationを更新します。cluster-proxyの標準Helm chartでtagを変更した場合も、このリソースのproxyServer.imageとproxyAgent.imageが更新されます。vX.Y.Zは配布するversionに置き換えてください。
apiVersion: proxy.open-cluster-management.io/v1alpha1
kind: ManagedProxyConfiguration
metadata:
name: cluster-proxy
spec:
authentication:
dump:
secrets: {}
signer:
type: SelfSigned
proxyServer:
image: quay.io/open-cluster-management/cluster-proxy:vX.Y.Z
replicas: 1
namespace: open-cluster-management
entrypoint:
type: PortForward
port: 8091
proxyAgent:
image: quay.io/open-cluster-management/cluster-proxy:vX.Y.Z
replicas: 1
rolloutを確認する
configのspecが変わると、新しいspec hashを使ったrolloutが始まります。期待する順番は次のとおりです。
- devへ新しいconfigを適用します
- devが成功状態になり、それがminSuccessTimeで設定された値である5分続いたらstgへ進みます
- stgでも同じ確認をして、prodへ進みます
Placementが作ったgroupは次のコマンドで確認できます。
kubectl -n open-cluster-management get placement cluster-proxy-placement -o yaml
kubectl -n open-cluster-management get placementdecision \
-l cluster.open-cluster-management.io/placement=cluster-proxy-placement \
-L cluster.open-cluster-management.io/decision-group-index \
-L cluster.open-cluster-management.io/decision-group-name
確認するのは、dev、stg、prodがすべて存在し、group indexが0、1、2の順になっていることです。各クラスタの進行状況はManagedClusterAddOn、配置したmanifestの状態はManifestWorkに反映されます。
kubectl get managedclusteraddon -A \
--field-selector metadata.name=cluster-proxy
kubectl get manifestwork -A -l open-cluster-management.io/addon-name=cluster-proxy
失敗した場合
progressDeadlineで設定した15分以内に成功しなかったクラスタは、その時点でtimeoutとして扱われます。maxFailures: 0の場合、失敗またはtimeoutのクラスタがある間は次のgroupへ進みません。対象クラスタが後から回復した場合は、成功状態がminSuccessTimeだけ続いた後にrolloutが自動的に再開されます。
注意点
Hub側の更新は段階化されない
Helmが直接管理するcluster-proxy-addon-managerと、service proxyを有効にした場合のcluster-proxy-addon-userは、どちらもHub上ですぐに更新されます。ManagedProxyConfiguration.spec.proxyServer.imageから作られるproxy-serverも、クラスタ単位のrolloutを待ちません。
そのためrolloutの途中では、Hubのproxy-serverが新version、stgとprodのproxy-agentが旧versionという状態になります。新旧version間に互換性がなければ、agentをまだ更新していないクラスタにも影響が出ます。
新しいmanager imageに埋め込まれたagent chartやレンダリング処理だけが変わり、参照中のconfigのspecが変わらない場合、hashは変化しません。この場合はrolloutが始まらず、複数のManifestWorkが一斉に更新されることもあり得ます。ここで段階的に検証できるのはproxy-agentのconfig変更であって、cluster-proxy release全体ではありません。
未分類クラスタと空のgroup
requiredClusterSelectorには一致しても、どのgroupClusterSelectorにも一致しないクラスタは除外されません。名前なしのdecision groupに入り、名前付きgroupの後ろで更新されます。この例ではenvironmentをdev、stg、prodに限定して混入を防いでいます。
また、一致するクラスタが0台のgroupは作られません。devが0台ならstgがgroup index 0、prodが1に繰り上がるため、rollout前に実際のdecision groupを確認してください。
生成されるリソースの実例
クラスタが各環境に1台ずつある場合、選択結果は次のようになります。
| group index | group | PlacementDecision | cluster |
|---|---|---|---|
| 0 | dev | cluster-proxy-placement-decision-1 | dev-cluster |
| 1 | stg | cluster-proxy-placement-decision-2 | stg-cluster |
| 2 | prod | cluster-proxy-placement-decision-3 | prod-cluster |
Placementコントローラーによって更新されたPlacementは次のとおりです。
apiVersion: cluster.open-cluster-management.io/v1beta1
kind: Placement
metadata:
name: cluster-proxy-placement
namespace: open-cluster-management
spec:
predicates:
- requiredClusterSelector:
labelSelector:
matchLabels:
cluster-proxy: enabled
matchExpressions:
- key: environment
operator: In
values:
- dev
- stg
- prod
decisionStrategy:
groupStrategy:
clustersPerDecisionGroup: "100%"
decisionGroups:
- groupName: dev
groupClusterSelector:
labelSelector:
matchLabels:
environment: dev
- groupName: stg
groupClusterSelector:
labelSelector:
matchLabels:
environment: stg
- groupName: prod
groupClusterSelector:
labelSelector:
matchLabels:
environment: prod
status:
numberOfSelectedClusters: 3
decisionGroups:
- decisionGroupIndex: 0
decisionGroupName: dev
decisions:
- cluster-proxy-placement-decision-1
clusterCount: 1
- decisionGroupIndex: 1
decisionGroupName: stg
decisions:
- cluster-proxy-placement-decision-2
clusterCount: 1
- decisionGroupIndex: 2
decisionGroupName: prod
decisions:
- cluster-proxy-placement-decision-3
clusterCount: 1
conditions:
- type: PlacementMisconfigured
status: "False"
reason: Succeedconfigured
message: Placement configurations check pass
lastTransitionTime: "<timestamp>"
- type: PlacementSatisfied
status: "True"
reason: AllDecisionsScheduled
message: All cluster decisions scheduled
lastTransitionTime: "<timestamp>"
このPlacementから、環境ごとに次のPlacementDecisionが生成されます。
apiVersion: cluster.open-cluster-management.io/v1beta1
kind: PlacementDecision
metadata:
name: cluster-proxy-placement-decision-1
namespace: open-cluster-management
labels:
cluster.open-cluster-management.io/placement: cluster-proxy-placement
cluster.open-cluster-management.io/decision-group-index: "0"
cluster.open-cluster-management.io/decision-group-name: dev
ownerReferences:
- apiVersion: cluster.open-cluster-management.io/v1beta1
kind: Placement
name: cluster-proxy-placement
uid: "<Placement UID>"
controller: true
blockOwnerDeletion: true
status:
decisions:
- clusterName: dev-cluster
reason: ""
---
apiVersion: cluster.open-cluster-management.io/v1beta1
kind: PlacementDecision
metadata:
name: cluster-proxy-placement-decision-2
namespace: open-cluster-management
labels:
cluster.open-cluster-management.io/placement: cluster-proxy-placement
cluster.open-cluster-management.io/decision-group-index: "1"
cluster.open-cluster-management.io/decision-group-name: stg
ownerReferences:
- apiVersion: cluster.open-cluster-management.io/v1beta1
kind: Placement
name: cluster-proxy-placement
uid: "<Placement UID>"
controller: true
blockOwnerDeletion: true
status:
decisions:
- clusterName: stg-cluster
reason: ""
---
apiVersion: cluster.open-cluster-management.io/v1beta1
kind: PlacementDecision
metadata:
name: cluster-proxy-placement-decision-3
namespace: open-cluster-management
labels:
cluster.open-cluster-management.io/placement: cluster-proxy-placement
cluster.open-cluster-management.io/decision-group-index: "2"
cluster.open-cluster-management.io/decision-group-name: prod
ownerReferences:
- apiVersion: cluster.open-cluster-management.io/v1beta1
kind: Placement
name: cluster-proxy-placement
uid: "<Placement UID>"
controller: true
blockOwnerDeletion: true
status:
decisions:
- clusterName: prod-cluster
reason: ""
PlacementDecision名の末尾は1から始まる一方、group indexは0から始まります。更新順を確認するときは、リソース名ではなくcluster.open-cluster-management.io/decision-group-indexラベルを見てください。