Control de la Programación de Pods en Kubernetes: Taints, Tolerations, nodeSelector y Node Affinity. Bloque 1. Tema 1.4 del CKA.
En Kubernetes, la programación de Pods es una de las funciones clave del "plano de control" (control plane). Por defecto, los Pods se distribuyen automáticamente entre los nodos disponibles, equilibrando la carga y optimizando el rendimiento del clúster. Sin embargo, en ciertos casos, es necesario tener un mayor control sobre dónde se ejecutan los Pods, y es aquí donde entran en juego Taints, Tolerations, NodeSelector y Node Affinit. Existen otros conceptos, más avanzados, que se estudirán en otro apartado.
Taints y Tolerations son mecanismos que trabajan juntos para controlar dónde no se deben ejecutar ciertos Pods, o para garantizar que solo ciertos tipos de Pods puedan ejecutarse en nodos específicos. Un Taint es una restricción que se aplica a un nodo para evitar que Pods no deseados se ejecuten en él, mientras que una Toleration permite a un Pod "tolerar" un Taint y ser programado en un nodo con esa restricción.
NodeSelector y Node Affinity son mecanismos que permiten especificar en qué nodos se desea que se ejecuten los Pods. nodeSelector es una forma sencilla de restringir la programación de un Pod a nodos específicos que tienen una determinada etiqueta. Por otro lado, Node Affinity ofrece una mayor flexibilidad, permitiendo configurar reglas más avanzadas y personalizadas basadas en etiquetas de los nodos.
Estos mecanismos son esenciales para gestionar la colocación de Pods de manera más controlada y personalizada, asegurando que se respeten las necesidades específicas de cada aplicación dentro del clúster.
Analogía para entenderlo bien:
Taints: Serían como las etiquetas que se ponen en las mesas de un restaurante. Por ejemplo, una mesa podría tener una etiqueta que diga "Reservada para el cumpleaños de tal persona". Estas etiquetas indican que esa mesa (nodo) no está disponible para cualquier cliente.
Tolerations: Serían las características de los clientes. Un cliente (pod) que sea de ese cumpleaños tendría una "tolerancia" a esa mesa.
NodeSelector: Imagina que cada mesa en un restaurante tiene un letrero indicando su ubicación específica, como "Terraza" o "Interior". Un cliente (Pod) que prefiere sentarse en la terraza puede solicitar específicamente una mesa en la "Terraza". Del mismo modo, nodeSelector permite que un Pod elija nodos que tengan una etiqueta específica (por ejemplo, "ubicación=terraza") para restringir dónde puede ejecutarse.
Node Affinity: Piensa en un evento de cine al aire libre donde las personas pueden tener preferencias sobre qué sección del parque prefieren, como la sección "con sombra" o "sin sombra". Sin embargo, algunos clientes son más flexibles que otros; pueden tener una "preferencia" por la sombra, pero están dispuestos a sentarse en el sol si no hay opción. Node Affinity funciona de manera similar, ya que permite a los Pods especificar preferencias para ejecutarse en ciertos nodos (por ejemplo, "con sombra") pero aún pueden considerar otras opciones si no hay nodos que cumplan todas sus preferencias.
Ahora que entendemos el concepto, vamos al detalle técnico:
1. Taints y Tolerations
Taints y Tolerations trabajan en conjunto para restringir o permitir la programación de Pods en nodos específicos. Un Taint es una restricción aplicada a un nodo que indica que ciertos Pods no deben ejecutarse allí, a menos que tengan una Toleration que coincida.
Taints:
- Aplicados a los nodos, marcan un nodo como "no deseado" para ciertos Pods.
- Contienen tres elementos:
Key
,Value
yEffect
. - Key: Una clave que representa el motivo del taint.
- Value: Un valor asociado con la clave (opcional).
- Effect: El efecto que tendrá el taint. Hay tres efectos posibles, cada uno aplica restricciones diferentes al nodo:
- NoSchedule: Evita que los nuevos pods se programen en el nodo, a menos que toleren el taint.
- PreferNoSchedule: Intenta evitar programar pods en el nodo, pero no es estrictamente prohibido.
- NoExecute: Los nuevos pods no se programarán en el nodo, y los pods existentes que no lo toleren serán expulsados del nodo
- Key: cumpleaños; Indica que la restricción de la mesa está relacionada con un evento específico: un cumpleaños.
- Value: Alba; Especifica que el cumpleaños es de Alba. Esto hace que la reserva sea aún más personalizada.
- Effect: NoSchedule;Estás reservando el nodo mesa1 exclusivamente para la fiesta de cumpleaños de Alba. Ninguna otra aplicación o servicio podrá ejecutarse en ese nodo a menos que esté específicamente diseñado para ello (es decir, tenga una tolerancia que coincida con el taint). Significa que ningún otro cliente, excepto aquellos que también estén celebrando el cumpleaños de Alba (y tengan la tolerancia correspondiente), puede sentarse en esa mesa.
Por entenderlo;
Tolerations:
Las tolerations se aplican a los pods y permiten que esos pods se ejecuten en nodos con taints que coincidan. Una toleration no significa que el pod debe ejecutarse en el nodo con el taint, sino que puede hacerlo si no hay otras restricciones.
Una toleration tiene una estructura similar a la de un taint:
- Key: La clave del taint que el pod puede tolerar.
- Operator: Define cómo debe coincidir la clave (igual a Exists o Equal).
- Value: El valor que el pod tolera (solo si el operador es Equal).
- Effect: El efecto del taint que el pod puede tolerar (NoSchedule, PreferNoSchedule o NoExecute).
- TolerationSeconds: Solo aplicable a taints con efecto NoExecute. Define cuánto tiempo el pod puede permanecer en un nodo con ese taint antes de ser expulsado.Se aplican a los Pods y les permiten programarse en nodos que tienen un Taint específico.
Una Toleration coincide con un Taint si tiene la misma clave y efecto.
En resumen, una tolerancia simplemente le dice al scheduler que el pod puede ser programado en un nodo con un taint específico, pero no garantiza que lo será. El scheduler seguirá considerando otros factores al tomar su decisión.
1/ Aplicar un Taint al nodo mediante kubectl:
kubectl taint nodes mesa1 cumpleaños=Alba:NoSchedule
El nodomesa1
ha sido marcado con un taint para restringir su uso a la fiesta de cumpleaños de Alba. Esta acción impide que cualquier pod sea programado en este nodo, a menos que dicho pod posea una tolerancia que coincida con el taint aplicado (Cumpleaños de Alba)
Esto evita que cualquier Pod sin la tolerancia adecuada se ejecute en el nodo.
Nota: Un taint puede aplicarse a un nodo usando tanto kubectl
como directamente en el manifiesto del nodo. En cambio para agregar una Toleration al Pod, siempre lo hacemos en el manifiesto.
Ejemplo de manifiesto que aplica un toleration a un pod:
apiVersion: v1
kind: Pod
metadata:
name: pod-cumpleaños
spec:
tolerations:
- key: "cumpleaños"
value: "Alba"
effect: "NoSchedule"
Nota: Si necesitas agregar una toleration a un pod ya existente, debes modificarel manifiesto YAML y recrear el pod.
2. NodeSelector
NodeSelector es un método sencillo para restringir la programación de un Pod a nodos específicos con etiquetas concretas. Es útil cuando los nodos tienen características específicas, como GPU, o están ubicados en una zona particular.
Ejemplo: Primero, etiqueta el nodo:
kubectl label nodes nodo1 tipo=gpu
Luego, hay que definir el Pod con nodeSelector
, en el manifiesto, o sea el archivo YAML del Pod:
apiVersion: v1
kind: Pod
metadata:
name: pod-gpu
spec:
nodeSelector:
tipo: gpu
Este Pod se programará solo en nodos que tengan la etiqueta tipo=gpu
.
En este ejemplo:
- El Pod se llama
pod-gpu
. - El campo
nodeSelector
indica que el Pod solo será programado en nodos que tengan la etiquetatipo=gpu
.
3. Node Affinity y Pod Anti-Affinity
Node Affinity es una versión más avanzada de nodeSelector, que permite reglas de selección más complejas y flexibles, mientras que Pod Anti-Affinity se enfoca en evitar que ciertos Pods se programen juntos en el mismo nodo.
Hay 2 parámetros principales que determinan la flexibilidad de las reglas:
- requiredDuringSchedulingIgnoredDuringExecution El Pod solo se programa en nodos que cumplen estrictamente con los criterios especificados, ya sea en Node Affinity (criterios de nodo) o Pod Anti-Affinity (criterios de distribución de Pods).
- preferredDuringSchedulingIgnoredDuringExecution: El Pod intenta programarse en nodos que cumplan con los criterios, pero no es obligatorio. Kubernetes priorizará los nodos que cumplen con el criterio, pero permitirá el despliegue en otros nodos si es necesario.
Ejemplo Node Affinity : Primero, etiqueta el nodo:
kubectl label nodes nodo1 prioridad=alta
Luego, en el manifiesto del Pod:
apiVersion: v1
kind: Pod
metadata:
name: pod-alta-prioridad
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: prioridad
operator: In
values:
- alta
Este Pod solo se programará en nodos con la etiqueta prioridad=alta
.
Pod Anti-Affinity, permite configurar restricciones para evitar que un Pod se programe en el mismo nodo que otros Pods con etiquetas específicas. Esto es útil cuando deseas distribuir Pods entre diferentes nodos, lo cual es común para aplicaciones que requieren alta disponibilidad o para evitar que múltiples instancias de un servicio estén en el mismo nodo.
Ejemplo Pod Anti-Affinity:
En este ejemplo, queremos asegurarnos de que un Pod no se ejecute en el mismo nodo que otros Pods con la etiqueta app=frontend
.
Primero, etiqueta los Pods de la aplicación existente:
kubectl label pod <nombre-del-pod> app=frontend
Luego, en el manifiesto del nuevo Pod, configuras podAntiAffinity para evitar que se programe junto a Pods con esa misma etiqueta:
apiVersion: v1
kind: Pod
metadata:
name: pod-anti-frontend
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: "kubernetes.io/hostname"
Descripción del ejemplo:
- labelSelector: Busca Pods en el mismo nodo que tengan la etiqueta
app=frontend
. - topologyKey: Aquí se usa
"kubernetes.io/hostname"
, lo cual significa que Kubernetes evitará programar el Pod en el mismo nodo (hostname
) que ya tenga Pods con la etiquetaapp=frontend
.
Esto garantiza que el Pod pod-anti-frontend
no se programe en el mismo nodo que otros Pods con la etiqueta app=frontend
, distribuyéndolos en distintos nodos según la clave de topología seleccionada.
4. Combinación de Node Affinity y Taints/Tolerations
Para un control absoluto sobre la programación de Pods, puedes combinar Node Affinity con Taints y Tolerations.
Ejemplo: Etiqueta el nodo y aplica un Taint:
kubectl label nodes nodo1 uso=exclusivo kubectl taint nodes nodo1 uso=exclusivo:NoSchedule
En el manifiesto del Pod, configuras nodeAffinity y Tolerations:
apiVersion: v1
kind: Pod
metadata:
name: pod-exclusivo
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: uso
operator: In
values:
- exclusivo
tolerations:
- key: "uso"
operator: "Equal"
value: "exclusivo"
effect: "NoSchedule"
Este Pod se programará únicamente en nodos etiquetados como uso=exclusivo
y que tengan el Taint correspondiente.
Resumen
Para controlar dónde se ejecutan los Pods:
- NodeSelector: Es la opción más sencilla para usar etiquetas de nodo.
- Node Affinity/Pod Anti-Affinity: Permite reglas de selección más detalladas.
- Taints y Tolerations: Evitan que ciertos Pods se ejecuten en nodos específicos, a menos que tengan la tolerancia adecuada.
Al combinar estas herramientas, puedes gestionar la programación de Pods de forma avanzada y asegurar que se ajusten a las necesidades de tu clúster y aplicaciones.
Comentarios
Publicar un comentario