Samordna stegvisa utrullningar över medlemskluster

Azure Kubernetes Fleet Manager stegvisa uppdateringskörningar erbjuder ett kontrollerat tillvägagångssätt för att distribuera arbetsbelastningar över flera medlemskluster med hjälp av en stegvis process. För att minimera risken distribueras den här metoden till målkluster sekventiellt, med valfria väntetider och godkännandegrindar mellan steg.

Den här artikeln visar hur du skapar och kör mellanlagrade uppdateringskörningar för att distribuera arbetsbelastningar progressivt och återställa till tidigare versioner när det behövs.

Note

Azure Kubernetes Fleet Manager tillhandahåller två metoder för mellanlagrade uppdateringar:

  • Klusteromfång: Använd ClusterStagedUpdateRun med ClusterResourcePlacement för flottadministratörer som hanterar ändringar på infrastrukturnivå
  • Namnområdesomfång: Använd StagedUpdateRun med ResourcePlacement för programteam som hanterar distributioner inom sina specifika namnområden

Exemplen i den här artikeln visar båda metoderna med hjälp av flikar. Välj fliken som matchar distributionsomfånget.

Prerequisites

  • Du behöver ett Azure-konto med en aktiv prenumeration. Skapa ett konto kostnadsfritt.

  • Om du vill förstå begreppen och terminologin som används i den här artikeln läser du den konceptuella översikten över stegvisa distributionsstrategier.

  • Du behöver Azure CLI version 2.58.0 eller senare installerat för att slutföra den här artikeln. Information om hur du installerar eller uppgraderar finns i Installera Azure CLI.

  • Om du inte redan har Kubernetes CLI (kubectl) kan du installera det med hjälp av det här kommandot:

    az aks install-cli
    
  • Du behöver Azure CLI-tillägget fleet . Du kan installera det genom att köra följande kommando:

    az extension add --name fleet
    

    az extension update Kör kommandot för att uppdatera till den senaste versionen av tillägget:

    az extension update --name fleet
    

Konfigurera demomiljön

Den här demonstrationen körs på en Fleet Manager med ett hubbkluster och tre medlemskluster. Om du inte har någon följer du snabbstarten för att skapa en Fleet Manager med ett hubbkluster. Anslut sedan Azure Kubernetes Service-kluster (AKS) som medlemmar.

Den här självstudien visar fasindelade uppdateringskörningar med hjälp av en demoflottsmiljö med tre medlemskluster som har följande etiketter:

klusternamn labels
member1 environment=canary, order=2
member2 environment=staging
member3 environment=canary, order=1

Om du vill gruppera kluster efter miljö och styra distributionsordningen i varje steg kan vi med dessa etiketter skapa faser.

Förbereda arbetsflöden för utplacering

Publicera arbetsbelastningar till hubbklustret så att de kan placeras på medlemskluster.

Skapa ett namnområde och en konfigurationskarta för arbetsbelastningen i hubbklustret:

kubectl create ns test-namespace
kubectl create cm test-cm --from-literal=key=value1 -n test-namespace

Om du vill distribuera resurserna skapar du ett ClusterResourcePlacement:

Note

spec.strategy.type är inställd på External för att tillåta en distribution som utlöses med en ClusterStagedUpdateRun.

apiVersion: placement.kubernetes-fleet.io/v1beta1
kind: ClusterResourcePlacement
metadata:
  name: example-placement
spec:
  resourceSelectors:
    - group: ""
      kind: Namespace
      name: test-namespace
      version: v1
  policy:
    placementType: PickAll
  strategy:
    type: External

Alla tre klustren bör schemaläggas eftersom vi använder policy PickAll, men inga resurser bör distribueras på medlemsklustren ännu eftersom vi inte har skapat någon ClusterStagedUpdateRun.

Kontrollera att placeringen är schemalagd:

kubectl get crp example-placement

Din utdata bör likna det följande exemplet:

NAME                GEN   SCHEDULED   SCHEDULED-GEN   AVAILABLE   AVAILABLE-GEN   AGE
example-placement   1     True        1                                           51s

Arbeta med resursögonblicksbilder

Fleet Manager skapar resursögonblicksbilder när resurserna ändras. Varje ögonblicksbild har ett unikt index som du kan använda för att referera till specifika versioner av dina resurser.

Tip

