From b682c6e1927fe9628f64b7c42660cd7858aba7f3 Mon Sep 17 00:00:00 2001 From: iamjanr Date: Tue, 18 Aug 2026 21:11:01 +0200 Subject: [PATCH 1/3] [PLT-4667] Document mp_role_name as mandatory and MachinePool limitations Requires mp_role_name for any cluster with MachinePool groups instead of relying on CAPA's dynamic per-nodegroup role; documents ownership for both create_iam values and adds a known-limitations table for MachinePool. --- .../operations-manual/pages/installation.adoc | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/stratio-docs/es/modules/operations-manual/pages/installation.adoc b/stratio-docs/es/modules/operations-manual/pages/installation.adoc index 74c7d449d6..fa4da37267 100644 --- a/stratio-docs/es/modules/operations-manual/pages/installation.adoc +++ b/stratio-docs/es/modules/operations-manual/pages/installation.adoc @@ -13,6 +13,7 @@ Para el aprovisionamiento automatizado en EKS, es necesario ejecutar acciones en + Para el despliegue de EKS, se deberá crear manualmente el rol "AWSServiceRoleForAmazonEKS" y asociarle la política "AmazonEKSServiceRolePolicy" (creada por defecto en AWS). + +[[eks_nodegroup_permissions]] NOTE: Si el _cluster_ incluye grupos de tipo _MachinePool_ (_nodegroups_ gestionados por EKS), el usuario de despliegue necesita permisos adicionales: `eks:CreateNodegroup`, `eks:DescribeNodegroup`, `eks:DeleteNodegroup`, `autoscaling:DescribeAutoScalingGroups` e `iam:CreateServiceLinkedRole`. Estos permisos ya están incluidos en el fichero _stratio-eks-policy.json_. * Sistemas operativos certificados @@ -534,16 +535,32 @@ En este apartado se indican las particularidades del _control-plane_ de Kubernet ^|Nombre ^|Descripción ^|Ejemplo ^|Opcional |_aws_ -|Valores específicos de EKS. Incluye la configuración del _logging_ del _control-plane_ ("api", "audit", "authenticator", "controllerManager" o "scheduler"). Opcionalmente, incluye el nombre de un rol IAM preexistente para los grupos de nodos gestionados (_mp++_++role++_++name_). Si se especifica, _Stratio Cloud Provisioner_ asigna ese rol a todos los grupos de nodos sin crear uno nuevo. +|Valores específicos de EKS. Incluye la configuración del _logging_ del _control-plane_ ("api", "audit", "authenticator", "controllerManager" o "scheduler"). Incluye también el nombre de un rol IAM preexistente para los grupos de nodos gestionados (_mp++_++role++_++name_) — si el _cluster_ va a tener grupos `MachinePool`, este campo debe indicarse siempre; sin él, cada _nodegroup_ recibe un rol IAM dinámico distinto (`capa_`) que no se admite dejar así. a| [source,yaml] ---- logging: api_server: true -mp_role_name: "eks-nodegroup-role" ---- +[[mp_role_name_ownership]] +IMPORTANT: Quién crea el rol indicado en `mp_role_name` depende de `security.aws.create_iam`: + +* **Con `create_iam: true`** — _Stratio Cloud Provisioner_ ya crea automáticamente el rol `eks-nodegroup.cluster-api-provider-aws.sigs.k8s.io` como parte de su propio _stack_ de CloudFormation. Basta con indicar ese mismo nombre, literal, para que `MachinePool` lo use en vez de crear un rol dinámico por _nodegroup_: ++ +[source,yaml] +---- +security: + aws: + create_iam: true +control_plane: + aws: + mp_role_name: "eks-nodegroup.cluster-api-provider-aws.sigs.k8s.io" +---- + +* **Con `create_iam: false`** — el rol no lo crea nadie automáticamente; es responsabilidad del usuario crearlo antes de la instalación, con un nombre a su elección (no tiene que coincidir con el anterior) y como mínimo estas políticas (las que EKS exige a cualquier nodo _worker_, con independencia de _Stratio Cloud Provisioner_): `AmazonEKSWorkerNodePolicy`, `AmazonEKS_CNI_Policy`, `AmazonEC2ContainerRegistryReadOnly`. Indicar aquí un rol que no existe hace fallar la creación de cualquier `MachinePool` al primer intento. + |Sí |_gcp_ @@ -725,7 +742,7 @@ En este ejemplo se aprecian las siguientes particularidades: ** Con etiquetas de Kubernetes. ** Con rangos de autoescalado. ** En una zona fija. -** Con personalizaciones en el disco. +** Con personalizaciones en el disco (aplican solo al grupo _MachineDeployment_ con AMI personalizada; ver nota tras el ejemplo). ** Con instancias tipo _spot_. ** Casos de distribución en AZs: balanceado y desbalanceado. @@ -822,6 +839,34 @@ spec: workload: custom ---- +NOTE: El grupo `eks-prod-xlarge` es un grupo _MachinePool_ (sin `node++_++image`). En _MachinePool_, `root++_++volume.type` y `root++_++volume.encrypted` no tienen efecto: EKS gestiona el volumen raíz del _nodegroup_ sin exponer esas opciones salvo que se use una plantilla de lanzamiento (_Launch Template_) de AWS, no soportada actualmente. Estos campos solo aplican a grupos _MachineDeployment_ con AMI personalizada, como `eks-prod-custom-ami` en este mismo ejemplo. + +==== Limitaciones conocidas — _MachinePool_ (EKS) + +[%header,cols="2,3"] +|=== +| Limitación +| Nota + +| AMI personalizada (`ami++_++id`) no soportada en _MachinePool_ +| Usa `ami++_++type` o cambia a _MachineDeployment_ (`node++_++image`) si necesitas una AMI específica. + +| Volumen CRI separado (`cri++_++volume`) no soportado en _MachinePool_ +| Usa disco único, o _MachineDeployment_ si es imprescindible. + +| `AL2023` no disponible como `ami++_++type` en _MachinePool_ +| Usa `BOTTLEROCKET++_++*`/`AL2++_++*` en _MachinePool_, o _MachineDeployment_ con `node++_++image` para AL2023. + +| Un solo tipo de instancia por _MachinePool_ (sin _fallback_ a otro tipo dentro del mismo grupo) +| Crea varios grupos con `spot: true` y distinto `size` para lograr redundancia. + +| `quantity: 0` en creación directa, o combinado con `labels`/`taints`, puede requerir ajustes +| Usa `max++_++size` igual o mayor al número de AZs; evita definir `labels`/`taints` en grupos a 0. + +| Instancias EC2 de _MachinePool_ sin _tag_ `Name` visible en la consola de AWS +| Son identificables por los _tags_ `kubernetes.io/cluster/` y `eks:nodegroup-name`. +|=== + ==== GKE En este ejemplo se pueden ver las siguientes particularidades: From a520ff45305eeab7411ed9e35e75f9403f8d1ee2 Mon Sep 17 00:00:00 2001 From: iamjanr Date: Tue, 18 Aug 2026 21:11:01 +0200 Subject: [PATCH 2/3] [PLT-4667] Rewrite the upgrade guide against the real 0.9.0 flow Realigns prerequisites, flags, and the MachineDeployment-to-MachinePool migration steps with the actual behavior of ecr_pull_through.py and upgrade-provisioner.py, and documents recovery steps for interrupted upgrades. --- .../operations-manual/pages/upgrade.adoc | 452 +++++++++++++++--- 1 file changed, 394 insertions(+), 58 deletions(-) diff --git a/stratio-docs/es/modules/operations-manual/pages/upgrade.adoc b/stratio-docs/es/modules/operations-manual/pages/upgrade.adoc index 2ccc40931f..a72cc46115 100644 --- a/stratio-docs/es/modules/operations-manual/pages/upgrade.adoc +++ b/stratio-docs/es/modules/operations-manual/pages/upgrade.adoc @@ -8,18 +8,18 @@ El _script_ `upgrade-provisioner.py` automatiza la actualización de _clusters_ * *Azure VMs* (no gestionado) * *GKE* en GCP (gestionado) -Permite actualizar la versión del _cluster_ de Kubernetes desde la instalada con `cloud-provisioner 0.7.X` a la proporcionada por `cloud-provisioner 0.8.X`. +Permite actualizar la versión del _cluster_ de Kubernetes desde la instalada con `cloud-provisioner 0.7.X` a la proporcionada por `cloud-provisioner 0.9.X`. -Para garantizar un entorno de ejecución reproducible, se ha creado la imagen Docker `cloud-provisioner-upgrade:0.17.0-0.8.X`, que incluye el _script_ de actualización y todas las dependencias necesarias. +Para garantizar un entorno de ejecución reproducible, se ha creado la imagen Docker `cloud-provisioner-upgrade:0.9.X`, que incluye el _script_ de actualización y todas las dependencias necesarias (Python 3, AWS CLI v2, Azure CLI, Google Cloud SDK, `kubectl`, `helm` y `clusterctl`, entre otras). La ruta completa de descarga depende de dónde esté publicada (registro privado ECR/ACR/GAR, o el Nexus de Stratio para trabajo interno) — ver <<_ejecución_del_contenedor_de_actualización>>. === Qué se actualiza * *Componentes comunes* a todas las plataformas: -** _cluster-operator_: `0.7.0-m.1` +** _cluster-operator_: `0.7.0` ** _cert-manager_: `v1.20.2` -** _flux2_: `2.18.4` -** _tigera-operator_: `v3.31.5` -** _cluster-autoscaler_: `9.52.1` +** _flux2_: `2.17.2` +** _tigera-operator_: `v3.31.6` +** _cluster-autoscaler_: `9.57.0` * *Cluster API Core* ** _cluster-api (CAPI)_: `v1.10.10` @@ -33,19 +33,32 @@ Para garantizar un entorno de ejecución reproducible, se ha creado la imagen Do * *_Charts_* específicos de plataforma: ** EKS (si está instalado): -*** _aws-load-balancer-controller_: `1.14.1` +*** _aws-load-balancer-controller_: `3.4.0` ** Azure VMs: -*** _azuredisk-csi-driver_: `1.33.5` -*** _azurefile-csi-driver_: `1.34.1` -*** _cloud-provider-azure_: `1.34.2` +*** _azuredisk-csi-driver_: `1.34.4` +*** _azurefile-csi-driver_: `1.35.3` +*** _cloud-provider-azure_: `1.35.3` == Requisitos * Técnicos: ** Tener Docker instalado en el sistema. ** Disponer de un archivo _kubeconfig_ con acceso al _cluster_ (.kube/config). -** Disponer de un archivo _secrets.yml_ (Ansible Vault) utilizado durante la creación del _cluster_. -** Tener un directorio local para copias de seguridad (se montará en el contenedor). +** Disponer de un archivo _secrets.yml_ (Ansible Vault) utilizado durante la creación del _cluster_, junto con su contraseña de Vault. La contraseña se pasa como argumento obligatorio (`-p`/`--vault-password`) al ejecutar el _script_ dentro del contenedor; no tiene valor por defecto. +** Disponer de credenciales AWS válidas para el _cluster_ (`~/.aws/config` y `~/.aws/credentials`). El contenedor fija `AWS_CONFIG_FILE=/upgrade/.aws/config` y `AWS_SHARED_CREDENTIALS_FILE=/upgrade/.aws/credentials`, por lo que el directorio `.aws` debe montarse en el contenedor; sin él, cualquier llamada del _script_ a la API de AWS falla. ++ +NOTE: Al arrancar, el _script_ valida la conectividad (`kubectl get ns`) y, si falla, regenera el _kubeconfig_ automáticamente para EKS/GKE (no para Azure). Esto arregla un _kubeconfig_ desactualizado, pero no una credencial AWS caducada. +** Tener un directorio local llamado `backup` para copias de seguridad (se montará en el contenedor en `/upgrade/backup`), creado dentro del mismo directorio de trabajo que el resto de la estructura (ver <<_estructura_necesaria>>). Usa siempre este mismo nombre en todos los _clusters_/clientes, para que la ubicación sea predecible al dar soporte. El _script_ gestiona su propia estructura de subcarpetas dentro de este directorio, una por ejecución con marca de tiempo; no es necesario que el directorio esté vacío ni recrearlo entre ejecuciones — basta con que exista como punto de montaje. +** Comprobar que el repositorio de Helm de *destino* publica ya el _chart_ de _cluster-operator_ en la versión objetivo. _Cluster-operator_ resuelve siempre su _chart_ desde `KeosCluster.spec.helm_repository.url` (a diferencia del resto de componentes, cuyo origen sí depende de `ClusterConfig.spec.private_helm_repo` — ver <<_uso_del_flag_private>>). ++ +IMPORTANT: El repositorio a verificar **no es necesariamente el que el _cluster_ tiene configurado hoy**. El _script_ pregunta interactivamente si quieres indicar uno nuevo (ver <<_prompts_interactivos>>); si respondes con uno distinto, ese pasa a ser el repositorio real usado durante toda la actualización, incluido el _chart_ de _cluster-operator_. Verifica el _chart_ en el repositorio que realmente vayas a usar en esta ejecución, no solo en el que aparece con el siguiente comando: ++ +[source,bash] +---- +kubectl get keoscluster -n cluster- -o jsonpath='{.spec.helm_repository.url}' +---- ++ +El _script_ descarga (`helm pull`) el _chart_ de _cluster-operator_ desde esa URL para aplicar sus CRDs (si el _chart_ las incluye) antes de actualizar el resto de componentes. Si el _chart_ no incluye CRDs, el _script_ continúa sin problema; lo único que detiene la actualización en este paso es que el `helm pull` falle (_chart_ o versión no encontrados en el repositorio). * Funcionales: + @@ -114,14 +127,22 @@ kubectl get pods -n capz-system + *Salida esperada:* todos los _pods_ en estado `Running` y sin errores en los _logs_. -** _Cluster-Operator_: +** _HelmReleases_: + [source,bash] ---- -kubectl get helmrelease cluster-operator -n kube-system +kubectl get helmrelease -A ---- + -*Salida esperada:* `Ready = True`. +*Salida esperada:* todos con `READY = True`. + +** anchor:comprobacion_automatica[]Comprobación automática — el _script_ ejecuta su propio chequeo de salud al arrancar (antes de tocar nada), independiente de los anteriores: ++ +-- +* Verifica `KeosCluster.status.ready`, salud de los _pods_ de todo el _cluster_ (`CrashLoopBackOff`/`ImagePullBackOff`/`ErrImagePull`/`CreateContainerConfigError`), réplicas HA de `capi`/`capa`/`capg`/`capz` (deben ser 2) y `Machine` atascadas fuera de sus fases normales. +* **No comprueba el estado de los `HelmRelease` directamente** — solo el de los _pods_ como proxy indirecto. Por eso la comprobación manual de arriba (`kubectl get helmrelease -A`) sigue siendo necesaria, no es redundante. +* Si encuentra algún problema, **aborta la actualización antes de empezar**, salvo que se indique `--skip-preflight-checks` (asumiendo el riesgo) o `--dry-run` (que solo informa de que abortaría). +-- === Permisos @@ -129,6 +150,8 @@ Es esencial xref:operations-manual:installation.adoc[revisar la documentación] == Preparación +Posiciónate en el directorio de trabajo desde el que se ejecutará el contenedor. Normalmente es el mismo _workspace_ desde el que se instaló el _cluster_ y `keos-installer`, ya que probablemente ya contenga varios de los ficheros necesarios (ver <<_estructura_necesaria>>); si no, usa un directorio específico para ello. + Crea un directorio local para copias de seguridad: [source,bash] @@ -140,11 +163,8 @@ NOTE: Este directorio debe montarse dentro del contenedor en `/upgrade/backup`. == Estructura necesaria -Asegúrate de que el directorio de trabajo incluya: +Asegúrate de que el directorio de trabajo incluya (solo lo que se monta desde el host — el _script_ principal, las plantillas Jinja2 y las dependencias ya están dentro de la imagen, no hace falta tenerlos aquí): -* `upgrade-provisioner.py`: _script_ principal. -* `templates/`: plantillas Jinja2. -* `requirements.txt`: dependencias necesarias. * `secrets.yml`: credenciales del _cluster_. * `.kube/config`: archivo _kubeconfig_ del _cluster_. * `backup/`: directorio para copias de seguridad (puede estar vacío inicialmente). @@ -158,6 +178,13 @@ El _flag_ `--private` *fuerza* el uso de repositorios privados para: * Las imágenes de contenedores (`private_registry`). * Los _charts_ de Helm (`private_helm_repo`). +Ambos son campos de `ClusterConfig.spec`, consultables con: + +[source,bash] +---- +kubectl get clusterconfig -n cluster- -o jsonpath='{.spec.private_registry}{"\n"}{.spec.private_helm_repo}{"\n"}' +---- + El comportamiento final del _script_ no depende solo del _flag_, sino también de los valores ya definidos en `ClusterConfig`. Esto implica que: @@ -197,8 +224,135 @@ Esto implica que: WARNING: El _flag_ `--private` solo es necesario si quieres *forzar el uso de repositorios privados* y el `ClusterConfig` actual ya no lo tiene habilitado. +== Ejecución del contenedor de actualización + +Este paso es común a los dos _scripts_ disponibles en la imagen (`ecr_pull_through.py` y `upgrade-provisioner.py`, ver <<_migración_a_ecr_pull_through_cache>> y <> respectivamente). + +Descarga la imagen: + +[source,bash] +---- +docker pull /cloud-provisioner-upgrade:0.9.X +---- + +Arranca el contenedor: + +[source,bash] +---- +docker run \ + --name cloud-provisioner-upgrade-0.9.X \ + --net host \ + -it \ + -v $PWD/secrets.yml:/upgrade/secrets.yml \ + -v $PWD/.kube/config:/upgrade/.kube/config \ + -v ~/.aws:/upgrade/.aws \ + -v $PWD/backup:/upgrade/backup \ + /cloud-provisioner-upgrade:0.9.X +---- + +Dentro del contenedor, lanza el _script_ que corresponda con los _flags_ oportunos — ver <<_migración_a_ecr_pull_through_cache>> o <> según el caso. + +NOTE: Ninguno de los dos _scripts_ genera un archivo de registro propio con marca de tiempo; toda su salida va a la consola del contenedor. Para conservar un registro completo de la ejecución, redirige la salida a un archivo, por ejemplo añadiendo `2>&1 | tee upgrade-$(date +%Y%m%d-%H%M%S).log` al comando anterior. + +== Migración a ECR _pull-through cache_ + +WARNING: Este procedimiento se aplica únicamente a _clusters_ EKS (AWS gestionado). No está disponible para Azure VMs ni para GKE. + +El _script_ `ecr_pull_through.py` actualiza `cluster-operator` a la versión indicada y activa `docker_registries[].ecr_pull_through_cache_enabled` en el `KeosCluster`, para que los componentes empiecen a resolver sus imágenes a través de las reglas de _pull-through cache_ de Amazon ECR en lugar de sus rutas directas. + +NOTE: Es una acción independiente del resto de la actualización. Habitualmente se ejecuta antes de `upgrade-provisioner.py`, dentro del mismo ciclo de actualización, cuando se quiere activar _pull-through cache_ a la vez que se sube de versión. + +Antes de aplicar ningún cambio, el _script_ guarda automáticamente una copia del estado previo (CRDs `keosclusters.installer.stratio.com`/`clusterconfigs.installer.stratio.com`, el `ConfigMap` de valores de _cluster-operator_ y un `state.json` con la versión y URLs anteriores) en `backup/ecr_pull_through//`. Esta copia es la que usa el _flag_ `--restore` (ver <<_recuperación_ante_fallos>>) para deshacer la operación. + +IMPORTANT: Este mecanismo de copia de seguridad y el _flag_ `--restore` son exclusivos de `ecr_pull_through.py`. `upgrade-provisioner.py` hace copias de seguridad distintas (manifiestos de `clusterctl move`, _webhooks_ de `capsule`, secretos de los _namespaces_ CAPX — activadas por defecto, desactivables con `--disable-backup`, ver <>) y su recuperación ante fallos es automática e interna al propio _script_, sin ningún _flag_ equivalente a `--restore` que el operador pueda lanzar a mano. No asumas que el comportamiento de uno aplica al otro. + +WARNING: Activar `ecr_pull_through_cache_enabled` en un _cluster_ existente no reescribe por sí solo las rutas de imagen de los componentes ya desplegados que no cambien de versión en la misma ejecución — ver la nota sobre configuración _day-0_ en xref:operations-manual:installation.adoc[]. + +=== Prerrequisitos + +* Las reglas de _pull-through cache_ deben existir ya en la cuenta _cloud_ para los _upstreams_ que utiliza _Stratio KEOS_ (`registry.k8s.io`, `docker.io`, `ghcr.io`, `quay.io`, `public.ecr.aws`) — el _script_ no las crea, solo asume que ya existen. +* El _node role_ de los nodos EC2 necesita los permisos IAM `ecr:BatchImportUpstreamImage` y `ecr:CreateRepository` (mismo requisito que la configuración _day-0_, ver xref:operations-manual:installation.adoc[]) — sin ellos, los nodos no pueden completar el _pull_ de imágenes a través de la caché aunque las reglas ya existan. Si el _cluster_ se creó sin `ecr_pull_through_cache_enabled` desde el principio, añade estos permisos al _stack_ de IAM con `clusterawsadm` antes de ejecutar este _script_. +* El repositorio de Helm de destino debe publicar ya el _chart_ de `cluster-operator` en la versión indicada en `--cluster-operator`, junto con su imagen correspondiente en el registro de contenedores. + +=== Sintaxis + +[source,bash] +---- +python3 ecr_pull_through.py -p --cluster-operator +---- + +[%header,cols="1,2,1,1"] +|=== +| _Flag_ | Descripción | Valor predeterminado | Obligatoria + +| `-p`, `--vault-password` +| Contraseña de Vault para descifrar los secretos. +| +| Sí + +| `-s`, `--secrets` +| Archivo de secretos cifrados. +| secrets.yml +| No + +| `-k`, `--kubeconfig` +| Archivo _kubeconfig_ a utilizar. +| ~/.kube/config +| No + +| `--cluster-operator` +| Versión objetivo de _cluster-operator_. +| +| Sí + +| `--helm-registry` +| Fuerza el repositorio de Helm a utilizar, sin preguntar de forma interactiva. +| _(repositorio actual del `KeosCluster`)_ +| No + +| `--restore` +| Restaura una copia de seguridad anterior en vez de actualizar (ver <<_recuperación_ante_fallos>>). Sin ruta, restaura la más reciente bajo `backup/ecr_pull_through/`. Con `--restore` presente, `--cluster-operator` deja de ser obligatorio. +| _(ninguno — modo actualización)_ +| No +|=== + +Al arrancar, si no se indica `--helm-registry`, el _script_ muestra el repositorio de Helm actualmente configurado en `KeosCluster.spec.helm_repository.url` y permite indicar uno nuevo. Pulsa ENTER para mantener el actual. + +=== Recuperación ante fallos + +Si el fallo se debe a que la imagen o el _chart_ de la versión indicada todavía no están publicados en el repositorio de destino, la solución más sencilla es publicar el artefacto que falte y volver a lanzar el _script_: es idempotente frente a un intento previo incompleto, no es necesario restaurar nada. + +Para deshacer una actualización ya aplicada (o parcialmente aplicada), usa `--restore` con el mismo resto de credenciales (`-p`, `-s`, `-k`): + +[source,bash] +---- +python3 ecr_pull_through.py -p --restore +---- + +Sin ruta tras `--restore`, restaura automáticamente la copia más reciente bajo `backup/ecr_pull_through/` — el caso normal, para deshacer el último intento. Para restaurar una copia distinta (por ejemplo, si hubo varios intentos fallidos seguidos y no quieres deshacer el último), indica su ruta explícita: + +[source,bash] +---- +python3 ecr_pull_through.py -p --restore backup/ecr_pull_through/ +---- + +IMPORTANT: La ruta es relativa al directorio de trabajo *dentro del contenedor* (`/upgrade`, donde está montado `-v $PWD/backup:/upgrade/backup`), nunca la ruta del *host*. Para listar las copias disponibles y copiar el nombre exacto, ejecuta `ls backup/ecr_pull_through/` dentro del propio contenedor antes de lanzar `--restore`. + +El _flag_ revierte, en este orden, los CRDs, el `ConfigMap` de valores de _cluster-operator_, `KeosCluster.spec.helm_repository.url`, `HelmRepository.spec.url`, la versión del _chart_ en el `HelmRelease` y, por último, `ecr_pull_through_cache_enabled` a su valor anterior — esperando a que el `HelmRelease` esté `Ready` y el `KeosCluster` `Provisioned` en el proceso, igual que en una actualización normal. + +=== Verificación + +[source,bash] +---- +kubectl get helmrelease cluster-operator -n kube-system +kubectl get keoscluster -n cluster- -o jsonpath='{.spec.docker_registries[0].ecr_pull_through_cache_enabled}' +---- + +*Salida esperada:* `HelmRelease` en `Ready = True` con el _chart_ en la versión indicada, y `ecr_pull_through_cache_enabled` en `true`. + == Uso del _script_ de actualización +[[upgrade_provisioner_sintaxis]] === Sintaxis Dentro del contenedor, ejecuta: @@ -236,13 +390,23 @@ Opciones principales: | secrets.yml | No +| `-y`, `--yes` +| No espera confirmación entre tareas — salta *solo* la confirmación inicial (ver <<_prompts_interactivos>>), no el _prompt_ del repositorio de Helm ni la confirmación del _bump_ de `k8s_version`. +| False +| No + +| `--cluster-operator` +| Versión objetivo de _cluster-operator_. +| La incluida en esta versión de _Stratio Cloud Provisioner_. +| No + | `--disable-backup` | Desactiva la copia de seguridad previa a la actualización (activada por defecto). | False | No | `--disable-prepare-capsule` -| Desactiva la preparación del entorno para el proceso de actualización. +| Desactiva la exclusión temporal de los _namespaces_ de sistema (`kube-system`, `tigera-operator`, `calico-system`, `cert-manager`, `capi-system`, etc.) en los _webhooks_ de admisión de `capsule`, para que no interfieran con la actualización. | False | No @@ -250,20 +414,95 @@ Opciones principales: | Indica que el _registry_ de Docker y el repositorio de Helm son privados. | False | No + +| `--ecr-pull-through` +| Reescribe las rutas de imagen de esta ejecución como si `ecr_pull_through_cache_enabled` fuera `true`, aunque no lo sea en el `KeosCluster`. Solo afecta a esta ejecución — no lo persiste. Para persistirlo, usa `ecr_pull_through.py`. +| False +| No + +| `--skip-preflight-checks` +| Omite las comprobaciones de salud del _cluster_ previas a la actualización (ver <>). *No recomendado*: un _cluster_ no saludable puede agravarse con la actualización (p. ej. un nodo a medio drenar o un controller CAPI atascado a 1 réplica). +| False +| No + +| `--k8s-version` +| Versión _minor_ de Kubernetes objetivo para el _bump_ (p. ej. `1.35`). Se aplica como un único _patch_ a `KeosCluster.spec.k8s_version`, sorteando el límite de +1 _minor_ por _patch_ del _webhook_ igual que ya hace el resto del _script_ para `clusterctl`. +| 1.35 +| No + +| `--start-from-k8s-version` +| Omite la confirmación Y/N previa al _bump_ de `k8s_version` (ver <<_prompts_interactivos>>). El _bump_ en sí sigue siendo un único _patch_ a `--k8s-version`, no un mecanismo de reanudación desde un paso intermedio. +| False +| No + +| `--dry-run` +| Simula la actualización sin aplicar cambios reales. +| False +| No |=== -=== Ejecución del contenedor de actualización +TIP: Se recomienda ejecutar siempre primero con `--dry-run` antes de la actualización real, para detectar problemas obvios (repositorio o _chart_ inexistente, credenciales inválidas, prerrequisitos no cumplidos) sin riesgo. Sin embargo, un `--dry-run` limpio **no es garantía** de que la actualización real vaya a completarse sin problemas: el modo simula sin ejecutar ningún comando que modifique el _cluster_ (`apply`, `patch`, `delete`, `scale`, `create`, `annotate`, `label`, `clusterctl upgrade apply`), así que cualquier fallo que solo se manifieste al aplicar esos cambios de verdad (un _webhook_ rechazando un _patch_ concreto, una reconciliación de `HelmRelease` que falla, un `clusterctl upgrade apply` real) queda sin probar. + +=== Prompts interactivos + +Al iniciar, el _script_ puede solicitar hasta tres confirmaciones por teclado, en este orden: + +. *Continuar con la actualización*: tras las comprobaciones previas del _cluster_, pulsa ENTER para continuar o cualquier otra tecla para abortar. Se omite con `-y`/`--yes`. +. *Repositorio de Helm*: muestra el repositorio actualmente configurado en `KeosCluster.spec.helm_repository.url` y permite indicar uno nuevo. Pulsa ENTER para mantener el actual. **No se puede omitir** — ni siquiera con `-y`, se pregunta siempre. +. *Bump de `k8s_version`* (solo si `KeosCluster.spec.k8s_version` va a cambiar): pide confirmación explícita `[y/N]` antes de aplicar el _patch_. Responder "n" o dejarlo en blanco cancela solo este paso (el resto de la actualización continúa). Se omite con `--start-from-k8s-version`. + +WARNING: Si indicas un repositorio de Helm distinto al ya configurado, todas las versiones de _charts_ que use el _script_ se resolverán contra ese nuevo repositorio. Cambia este valor únicamente si el nuevo repositorio publica el mismo universo de versiones (`kubernetes-universe`) que corresponde a esta versión de _Stratio Cloud Provisioner_; un repositorio de un universo distinto puede resolver versiones de _charts_ incompatibles entre sí. +Para automatizar la ejecución sin intervención manual (por ejemplo, en un _pipeline_), combina `-y`/`--start-from-k8s-version` con las respuestas necesarias por _stdin_ para el _prompt_ del repositorio de Helm (que nunca se puede desactivar) antes de lanzar el contenedor. + +[[upgrade_provisioner_recuperacion]] +=== Recuperación ante fallos + +Como ya se indica en <<_ejecución_del_contenedor_de_actualización>>, `upgrade-provisioner.py` no tiene un _flag_ equivalente a `--restore` de `ecr_pull_through.py` — su recuperación es automática e interna, activada por el propio _script_ cuando detecta un fallo dentro de la que este documento llama "sección crítica": el tramo de la actualización en el que `cluster-operator` está suspendido, `keoscluster-controller-manager` detenido y los _webhooks_ de `KeosCluster` deshabilitados. Para saber si un fallo concreto ocurrió dentro de ese tramo, busca en la salida de la consola si aparece `[INFO] Suspending cluster-operator helmrelease:` — si ese mensaje ya salió y el fallo ocurrió antes de ver `[INFO] Resuming cluster-operator helmrelease: OK`, el fallo fue dentro de la sección crítica. + +La recuperación automática restaura los _webhooks_ y reinicia el controlador, pero **no cubre todos los fallos posibles** — en concreto, un fallo de `clusterctl upgrade apply` puede dejar el _cluster_ en un estado que requiere intervención manual adicional, descrito a continuación. + +==== Fallo de `clusterctl upgrade apply` con el _namespace_ del _provider_ vacío + +`clusterctl upgrade apply` borra el _provider_ de infraestructura en su versión actual antes de aplicar la versión nueva. Si el comando falla entre ambos pasos (por ejemplo, por una interrupción de red transitoria durante la llamada), el _namespace_ del _provider_ (`capa-system` para AWS) puede quedar completamente vacío — sin `Deployment`, sin RBAC, sin _webhooks_ y, crucialmente, sin el secreto de credenciales que el propio _provider_ gestiona (`capa-manager-bootstrap-credentials`). + +La recuperación automática del _script_ (restaurar _webhooks_ de `KeosCluster` y reiniciar su controlador) no toca este secreto ni reinstala el _provider_ — es un problema distinto y más profundo, fuera del alcance de esa recuperación. + +**Síntoma en el siguiente reintento**: `upgrade-provisioner.py` vuelve a fallar en el mismo paso (`clusterctl upgrade apply`), esta vez con un error de sintaxis de _shell_ poco descriptivo (`Syntax error: "(" unexpected`) en lugar de un mensaje claro sobre el secreto ausente. Esto ocurre porque el _script_ construye la variable `AWS_B64ENCODED_CREDENTIALS` leyendo ese secreto sin comprobar si la lectura tuvo éxito; si el secreto no existe, el propio mensaje de error de `kubectl` se interpola sin querer dentro del comando de `clusterctl` que se ejecuta a continuación. + +**Recuperación manual**: + +. Localiza el secreto en el backup de _CAPX secrets_ que el _script_ genera automáticamente en cada ejecución (`Backing up CAPX secrets: OK`), dentro de `backup/upgrade//capx-secrets//`. Usa la copia de la ejecución **anterior** al fallo — la de la propia ejecución que falló ya no contiene el secreto, porque se generó cuando el _namespace_ ya estaba vacío: ++ [source,bash] ---- -docker run \ - --name cloud-provisioner-upgrade-0.8.X \ - --net host \ - -it \ - -v $PWD/secrets.yml:/upgrade/secrets.yml \ - -v $PWD/.kube/config:/upgrade/.kube/config \ - -v $PWD/backup:/upgrade/backup \ - cloud-provisioner-upgrade:0.17.0-0.8.X +find backup/upgrade/*/capx-secrets/capa-system -name "capa-manager-bootstrap-credentials.yaml" +---- + +. Restaura el secreto: ++ +[source,bash] +---- +kubectl apply -f backup/upgrade//capx-secrets/capa-system/capa-manager-bootstrap-credentials.yaml +---- + +. Relanza `upgrade-provisioner.py` con el mismo comando. Con el secreto restaurado, `clusterctl upgrade apply` se ejecuta correctamente y reinstala el _provider_ completo (`Deployment`, RBAC, CRDs, _webhooks_). + +IMPORTANT: Si el fallo de `clusterctl` ocurrió dentro de la sección crítica, es habitual que el reintento tropiece además con dos efectos secundarios de esa misma interrupción, independientes entre sí: + +* **`capi-controller-manager` con menos de 2 réplicas disponibles** — bloquea la comprobación previa del _script_ (`availableReplicas=1 (expected 2 for HA)`). Corrígelo antes de reintentar: ++ +[source,bash] +---- +kubectl scale deployment capi-controller-manager -n capi-system --replicas=2 +---- + +* **`HelmRelease` de `cluster-operator` con `spec.suspend: true`** — la sección crítica lo suspende y lo reactiva al finalizar; si el fallo interrumpió ese ciclo antes de la reactivación, cualquier paso posterior que espere a que el `HelmRelease` refleje un cambio de versión se queda esperando indefinidamente sin ningún mensaje de error. Compruébalo y reactívalo si hace falta: ++ +[source,bash] +---- +kubectl get helmrelease cluster-operator -n kube-system -o jsonpath='{.spec.suspend}' +kubectl patch helmrelease cluster-operator -n kube-system --type=merge -p '{"spec":{"suspend":false}}' ---- == Descripción general del proceso de actualización @@ -276,10 +515,13 @@ El _script_ ejecuta el siguiente flujo de trabajo: . *Pre-actualización* ** Escala _cluster-autoscaler_ a 0 para evitar escalado automático durante la actualización. (No aplica en GKE). ++ +NOTE: Este escalado a 0 dura solo hasta que se actualiza el propio _chart_ de `cluster-autoscaler` (paso "Actualización de _charts_" más abajo) — su `ConfigMap` de valores fija `replicaCount: 2`, así que Flux lo restaura a 2 réplicas ahí, antes de llegar a la sección crítica de `clusterctl upgrade apply`. No se mantiene a 0 durante toda la actualización. . *Copia de seguridad* ** Componentes CAPX (mediante `clusterctl move`). ** Configuraciones de _webhooks_ de Capsule. +** Secretos de los _namespaces_ CAPX. . *Preparación de Capsule* ** Modifica los _webhooks_ para excluir _namespaces_ críticos de la validación y la mutación. @@ -292,7 +534,9 @@ El _script_ ejecuta el siguiente flujo de trabajo: . *Preparación de _Cluster-Operator_* ** Suspende el _HelmRelease_ de _cluster-operator_. +** Verifica que `KeosCluster` esté _ready_/`Provisioned` antes de entrar en la sección crítica. ** Detiene el _deployment_ de _keoscluster-controller_. +** Hace copia de seguridad de las configuraciones de los _webhooks_ de `KeosCluster`. ** Desactiva los _webhooks_ de validación/mutación de _keoscluster_. ** Actualiza _ClusterConfig_ con las nuevas versiones de componentes. @@ -306,22 +550,31 @@ clusterctl upgrade apply \ --wait-providers ---- +. *Actualización de la versión de Kubernetes* (si `KeosCluster.spec.k8s_version` cambia respecto a la versión actual) +** Parchea `KeosCluster.spec.k8s_version` con la nueva versión. +** Restaura los _webhooks_ de _keoscluster_ e inicia de nuevo el _deployment_ de _keoscluster-controller_. +** Verifica que _cluster-operator_ haya propagado el cambio al recurso de plano de control gestionado por el proveedor (`AWSManagedControlPlane` en EKS) antes de continuar. + +IMPORTANT: Este paso solo actualiza el **plano de control**. Los grupos de trabajo _MachineDeployment_ (con o sin `node_image` fijo) quedan deliberadamente "pineados" a su versión de Kubernetes anterior — _cluster-operator_ salta el _bump_ para ellos explícitamente, no es un efecto secundario. Solo los grupos _MachinePool_ reciben el _bump_ de versión real. Para actualizar la versión de los _MachineDeployment_, migra a _MachinePool_ (ver <<_migración_de_machinedeployments_a_machinepools>>). + . *Post-actualización* -** Restaura los _webhooks_ de _keoscluster_. -** Inicia el _deployment_ de _keoscluster-controller_. ** Reanuda el _HelmRelease_ de _cluster-operator_. ** Espera a que el _cluster-operator_ esté _ready_. -** Espera a que todos los componentes estén en estado _ready_. +** Espera a que la infraestructura real del proveedor _cloud_ alcance la nueva versión de Kubernetes (en EKS, hasta 90 minutos; AWS aplica los _minors_ de uno en uno de forma automática, por lo que un salto de varios _minors_ puede observarse como varias transiciones sucesivas `UPDATING` → `ACTIVE` antes de alcanzar la versión final). +** Si no hubo _bump_ de `k8s_version` (la espera de ese caso ya la cubre el paso anterior), espera a que `KeosCluster.status.ready` sea `true`. +** Espera a que el _deployment_ `keoscluster-controller-manager` esté en estado `Available`. ** Restaura las réplicas de _cluster-autoscaler_ a 2. == Monitorización durante la actualización -* Monitorizar _pods_ críticos. +* Monitorizar _pods_ no sanos (genérico, válido para cualquier _provider_ — no depende de una lista de nombres de componente que se puede quedar desactualizada). + [source,bash] ---- -watch -n2 'kubectl get pods -A | grep -E "cluster-operator|capi|cap.|autoscaler|tigera"' +watch -n5 'kubectl get pods -A | grep -Ev "Running|Completed"' ---- ++ +NOTE: Durante una actualización sana, este comando no debería mostrar nada. * Seguir _HelmReleases_. + @@ -337,6 +590,13 @@ watch -n2 kubectl get helmreleases -A watch -n2 kubectl get providers -A ---- +* Durante la actualización de la versión de Kubernetes, el _script_ no muestra progreso mientras espera a que la infraestructura real del proveedor _cloud_ complete el cambio. En EKS, sigue el estado real del plano de control directamente en AWS: ++ +[source,bash] +---- +watch -n30 aws eks describe-cluster --name --query 'cluster.{status:status,version:version}' --output table +---- + == Verificación final * Verificar imágenes de contenedor. @@ -382,9 +642,14 @@ kubectl get keoscluster -A kubectl get machines -A kubectl get machinedeployments -A kubectl get machinepools -A -kubectl get nodes -# Verificar que los logs de CAPX no contengan errores tras la actualización +kubectl get nodes -o custom-columns=NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion +kubectl logs -n capi-system deploy/capi-controller-manager --since=30m | grep -i error +kubectl logs -n capa-system deploy/capa-controller-manager --since=30m | grep -i error ---- ++ +NOTE: En un salto de varios _minors_ de `k8s_version`, es esperable ver errores transitorios en los _logs_ de `capa-controller-manager` — `InvalidParameterException: Addon version specified is not supported` al actualizar addons EKS (p. ej. `kube-proxy`) mientras el plano de control real de AWS aún no llegó al _minor_ intermedio necesario, y `connection to the workload cluster is down` durante la ventana de actualización del propio plano de control. Ambos se autorresuelven solos en los minutos siguientes sin intervención, una vez `AWSManagedControlPlane.status.conditions[EKSAddonsConfigured]` pasa a `True`. Solo trátalos como problema real si persisten más allá de la ventana de actualización. ++ +*Salida esperada:* `KeosCluster.spec.k8s_version` coincide con la versión objetivo. Los grupos _MachinePool_ reportan esa misma versión en `kubeletVersion`. Los grupos _MachineDeployment_ (legacy o con `node_image` fijo) **no cambian** — quedan pineados a su versión anterior hasta que se migren a _MachinePool_ (ver <<_migración_de_machinedeployments_a_machinepools>>); no lo trates como un fallo de la actualización. == _Clusters_ EKS con _MachinePools_ @@ -394,59 +659,130 @@ NOTE: Los _MachinePools_ solo están disponibles en _clusters_ creados con esta WARNING: Este procedimiento se aplica únicamente a _clusters_ EKS (AWS gestionado). No está disponible para Azure VMs ni para GKE. -La migración es un proceso asistido y en fases. El _script_ `migrate-workers-to-machinepool.py` prepara el _cluster_ y valida la capacidad antes de cada drenado. Los nodos se migran manualmente, uno a uno, al ritmo que decidas. +Migrar un grupo de trabajo existente de _MachineDeployment_ a _MachinePool_ tiene tres partes: confirmar que el _cluster_ cumple los prerrequisitos, configurar el _role_ IAM fijo obligatorio para los `MachinePool`, y migrar cada grupo de nodos manualmente. ==== Prerrequisitos -* cluster-operator >= 0.6.1 y CAPA >= v2.9.2 en el _cluster_. +El _cluster_ necesita: + +* cluster-operator >= 0.7.0 y CAPA >= v2.9.3 (si no, ejecuta primero `upgrade-provisioner.py`). * `KeosCluster.status.ready = true`. -* La política EKS del usuario de despliegue debe incluir los permisos de gestión de _nodegroups_ del fichero _stratio-eks-policy.json_: `eks:CreateNodegroup`, `eks:DescribeNodegroup`, `eks:DeleteNodegroup`, `autoscaling:DescribeAutoScalingGroups` e `iam:CreateServiceLinkedRole`. +* La política EKS del usuario de despliegue con los permisos de _nodegroups_ ya documentados en xref:operations-manual:installation.adoc#eks_nodegroup_permissions[] (`eks:CreateNodegroup`, `eks:DescribeNodegroup`, `eks:DeleteNodegroup`, `autoscaling:DescribeAutoScalingGroups`, `iam:CreateServiceLinkedRole`) — incluidos en _stratio-eks-policy.json_. Si el _cluster_ se creó sin ellos, actualiza el _stack_ de IAM con `clusterawsadm` (mismo procedimiento que en la instalación). + +Para confirmar los dos primeros puntos de una vez, ejecuta este _script_ (de solo lectura, no actualiza ni crea nada) dentro del contenedor de _Stratio Cloud Provisioner_: + +[source,bash] +---- +python3 activate-capa-machinepool-features.py \ + -p \ + 2>&1 | tee activate-mp-$(date +%Y%m%d-%H%M%S).log +---- + +NOTE: El _script_ no genera un archivo de registro propio con marca de tiempo (igual que `ecr_pull_through.py` y `upgrade-provisioner.py`) — toda su salida va a la consola del contenedor. El `tee` de arriba conserva un registro completo de la ejecución. + +Además de la versión, comprueba que los _feature gates_ de CAPA (`MachinePool=true`, `EKSAllowAddRoles=true`) ya estén habilitados — no los activa él mismo, eso lo hace `upgrade-provisioner.py` al reinstalar CAPA vía `clusterctl upgrade apply`; un `kubectl patch` directo aquí se perdería en la siguiente actualización real. Si algo falla, el _script_ indica que hay que ejecutar `upgrade-provisioner.py` primero. Si el _cluster_ ya pasó por una actualización normal a una versión con `cluster-operator >= 0.7.0`/`CAPA >= v2.9.3`, ejecutarlo es solo una confirmación rápida, no un paso imprescindible. + +IMPORTANT: Si se acaba de ejecutar `upgrade-provisioner.py`, no asumas que `KeosCluster.status.ready` ya es `true` solo porque el _script_ terminó con `Upgrade process finished successfully` — la reconciliación no es inmediata, puede tardar varios minutos en el siguiente ciclo de _resync_ del controlador. Comprueba el valor real (`kubectl get keoscluster -A`, esperando `PHASE: Provisioned` y `READY: true`) antes de continuar si el paso anterior falla por este motivo. -Si el _cluster_ tiene versiones anteriores, ejecuta primero `upgrade-provisioner.py`. +El _role_ de servicio `AWSServiceRoleForAmazonEKSNodegroup` (el que usa el propio servicio EKS para gestionar el _Auto Scaling Group_/_launch template_ detrás de cada _nodegroup_ gestionado) no lo crea ningún _script_ de _Stratio Cloud Provisioner_ — AWS lo crea automáticamente en el primer _nodegroup_ gestionado que se cree en la cuenta/región, siempre que el usuario de despliegue tenga el permiso `iam:CreateServiceLinkedRole` (ya listado arriba). No se requiere ninguna acción manual para este _role_. -==== Fase 1: preparación del _cluster_ +==== Configurar el _role_ IAM fijo para los _MachinePool_ -IMPORTANT: Antes de ejecutar el _script_, verifica que la imagen y el _chart_ de _cluster-operator_ de esta versión estén disponibles en el registro de contenedores y en el repositorio de Helm configurados para el _cluster_. Si el _cluster_ usa registros privados (`private_registry=true` o `private_helm_repo=true`), asegúrate de que los artefactos se hayan publicado antes de continuar. +IMPORTANT: Este paso es obligatorio al migrar a `MachinePool` — no se admite dejar los _nodegroups_ con el _role_ IAM dinámico que CAPA crea por defecto (`capa_`, distinto en cada recreación del _nodegroup_). Fijar `mp_role_name` es la única forma soportada de gestionar permisos IAM consistentes sobre los nodos `MachinePool` (por ejemplo, para `ecr_pull_through_cache_enabled` — ver <<_migración_a_ecr_pull_through_cache>>); con un _role_ dinámico habría que volver a conceder esos permisos a mano cada vez que el _nodegroup_ se recrea, con un nombre de _role_ distinto cada vez. -Ejecuta el _script_ de preparación dentro del contenedor de _Stratio Cloud Provisioner_: +Se fija con `spec.control_plane.aws.mp_role_name`, a un _role_ IAM único y reutilizable para todos los `MachinePool` del _cluster_. Con `security.aws.create_iam: true`, _Stratio Cloud Provisioner_ ya crea automáticamente el _role_ `eks-nodegroup.cluster-api-provider-aws.sigs.k8s.io` como parte del _stack_ de CloudFormation — sin usarlo en ningún sitio hasta que se indique explícitamente aquí. Fíjalo con un `patch` (nunca `apply`, ver convención del proyecto): [source,bash] ---- -python3 migrate-workers-to-machinepool.py \ - --kubeconfig ~/.kube/config +kubectl patch keoscluster -n cluster- --type=merge \ + -p '{"spec":{"control_plane":{"aws":{"mp_role_name":"eks-nodegroup.cluster-api-provider-aws.sigs.k8s.io"}}}}' ---- -El _script_ usa por defecto la versión de _cluster-operator_ incluida en esta versión de _Stratio Cloud Provisioner_. Puedes sobrescribirla con `--cluster-operator-version ` si es necesario. +IMPORTANT: En un _cluster_ creado con una versión anterior a la 0.9.x, este _role_ puede no existir todavía aunque tenga `security.aws.create_iam: true` — ver <<_si_el_role_no_existe_todavía_en_un_cluster_con_create_iam_true>> más abajo. Con `security.aws.create_iam: false` (IAM gestionado por el cliente), el _role_ no se crea automáticamente en ningún caso — hay que crearlo a mano con un nombre a elección del cliente, con los permisos equivalentes (ver la referencia del campo `mp_role_name` en xref:operations-manual:installation.adoc#mp_role_name_ownership[]). -El _script_ valida los prerrequisitos, activa los _feature gates_ de CAPA (`MachinePool=true` y `EKSAllowAddRoles=true`) y actualiza el _cluster-operator_ a la versión indicada. +Este cambio no afecta a los `MachinePool` que ya existan — solo a los que se creen después del `patch`. Para migrar uno ya creado con un _role_ dinámico al _role_ fijo hay que recrearlo (no es un campo actualizable in-situ en un _nodegroup_ EKS ya existente). + +===== Si el _role_ no existe todavía en un _cluster_ con `create_iam: true` + +El _stack_ de CloudFormation de un _cluster_ con `security.aws.create_iam: true` incluye el _role_ `eks-nodegroup.cluster-api-provider-aws.sigs.k8s.io` desde que _Stratio Cloud Provisioner_ empezó a generar esa configuración por defecto (`AWSIAMConfiguration`, bloque `spec.eks.managedMachinePool`). Un _cluster_ cuyo _stack_ se creó antes de eso puede no tenerlo todavía. Compruébalo: + +[source,bash] +---- +aws iam get-role --role-name eks-nodegroup.cluster-api-provider-aws.sigs.k8s.io +---- -==== Fase 2: migración de grupos de nodos +Si no existe, actualiza el _stack_ existente con `clusterawsadm` — es una operación idempotente (`create-cloudformation-stack` y `update-cloudformation-stack` son alias del mismo comando) que añade lo que falte sin afectar al resto de recursos ya creados por el _stack_. Añade el bloque `eks.managedMachinePool` a la configuración (mismo patrón que el resto de esta guía, ver xref:operations-manual:installation.adoc[] para la configuración base de IAM): -Repite los siguientes pasos para cada grupo de nodos que quieras migrar: +[source,bash] +---- +cat > /tmp/eks-mp.config << 'EOF' +apiVersion: bootstrap.aws.infrastructure.cluster.x-k8s.io/v1beta1 +kind: AWSIAMConfiguration +spec: + bootstrapUser: + enable: false + eks: + enable: true + iamRoleCreation: false + defaultControlPlaneRole: + disable: false + managedMachinePool: + disable: false + controlPlane: + enableCSIPolicy: true + nodes: + extraPolicyAttachments: + - arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy +EOF + +clusterawsadm bootstrap iam create-cloudformation-stack \ + --config /tmp/eks-mp.config \ + --region +---- + +Si el _cluster_ también tiene `ecr_pull_through_cache_enabled: true`, añade además las políticas de esa configuración (ver <<_migración_a_ecr_pull_through_cache>>) al mismo bloque `managedMachinePool.extraPolicyAttachments`, para que los nodos `MachinePool` también las tengan. + +==== Migrar un grupo de nodos + +Repite estos pasos para cada grupo que quieras migrar, una vez activado el soporte de _MachinePool_: . Añade el nuevo grupo _MachinePool_ al objeto `KeosCluster`. Omite `node_image` e indica `ami_type` de forma opcional (por defecto, "BOTTLEROCKET_x86_64"): + [source,bash] ---- -kubectl patch keoscluster -n cluster- \ +kubectl -n cluster- patch keoscluster \ --type=json \ - -p '[{"op":"add","path":"/spec/worker_nodes/-","value":{"name":"-mp","size":"","quantity":,"az":"","min_size":,"max_size":}}]' + -p '[{"op":"add","path":"/spec/worker_nodes/-","value":{"name":"","size":"","quantity":,"az":"","min_size":,"max_size":}}]' ---- + NOTE: Usa `--type=json` con la operación `add` y el path `/spec/worker_nodes/-` para añadir el grupo sin reemplazar los existentes. Nunca uses `kubectl apply` sobre el `KeosCluster`: _cluster-operator_ detecta la anotación `kubectl.kubernetes.io/last-applied-configuration` que genera `apply` y salta el ciclo de reconciliación real, por lo que los cambios en `spec.worker_nodes` nunca se procesan. ++ +WARNING: `spec.worker_nodes[].name` (`` arriba) admite entre 3 y 25 caracteres (_webhook_ de `KeosCluster`) y debe ser único. **No le añadas tú el sufijo `-mp`/`-md`**: _cluster-operator_ ya añade `-mp-<índice>` (o `-md-<índice>` en `MachineDeployment`) automáticamente al nombre que des (`controllers/templates/aws/aws.eks.tmpl`). -. Espera a que los nodos de _MachinePool_ estén en estado _Ready_. -. Verifica la capacidad y obtén las instrucciones de drenado y eliminación: +. Espera a que el nuevo grupo esté sano: + [source,bash] ---- -python3 migrate-workers-to-machinepool.py \ - --check-ready -mp +kubectl -n cluster- get machinepool -l cluster.x-k8s.io/deployment-name=-mp-<índice> \ + -o jsonpath='{.items[0].status.readyReplicas}/{.items[0].status.replicas}' ---- + +. Identifica los nodos reales del `MachineDeployment` a reemplazar y drénalos uno a uno, verificando el estado del _cluster_ entre cada uno: ++ +IMPORTANT: El _label_ `cluster.x-k8s.io/deployment-name` vive en el objeto `Machine` (CAPI), no en el `Node` de Kubernetes — `kubectl get nodes -l cluster.x-k8s.io/deployment-name=...` siempre da 0 resultados. Resuelve el nombre real del `Node` a través del `Machine`: + -El _script_ imprime los comandos de drenado para cada nodo del grupo _MachineDeployment_ equivalente, así como las instrucciones para eliminar la entrada de ese grupo del objeto `KeosCluster`. Revisa las instrucciones antes de ejecutarlas. +[source,bash] +---- +kubectl -n cluster- get machine -l cluster.x-k8s.io/deployment-name= \ + -o jsonpath='{.items[*].status.nodeRef.name}' +kubectl drain --ignore-daemonsets --delete-emptydir-data --timeout=10m +---- -. Ejecuta los comandos de drenado que imprime el _script_, uno a uno. Verifica el estado del _cluster_ entre cada nodo. -. Sigue las instrucciones que imprime el _script_ para eliminar el grupo _MachineDeployment_ del objeto `KeosCluster`. +. Elimina la entrada del `MachineDeployment` migrado de `spec.worker_nodes` en el `KeosCluster` (mismo mecanismo `--type=json`, operación `remove`) y verifica que no queden objetos `MachineDeployment` de ese grupo: ++ +[source,bash] +---- +kubectl get machinedeployment -A | grep +---- NOTE: No elimines el grupo _MachineDeployment_ hasta que todos sus nodos estén drenados y el grupo _MachinePool_ tenga capacidad suficiente para absorber la carga de trabajo. From 060d840549f3cf151a3d82622e1467638b340c35 Mon Sep 17 00:00:00 2001 From: iamjanr Date: Wed, 19 Aug 2026 11:11:18 +0200 Subject: [PATCH 3/3] [PLT-4667] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 642b80e2d0..e2be670760 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## 0.9.0 (upcoming) +* [PLT-4667] Rewrite the EKS upgrade guide (`upgrade.adoc`) against the real 0.9.0 flow; document the fixed `mp_role_name` IAM role requirement for MachinePool and known MachinePool limitations + * [PLT-4265] Harden `upgrade-provisioner.py` for the cloud-provisioner 0.9.0/K8s 1.35 upgrade path: add `k8s_version` bump support, pre-flight health checks, and controlled recovery on failure; align component versions and dependencies * [PLT-4603] Allow `ami_type: BOTTLEROCKET_x86_64_NVIDIA` for EKS MachinePool worker nodes (was rejected by the CLI validator, only `BOTTLEROCKET_x86_64` was accepted) * [PLT-4562] Bump Calico v3.31.5→v3.31.6, tigera-operator controller v1.40.11→v1.40.13 (k8s 1.35 only) to resolve vulnerabilities