Nube e infraestructura

Comprensión de la mecánica de eliminación en Kubernetes mediante finalizers y owner references

Una guía de 2021 explica cómo los finalizers bloquean la eliminación de recursos y cómo las owner references gestionan las eliminaciones en cascada en clústeres de Kubernetes.

Ilustración de un contenedor con componentes internos y un símbolo de bloqueo que representa los finalizers.
Imagen: Kubernetes Blog, con licencia CC BY 4.0

Traducido automáticamente del original en inglés.

En una publicación del blog de Kubernetes de mayo de 2021, Aaron Alpar detalló la mecánica interna de la eliminación de objetos en Kubernetes. El artículo aclara por qué algunos recursos persisten después de emitir un comando de eliminación y explica el papel de los finalizers y las owner references en la gestión del estado del clúster.

Qué ocurrió

Kubernetes ofrece comandos estándar para crear, leer, actualizar y eliminar objetos, pero el proceso de eliminación es más complejo que una simple retirada del almacenamiento. Cuando un usuario emite un comando kubectl delete, el sistema no siempre elimina inmediatamente el objeto de su registro, etcd. En cambio, la operación puede entrar en un estado pendiente si se cumplen condiciones específicas, como la presencia de finalizers o relaciones complejas de propiedad.

El artículo demuestra que, aunque las eliminaciones básicas funcionan como se espera para recursos simples como ConfigMaps sin metadatos adicionales, añadir finalizers cambia significativamente el comportamiento. Un finalizer actúa como un hook previo a la eliminación, indicando a los controladores que deben realizarse operaciones de limpieza antes de que el recurso sea retirado completamente. Si estos hooks no se resuelven, el objeto permanece en un estado de terminación, visible mediante una marca de tiempo de eliminación, pero aún presente en el clúster.

Además, la relación entre recursos, definida por las owner references, dicta cómo se eliminan grupos de objetos conjuntamente. Eliminar un objeto padre puede desencadenar la eliminación de sus hijos, un proceso conocido como cascada. Sin embargo, este comportamiento puede modificarse utilizando políticas de propagación, lo que permite a los desarrolladores dejar huérfanos a los hijos o controlar el orden de eliminación. Comprender estos mecanismos es crítico para depurar namespaces atascados o recursos persistentes.

Cómo funciona

Los finalizers son claves adjuntas a los metadatos de un recurso que impiden la recolección inmediata de basura (garbage collection). Funcionan de manera similar a las anotaciones, pero tienen peso semántico para los controladores. Cuando se realiza una solicitud de eliminación para un objeto con finalizers, Kubernetes actualiza el objeto con un deletionTimestamp pero bloquea su eliminación de etcd. El objeto permanece en este estado hasta que un controlador elimina las claves de finalizer, señalando que la limpieza está completa. Si ningún controlador gestiona el finalizer, este se convierte en un "dead" finalizer, requiriendo intervención manual mediante un comando patch para eliminar la clave y permitir que la eliminación continúe.

Figure from the original article: Comprensión de la mecánica de eliminación en Kubernetes mediante finalizers y owner references
Figura del artículo original · Kubernetes Blog · CC BY 4.0

Las owner references establecen relaciones padre-hijo entre recursos dentro del mismo namespace. Cada referencia incluye el nombre y el identificador único (UID) del objeto padre. Cuando se elimina un padre, Kubernetes revisa estas referencias para determinar si los hijos también deben ser eliminados. Esta eliminación en cascada está controlada por una política de propagación. La política predeterminada, que cambió a background en kubectl v1.20, permite que el padre sea eliminado primero mientras los hijos se retiran de forma asincrónica. Otras opciones incluyen foreground, donde los hijos se eliminan antes que el padre, y orphan, que ignora las owner references y deja intactos a los hijos.

Detalles clave

  • Los finalizers son listas de claves en los recursos que señalan operaciones previas a la eliminación a los controladores.
  • Los objetos con finalizers no se eliminan inmediatamente; reciben un deletionTimestamp y permanecen visibles hasta que se limpian los finalizers.
  • Las owner references vinculan recursos mediante nombre y UID, habilitando eliminaciones en cascada de objetos hijos cuando se elimina un padre.
  • El comportamiento de cascada predeterminado en kubectl v1.20 y posteriores es background, mientras que en versiones anteriores el valor predeterminado era true.
  • Las políticas de propagación (Foreground, Background, Orphan) controlan el orden de eliminación y solo pueden establecerse mediante llamadas directas a la API, no mediante flags estándar de kubectl.
  • Los namespaces atascados pueden forzarse a finalizar actualizando el subrecurso finalize vía la API, aunque esto conlleva el riesgo de dejar objetos huérfanos.

Por qué importa

Para los ingenieros que construyen y mantienen plataformas Kubernetes, comprender la mecánica de eliminación evita confusiones cuando los recursos no desaparecen como se esperaba. Un escenario común implica un namespace que permanece en estado Terminating porque un recurso personalizado o un controlador de terceros ha añadido un finalizer que ya no está siendo procesado. Sin saber cómo inspeccionar y parchear los finalizers, los operadores pueden tener dificultades para limpiar los clústeres, lo que conduce a fugas de recursos y fallos en los despliegues.

Figure from the original article: Comprensión de la mecánica de eliminación en Kubernetes mediante finalizers y owner references
Figura del artículo original · Kubernetes Blog · CC BY 4.0

Además, gestionar correctamente las owner references asegura que las desinstalaciones de aplicaciones sean limpias y predecibles. Si un desarrollador elimina un Deployment sin comprender las reglas de cascada, podría inadvertidamente dejar atrás Pods o Services que consumen recursos. Por el contrario, saber cómo usar la política orphan permite estrategias de migración seguras donde los recursos hijos necesitan sobrevivir a la eliminación de su padre original. Este conocimiento es esencial para escribir operadores robustos y scripts de automatización que interactúan con la API de Kubernetes.

Qué puedes hacer

  • Inspecciona objetos atascados en la eliminación comprobando su salida YAML en busca de campos finalizers y deletionTimestamp.
  • Elimina manualmente los dead finalizers usando kubectl patch con una operación JSON para quitar la clave de finalizer específica de los metadatos.
  • Usa kubectl get con owner references para visualizar las dependencias entre recursos antes de realizar eliminaciones masivas.
  • Prueba el comportamiento de cascada en un entorno no productivo creando ConfigMaps padre-hijo y observando los efectos de diferentes comandos de eliminación.
  • Utiliza kubectl proxy para realizar llamadas directas a la API cuando necesites especificar políticas de propagación como Foreground o Background.
  • Ten precaución al forzar la finalización de namespaces vía la API, ya que puede dejar recursos huérfanos que requieren limpieza manual.

Herramientas de la Tienda de Bytechap

Seguir leyendo

Todos los artículos