Mer information om resursögonblicksbilder och hur de fungerar finns i Förstå resursögonblicksbilder.

Kontrollera aktuella resursögonblicksbilder

Så här kontrollerar du aktuella resursögonblicksbilder:

kubectl get clusterresourcesnapshots --show-labels

Din utdata bör likna det följande exemplet:

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

Vi har bara en version av ögonblicksbilden. Det är den senaste (kubernetes-fleet.io/is-latest-snapshot=true) och har resursindex 0 (kubernetes-fleet.io/resource-index=0).

Skapa en ny resursögonblicksbild

Ändra nu konfigurationskartan med ett nytt värde:

kubectl edit cm test-cm -n test-namespace

Uppdatera värdet från value1 till value2:

kubectl get configmap test-cm -n test-namespace -o yaml

Din utdata bör likna det följande exemplet:

apiVersion: v1
data:
  key: value2 # value updated here, old value: value1
kind: ConfigMap
metadata:
  creationTimestamp: ...
  name: test-cm
  namespace: test-namespace
  resourceVersion: ...
  uid: ...

Nu bör du se två versioner av resursögonblicksbilder med index 0 respektive 1:

kubectl get clusterresourcesnapshots --show-labels

Din utdata bör likna det följande exemplet:

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

Den aktuella etiketten har satts till example-placement-1-snapshot, som innehåller de senaste configmap-data:

kubectl get clusterresourcesnapshots example-placement-1-snapshot -o yaml

Din utdata bör likna det följande exemplet:

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/v1beta1
    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

Distribuera en stegvis uppdateringsstrategi

A ClusterStagedUpdateStrategy definierar orkestreringsmönstret som grupperar kluster i faser och anger distributionssekvensen. Den väljer medlemskluster efter etiketter. I vår demonstration skapar vi en med två steg, mellanlagring och kanariefågel:

apiVersion: placement.kubernetes-fleet.io/v1beta1
kind: ClusterStagedUpdateStrategy
metadata:
  name: example-strategy
spec:
  stages:
    - name: staging
      labelSelector:
        matchLabels:
          environment: staging
      afterStageTasks:
        - type: TimedWait
          waitTime: 1m
    - name: canary
      labelSelector:
        matchLabels:
          environment: canary
      sortingLabelKey: order
      afterStageTasks:
        - type: Approval

Distribuera en etappvis uppdatering för att införa den senaste ändringen

En ClusterStagedUpdateRun kör distributionen av en ClusterResourcePlacement efter en ClusterStagedUpdateStrategy. För att utlösa den stegvisa uppdateringskörningen för vårt ClusterResourcePlacement (CRP) skapar vi ett ClusterStagedUpdateRun som anger CRP-namnet, namnet på updateRun-strategin och resursögonblicksbildens senaste index ("1"):

apiVersion: placement.kubernetes-fleet.io/v1beta1
kind: ClusterStagedUpdateRun
metadata:
  name: example-run
spec:
  placementName: example-placement
  resourceSnapshotIndex: "1"
  stagedRolloutStrategyName: example-strategy

Den etappvisa uppdateringskörningen initieras och körs:

kubectl get csur example-run

Din utdata bör likna det följande exemplet:

NAME          PLACEMENT           RESOURCE-SNAPSHOT-INDEX   POLICY-SNAPSHOT-INDEX   INITIALIZED   SUCCEEDED   AGE
example-run   example-placement   1                         0                       True                      7s

En mer detaljerad titt på statusen efter en minuts TimedWait förflutit:

kubectl get csur example-run -o yaml

Din utdata bör likna det följande exemplet:

apiVersion: placement.kubernetes-fleet.io/v1beta1
kind: ClusterStagedUpdateRun
metadata:
  ...
  name: example-run
  ...
spec:
  placementName: example-placement
  resourceSnapshotIndex: "1"
  stagedRolloutStrategyName: example-strategy
status:
  conditions:
  - lastTransitionTime: "2025-07-22T21:28:08Z"
    message: ClusterStagedUpdateRun initialized successfully
    observedGeneration: 1
    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: 1
    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"
  stagedUpdateStrategySnapshot: # snapshot of the strategy used for this update run
    stages:
    - afterStageTasks:
      - type: TimedWait
        waitTime: 1m0s
      labelSelector:
        matchLabels:
          environment: staging
      name: staging
    - afterStageTasks:
      - type: Approval
      labelSelector:
        matchLabels:
          environment: canary
      name: canary
      sortingLabelKey: order
  stagesStatus: # detailed status for each stage
  - afterStageTaskStatus:
    - conditions:
      - lastTransitionTime: "2025-07-22T21:29:23Z"
        message: Wait time elapsed
        observedGeneration: 1
        reason: AfterStageTaskWaitTimeElapsed
        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: 1
        reason: ClusterUpdatingStarted
        status: "True"
        type: Started
      - lastTransitionTime: "2025-07-22T21:28:23Z"
        message: Cluster update completed successfully
        observedGeneration: 1
        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: 1
      reason: StageUpdatingSucceeded
      status: "False"
      type: Progressing
    - lastTransitionTime: "2025-07-22T21:29:23Z"
      message: Stage update completed successfully
      observedGeneration: 1
      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"
  - afterStageTaskStatus:
    - approvalRequestName: example-run-canary # ClusterApprovalRequest name for this stage
      conditions:
      - lastTransitionTime: "2025-07-22T21:29:53Z"
        message: ClusterApprovalRequest is created
        observedGeneration: 1
        reason: AfterStageTaskApprovalRequestCreated
        status: "True"
        type: ApprovalRequestCreated
      type: Approval
    clusters:
    - clusterName: member3 # according to the labelSelector and sortingLabelKey, member3 is selected first in this stage
      conditions:
      - lastTransitionTime: "2025-07-22T21:29:23Z"
        message: Cluster update started
        observedGeneration: 1
        reason: ClusterUpdatingStarted
        status: "True"
        type: Started
      - lastTransitionTime: "2025-07-22T21:29:38Z"
        message: Cluster update completed successfully
        observedGeneration: 1
        reason: ClusterUpdatingSucceeded
        status: "True" # member3 update is completed
        type: Succeeded
    - clusterName: member1 # member1 is selected after member3 because of order=2 label
      conditions:
      - lastTransitionTime: "2025-07-22T21:29:38Z"
        message: Cluster update started
        observedGeneration: 1
        reason: ClusterUpdatingStarted
        status: "True"
        type: Started
      - lastTransitionTime: "2025-07-22T21:29:53Z"
        message: Cluster update completed successfully
        observedGeneration: 1
        reason: ClusterUpdatingSucceeded
        status: "True" # member1 update is completed
        type: Succeeded
    conditions:
    - lastTransitionTime: "2025-07-22T21:29:53Z"
      message: All clusters in the stage are updated, waiting for after-stage tasks
        to complete
      observedGeneration: 1
      reason: StageUpdatingWaiting
      status: "False" # stage canary is waiting for approval task completion
      type: Progressing
    stageName: canary
    startTime: "2025-07-22T21:29:23Z"

Vi kan se att TimedWait-perioden för staging-fasen förflutit och vi ser också att ClusterApprovalRequest objektet för godkännandeuppgiften i kanariefasen skapades. Vi kan kontrollera den genererade ClusterApprovalRequest och se att ingen har godkänt den ännu.

kubectl get clusterapprovalrequest

Din utdata bör likna det följande exemplet:

NAME                 UPDATE-RUN    STAGE    APPROVED   APPROVALACCEPTED   AGE
example-run-canary   example-run   canary                                 2m39s

Godkänn den etappvisa uppdateringskörning

Vi kan godkänna ClusterApprovalRequest genom att skapa en json-korrigeringsfil och tillämpa den:

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

Skicka en korrigeringsbegäran för att godkänna med hjälp av JSON-filen som skapats.

kubectl patch clusterapprovalrequests example-run-canary --type='merge' --subresource=status --patch-file approval.json

Kontrollera sedan att du har godkänt begäran:

kubectl get clusterapprovalrequest

Din utdata bör likna det följande exemplet:

NAME                 UPDATE-RUN    STAGE    APPROVED   APPROVALACCEPTED   AGE
example-run-canary   example-run   canary   True       True               3m35s

Nu kan ClusterStagedUpdateRun fortsätta och slutföra:

kubectl get csur example-run

Din utdata bör likna det följande exemplet:

NAME          PLACEMENT           RESOURCE-SNAPSHOT-INDEX   POLICY-SNAPSHOT-INDEX   INITIALIZED   SUCCEEDED   AGE
example-run   example-placement   1                         0                       True          True        5m28s

