Compartir a través de


Configuración de directivas de interrupción de nodos para nodos de aprovisionamiento automático de nodos (NAP) en Azure Kubernetes Service (AKS)

En este artículo se explica cómo configurar directivas de interrupción del nodo para nodos de aprovisionamiento automático de nodos (NAP) de Azure Kubernetes Service (AKS) y cómo funciona la interrupción para optimizar el uso de recursos y la eficiencia de los costos.

NAP optimiza el clúster mediante:

  • Quitar o reemplazar nodos infrautilizados.
  • Consolidación de cargas de trabajo para reducir los costos.
  • Respetar los presupuestos de interrupción y las ventanas de mantenimiento.
  • Proporcionar control manual cuando sea necesario.

Antes de empezar

¿Cómo funciona la interrupción del nodo para los nodos NAP?

Karpenter establece un finalizador de Kubernetes en cada nodo y en cada reclamo de nodo que aprovisiona. El finalizador bloquea la eliminación del objeto de nodo, mientras que el controlador de terminación marca y purga el nodo antes de quitar la reclamación del nodo subyacente.

Cuando las cargas de trabajo de los nodos se reducen, NAP utiliza reglas de interrupción en la especificación del grupo de nodos para decidir cuándo y cómo quitar esos nodos y potencialmente reprogramar las cargas de trabajo para lograr eficiencia.

Métodos de interrupción del nodo

NAP detecta automáticamente los nodos aptos para la interrupción y pone en marcha los reemplazos cuando sea necesario. Puede desencadenar interrupciones a través de métodos automatizados como Expiration, Consolidation y Drift, métodos manuales o sistemas externos.

Expiration

La expiración le permite establecer una antigüedad máxima para los nodos NAP. Los nodos se marcan como expirados e interrumpidos después de alcanzar la edad especificada para el valor spec.disruption.expireAfter del grupo de nodos.

Configuración de expiración de ejemplo

En el ejemplo siguiente se muestra cómo establecer la hora de expiración de los nodos NAP en 24 horas:

spec:
  disruption:
    expireAfter: 24h  # Expire nodes after 24 hours

Consolidación

NAP funciona para reducir activamente el costo del clúster mediante la identificación de cuándo se pueden quitar los nodos porque están vacíos o infrautilizados, o cuando los nodos se pueden reemplazar por variantes de precio inferior. Este proceso se denomina Consolidación. NAP usa principalmente la consolidación para eliminar o reemplazar nodos para una ubicación óptima del pod.

NAP realiza los siguientes tipos de consolidación para optimizar el uso de recursos:

  • Consolidación de nodos vacíos: elimina los nodos vacíos en paralelo.
  • Consolidación de varios nodos: elimina varios nodos, posiblemente iniciando un único reemplazo.
  • Consolidación de un solo nodo: elimina cualquier nodo único, posiblemente iniciando un reemplazo.

Puede desencadenar la consolidación a través del spec.disruption.consolidationPolicy campo de la especificación del grupo de nodos mediante las configuraciones WhenEmpty o WhenEmptyOrUnderUtilized. También puede establecer el consolidateAfter campo , que es una condición basada en el tiempo que determina cuánto tiempo espera NAP después de detectar una oportunidad de consolidación antes de interrumpir el nodo.

Configuración de consolidación de ejemplo

En el ejemplo siguiente se muestra cómo configurar NAP para consolidar los nodos cuando están vacíos y esperar 30 segundos después de detectar una oportunidad de consolidación antes de interrumpir el nodo:

  disruption:
    # Describes which types of nodes NAP should consider for consolidation
    # `WhenEmptyOrUnderUtilized`: NAP considers all nodes for consolidation and attempts to remove or replace nodes when it discovers that the node is empty or underutilized and could be changed to reduce cost
    # `WhenEmpty`: NAP only considers nodes for consolidation that don't contain any workload pods
    
    consolidationPolicy: WhenEmpty

    # The amount of time NAP should wait after discovering a consolidation decision
    # Currently, you can only set this value when the consolidation policy is `WhenEmpty`
    # You can choose to disable consolidation entirely by setting the string value `Never`
    consolidateAfter: 30s

Drift

El desfase controla los cambios en los recursos NodePool/AKSNodeClass. Los valores en el NodeClaimTemplateSpec/AKSNodeClassSpec se reflejan de la misma manera en que se establecen. Un NodeClaim se considera desfasado si los valores del NodePool/AKSNodeClass asociado no coinciden con los valores de NodeClaim. De forma similar a la relación deployment.spec.template ascendente con los pods, Karpenter anota el NodePool/AKSNodeClass asociado con un hash de NodeClaimTemplateSpec para comprobar el desfase. Karpenter quita la Drifted condición de estado en los escenarios siguientes:

  • La puerta de característica Drift no está habilitada, pero NodeClaim está desfasado.
  • NodeClaim no está desfasado, pero tiene la condición de estado.

Karpenter o la interfaz del proveedor de nube pueden detectar casos especiales desencadenados por NodeClaim/Instance/NodePool/AKSNodeClasscambios.

Casos especiales en el desfase

En casos especiales, el desfase puede corresponder a varios valores y debe controlarse de forma diferente. El desfase en campos resueltos puede crear casos en los que el desfase se produce sin cambios en definiciones de recursos personalizados (CRD) o en los que los cambios de CRD no dan lugar a un desfase.

Por ejemplo, si un NodeClaim tiene node.kubernetes.io/instance-type: Standard_D2s_v3, y los requisitos cambian de node.kubernetes.io/instance-type In [Standard_D2s_v3] a node.kubernetes.io/instance-type In [Standard_D2s_v3, Standard_D4s_v3], el NodeClaim no se desvía porque su valor sigue siendo compatible con los nuevos requisitos. Por el contrario, si NodeClaim usa NodeClaimimageFamily, pero el campo spec.imageFamily cambia, Karpenter detecta NodeClaim como desfasado y reemplaza el nodo para cumplir con esa especificación.

Importante

Karpenter supervisa los cambios de configuración de subred y detecta el desfase cuando se modifica el vnetSubnetID en un AKSNodeClass. Comprender este comportamiento es fundamental al administrar configuraciones de red personalizadas. Para obtener más información, consulte Comportamiento del desfase de subred.

Para obtener más información, consulte Drift Design.

Período de gracia de finalización

Puede establecer un período de gracia de terminación para los nodos NAP mediante el spec.template.spec.terminationGracePeriod campo de la especificación del grupo de nodos. Esta configuración le permite configurar cuánto tiempo espera Karpenter para que los pods finalicen correctamente. Esta configuración tiene prioridad sobre terminationGracePeriodSeconds de un pod y pasa por alto PodDisruptionBudgets y la anotación karpenter.sh/do-not-disrupt.

Configuración del período de gracia de finalización de ejemplo

En el ejemplo siguiente se muestra cómo establecer un período de gracia de terminación de 30 segundos para los nodos NAP:

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: default
spec:
  template:
    spec:
      terminationGracePeriod: 30s

Presupuestos de interrupciones

Puede limitar la interrupción de Karpenter modificando el campo spec.disruption.budgets en la especificación del grupo de nodos. Si deja esta configuración sin definir, Karpenter tiene como valor predeterminado un presupuesto con nodes: 10%. Los presupuestos consideran los nodos que se eliminan por cualquier motivo y solo impiden que Karpenter sufra interrupciones voluntarias debido a la expiración, el desfase, el vacío y la consolidación.

Al calcular si un presupuesto previene interrupciones en los nodos, Karpenter cuenta el total de nodos que pertenecen a un grupo de nodos y, a continuación, resta los nodos que se eliminan y los nodos que son NotReady. Si el presupuesto está configurado con un valor de porcentaje, como 20%, Karpenter calcula el número de interrupciones permitidas como allowed_disruptions = roundup(total * percentage) - total_deleting - total_notready. Para varios presupuestos de un grupo de nodos, Karpenter toma el valor mínimo (más restrictivo) de cada uno de los presupuestos.

Campos de programación y duración

Al usar presupuestos, puede establecer opcionalmente los campos schedule y duration para crear presupuestos basados en tiempo. Estos campos permiten definir ventanas de mantenimiento o períodos de tiempo específicos cuando los límites de interrupción son más estrictos.

  • Schedule usa la sintaxis de trabajo cron con macros especiales como @yearly, @monthly, @weekly, @daily, . @hourly
  • La duración permite duraciones compuestas como 10h5m, 30mo 160h. La duración y la programación deben definirse juntas.

Ejemplos de programación y duración

Presupuesto de la ventana de mantenimiento

Evitar interrupciones durante el horario comercial:

budgets:
- nodes: "0"
  schedule: "0 9 * * 1-5"  # 9 AM Monday-Friday
  duration: 8h             # For 8 hours
Interrupciones solo de fin de semana

Permitir solo interrupciones los fines de semana:

budgets:
- nodes: "50%"
  schedule: "0 0 * * 6"    # Saturday midnight
  duration: 48h            # All weekend
- nodes: "0"               # Block all other times
Presupuesto de lanzamiento gradual

Permitir tasas de interrupción crecientes:

budgets:
- nodes: "1"
  schedule: "0 2 * * *"    # 2 AM daily
  duration: 2h
- nodes: "3"
  schedule: "0 4 * * *"    # 4 AM daily
  duration: 4h

Ejemplos de configuración de presupuesto

La especificación siguiente NodePool tiene tres presupuestos configurados:

  • El primer presupuesto permite que el 20 % de los nodos del conjunto de nodos se interrumpan a la vez.
  • El segundo presupuesto actúa como límite máximo, lo que solo permite cinco interrupciones cuando hay más de 25 nodos.
  • El último presupuesto bloquea las interrupciones durante los primeros 10 minutos de cada día.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: default
spec:
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    expireAfter: 720h # 30 * 24h = 720h
    budgets:
    - nodes: "20%"      # Allow 20% of nodes to be disrupted
    - nodes: "5"        # Cap at maximum 5 nodes
    - nodes: "0"        # Block all disruptions during maintenance window
      schedule: "@daily" # Scheduled daily
      duration: 10m # Duration of 10 minutes

Interrupción manual del nodo

Puede interrumpir manualmente los nodos NAP mediante kubectl o eliminando NodePool recursos.

Eliminación de nodos con kubectl

Puede quitar manualmente los nodos mediante el kubectl delete node comando . Puede eliminar nodos específicos, todos los nodos administrados por NAP o nodos de un grupo de nodos específico mediante etiquetas, por ejemplo:

# Delete a specific node
kubectl delete node $NODE_NAME

# Delete all NAP-managed nodes
kubectl delete nodes -l karpenter.sh/nodepool

# Delete nodes from a specific nodepool
kubectl delete nodes -l karpenter.sh/nodepool=$NODEPOOL_NAME

Eliminar NodePool recursos

NodePool posee NodeClaims a través de una referencia de propietario. NAP finaliza los nodos de manera elegante mediante la eliminación en cascada al eliminar el recurso asociado NodePool.

Controlar la interrupción mediante anotaciones

Puede bloquear o restringir la disrupción para pods específicos, nodos o grupos completos de nodos mediante anotaciones.

Controles de pod

Puede bloquear que NAP interrumpa ciertos pods estableciendo la anotación karpenter.sh/do-not-disrupt: "true":

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    metadata:
      annotations:
        karpenter.sh/do-not-disrupt: "true"

Esta anotación evita interrupciones voluntarias para expiración, consolidación y desfase. Sin embargo, no impide la interrupción de sistemas externos ni interrupciones manuales a través de la eliminación de kubectl o NodePool.

Controles de nodo

Impedir que NAP interrumpa los nodos específicos:

apiVersion: v1
kind: Node
metadata:
  annotations:
    karpenter.sh/do-not-disrupt: "true"

Controles de grupo de nodos

Desactive la interrupción para todos los nodos en NodePool.

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: default
spec:
  template:
    metadata:
      annotations:
        karpenter.sh/do-not-disrupt: "true"

Pasos siguientes

Para obtener más información sobre el aprovisionamiento automático de nodos en AKS, consulte los siguientes artículos: