Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Se aplica a: ✔️ Fleet Manager con clúster central
Las ejecuciones de actualización escalonadas basadas en la ubicación de Azure Kubernetes Fleet Manager proporcionan un enfoque controlado para implementar cargas de trabajo de Kubernetes en varios clústeres miembros a través de un proceso paso a paso. Para minimizar el riesgo, este enfoque se implementa en clústeres de destino secuencialmente, con tiempos de espera opcionales y puertas de aprobación entre fases.
En este artículo se muestra cómo crear y ejecutar ejecuciones de actualizaciones preconfiguradas para implementar cargas de trabajo progresivamente y revertirlas a versiones anteriores cuando sea necesario.
Azure Kubernetes Fleet Manager admite dos ámbitos para las actualizaciones por etapas:
-
Limitado a clúster: use
ClusterStagedUpdateRunconClusterResourcePlacementpara administradores de flotas que se encarguen de los cambios a nivel de infraestructura. -
Con ámbito de espacio de nombres: use
StagedUpdateRunconResourcePlacementpara los equipos de gestión de aplicaciones que administran despliegues dentro de sus espacios de nombres específicos.
Importante
ResourcePlacement usa la versión de la placement.kubernetes-fleet.io/v1beta1 API y está actualmente en versión preliminar. Algunas características que se muestran en este artículo, como ResourceSnapshot, también forman parte de la API v1beta1 y no están disponibles en la API v1.
En los ejemplos de este artículo se muestran ambos enfoques mediante pestañas. Elija la pestaña que coincida con el ámbito de implementación.
Antes de empezar
Prerequisites
Necesita una cuenta de Azure con una suscripción activa. Cree una cuenta gratuita.
Para comprender los conceptos y la terminología que se usan en este artículo, lea la introducción conceptual de las estrategias de lanzamiento preconfigurado.
Necesita Azure CLI versión 2.58.0 o posterior instalada para completar este artículo. Para instalar o actualizar, consulte Instalar el Azure CLI.
Si aún no la tiene instalada, puede instalar la CLI de Kubernetes (kubectl) mediante este comando:
az aks install-cliUsted necesita la Azure CLI extensión
fleet. Puede instalarlo ejecutando el siguiente comando:az extension add --name fleetEjecute el comando
az extension updatepara actualizar a la versión más reciente de la extensión:az extension update --name fleet
Configuración del entorno de demostración
Esta demostración se ejecuta en un Administrador de flotas con un clúster de concentrador y tres clústeres miembros. Si no tiene uno, siga el inicio rápido para crear un Gestor de Flotas con un clúster central. A continuación, únase a clústeres de Azure Kubernetes Service (AKS) como miembros.
En este tutorial se muestran las ejecuciones de actualizaciones por etapas en un entorno de flota de demostración que comprende tres clústeres miembros que tienen las etiquetas siguientes:
| nombre de miembro | labels |
|---|---|
| member1 | environment=canary, order=2 |
| member2 | environment=staging |
| member3 | environment=canary, order=1 |
Estas etiquetas permiten la creación de fases y controlar el orden de implementación dentro de cada fase.
Aplique etiquetas a los clústeres de miembros mediante el comando que se muestra.
az fleet member update \
--resource-group $GROUP \
--fleet-name $FLEET_NAME \
--name member2 \
--labels environment=staging
Preparación de cargas de trabajo de Kubernetes para ubicación
Publique cargas de trabajo de Kubernetes en el clúster de concentrador para que se puedan colocar en clústeres miembro.
Cree un espacio de nombres y un ConfigMap para la carga de trabajo en el clúster central:
kubectl create namespace test-namespace
kubectl create configmap test-cm --from-literal=key=value1 -n test-namespace
Para implementar los recursos, cree un ClusterResourcePlacement:
Note
spec.strategy.type se establece en External para permitir el lanzamiento desencadenado con un 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
Los tres clústeres deben programarse, puesto que usamos la directiva PickAll, pero no se deben desplegar recursos en los clústeres miembro porque aún no se ha creado un ClusterStagedUpdateRun.
Confirme que la colocación está planificada:
kubectl get clusterresourceplacement example-placement
La salida debería parecerse al siguiente ejemplo.
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 51s
Creación de una estrategia de actualización preconfigurada
Un ClusterStagedUpdateStrategy define el patrón de orquestación que agrupa los clústeres en fases y especifica la secuencia de lanzamiento. Selecciona los clústeres de miembros por etiquetas. Para nuestra demostración, creamos una con dos fases, almacenamiento provisional y valor controlado:
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%
Trabajar con instantáneas de recursos
Fleet Manager crea instantáneas de recursos cuando los recursos cambian si la ubicación tiene una estrategia de lanzamiento de RollingUpdate. Cada instantánea tiene un índice único que puede usar para hacer referencia a versiones específicas de los recursos.
Cuando una ubicación usa la estrategia de lanzamiento External, las instantáneas de recursos no se crean automáticamente. En su lugar, se crean al ejecutar una actualización escalonada. Esto significa que, cuando se crea por primera vez una ubicación con una estrategia de lanzamiento External, no existen instantáneas de recursos hasta que se ejecuta la primera ejecución de actualización por etapas.
Note
Si una ubicación antes usaba la estrategia RollingUpdate y se cambia a External, las instantáneas de recursos existentes permanecen disponibles. Puede hacer referencia a estas instantáneas existentes al crear ejecuciones de actualización en etapas.
Tip
Para más información sobre las instantáneas de recursos y cómo funcionan, consulte Instantáneas de recursos.
Revise las instantáneas de recursos actuales
Dado que ClusterResourcePlacement usa la External estrategia, todavía no existen instantáneas de recursos. Vamos a comprobar:
kubectl get clusterresourcesnapshots --show-labels
La salida no debe mostrar ningún recurso:
No resources found
Creación de la primera instantánea de recursos
Para crear la primera instantánea de recursos, necesita crear un ClusterStagedUpdateRun con el campo resourceSnapshotIndex omitido. El controlador de ejecución de actualizaciones detecta que no existen instantáneas y crea una automáticamente.
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-initial-run
spec:
placementName: example-placement
stagedRolloutStrategyName: example-strategy
state: Run
Una vez completada la ejecución de la actualización, compruebe las instantáneas de recursos:
kubectl get clusterresourcesnapshots --show-labels
La salida debería parecerse al siguiente ejemplo.
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
Ahora tiene una versión de la instantánea. Es la versión más reciente (kubernetes-fleet.io/is-latest-snapshot=true) actual y tiene el índice de recursos 0 (kubernetes-fleet.io/resource-index=0).
Creación de una nueva instantánea de recursos
Ahora modifique configMap con un nuevo valor:
kubectl edit configmap test-cm -n test-namespace
Actualice el valor de value1 a value2:
kubectl get configmap test-cm -n test-namespace -o yaml
La salida debería parecerse al siguiente ejemplo.
apiVersion: v1
data:
key: value2 # value updated here, old value: value1
kind: ConfigMap
metadata:
creationTimestamp: ...
name: test-cm
namespace: test-namespace
resourceVersion: ...
uid: ...
Dado que la ubicación usa la estrategia External, la nueva instantánea de recursos no se crea automáticamente. Cree otro ClusterStagedUpdateRun sin el campo resourceSnapshotIndex para provocar la creación de una nueva instantánea:
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-snapshot-run
spec:
placementName: example-placement
stagedRolloutStrategyName: example-strategy
state: Run
Una vez completada la ejecución de la actualización, debería ver dos versiones de instantáneas de recursos con el índice 0 y 1, respectivamente, la más reciente es el índice 1:
kubectl get clusterresourcesnapshots --show-labels
La salida debería parecerse al siguiente ejemplo.
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
La etiqueta más reciente se establece en example-placement-1-snapshot, que contiene los datos configMap más recientes:
kubectl get clusterresourcesnapshots example-placement-1-snapshot -o yaml
La salida debería parecerse al siguiente ejemplo.
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
Preparar una ejecución de actualización por etapas para desplegar los cambios
Un ClusterStagedUpdateRun ejecuta el lanzamiento de un ClusterResourcePlacement tras un ClusterStagedUpdateStrategy. Para activar la ejecución de actualización escalonada en nuestro ClusterResourcePlacement (CRP), creamos un ClusterStagedUpdateRun que indica el nombre de CRP, el nombre de la estrategia de ejecución de updateRun, el último índice de instantáneas de recursos ("1") y el estado en "Initialize":
Note
Al usar la External estrategia de lanzamiento, puede omitir el resourceSnapshotIndex campo si desea implementar los recursos más recientes. El controlador de ejecución de actualización crea automáticamente una nueva instantánea de recursos cuando resourceSnapshotIndex se omite.
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-run
spec:
placementName: example-placement
resourceSnapshotIndex: "1"
stagedRolloutStrategyName: example-strategy
state: Initialize
La ejecución de la actualización escalonada se inicializa pero no está en ejecución:
kubectl get clusterstagedupdaterrun example-run
La salida debería parecerse al siguiente ejemplo.
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Iniciar una ejecución de actualización preconfigurada
Para iniciar la ejecución de una actualización escalonada, debe aplicar un parche al campo state en la especificación a Run:
kubectl patch clusterstagedupdaterrun example-run --type merge -p '{"spec":{"state":"Run"}}'
Note
También puede crear una ejecución de actualización con el campo state inicialmente establecido en Run, lo cual inicializa e inicia la ejecución de la actualización en un solo paso.
La ejecución de la actualización preconfigurada se inicializa y ejecuta:
kubectl get clusterstagedupdaterrun example-run
La salida debería parecerse al siguiente ejemplo.
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Un vistazo más detallado al estado después de que transcurre un minuto TimedWait :
kubectl get clusterstagedupdaterrun example-run -o yaml
La salida debería parecerse al siguiente ejemplo.
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"
Podemos ver que el período TimedWait para la fase de ensayo transcurre y también vemos que se creó el objeto ClusterApprovalRequest para la tarea de aprobación en la fase de valor controlado. Podemos comprobar el generado ClusterApprovalRequest y ver que nadie lo ha aprobado aún
kubectl get clusterapprovalrequest
La salida debería parecerse al siguiente ejemplo.
NAME UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary 2m39s
Aprobar la ejecución de la actualización escalonada
Podemos aprobar el ClusterApprovalRequest creando un archivo de parche json y aplicándolo:
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: asegúrese de que
observedGenerationcoincide con la generación del objeto de aprobación.
Envíe una solicitud de revisión para obtener la aprobación utilizando el archivo JSON creado.
kubectl patch clusterapprovalrequests example-run-before-canary --type='merge' --subresource=status --patch-file approval.json
A continuación, compruebe que ha aprobado la solicitud:
kubectl get clusterapprovalrequest
La salida debería parecerse al siguiente ejemplo.
NAME UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary True True 3m35s
Ahora ClusterStagedUpdateRun puede continuar y completar:
kubectl get clusterstagedupdaterrun example-run
La salida debería parecerse al siguiente ejemplo.
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True True 5m28s
Verifique la finalización del lanzamiento
ClusterResourcePlacement También muestra que el despliegue está completado y están disponibles todos los recursos en los clústeres miembros.
kubectl get clusterresourceplacement example-placement
La salida debería parecerse al siguiente ejemplo.
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 True 1 8m55s
ConfigMap test-cm debe implementarse en los tres clústeres miembros, con los datos más recientes:
apiVersion: v1
data:
key: value2
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
Detener una ejecución de actualización escalonada
Para detener la ejecución de una actualización programada de un clúster en funcionamiento, debe modificar el campo state en la especificación a Stop. Esta acción detiene correctamente la ejecución de la actualización, lo que permite que los clústeres en curso completen sus actualizaciones antes de detener todo el proceso de lanzamiento:
kubectl patch clusterstagedupdaterun example-run --type merge -p '{"spec":{"state":"Stop"}}'
La ejecución de la actualización por etapas se ha inicializado y ya no está en ejecución.
kubectl get clusterstagedupdaterun example-run
La salida debería parecerse al siguiente ejemplo.
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Un vistazo más detallado al estado después de que se detenga la ejecución de la actualización:
kubectl get clusterstagedupdaterun example-run -o yaml
La salida debería parecerse al siguiente ejemplo.
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"
Implementación de una segunda ejecución de actualización preconfigurada para revertir a una versión anterior
Supongamos que el administrador de la carga de trabajo quiere revertir el cambio de ConfigMap y revertir el valor value2 a value1. En lugar de actualizar manualmente el ConfigMap desde el hub, pueden crear un nuevo ClusterStagedUpdateRun con un índice de instantánea de recursos anterior, "0" en nuestro contexto, y pueden reutilizar la misma estrategia.
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: example-run-2
spec:
placementName: example-placement
resourceSnapshotIndex: "0"
stagedRolloutStrategyName: example-strategy
state: Run
Vamos a comprobar el nuevo ClusterStagedUpdateRun:
kubectl get clusterstagedupdaterun
La salida debería parecerse al siguiente ejemplo.
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
Después de que transcurra un minuto TimedWait, deberíamos ver el objeto ClusterApprovalRequest creado para el nuevo ClusterStagedUpdateRun:
kubectl get clusterapprovalrequest
La salida debería parecerse al siguiente ejemplo.
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
Para aprobar el nuevo ClusterApprovalRequest objeto, vamos a reutilizar el mismo approval.json archivo para aplicarle revisiones:
kubectl patch clusterapprovalrequests example-run-2-before-canary --type='merge' --subresource=status --patch-file approval.json
Compruebe si el nuevo objeto está aprobado:
kubectl get clusterapprovalrequest
La salida debería parecerse al siguiente ejemplo.
NAME UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-2-before-canary example-run-2 canary True True 2m7s
example-run-before-canary example-run canary True True 15m
ConfigMap test-cm ahora debe implementarse en los tres clústeres miembros, con los datos revertidos a value1:
apiVersion: v1
data:
key: value1
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
Limpieza de recursos
Cuando haya terminado con este tutorial, puede limpiar los recursos que ha creado:
kubectl delete clusterstagedupdaterun example-run example-run-2
kubectl delete clusterstagedupdatestrategy example-strategy
kubectl delete clusterresourceplacement example-placement
kubectl delete namespace test-namespace
Preparación de cargas de trabajo de Kubernetes para ubicación
Publique cargas de trabajo de Kubernetes en el clúster de concentrador para que se puedan colocar en clústeres miembro.
Cree un espacio de nombres y un ConfigMap para la carga de trabajo en el clúster central:
kubectl create namespace test-namespace
kubectl create configmap test-cm --from-literal=key=value1 -n test-namespace
Como ResourcePlacement está limitado al espacio de nombres, implemente primero el espacio de nombres en todos los clústeres miembro mediante ClusterResourcePlacement, indicando NamespaceOnly según el ámbito de selección:
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
Compruebe que el espacio de nombres está implementado en todos los clústeres miembro:
kubectl get clusterresourceplacement test-namespace-placement
La salida debería parecerse al siguiente ejemplo.
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
test-namespace-placement 1 True 1 True 1 30s
Para implementar el ConfigMap, cree un ResourcePlacement limitado a un espacio de nombres.
Note
spec.strategy.type se establece en External para permitir el lanzamiento desencadenado con un 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
Los tres clústeres deben estar planificados, ya que se usará la directiva PickAll, pero el ConfigMap no se deberá implementar en los clústeres miembro porque aún no se ha creado un StagedUpdateRun.
Confirme que la colocación está planificada:
kubectl get resourceplacement example-placement -n test-namespace
La salida debería parecerse al siguiente ejemplo.
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 51s
Creación de una estrategia de actualización preconfigurada
Un StagedUpdateStrategy define el patrón de orquestación que agrupa los clústeres en fases y especifica la secuencia de lanzamiento. Selecciona los clústeres de miembros por etiquetas. Para nuestra demostración, creamos una con dos fases, almacenamiento provisional y valor controlado:
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%
Trabajar con instantáneas de recursos
Fleet Manager crea instantáneas de recursos cuando los recursos cambian si la ubicación tiene una estrategia de lanzamiento de RollingUpdate. Cada instantánea tiene un índice único que puede usar para hacer referencia a versiones específicas de los recursos.
Cuando una ubicación usa la estrategia de lanzamiento External, las instantáneas de recursos no se crean automáticamente. En su lugar, se crean al ejecutar una actualización escalonada. Esto significa que, cuando se crea por primera vez una ubicación con una External estrategia de despliegue, no hay instantáneas de recursos hasta que se ejecuta la primera ejecución de actualización escalonada.
Note
Si una ubicación antes usaba la estrategia RollingUpdate y se cambia a External, las instantáneas de recursos existentes permanecen disponibles. Puede hacer referencia a estas instantáneas existentes al crear ejecuciones de actualización en etapas.
Tip
Para más información sobre las instantáneas de recursos y cómo funcionan, consulte Instantáneas de recursos.
Revise las instantáneas de recursos actuales
Dado que ResourcePlacement usa la External estrategia, todavía no existen instantáneas de recursos. Vamos a comprobar:
kubectl get resourcesnapshots -n test-namespace --show-labels
La salida no debe mostrar ningún recurso:
No resources found in test-namespace namespace.
Creación de la primera instantánea de recursos
Para crear la primera captura de recursos, debe crear un
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
Una vez completada la ejecución de la actualización, compruebe las instantáneas de recursos:
kubectl get resourcesnapshots -n test-namespace --show-labels
La salida debería parecerse al siguiente ejemplo.
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
Ahora tiene una versión de la instantánea. Es la versión más reciente (kubernetes-fleet.io/is-latest-snapshot=true) actual y tiene el índice de recursos 0 (kubernetes-fleet.io/resource-index=0).
Creación de una nueva instantánea de recursos
Ahora modifique configMap con un nuevo valor:
kubectl edit configmap test-cm -n test-namespace
Actualice el valor de value1 a value2:
kubectl get configmap test-cm -n test-namespace -o yaml
La salida debería parecerse al siguiente ejemplo.
apiVersion: v1
data:
key: value2 # value updated here, old value: value1
kind: ConfigMap
metadata:
creationTimestamp: ...
name: test-cm
namespace: test-namespace
resourceVersion: ...
uid: ...
Dado que la colocación utiliza la External estrategia, la nueva captura de estado del recurso no se crea automáticamente. Cree otra StagedUpdateRun con el campo resourceSnapshotIndexomitido para desencadenar la creación de una nueva instantánea:
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
Una vez completada la ejecución de la actualización, debería ver dos versiones de instantáneas de recursos con el índice 0 y 1 respectivamente:
kubectl get resourcesnapshots -n test-namespace --show-labels
La salida debería parecerse al siguiente ejemplo.
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
La etiqueta más reciente se establece en example-placement-1-snapshot, que contiene los datos configMap más recientes:
kubectl get resourcesnapshots example-placement-1-snapshot -n test-namespace -o yaml
La salida debería parecerse al siguiente ejemplo.
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
Preparar una ejecución de actualización por etapas para desplegar los cambios
Un StagedUpdateRun ejecuta el lanzamiento de un ResourcePlacement tras un StagedUpdateStrategy. Para activar la ejecución de actualización escalonada en nuestro ResourcePlacement (RP), creamos un StagedUpdateRun que indica el nombre de RP, el nombre de la estrategia de ejecución de updateRun, el último índice de instantáneas de recursos ("1") y el estado en "Initialize":
Note
Al usar la External estrategia de lanzamiento, puede omitir el resourceSnapshotIndex campo si desea implementar los recursos más recientes. El controlador de ejecución de actualización crea automáticamente una nueva instantánea de recursos cuando resourceSnapshotIndex se omite.
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
La ejecución de la actualización escalonada se inicializa pero no está en ejecución:
kubectl get stagedupdaterrun example-run -n test-namespace
La salida debería parecerse al siguiente ejemplo.
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Iniciar una ejecución de actualización preconfigurada
Para iniciar la ejecución de una actualización escalonada, debe aplicar un parche al campo state en la especificación a Run:
kubectl patch stagedupdaterrun example-run -n test-namespace --type merge -p '{"spec":{"state":"Run"}}'
Note
También puede crear una ejecución de actualización con el campo state inicialmente establecido en Run, lo cual inicializa e inicia la ejecución de la actualización en un solo paso.
La ejecución de la actualización preconfigurada se inicializa y ejecuta:
kubectl get stagedupdaterrun example-run -n test-namespace
La salida debería parecerse al siguiente ejemplo.
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Una vez transcurrido un minuto TimedWait, compruebe la solicitud de aprobación:
kubectl get approvalrequests -n test-namespace
La salida debería parecerse al siguiente ejemplo.
NAME STAGED-UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary 2m39s
Aprobar la ejecución de la actualización escalonada
Podemos aprobar el ApprovalRequest creando un archivo de parche json y aplicándolo:
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
Asegúrese de que observedGeneration es el mismo que la generación del objeto de aprobación.
Envíe una solicitud de revisión para obtener la aprobación utilizando el archivo JSON creado.
kubectl patch approvalrequests example-run-before-canary -n test-namespace --type='merge' --subresource=status --patch-file approval.json
A continuación, compruebe que ha aprobado la solicitud:
kubectl get approvalrequests -n test-namespace
La salida debería parecerse al siguiente ejemplo.
NAME STAGED-UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-before-canary example-run canary True True 3m35s
Ahora StagedUpdateRun puede continuar y completar:
kubectl get stagedupdaterrun example-run -n test-namespace
La salida debería parecerse al siguiente ejemplo.
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True True 5m28s
Verifique la finalización del lanzamiento
ResourcePlacement También muestra que el despliegue está completado y están disponibles todos los recursos en los clústeres miembros.
kubectl get resourceplacement example-placement -n test-namespace
La salida debería parecerse al siguiente ejemplo.
NAME GEN SCHEDULED SCHEDULED-GEN AVAILABLE AVAILABLE-GEN AGE
example-placement 1 True 1 True 1 8m55s
ConfigMap test-cm debe implementarse en los tres clústeres miembros, con los datos más recientes:
apiVersion: v1
data:
key: value2
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
Detener una ejecución de actualización escalonada
Para detener la ejecución de una actualización escalonada en curso, debe aplicar revisiones al campo state en la especificación para pasarlo a Stop. Esta acción detiene correctamente la ejecución de la actualización, lo que permite que los clústeres en curso completen sus actualizaciones antes de detener todo el proceso de lanzamiento:
kubectl patch stagedupdaterun example-run -n test-namespace --type merge -p '{"spec":{"state":"Stop"}}'
La ejecución de la actualización por etapas se ha inicializado y ya no está en ejecución.
kubectl get stagedupdaterun example-run -n test-namespace
La salida debería parecerse al siguiente ejemplo.
NAME PLACEMENT RESOURCE-SNAPSHOT-INDEX POLICY-SNAPSHOT-INDEX INITIALIZED SUCCEEDED AGE
example-run example-placement 1 0 True 7s
Un vistazo más detallado al estado después de que se detenga la ejecución de la actualización:
kubectl get stagedupdaterun example-run -n test-namespace -o yaml
La salida debería parecerse al siguiente ejemplo.
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"
Implementación de una segunda ejecución de actualización preconfigurada para revertir a una versión anterior
Supongamos que el administrador de la carga de trabajo quiere revertir el cambio de ConfigMap y revertir el valor value2 a value1. En lugar de actualizar manualmente el configmap desde el hub, pueden crear un nuevo StagedUpdateRun con un índice de instantánea de recursos anterior, "0" en nuestro contexto, y pueden reutilizar la misma estrategia:
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
Vamos a comprobar el nuevo StagedUpdateRun:
kubectl get stagedupdaterun -n test-namespace
La salida debería parecerse al siguiente ejemplo.
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
Después de que transcurra un minuto TimedWait, deberíamos ver el objeto ApprovalRequest creado para el nuevo StagedUpdateRun:
kubectl get approvalrequests -n test-namespace
La salida debería parecerse al siguiente ejemplo.
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
Para aprobar el nuevo ApprovalRequest objeto, vamos a reutilizar el mismo approval.json archivo para aplicarle revisiones:
kubectl patch approvalrequests example-run-2-before-canary -n test-namespace --type='merge' --subresource=status --patch-file approval.json
Compruebe si el nuevo objeto está aprobado:
kubectl get approvalrequests -n test-namespace
La salida debería parecerse al siguiente ejemplo.
NAME STAGED-UPDATE-RUN STAGE APPROVED APPROVALACCEPTED AGE
example-run-2-before-canary example-run-2 canary True True 2m7s
example-run-before-canary example-run canary True True 15m
ConfigMap test-cm ahora debe implementarse en los tres clústeres miembros, con los datos revertidos a value1:
apiVersion: v1
data:
key: value1
kind: ConfigMap
metadata:
...
name: test-cm
namespace: test-namespace
...
Limpieza de recursos
Cuando haya terminado con este tutorial, puede limpiar los recursos que ha creado:
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
Diferencias clave entre los enfoques
| Aspecto | De ámbito de clúster | De ámbito de espacio de nombres |
|---|---|---|
| Recurso de estrategia |
ClusterStagedUpdateStrategy (nombre corto: csus) |
StagedUpdateStrategy (nombre corto: sus) |
| Actualizar recurso de ejecución |
ClusterStagedUpdateRun (nombre corto: csur) |
StagedUpdateRun (nombre corto: sur) |
| Selección de ubicación de destino |
ClusterResourcePlacement (nombre corto: crp) |
ResourcePlacement (nombre corto: rp) |
| Recurso de aprobación |
ClusterApprovalRequest (nombre corto: careq) |
ApprovalRequest (nombre corto: areq) |
| Recurso de instantánea | ClusterResourceSnapshot |
ResourceSnapshot |
| Ámbito | En todo el clúster | Enlazado al espacio de nombres |
| Caso de uso | Implementaciones de infraestructura | Lanzamientos de aplicaciones |
| Permisos | Nivel de administrador del clúster | Nivel de espacio de nombres |
Pasos siguientes
En este artículo, ha aprendido a usar ejecuciones de actualizaciones preconfiguradas para orquestar las implementaciones entre clústeres miembro. Ha creado estrategias de actualización preconfiguradas para despliegues con ámbito de clúster y con ámbito de espacio de nombres, ha ejecutado implementaciones progresivas y ha realizado reversiones a versiones anteriores.
Para más información sobre las ejecuciones de actualizaciones preconfiguradas y los conceptos relacionados, consulte los siguientes recursos:
- Definición de una estrategia de implementación para la ubicación de recursos de Fleet Manager
- Comprender los campos de estado y las condiciones para la colocación de recursos de Fleet Manager
- Ver registros del agente en Azure Kubernetes Fleet Manager