Kontrollera att distributionen har slutförts

Visar ClusterResourcePlacement också att distributionen har slutförts och att resurser är tillgängliga i alla medlemskluster:

kubectl get crp example-placement

Din utdata bör likna det följande exemplet:

NAME                GEN   SCHEDULED   SCHEDULED-GEN   AVAILABLE   AVAILABLE-GEN   AGE
example-placement   1     True        1               True        1               8m55s

Configmap test-cm ska distribueras på alla tre medlemskluster med senaste data:

apiVersion: v1
data:
  key: value2
kind: ConfigMap
metadata:
  ...
  name: test-cm
  namespace: test-namespace
  ...

Distribuera en andra ClusterStagedUpdateRun för att återställa till en tidigare version

Distribuera en andra stegvis uppdateringskörning för att återställa

Anta att arbetsbelastningsadministratören vill återställa konfigurationsmappsändringen och återställa värdet value2 till value1. I stället för att manuellt uppdatera konfigurationskartan från hubben kan de skapa en ny ClusterStagedUpdateRun med ett tidigare resursögonblicksindex, "0" i vår kontext och de kan återanvända samma strategi:

apiVersion: placement.kubernetes-fleet.io/v1beta1
kind: ClusterStagedUpdateRun
metadata:
  name: example-run-2
spec:
  placementName: example-placement
  resourceSnapshotIndex: "0"
  stagedRolloutStrategyName: example-strategy

Nu ska vi kontrollera den nya ClusterStagedUpdateRun:

kubectl get csur

Din utdata bör likna det följande exemplet:

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

Efter en minuts TimedWait förflutit bör vi se objektet ClusterApprovalRequest som skapats för den nya ClusterStagedUpdateRun:

kubectl get clusterapprovalrequest

Din utdata bör likna det följande exemplet:

NAME                   UPDATE-RUN      STAGE    APPROVED   APPROVALACCEPTED   AGE
example-run-2-canary   example-run-2   canary                                 75s
example-run-canary     example-run     canary   True       True               14m

Om du vill godkänna det nya ClusterApprovalRequest objektet ska vi återanvända samma approval.json fil för att korrigera det:

kubectl patch clusterapprovalrequests example-run-2-canary --type='merge' --subresource=status --patch-file approval.json

Kontrollera om det nya objektet har godkänts:

kubectl get clusterapprovalrequest                                                                            

Din utdata bör likna det följande exemplet:

NAME                   UPDATE-RUN      STAGE    APPROVED   APPROVALACCEPTED   AGE
example-run-2-canary   example-run-2   canary   True       True               2m7s
example-run-canary     example-run     canary   True       True               15m

Konfigurationskartan test-cm bör nu distribueras på alla tre medlemskluster, med data återställda till value1:

apiVersion: v1
data:
  key: value1
kind: ConfigMap
metadata:
  ...
  name: test-cm
  namespace: test-namespace
  ...

Viktiga skillnader mellan metoder

Aspekt Klusteromfattning Namespace-Scoped
Strategiresurs ClusterStagedUpdateStrategy StagedUpdateStrategy
Uppdatera körresurs ClusterStagedUpdateRun StagedUpdateRun
Målplacering ClusterResourcePlacement ResourcePlacement
Godkännanderesurs ClusterApprovalRequest (kort namn: careq) ApprovalRequest (kort namn: areq)
Resurs för ögonblicksbild ClusterResourceSnapshot ResourceSnapshot
Scope Klusteromfattande Namnområdesbunden
Användningsfall Infrastrukturutrullningar Applikationsdistributioner
behörigheter Klusteradministratörsnivå Namnområdenivå

Rensa resurser

När du är klar med den här självstudien kan du rensa de resurser som du har skapat:

kubectl delete csur example-run example-run-2
kubectl delete csus example-strategy
kubectl delete crp example-placement
kubectl delete namespace test-namespace

Nästa steg

I den här artikeln lärde du dig hur du använder faserade uppdateringskörningar för att samordna distributioner över medlemskluster. Du har skapat stegvisa uppdateringsstrategier för både klusteromfattande distributioner och namnområdesomfångsdistributioner, kört progressiva distributioner och utfört återställningar till tidigare versioner.

Mer information om etappvisa uppdateringskörningar och relaterade begrepp finns i följande resurser: