Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Si applica a: ✔️ Gestione flotta con un cluster hub
Le esecuzioni di aggiornamento a fasi di posizionamento di Gestione flotta Kubernetes di Azure offrono un approccio controllato alla distribuzione di carichi di lavoro Kubernetes tra più cluster membri mediante un processo fase per fase. Per ridurre al minimo i rischi, questo approccio viene distribuito in sequenza nei cluster di destinazione, con tempi di attesa facoltativi e controlli di approvazione tra fasi.
Questo articolo illustra come creare ed eseguire esecuzioni di aggiornamenti a fasi per distribuire i carichi di lavoro progressivamente ed eseguire il rollback alle versioni precedenti quando necessario.
Azure Kubernetes Fleet Manager supporta due ambiti per gli aggiornamenti a fasi:
-
Ambito cluster: usare
ClusterStagedUpdateRunconClusterResourcePlacementper gli amministratori della flotta che gestiscono le modifiche a livello di infrastruttura. -
Con ambito spazio dei nomi: usare
StagedUpdateRunconResourcePlacementper i team delle applicazioni che gestiscono le distribuzioni negli spazi dei nomi specifici.
Importante
ResourcePlacement usa la versione dell'API placement.kubernetes-fleet.io/v1beta1 ed è attualmente in anteprima. Alcune funzionalità illustrate in questo articolo, ad esempio ResourceSnapshot, fanno anche parte dell'API v1beta1 e non sono disponibili nell'API v1.
Gli esempi in questo articolo illustrano entrambi gli approcci usando le schede. Scegliere la scheda corrispondente all'ambito di distribuzione.
Prima di iniziare
Prerequisites
È necessario un account Azure con una sottoscrizione attiva. Creare un account gratuito.
Per comprendere i concetti e la terminologia usati in questo articolo, leggere la panoramica concettuale delle strategie di implementazione a fasi.
Per completare questo articolo, è necessario Azure CLI versione 2.58.0 o successiva. Per installare o aggiornare, vedere Installare il Azure CLI.
Se l'interfaccia della riga di comando di Kubernetes (kubectl) non è ancora disponibile, è possibile installarla usando questo comando:
az aks install-cliÈ necessaria l'estensione
fleetAzure CLI. È possibile installarlo eseguendo il comando seguente:az extension add --name fleetEseguire il comando
az extension updateper effettuare l'aggiornamento alla versione più recente dell'estensione:az extension update --name fleet
Configurare l'ambiente demo
Questa demo viene eseguita in un Fleet Manager con un cluster hub e tre cluster membri. Se non è disponibile, seguire la guida introduttiva per creare un Fleet Manager con un cluster hub. Successivamente, aggiungi i cluster del servizio Azure Kubernetes (AKS) come membri.
Questa esercitazione illustra le esecuzioni degli aggiornamenti a fasi usando un ambiente demo fleet con tre cluster membri con le etichette seguenti:
| nome membro | labels |
|---|---|
| member1 | environment=canary, order=2 |
| member2 | environment=staging |
| member3 | environment=canary, order=1 |
Queste etichette consentono la creazione di fasi e di controllare l'ordine di distribuzione all'interno di ogni fase.
Applicare etichette ai cluster membri usando il comando visualizzato.
az fleet member update \
--resource-group $GROUP \
--fleet-name $FLEET_NAME \
--name member2 \
--labels environment=staging
Preparare i carichi di lavoro di Kubernetes per il posizionamento
Pubblicare carichi di lavoro Kubernetes nel cluster hub in modo che possano essere inseriti nei cluster membri.
Creare un namespace e un oggetto ConfigMap per il carico di lavoro nel cluster hub:
kubectl create namespace test-namespace
kubectl create configmap test-cm --from-literal=key=value1 -n test-namespace
Per distribuire le risorse, creare un oggetto ClusterResourcePlacement:
Note
spec.strategy.type è impostato su External per consentire l'implementazione attivata con 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
Tutti e tre i cluster devono essere pianificati perché vengono usati i criteri PickAll, ma non è necessario distribuire risorse nei cluster membri perché non è stato ancora creato un oggetto ClusterStagedUpdateRun.
Verificare che il posizionamento sia pianificato:
kubectl get clusterresourceplacement example-placement
L'output dovrebbe essere simile all'esempio seguente:
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 51s
Creare una strategia di aggiornamento a fasi
Un ClusterStagedUpdateStrategy oggetto definisce il modello di orchestrazione che raggruppa i cluster in fasi e specifica la sequenza di implementazione. Seleziona i cluster membri in base alle etichette. Per la dimostrazione, ne viene creata una con due fasi, staging e canary:
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%
Gestire gli snapshot delle risorse
Fleet Manager crea snapshot delle risorse quando queste cambiano se il posizionamento è stato configurato con una strategia di implementazione di RollingUpdate. Ogni snapshot ha un indice univoco che è possibile usare per fare riferimento a versioni specifiche delle risorse.
Quando un'implementazione utilizza la strategia di rollout External, gli snapshot delle risorse non vengono creati automaticamente. Vengono invece creati quando si esegue un'esecuzione di aggiornamento a fasi. Ciò significa che quando si crea per la prima volta un posizionamento con una strategia di implementazione External, non esistono snapshot di risorse fino a quando non si esegue la prima esecuzione dell'aggiornamento a fasi.
Note
Se in precedenza un posizionamento usava la RollingUpdate strategia e viene modificato in External, tutti gli snapshot di risorse esistenti rimangono disponibili. È possibile fare riferimento a questi snapshot esistenti durante la creazione di esecuzioni di aggiornamenti a fasi.
Tip
Per altre informazioni sugli snapshot delle risorse e sul relativo funzionamento, vedere Snapshot delle risorse.
Controllare gli snapshot delle risorse correnti
Poiché ClusterResourcePlacement utilizza la strategia External, non esistono ancora snapshot delle risorse. Verifichiamo:
kubectl get clusterresourcesnapshots --show-labels
L'output non dovrebbe mostrare alcuna risorsa:
No resources found
Creare il primo snapshot della risorsa
Per creare il primo snapshot della risorsa, è necessario creare un ClusterStagedUpdateRun con il campo resourceSnapshotIndex omesso. Il controller di esecuzione dell'aggiornamento rileva che non esistono snapshot e ne crea uno automaticamente.
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-initial-run
spec:
placementName: example-placement
stagedRolloutStrategyName: example-strategy
state: Run
Al termine dell'esecuzione dell'aggiornamento, controllare gli snapshot delle risorse:
kubectl get clusterresourcesnapshots --show-labels
L'output dovrebbe essere simile all'esempio seguente:
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
È ora disponibile una versione dello snapshot. È l'ultima versione (kubernetes-fleet.io/is-latest-snapshot=true) e contiene l'indice delle risorse 0 (kubernetes-fleet.io/resource-index=0).
Creare un nuovo snapshot della risorsa
Modificare ora ConfigMap con un nuovo valore:
kubectl edit configmap test-cm -n test-namespace
Aggiornare il valore da value1 a value2:
kubectl get configmap test-cm -n test-namespace -o yaml
L'output dovrebbe essere simile all'esempio seguente:
apiVersion: v1
data:
key: value2 # value updated here, old value: value1
kind: ConfigMap
metadata:
creationTimestamp: ...
name: test-cm
namespace: test-namespace
resourceVersion: ...
uid: ...
Poiché il posizionamento usa la External strategia, il nuovo snapshot delle risorse non viene creato automaticamente. Creare un'altra ClusterStagedUpdateRun con il resourceSnapshotIndex campo omesso per attivare la creazione di un nuovo snapshot:
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-snapshot-run
spec:
placementName: example-placement
stagedRolloutStrategyName: example-strategy
state: Run
Al termine dell'esecuzione dell'aggiornamento, verranno visualizzate due versioni degli snapshot delle risorse con indice 0 e 1 rispettivamente, ovvero l'indice 1 più recente:
kubectl get clusterresourcesnapshots --show-labels
L'output dovrebbe essere simile all'esempio seguente:
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
L'etichetta più recente è impostata su example-placement-1-snapshot, che contiene i dati ConfigMap più recenti:
kubectl get clusterresourcesnapshots example-placement-1-snapshot -o yaml
L'output dovrebbe essere simile all'esempio seguente:
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
Preparare un'esecuzione di aggiornamento a fasi per l'implementazione delle modifiche
Un ClusterStagedUpdateRun esegue il rollout di un ClusterResourcePlacement in seguito a un ClusterStagedUpdateStrategy. Per attivare l'esecuzione dell'aggiornamento a fasi per ClusterResourcePlacement (CRP), viene creato un ClusterStagedUpdateRun oggetto che specifica il nome CRP, il nome della strategia updateRun, l'indice dello snapshot della risorsa più recente ("1") e lo stato "Initialize":
Note
Quando si usa la External strategia di implementazione, è possibile omettere il resourceSnapshotIndex campo se si desidera distribuire le risorse più recenti. Il controller di esecuzione dell'aggiornamento crea automaticamente un nuovo snapshot della risorsa quando resourceSnapshotIndex viene omesso.
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-run
spec:
placementName: example-placement
resourceSnapshotIndex: "1"
stagedRolloutStrategyName: example-strategy
state: Initialize
L'esecuzione dell'aggiornamento a fasi viene inizializzata ma non è in esecuzione:
kubectl get clusterstagedupdaterrun example-run
L'output dovrebbe essere simile all'esempio seguente:
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Avviare un'esecuzione di aggiornamento a fasi
Per avviare l'esecuzione di un aggiornamento a fasi, è necessario applicare una patch al campo state a Run:
kubectl patch clusterstagedupdaterrun example-run --type merge -p '{"spec":{"state":"Run"}}'
Note
È anche possibile creare un'esecuzione di aggiornamento con il campo state impostato inizialmente su Run, che inizializza e avvia l'esecuzione dell'aggiornamento in un solo passaggio.
L'esecuzione dell'aggiornamento a fasi viene inizializzata ed eseguita:
kubectl get clusterstagedupdaterrun example-run
L'output dovrebbe essere simile all'esempio seguente:
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Un'analisi più dettagliata dello stato dopo la scadenza di un minuto TimedWait :
kubectl get clusterstagedupdaterrun example-run -o yaml
L'output dovrebbe essere simile all'esempio seguente:
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"
È possibile notare che il periodo TimedWait per la fase di staging scade e si nota anche che è stato creato l'oggetto per l'attività ClusterApprovalRequest di approvazione nella fase canary. È possibile controllare il generato ClusterApprovalRequest e vedere che nessuno lo ha ancora approvato
kubectl get clusterapprovalrequest
L'output dovrebbe essere simile all'esempio seguente:
NAME UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary 2m39s
Approvare l'esecuzione dell'aggiornamento a fasi
È possibile approvare ClusterApprovalRequest creando un file di patch JSON e applicandolo:
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
Nota: assicurarsi che
observedGenerationcorrisponda alla generazione dell'oggetto approvato.
Inviare una richiesta di patch per approvare usando il file JSON creato.
kubectl patch clusterapprovalrequests example-run-before-canary --type='merge' --subresource=status --patch-file approval.json
Verificare quindi di aver approvato la richiesta:
kubectl get clusterapprovalrequest
L'output dovrebbe essere simile all'esempio seguente:
NAME UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary True True 3m35s
Ora è possibile procedere e completare ClusterStagedUpdateRun:
kubectl get clusterstagedupdaterrun example-run
L'output dovrebbe essere simile all'esempio seguente:
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True True 5m28s
Verificare il completamento dell'implementazione
ClusterResourcePlacement mostra anche l'implementazione completata e le risorse sono disponibili in tutti i cluster membri:
kubectl get clusterresourceplacement example-placement
L'output dovrebbe essere simile all'esempio seguente:
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 True 1 8m55s
Il test-cm di ConfigMap deve essere distribuito in tutti e tre i cluster membri, con i dati più recenti:
apiVersion: v1
data:
key: value2
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
Interrompere un'esecuzione di aggiornamento a fasi
Per arrestare l'esecuzione di un aggiornamento del cluster a fasi in esecuzione, è necessario applicare patch al campo state nella specifica a Stop. Questa azione interrompe normalmente l'esecuzione dell'aggiornamento, consentendo ai cluster in corso di completare gli aggiornamenti prima di arrestare l'intero processo di implementazione:
kubectl patch clusterstagedupdaterun example-run --type merge -p '{"spec":{"state":"Stop"}}'
L'esecuzione dell'aggiornamento a fasi viene inizializzata e non è più in esecuzione:
kubectl get clusterstagedupdaterun example-run
L'output dovrebbe essere simile all'esempio seguente:
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Uno stato più dettagliato dopo l'arresto dell'esecuzione dell'aggiornamento:
kubectl get clusterstagedupdaterun example-run -o yaml
L'output dovrebbe essere simile all'esempio seguente:
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"
Avviare una seconda esecuzione di aggiornamento suddiviso in fasi per effettuare il rollback a una versione precedente
Si supponga che l'amministratore del carico di lavoro voglia eseguire il rollback della modifica di ConfigMap, ripristinando il valore value2 in value1. Anziché aggiornare manualmente il ConfigMap dall'hub, è possibile creare un nuovo oggetto ClusterStagedUpdateRun con un indice snapshot della risorsa precedente, "0" nel contesto, e riutilizzare la stessa strategia:
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-run-2
spec:
placementName: example-placement
resourceSnapshotIndex: "0"
stagedRolloutStrategyName: example-strategy
state: Run
Esaminiamo il nuovo ClusterStagedUpdateRun:
kubectl get clusterstagedupdaterun
L'output dovrebbe essere simile all'esempio seguente:
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
Al termine di un minutoTimedWait, verrà visualizzato l'oggetto ClusterApprovalRequest creato per il nuovo ClusterStagedUpdateRun.
kubectl get clusterapprovalrequest
L'output dovrebbe essere simile all'esempio seguente:
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
Per approvare il nuovo ClusterApprovalRequest oggetto, riutilizzare lo stesso approval.json file per applicare patch:
kubectl patch clusterapprovalrequests example-run-2-before-canary --type='merge' --subresource=status --patch-file approval.json
Verificare se il nuovo oggetto è approvato:
kubectl get clusterapprovalrequest
L'output dovrebbe essere simile all'esempio seguente:
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
L'oggetto ConfigMap test-cm dovrebbe ora essere distribuito in tutti e tre i cluster membri, con i dati ripristinati in value1:
apiVersion: v1
data:
key: value1
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
Pulire le risorse
Al termine di questa esercitazione, è possibile pulire le risorse create:
kubectl delete clusterstagedupdaterun example-run example-run-2
kubectl delete clusterstagedupdatestrategy example-strategy
kubectl delete clusterresourceplacement example-placement
kubectl delete namespace test-namespace
Preparare i carichi di lavoro di Kubernetes per il posizionamento
Pubblicare carichi di lavoro Kubernetes nel cluster hub in modo che possano essere inseriti nei cluster membri.
Creare un namespace e un oggetto ConfigMap per il carico di lavoro nel cluster hub:
kubectl create namespace test-namespace
kubectl create configmap test-cm --from-literal=key=value1 -n test-namespace
Poiché ResourcePlacement ha l'ambito di spazio dei nomi, distribuire prima Namespace in tutti i cluster membri usando ClusterResourcePlacement, specificando NamespaceOnly per l'ambito di selezione:
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
Verificare che Namespace sia distribuito in tutti i cluster membri:
kubectl get clusterresourceplacement test-namespace-placement
L'output dovrebbe essere simile all'esempio seguente:
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
test-namespace-placement 1 True 1 True 1 30s
Per distribuire ConfigMap, creare un oggetto ResourcePlacement con ambito di spazio dei nomi:
Note
spec.strategy.type è impostato su External per consentire l'implementazione attivata con 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
Tutti e tre i cluster devono essere pianificati perché viene usato il PickAll criterio, ma la ConfigMap non deve ancora essere distribuita nei cluster membri perché non è stato ancora creato un StagedUpdateRun.
Verificare che il posizionamento sia pianificato:
kubectl get resourceplacement example-placement -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 51s
Creare una strategia di aggiornamento a fasi
Un StagedUpdateStrategy oggetto definisce il modello di orchestrazione che raggruppa i cluster in fasi e specifica la sequenza di implementazione. Seleziona i cluster membri in base alle etichette. Per la dimostrazione, ne viene creata una con due fasi, staging e canary:
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%
Gestire gli snapshot delle risorse
Fleet Manager crea snapshot delle risorse quando le risorse cambiano se il posizionamento ha una strategia di implementazione di RollingUpdate. Ogni snapshot ha un indice univoco che è possibile usare per fare riferimento a versioni specifiche delle risorse.
Quando un posizionamento usa la strategia di implementazione External, gli snapshot delle risorse non vengono creati automaticamente. Vengono invece creati quando si esegue un'esecuzione di aggiornamento a fasi. Ciò significa che quando si crea per la prima volta un posizionamento con una strategia di implementazione External, non esistono snapshot di risorse fino a quando non si esegue la prima esecuzione dell'aggiornamento a fasi.
Note
Se in precedenza un posizionamento usava la RollingUpdate strategia e viene modificato in External, tutti gli snapshot di risorse esistenti rimangono disponibili. È possibile fare riferimento a questi snapshot esistenti durante la creazione di esecuzioni di aggiornamenti a fasi.
Tip
Per altre informazioni sugli snapshot delle risorse e sul relativo funzionamento, vedere Snapshot delle risorse.
Controllare gli snapshot delle risorse correnti
Poiché ResourcePlacement usa la strategia External, non esistono ancora istantanee di risorse. Verifichiamo:
kubectl get resourcesnapshots -n test-namespace --show-labels
L'output non dovrebbe mostrare alcuna risorsa:
No resources found in test-namespace namespace.
Creare il primo snapshot della risorsa
Per creare il primo snapshot della risorsa, è necessario creare un StagedUpdateRun con il campo resourceSnapshotIndex omesso. Il controller di esecuzione dell'aggiornamento rileva che non esistono snapshot e ne crea uno automaticamente.
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
Al termine dell'esecuzione dell'aggiornamento, controllare gli snapshot delle risorse:
kubectl get resourcesnapshots -n test-namespace --show-labels
L'output dovrebbe essere simile all'esempio seguente:
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
È ora disponibile una versione dello snapshot. È l'ultima versione (kubernetes-fleet.io/is-latest-snapshot=true) e contiene l'indice delle risorse 0 (kubernetes-fleet.io/resource-index=0).
Creare un nuovo snapshot della risorsa
Modificare ora ConfigMap con un nuovo valore:
kubectl edit configmap test-cm -n test-namespace
Aggiornare il valore da value1 a value2:
kubectl get configmap test-cm -n test-namespace -o yaml
L'output dovrebbe essere simile all'esempio seguente:
apiVersion: v1
data:
key: value2 # value updated here, old value: value1
kind: ConfigMap
metadata:
creationTimestamp: ...
name: test-cm
namespace: test-namespace
resourceVersion: ...
uid: ...
Poiché il posizionamento usa la External strategia, il nuovo snapshot delle risorse non viene creato automaticamente. Creare un'altra StagedUpdateRun con il resourceSnapshotIndex campo omesso per attivare la creazione di un nuovo snapshot:
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
Al termine dell'esecuzione dell'aggiornamento, verranno visualizzate due versioni degli snapshot delle risorse con indice 0 e 1 rispettivamente:
kubectl get resourcesnapshots -n test-namespace --show-labels
L'output dovrebbe essere simile all'esempio seguente:
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
L'etichetta più recente è impostata su example-placement-1-snapshot, che contiene i dati ConfigMap più recenti:
kubectl get resourcesnapshots example-placement-1-snapshot -n test-namespace -o yaml
L'output dovrebbe essere simile all'esempio seguente:
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
Preparare un'esecuzione di aggiornamento a fasi per l'implementazione delle modifiche
Un StagedUpdateRun esegue il rollout di un ResourcePlacement in seguito a un StagedUpdateStrategy. Per attivare l'esecuzione dell'aggiornamento a fasi per ResourcePlacement (RP), viene creato un StagedUpdateRun oggetto che specifica il nome di RP, il nome della strategia di updateRun, l'indice più recente dello snapshot delle risorse ("1") e lo stato come "Initialize".
Note
Quando si usa la External strategia di implementazione, è possibile omettere il resourceSnapshotIndex campo se si desidera distribuire le risorse più recenti. Il controller di esecuzione dell'aggiornamento crea automaticamente un nuovo snapshot della risorsa quando resourceSnapshotIndex viene omesso.
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
L'esecuzione dell'aggiornamento a fasi viene inizializzata ma non è in esecuzione:
kubectl get stagedupdaterrun example-run -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Avviare un'esecuzione di aggiornamento a fasi
Per avviare l'esecuzione di un aggiornamento a fasi, è necessario applicare una patch al campo state a Run:
kubectl patch stagedupdaterrun example-run -n test-namespace --type merge -p '{"spec":{"state":"Run"}}'
Note
È anche possibile creare un'esecuzione di aggiornamento con il campo state impostato inizialmente su Run, che inizializza e avvia l'esecuzione dell'aggiornamento in un solo passaggio.
L'esecuzione dell'aggiornamento a fasi viene inizializzata ed eseguita:
kubectl get stagedupdaterrun example-run -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Dopo la scadenza di un minuto TimedWait, verificare la richiesta di approvazione:
kubectl get approvalrequests -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
NAME STAGED-UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary 2m39s
Approvare l'esecuzione dell'aggiornamento a fasi
È possibile approvare ApprovalRequest creando un file di patch JSON e applicandolo:
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
Assicurarsi che observedGeneration sia uguale alla generazione dell'oggetto di approvazione.
Inviare una richiesta di patch per approvare usando il file JSON creato.
kubectl patch approvalrequests example-run-before-canary -n test-namespace --type='merge' --subresource=status --patch-file approval.json
Verificare quindi di aver approvato la richiesta:
kubectl get approvalrequests -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
NAME STAGED-UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary True True 3m35s
Ora è possibile procedere e completare StagedUpdateRun:
kubectl get stagedupdaterrun example-run -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True True 5m28s
Verificare il completamento dell'implementazione
ResourcePlacement mostra anche l'implementazione completata e le risorse sono disponibili in tutti i cluster membri:
kubectl get resourceplacement example-placement -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 True 1 8m55s
Il test-cm di ConfigMap deve essere distribuito in tutti e tre i cluster membri, con i dati più recenti:
apiVersion: v1
data:
key: value2
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
Interrompere un'esecuzione di aggiornamento a fasi
Per arrestare un aggiornamento a fasi in esecuzione, è necessario modificare il campo state nella specifica a Stop. Questa azione interrompe normalmente l'esecuzione dell'aggiornamento, consentendo ai cluster in corso di completare gli aggiornamenti prima di arrestare l'intero processo di implementazione:
kubectl patch stagedupdaterun example-run -n test-namespace --type merge -p '{"spec":{"state":"Stop"}}'
L'esecuzione dell'aggiornamento a fasi viene inizializzata e non è più in esecuzione:
kubectl get stagedupdaterun example-run -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Uno stato più dettagliato dopo l'arresto dell'esecuzione dell'aggiornamento:
kubectl get stagedupdaterun example-run -n test-namespace -o yaml
L'output dovrebbe essere simile all'esempio seguente:
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"
Avviare una seconda esecuzione di aggiornamento suddiviso in fasi per effettuare il rollback a una versione precedente
Si supponga che l'amministratore del carico di lavoro voglia eseguire il rollback della modifica di ConfigMap, ripristinando il valore value2 in value1. Anziché aggiornare manualmente ConfigMap dall'hub, è possibile crearne un nuovo oggetto StagedUpdateRun con un indice di snapshot della risorsa precedente ("0" in questo contesto) e riutilizzare la stessa strategia:
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
Esaminiamo il nuovo StagedUpdateRun:
kubectl get stagedupdaterun -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
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
Al termine di un minutoTimedWait, verrà visualizzato l'oggetto ApprovalRequest creato per il nuovo StagedUpdateRun.
kubectl get approvalrequests -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
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
Per approvare il nuovo ApprovalRequest oggetto, riutilizzare lo stesso approval.json file per applicare patch:
kubectl patch approvalrequests example-run-2-before-canary -n test-namespace --type='merge' --subresource=status --patch-file approval.json
Verificare se il nuovo oggetto è approvato:
kubectl get approvalrequests -n test-namespace
L'output dovrebbe essere simile all'esempio seguente:
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
L'oggetto ConfigMap test-cm dovrebbe ora essere distribuito in tutti e tre i cluster membri, con i dati ripristinati in value1:
apiVersion: v1
data:
key: value1
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
Pulire le risorse
Al termine di questa esercitazione, è possibile pulire le risorse create:
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
Differenze principali tra approcci
| Aspetto | Con ambito cluster | Con ambito spazio dei nomi |
|---|---|---|
| Risorsa strategia |
ClusterStagedUpdateStrategy (nome breve: csus) |
StagedUpdateStrategy (nome breve: sus) |
| Aggiornare la risorsa di esecuzione |
ClusterStagedUpdateRun (nome breve: csur) |
StagedUpdateRun (nome breve: sur) |
| Posizionamento di destinazione |
ClusterResourcePlacement (nome breve: crp) |
ResourcePlacement (nome breve: rp) |
| Risorsa di approvazione |
ClusterApprovalRequest (nome breve: careq) |
ApprovalRequest (nome breve: areq) |
| Risorsa Snapshot | ClusterResourceSnapshot |
ResourceSnapshot |
| Scope | A livello di cluster | Vincolato allo spazio dei nomi |
| Caso d'uso | Implementazioni dell'infrastruttura | Distribuzioni di applicazioni |
| Autorizzazioni | Livello di amministratore del cluster | Livello del namespace |
Passaggi successivi
In questo articolo si è appreso come usare le esecuzioni di aggiornamento a fasi per orchestrare le implementazioni tra cluster membri. Sono state create strategie di aggiornamento a fasi sia per le distribuzioni con ambito cluster che per le distribuzioni con ambito spazio dei nomi, sono state eseguite implementazioni progressive ed è stato eseguito il rollback alle versioni precedenti.
Per altre informazioni sulle esecuzioni degli aggiornamenti a fasi e sui concetti correlati, vedere le risorse seguenti: