Sdílet prostřednictvím


Použití ClusterStagedUpdateRun k orchestraci fázovaných zavedení napříč členskými clustery

Spuštění fázovaných aktualizací Azure Kubernetes Fleet Manageru poskytují řízený přístup k nasazování úloh napříč několika členskými clustery pomocí postupného procesu. Tento přístup umožňuje minimalizovat riziko nasazením do cílových clusterů postupně s volitelnými dobami čekání a schvalovacími branami mezi fázemi.

V tomto článku se dozvíte, jak vytvářet a spouštět fázované aktualizační běhy pro postupné nasazování úloh a v případě potřeby se vrátit k předchozím verzím.

Prerequisites

  • Potřebujete účet Azure s aktivním předplatným. Vytvořte si bezplatný účet.

  • Pokud chcete porozumět konceptům a terminologii používaným v tomto článku, přečtěte si koncepční přehled fázovaných strategií zavedení.

  • K dokončení tohoto článku potřebujete azure CLI verze 2.58.0 nebo novější. Pokud chcete nainstalovat nebo upgradovat, přečtěte si téma Instalace Azure CLI.

  • Pokud rozhraní příkazového řádku Kubernetes (kubectl) ještě nemáte, můžete ho nainstalovat pomocí tohoto příkazu:

    az aks install-cli
    
  • Potřebujete fleet rozšíření Azure CLI. Můžete ho nainstalovat spuštěním následujícího příkazu:

    az extension add --name fleet
    

    Spuštěním az extension update příkazu aktualizujte na nejnovější verzi rozšíření:

    az extension update --name fleet
    

Konfigurace ukázkového prostředí

Tato ukázka běží na Správci flotily s clusterem centra a třemi členskými clustery. Pokud ho nemáte, vytvořte pomocí tohoto rychlého průvodce Správce flotily s ústředním clusterem. Pak připojte clustery Azure Kubernetes Service (AKS) jako členy.

Tento kurz ukazuje postupné spuštění aktualizací s využitím ukázkového prostředí flotily se třemi členskými clustery, které mají následující popisky:

název clusteru labels
člen1 environment=kanár, order=2
member2 prostředí=staging
člen3 prostředí=kanár, pořadí=1

Tyto popisky nám umožňují vytvářet fáze, které seskupují clustery podle prostředí, a řídit pořadí nasazení v rámci každé fáze.

Příprava úloh na umístění

Dále publikujte úlohy do clusteru centra, aby je bylo možné umístit do členských clusterů.

Vytvořte obor názvů a mapu konfigurace pro úlohu v clusteru centra:

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

Pokud chcete nasadit prostředky, vytvořte ClusterResourcePlacement:

Note

Je spec.strategy.type nastaveno tak, aby External umožnilo spuštění, které je aktivováno pomocí 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

Všechny tři clustery by měly být naplánovány, protože používáme politiku PickAll, ale žádné prostředky by se zatím neměly nasazovat v členských clusterech, protože jsme nevytvořili ClusterStagedUpdateRun.

Ověřte, že je umístění naplánované:

kubectl get crp example-placement

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Práce se snímky prostředků

Správce flotily vytvoří snímky prostředků při změně prostředků. Každý snímek má jedinečný index, který můžete použít k odkazování na konkrétní verze vašich prostředků.

Tip

Další informace o snímcích prostředků a jejich fungování najdete v tématu Principy snímků prostředků.

Zkontrolujte aktuální snímky zdrojů

Chcete-li zkontrolovat aktuální snímky zdrojů:

kubectl get clusterresourcesnapshots --show-labels

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Máme jenom jednu verzi snímku. Je to nejnovější (kubernetes-fleet.io/is-latest-snapshot=true) a má index prostředků 0 (kubernetes-fleet.io/resource-index=0).

Vytvoření nového snímku prostředku

Teď upravte mapu konfigurace novou hodnotou:

kubectl edit cm test-cm -n test-namespace

Aktualizujte hodnotu z value1 hodnoty na value2:

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

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Teď byste měli vidět dvě verze snímků prostředků s indexem 0 a 1 v uvedeném pořadí:

kubectl get clusterresourcesnapshots --show-labels

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Nejnovější štítek je nastaven na example-placement-1-snapshot, který obsahuje nejnovější data konfigurační mapy.

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

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Proveďte nasazení s použitím ClusterStagedUpdateStrategy

A ClusterStagedUpdateStrategy definuje orchestrační vzorec, který seskupuje clustery do fází a určuje pořadí zavádění. Vybere členské clustery podle štítků. Pro naši ukázku vytvoříme jednu se dvěma fázemi, přípravou a kanárkou:

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

Nasazení ClusterStagedUpdateRun pro zavedení nejnovější změny

ClusterStagedUpdateRun spustí zavedení ClusterResourcePlacement v návaznosti na ClusterStagedUpdateStrategy. Pro spuštění fázovaného běhu aktualizace pro ClusterResourcePlacement (CRP) vytvoříme ClusterStagedUpdateRun, ve kterém určíme název CRP, název strategie updateRun a nejnovější index snímků prostředků ("1"):

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

Fázované spuštění aktualizace se inicializuje a spustí:

kubectl get csur example-run

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Podrobnější pohled na stav po uplynutí jedné minuty TimedWait :

kubectl get csur example-run -o yaml

Výstup by měl vypadat podobně jako v následujícím příkladu:

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"

Vidíme, že uplynulo období TimedWait pro přípravnou fázi a vidíme také, že ClusterApprovalRequest byl vytvořen objekt pro úkol schválení v kanárské fázi. Můžeme zkontrolovat vygenerovaný clusterApprovalRequest a zjistit, že ještě není schválený.

kubectl get clusterapprovalrequest

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Soubor oprav JSON můžeme schválit ClusterApprovalRequest tak, že vytvoříme soubor opravy JSON a použijeme ho:

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

Odešlete žádost o opravu ke schválení pomocí vytvořeného souboru JSON.

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

Pak ověřte, že je schválená:

kubectl get clusterapprovalrequest

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

ClusterStagedUpdateRun nyní může pokračovat a dokončit:

kubectl get csur example-run

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Zobrazí ClusterResourcePlacement se také dokončené zavedení a prostředky jsou k dispozici ve všech členských clusterech:

kubectl get crp example-placement

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Konfigurační mapa test-cm by se měla nasadit na všechny tři členské clustery s nejnovějšími daty:

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

Nasadit druhý ClusterStagedUpdateRun pro vrácení zpět na předchozí verzi

Teď předpokládejme, že správce úlohy chce vrátit zpět změnu konfigurační mapy a vrátit hodnotu value2 zpět na value1. Místo ruční aktualizace mapy konfigurace z centra můžou vytvořit nový ClusterStagedUpdateRun s předchozím indexem snímků prostředků 0 v našem kontextu a mohou znovu použít stejnou strategii:

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

Zkontrolujme nové ClusterStagedUpdateRun:

kubectl get csur

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Po uplynutí jedné minuty TimedWait bychom měli vidět ClusterApprovalRequest objekt vytvořený pro nový ClusterStagedUpdateRun:

kubectl get clusterapprovalrequest

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Pokud chcete nový ClusterApprovalRequest objekt schválit, znovu použijeme stejný approval.json soubor, abychom ho opravily:

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

Ověřte, jestli je nový objekt schválen:

kubectl get clusterapprovalrequest                                                                            

Výstup by měl vypadat podobně jako v následujícím příkladu:

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

Mapa konfigurace test-cm by teď měla být nasazena ve všech třech členských clusterech s daty vrácenými zpět na value1:

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

Vyčistěte zdroje

Až tento kurz dokončíte, můžete prostředky, které jste vytvořili, vyčistit:

# Delete the staged update runs
kubectl delete csur example-run example-run-2

# Delete the staged update strategy
kubectl delete csus example-strategy

# Delete the cluster resource placement
kubectl delete crp example-placement

# Delete the test namespace (this will also delete the configmap)
kubectl delete namespace test-namespace

Další kroky

V tomto článku jste zjistili, jak pomocí ClusterStagedUpdateRun orchestrovat postupné zavedení napříč členskými clustery. Vytvořili jste fázované strategie aktualizací, provedli postupné zavádění a provedli vrácení zpět do předchozích verzí.

Další informace o fázovaných spuštěních aktualizací a souvisejících konceptech najdete v následujících zdrojích informací: