Kubernetes Scheduling, Preemption, and Eviction
Versiones compatibles: Kubernetes 1.32 - 1.34 Última actualización: February 22, 2026
En Kubernetes, scheduling (programación) es el proceso de colocar pods en nodes apropiados. Preemption es el proceso de eliminar pods de menor prioridad para dejar espacio a pods de mayor prioridad, y eviction es el proceso de mover pods de forma segura cuando ocurren problemas en los nodes. En este capítulo, aprenderemos sobre los mecanismos de scheduling de Kubernetes, la selección de nodes, preemption, eviction y los métodos de optimización de scheduling en Amazon EKS.
Lab Environment Setup
Para seguir los ejemplos de este documento, necesitas las siguientes herramientas y entorno:
Required Tools
- kubectl v1.34 o superior
- Un cluster Kubernetes funcional (EKS, minikube, kind, etc.)
- Un cluster con múltiples nodes (para pruebas de scheduling)
Scheduling Example Setup
# Create namespace
kubectl create namespace scheduling-demo
# Add labels to nodes (if you have multiple nodes)
kubectl label nodes <node-name> disktype=ssd
kubectl label nodes <node-name> gpu=true
# Create a pod using node affinity
kubectl -n scheduling-demo apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: nginx-ssd
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
EOF
# Create priority class
kubectl apply -f - <<EOF
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for critical service pods only."
EOF
# Create Pod Disruption Budget (PDB)
kubectl -n scheduling-demo apply -f - <<EOF
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: nginx-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: nginx
EOFKubernetes Scheduling Architecture
Scheduling Concept Comparison
| Concept | Purpose | Use Cases | Kubernetes Version |
|---|---|---|---|
| Node Selector | Place pods on nodes with specific labels | Simple node selection | All versions |
| Node Affinity | Define complex node selection rules | Advanced node selection | 1.6+ |
| Pod Affinity | Place pods close to other pods | Co-locating related services | 1.6+ |
| Pod Anti-Affinity | Place pods away from other pods | Ensuring high availability | 1.6+ |
| Taints and Tolerations | Allow only specific pods on nodes | Dedicated nodes, node isolation | 1.6+ |
| Topology Spread Constraints | Spread pods across topology domains | Distribution across availability zones | 1.16+ (GA in 1.19) |
| Priority and Preemption | Prioritize important workloads | Critical service guarantees | 1.8+ (GA in 1.11) |
| Pod Disruption Budget | Limit simultaneously disrupted pods | Ensuring high availability | 1.4+ (GA in 1.21) |
Basic Scheduling Concepts
Concepto clave: El Kubernetes scheduler es un componente del control plane que selecciona el node óptimo para ejecutar pods, operando en dos fases: filtering y scoring.
Scheduling Process
Filtering Phase (Predicates)
- Identifica un conjunto adecuado de nodes que pueden ejecutar el pod
- Considera requisitos de recursos, node selectors, reglas de affinity, taints/tolerations, etc.
- Excluye un node si no se cumple alguna condición
Scoring Phase (Priorities)
- Asigna puntuaciones a los nodes que pasaron el filtering
- Considera la utilización de recursos, distribución de pods, preferencias de affinity, etc.
- Selecciona el node con la puntuación más alta
Binding Phase
- Asigna el pod al node seleccionado
- Actualiza la información de binding en el API server
Table of Contents
- Scheduling Overview
- How the Scheduler Works
- Node Selection
- Pod Affinity and Anti-Affinity
- Taints and Tolerations
- Node Affinity
- Pod Priority and Preemption
- Pod Eviction
- Pod Disruption Budget (PDB)
- Node Pressure Eviction
- TopologySpreadConstraints
- Pod Deletion Cost
- Descheduler
- Scheduling Optimization in Amazon EKS
- Scheduling Best Practices
- Conclusion
Scheduling Overview
El Kubernetes scheduler es un componente del control plane que coloca pods en nodes apropiados. El scheduler considera diversos factores para determinar el node óptimo donde colocar pods:
- Resource Requirements: CPU, memoria y otros recursos solicitados por el pod
- Hardware/Software/Policy Constraints: Node selectors, node affinity, taints, etc.
- Affinity/Anti-Affinity Specifications: Relaciones de ubicación con otros pods
- Data Locality: Colocar pods cerca de los datos
- Inter-Workload Interference: Minimizar la interferencia entre distintos workloads
- Deadlines: Considerar workloads con restricciones de tiempo
Scheduling Process
El proceso de scheduling se divide ampliamente en dos fases:
Filtering: Identifica un conjunto de nodes que pueden ejecutar el pod
- Comprueba si se cumplen los requisitos de recursos
- Comprueba constraints como node selectors, affinity, taints
Scoring: Puntúa los nodes filtrados para seleccionar el node óptimo
- Equilibrio de utilización de recursos
- Affinity/anti-affinity entre pods
- Localidad de datos
- Taints/tolerations
How the Scheduler Works
El Kubernetes scheduler opera mediante el siguiente proceso:
- Pod Queue Watching: El scheduler observa el API server en busca de pods no programados.
- Node Filtering: Identifica un conjunto de nodes que pueden ejecutar el pod.
- Node Scoring: Puntúa los nodes filtrados.
- Node Selection: Selecciona el node con la puntuación más alta.
- Binding: Vincula el pod al node seleccionado.
Scheduling Plugins
El Kubernetes scheduler está diseñado para ser extensible mediante una arquitectura de plugins. Diversos plugins operan en distintas etapas del proceso de scheduling:
Filter Plugins: Filtran los nodes donde el pod no puede ejecutarse
- NodeResourcesFit: Comprueba la capacidad de recursos del node
- NodeName: Comprueba el campo nodeName del pod
- NodeUnschedulable: Comprueba la schedulability del node
- TaintToleration: Comprueba taints y tolerations
Score Plugins: Asignan puntuaciones a los nodes
- NodeResourcesBalancedAllocation: Considera el equilibrio de uso de recursos
- ImageLocality: Considera la localidad de la imagen
- InterPodAffinity: Considera la affinity entre pods
- NodeAffinity: Considera la node affinity
Multiple Schedulers
Kubernetes puede ejecutar múltiples schedulers simultáneamente. Esto permite implementar lógica de scheduling personalizada para workloads específicos.
apiVersion: v1
kind: Pod
metadata:
name: custom-scheduled-pod
spec:
schedulerName: my-custom-scheduler
containers:
- name: container
image: nginxEn el ejemplo anterior, el campo schedulerName especifica el scheduler que debe programar el pod.
Node Selection
Kubernetes proporciona varios mecanismos para colocar pods en nodes específicos.
Node Selector
Node selector es la forma más simple de restringir pods para que solo se coloquen en nodes con labels específicos.
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
nodeSelector:
gpu: "true"
containers:
- name: gpu-container
image: nvidia/cudaEn el ejemplo anterior, el pod solo se coloca en nodes con el label gpu=true.
nodeName
Puedes usar el campo nodeName para colocar directamente un pod en un node específico. Este método omite el scheduler y generalmente no se recomienda.
apiVersion: v1
kind: Pod
metadata:
name: specific-node-pod
spec:
nodeName: worker-node-1
containers:
- name: container
image: nginxEn el ejemplo anterior, el pod se coloca directamente en el node llamado worker-node-1.
Pod Affinity and Anti-Affinity
Pod affinity y anti-affinity proporcionan formas de colocar pods según las relaciones entre pods.
Pod Affinity
Pod affinity hace que los pods se coloquen en el mismo node o dominio de topología que pods con labels específicos.
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostname
containers:
- name: frontend
image: nginxEn el ejemplo anterior, el pod frontend se coloca en el mismo host que pods con el label app=cache.
Pod Anti-Affinity
Pod anti-affinity hace que los pods se coloquen en un node o dominio de topología diferente al de pods con labels específicos.
apiVersion: v1
kind: Pod
metadata:
name: frontend
labels:
app: frontend
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: kubernetes.io/hostname
containers:
- name: frontend
image: nginxEn el ejemplo anterior, el pod frontend se coloca en un host diferente al de otros pods con el label app=frontend. Esto es útil para distribuir instancias de la misma aplicación entre múltiples nodes para alta disponibilidad.
Affinity Types
Pod affinity y anti-affinity tienen dos tipos:
- requiredDuringSchedulingIgnoredDuringExecution: Requisito estricto que debe cumplirse durante el scheduling
- preferredDuringSchedulingIgnoredDuringExecution: Requisito flexible que se prefiere, pero no es obligatorio
# preferredDuringSchedulingIgnoredDuringExecution example
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostnameEn el ejemplo anterior, el campo weight indica el peso de esta preferencia. Cuando hay múltiples preferencias, las preferencias con mayor peso se consideran más importantes.
Taints and Tolerations
Taints y tolerations son mecanismos que permiten a los nodes rechazar pods específicos.
Taints
Los taints se aplican a nodes para restringir que pods se programen en ellos.
# Add taint to node
kubectl taint nodes node1 key=value:NoScheduleHay tres efectos de taint:
- NoSchedule: Los pods sin tolerations no se programan en el node
- PreferNoSchedule: Se prefiere no programar pods sin tolerations en el node
- NoExecute: Los pods sin tolerations se evictan del node
Tolerations
Las tolerations se aplican a pods para permitir que se programen en nodes con taints.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
containers:
- name: nginx
image: nginxEn el ejemplo anterior, el pod se puede programar en nodes con el taint key=value:NoSchedule.
Use Cases
Casos de uso comunes para taints y tolerations:
- Dedicated Nodes: Designar nodes para ejecutar solo workloads específicos
- Special Hardware: Gestionar nodes con hardware especial como GPUs
- Node Maintenance: Evitar el scheduling de nuevos pods en nodes en mantenimiento
- Node Issues: Evictar pods de nodes con problemas
Default Taints
Kubernetes aplica taints predeterminados a algunos nodes:
- node.kubernetes.io/not-ready: El node no está listo
- node.kubernetes.io/unreachable: El node es inalcanzable
- node.kubernetes.io/memory-pressure: El node tiene presión de memoria
- node.kubernetes.io/disk-pressure: El node tiene presión de disco
- node.kubernetes.io/pid-pressure: El node tiene presión de PID
- node.kubernetes.io/network-unavailable: La red del node no está disponible
- node.kubernetes.io/unschedulable: El node no es schedulable
Node Affinity
Node affinity proporciona una forma más expresiva de colocar pods en conjuntos específicos de nodes. Permite especificar condiciones más complejas que node selector.
Node Affinity Types
Node affinity tiene dos tipos:
- requiredDuringSchedulingIgnoredDuringExecution: Requisito estricto que debe cumplirse durante el scheduling
- preferredDuringSchedulingIgnoredDuringExecution: Requisito flexible que se prefiere, pero no es obligatorio
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: nginxEn el ejemplo anterior, el pod solo se coloca en nodes donde el label kubernetes.io/e2e-az-name es e2e-az1 o e2e-az2. Además, se coloca preferentemente en nodes con el label another-node-label-key=another-node-label-value.
Operators
Node affinity admite varios operadores:
- In: El valor del label coincide con uno de los valores especificados
- NotIn: El valor del label no coincide con los valores especificados
- Exists: Existe un label con la key especificada
- DoesNotExist: No existe un label con la key especificada
- Gt: El valor del label es mayor que el valor especificado
- Lt: El valor del label es menor que el valor especificado
Pod Priority and Preemption
Kubernetes proporciona características de pod priority y preemption para garantizar que workloads importantes puedan asegurar recursos del cluster.
PriorityClass
PriorityClass define la importancia relativa de los pods. Cuanto mayor sea el valor de prioridad, más importante es el pod.
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for critical workloads."En el ejemplo anterior, el campo value indica el valor de prioridad. Cuanto mayor sea el valor, mayor será la prioridad. Si el campo globalDefault se establece en true, esta priority class se aplica a pods sin una priority class especificada.
Applying PriorityClass to Pods
Para aplicar una priority class a un pod, usa el campo priorityClassName.
apiVersion: v1
kind: Pod
metadata:
name: high-priority-pod
spec:
priorityClassName: high-priority
containers:
- name: container
image: nginxPreemption
Preemption es el proceso de eliminar pods de menor prioridad para programar pods de mayor prioridad. Cuando el scheduler no puede encontrar un node para programar un pod de mayor prioridad, hace preemption de pods de menor prioridad para asegurar recursos.
Proceso de preemption:
- El scheduler no puede encontrar un node para programar un pod de mayor prioridad
- El scheduler selecciona un node para eliminar pods de menor prioridad mediante preemption
- Envía una señal de terminación a los pods de menor prioridad en el node seleccionado
- Cuando los pods terminan de forma correcta, programa el pod de mayor prioridad en ese node
Preemption Considerations
Aspectos a considerar al usar preemption:
- Graceful Termination Period: Los pods preempted pasan por el proceso de terminación graceful durante el tiempo especificado en
terminationGracePeriodSeconds - PodDisruptionBudget: Preemption no respeta PodDisruptionBudget
- System Priority Classes: Kubernetes proporciona priority classes para componentes del sistema
system-cluster-critical: Pods críticos para la operación del clustersystem-node-critical: Pods críticos para la operación del node
Pod Eviction
Pod eviction es el proceso de mover pods de forma segura cuando ocurren problemas en los nodes. Eviction puede ocurrir por diversas razones.
Eviction Types
Eviction by kube-controller-manager:
- Cuando un node permanece en estado NotReady durante el período
pod-eviction-timeout(predeterminado 5 minutos) - Cuando un node está en estado Unreachable
- Cuando un node permanece en estado NotReady durante el período
Eviction by kubelet:
- Escasez de recursos del node (memoria, disco, etc.)
- Problemas de hardware
Eviction by user:
- Ejecutar el comando
kubectl drain - Tareas de mantenimiento de nodes
- Ejecutar el comando
kubelet Eviction Signals
kubelet monitorea las siguientes señales de eviction:
- memory.available: Memoria disponible
- nodefs.available: Espacio disponible en el sistema de archivos del node
- nodefs.inodesFree: Inodes disponibles en el sistema de archivos del node
- imagefs.available: Espacio disponible en el sistema de archivos de imágenes
- imagefs.inodesFree: Inodes disponibles en el sistema de archivos de imágenes
- pid.available: IDs de proceso disponibles
Se pueden establecer umbrales soft y hard para cada señal:
- Soft Threshold: Evicta pods después del
grace-periodcuando se supera el umbral - Hard Threshold: Evicta pods inmediatamente cuando se supera el umbral
# kubelet configuration example
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
evictionSoft:
memory.available: "200Mi"
nodefs.available: "15%"
evictionSoftGracePeriod:
memory.available: "1m"
nodefs.available: "2m"
evictionPressureTransitionPeriod: "30s"Eviction Priority
kubelet evicta pods en el siguiente orden:
- Pods con clase QoS BestEffort
- Pods con clase QoS Burstable (comenzando por pods cuyo uso de recursos supera los requests)
- Pods con clase QoS Guaranteed (pods con requests y limits iguales)
Pod Disruption Budget (PDB)
Pod Disruption Budget (PDB) es una forma de mantener la disponibilidad de la aplicación durante disruptions voluntarias. PDB limita el número de pods que pueden interrumpirse simultáneamente.
PDB Definition
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: frontend-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: frontendo
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: frontend-pdb
spec:
maxUnavailable: 1
selector:
matchLabels:
app: frontendEn los ejemplos anteriores:
minAvailable: Número mínimo de pods que siempre deben estar disponiblesmaxUnavailable: Número máximo de pods que pueden no estar disponibles al mismo tiemposelector: Label selector que selecciona los pods a los que se aplica el PDB
PDB Operation
- Cuando ocurren disruptions voluntarias como node drain, Kubernetes comprueba el PDB
- Si se cumplen las condiciones del PDB, continúa con la eviction del pod
- Si no se cumplen las condiciones del PDB, deniega la eviction del pod
PDB Best Practices
- Set PDB for all critical workloads: Establece PDB para todos los workloads que requieran alta disponibilidad
- Choose appropriate values: Selecciona valores de
minAvailableomaxUnavailableapropiados para las características del workload - Consider replica count: El valor del PDB debe ser menor que el número de replicas
- Regular testing: Prueba la operación del PDB mediante node drain y tareas similares
Node Pressure Eviction
Node pressure eviction es un mecanismo en el que los pods se evictan debido a escasez de recursos del node.
Node Condition Status
kubelet informa los siguientes estados de condición del node:
- MemoryPressure: El node tiene poca memoria
- DiskPressure: El node tiene poco espacio en disco
- PIDPressure: El node tiene pocos IDs de proceso
Cuando ocurren estas condiciones, kubelet evicta pods para asegurar recursos.
Eviction Policy Configuration
Las eviction policies se pueden establecer en la configuración de kubelet:
# kubelet configuration example
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
evictionSoft:
memory.available: "200Mi"
nodefs.available: "15%"
evictionSoftGracePeriod:
memory.available: "1m"
nodefs.available: "2m"
evictionMinimumReclaim:
memory.available: "50Mi"
nodefs.available: "5%"
evictionPressureTransitionPeriod: "30s"En el ejemplo anterior:
evictionMinimumReclaim: Recursos mínimos que deben recuperarse después de la evictionevictionPressureTransitionPeriod: Tiempo de espera entre transiciones de estado de presión
TopologySpreadConstraints
TopologySpreadConstraints proporcionan control detallado sobre cómo se distribuyen los pods entre dominios de topología como availability zones, nodes o regions. Esta característica ofrece más flexibilidad que Pod anti-affinity para lograr alta disponibilidad y utilización eficiente de recursos.
Key Fields
| Field | Description | Required |
|---|---|---|
| maxSkew | Maximum allowed difference in pod count between any two topology domains | Yes |
| topologyKey | Node label key that defines topology domains | Yes |
| whenUnsatisfiable | Action when constraints cannot be satisfied: DoNotSchedule or ScheduleAnyway | Yes |
| labelSelector | Selects which pods to count for spread calculation | Yes |
| minDomains | Minimum number of topology domains required (1.27+) | No |
| matchLabelKeys | Pod label keys to match for spread calculation (1.27+) | No |
whenUnsatisfiable Options
- DoNotSchedule: El scheduler no programará el pod si la constraint no puede satisfacerse (hard constraint)
- ScheduleAnyway: El scheduler aún programa el pod, dando mayor prioridad a nodes que minimizan el skew (soft constraint)
EKS Availability Zone Spread Example
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 6
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: web
containers:
- name: web
image: nginx:1.25
resources:
requests:
cpu: 100m
memory: 128MiEsta configuración garantiza:
- Los pods se distribuyen uniformemente entre availability zones (hard constraint)
- Los pods se distribuyen preferentemente entre nodes dentro de cada zone (soft constraint)
minDomains and matchLabelKeys (Kubernetes 1.27+)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-with-min-domains
spec:
replicas: 4
selector:
matchLabels:
app: distributed-app
template:
metadata:
labels:
app: distributed-app
version: v1
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: distributed-app
minDomains: 3
matchLabelKeys:
- version
containers:
- name: app
image: myapp:v1- minDomains: Garantiza que los pods se distribuyan entre al menos 3 zones. Si hay menos zones disponibles, el scheduling se bloquea.
- matchLabelKeys: Usa automáticamente el valor del label
versiondel pod en el selector, lo que permite spread por revision sin modificar el selector.
Advantages Over Pod Anti-Affinity
| Aspect | TopologySpreadConstraints | Pod Anti-Affinity |
|---|---|---|
| Flexibility | Allows controlled skew (maxSkew > 1) | Binary: either same or different domain |
| Soft constraints | ScheduleAnyway for best-effort | preferredDuringScheduling but less control |
| Multi-level | Multiple constraints with different topologyKeys | Requires complex nested rules |
| Performance | Better scheduler performance at scale | Can slow scheduling with many pods |
| Use case | Even distribution with tolerance | Strict separation |
Pod Deletion Cost
Pod Deletion Cost es una característica que permite controlar qué pods se eliminan primero durante operaciones de scale-down. Al establecer la annotation controller.kubernetes.io/pod-deletion-cost, puedes influir en el orden en que se terminan los pods.
How It Works
Cuando un controller (como HPA o scale-down manual) necesita reducir replicas, considera:
- Los pods con menor deletion cost se eliminan primero
- El deletion cost predeterminado es 0
- Rango válido: -2147483648 a 2147483647
Basic Example
apiVersion: v1
kind: Pod
metadata:
name: worker-pod
annotations:
controller.kubernetes.io/pod-deletion-cost: "100"
spec:
containers:
- name: worker
image: worker:latestHPA Scale-Down Priority Control
Usa deletion cost para proteger pods importantes durante el scale-down de HPA:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-service
spec:
replicas: 5
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
# Lower cost pods are deleted first during scale-down
annotations:
controller.kubernetes.io/pod-deletion-cost: "0"
spec:
containers:
- name: web
image: nginx:1.25Cache Protection Pattern
Protege pods con caches calientes ajustando dinámicamente el deletion cost:
apiVersion: apps/v1
kind: Deployment
metadata:
name: cache-service
spec:
replicas: 3
selector:
matchLabels:
app: cache
template:
metadata:
labels:
app: cache
spec:
containers:
- name: cache
image: redis:7
- name: cost-updater
image: bitnami/kubectl:latest
command:
- /bin/sh
- -c
- |
# Update deletion cost based on cache warmth
while true; do
CACHE_SIZE=$(redis-cli DBSIZE | awk '{print $2}')
# Higher cache size = higher cost = less likely to be deleted
kubectl annotate pod $POD_NAME \
controller.kubernetes.io/pod-deletion-cost="$CACHE_SIZE" \
--overwrite
sleep 60
done
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.namePractical Use Cases
- Stateful workloads: Proteger pods con estado acumulado
- Leader election: Mantener los leader pods ejecutándose durante más tiempo
- Connection draining: Dar tiempo para conexiones de larga duración
- Cache warming: Preservar pods con caches calientes
- Batch processing: Mantener pods procesando jobs grandes
Descheduler
El Descheduler es un componente de Kubernetes que evicta pods de nodes para permitir que el scheduler los reprograme en nodes más apropiados. A diferencia del scheduler, que solo coloca pods nuevos, el descheduler ayuda a mantener la colocación óptima de pods a lo largo del tiempo.
Why Descheduling Is Needed
- Cluster changes: Nuevos nodes añadidos, labels de nodes cambiados
- Pod drift: La colocación inicial se vuelve subóptima con el tiempo
- Affinity violations: Reglas violadas después de cambios en el cluster
- Resource imbalance: Algunos nodes sobreutilizados, otros infrautilizados
- Failed pods: Pods atascados en bucles de reinicio
Key Strategies
| Strategy | Description | Use Case |
|---|---|---|
| RemoveDuplicates | Removes duplicate pods from the same node | Ensure HA after node failures |
| LowNodeUtilization | Moves pods from overutilized to underutilized nodes | Balance cluster resources |
| RemovePodsHavingTooManyRestarts | Evicts pods with excessive restarts | Clean up problematic pods |
| PodLifeTime | Evicts pods older than specified age | Force fresh scheduling |
| RemovePodsViolatingInterPodAntiAffinity | Evicts pods violating anti-affinity rules | Restore affinity compliance |
| RemovePodsViolatingNodeAffinity | Evicts pods violating node affinity | Restore affinity compliance |
| RemovePodsViolatingTopologySpreadConstraint | Evicts pods violating spread constraints | Restore even distribution |
Helm Installation
# Add the descheduler Helm repository
helm repo add descheduler https://kubernetes-sigs.github.io/descheduler/
# Install descheduler
helm install descheduler descheduler/descheduler \
--namespace kube-system \
--set schedule="*/5 * * * *" \
--set deschedulerPolicy.strategies.RemoveDuplicates.enabled=true \
--set deschedulerPolicy.strategies.LowNodeUtilization.enabled=trueDeschedulerPolicy Configuration
apiVersion: "descheduler/v1alpha2"
kind: "DeschedulerPolicy"
profiles:
- name: default
pluginConfig:
- name: RemoveDuplicates
args:
excludeOwnerKinds:
- DaemonSet
- name: LowNodeUtilization
args:
thresholds:
cpu: 20
memory: 20
pods: 20
targetThresholds:
cpu: 50
memory: 50
pods: 50
useDeviationThresholds: false
- name: RemovePodsHavingTooManyRestarts
args:
podRestartThreshold: 10
includingInitContainers: true
- name: PodLifeTime
args:
maxPodLifeTimeSeconds: 86400 # 24 hours
podStatusPhases:
- Running
- name: RemovePodsViolatingTopologySpreadConstraint
args:
constraints:
- DoNotSchedule
plugins:
deschedule:
enabled:
- RemoveDuplicates
- LowNodeUtilization
- RemovePodsHavingTooManyRestarts
- PodLifeTime
- RemovePodsViolatingTopologySpreadConstraintPDB Respect
El descheduler respeta Pod Disruption Budgets (PDBs). Si evictar un pod violaría un PDB, el descheduler no evictará ese pod:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: webCon este PDB aplicado, el descheduler garantizará que al menos 2 pods con el label app: web permanezcan disponibles durante las operaciones de descheduling.
Descheduler CronJob Example
apiVersion: batch/v1
kind: CronJob
metadata:
name: descheduler
namespace: kube-system
spec:
schedule: "*/30 * * * *"
jobTemplate:
spec:
template:
spec:
serviceAccountName: descheduler
containers:
- name: descheduler
image: registry.k8s.io/descheduler/descheduler:v0.28.0
args:
- --policy-config-file=/policy/policy.yaml
- --v=3
volumeMounts:
- name: policy
mountPath: /policy
volumes:
- name: policy
configMap:
name: descheduler-policy
restartPolicy: OnFailureDeep Dive: Para obtener información detallada sobre custom schedulers, consulta:
Scheduling Optimization in Amazon EKS
En Amazon EKS, puedes optimizar workloads usando características de scheduling de Kubernetes.
Node Groups and Instance Types
En EKS, puedes proporcionar recursos apropiados para workloads utilizando diversos node groups e instance types:
- Various Instance Types: Compute optimized, memory optimized, storage optimized, etc.
- Spot Instances: Spot instances para workloads rentables
- GPU Instances: GPU instances para workloads de AI/ML
Puedes usar node labels y taints para colocar workloads específicos en node groups específicos:
# Set labels and taints when creating node group
eksctl create nodegroup \
--cluster my-cluster \
--name gpu-nodes \
--node-labels="workload-type=gpu" \
--node-type=p3.2xlarge \
--taints="gpu=true:NoSchedule"Availability Zone Distribution
En EKS, puedes distribuir workloads entre múltiples availability zones usando pod anti-affinity y topology spread constraints:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web
containers:
- name: web
image: nginxEn el ejemplo anterior, topologySpreadConstraints distribuye pods uniformemente entre múltiples availability zones.
Auto Scaling with Karpenter
En Amazon EKS, puedes usar Karpenter para aprovisionar automáticamente nodes apropiados para workloads:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: kubernetes.io/arch
operator: In
values: ["amd64", "arm64"]
nodeClassRef:
name: default-class
limits:
cpu: 1000
memory: 1000Gi
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 30s
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default-class
spec:
subnetSelector:
karpenter.sh/discovery: my-cluster
securityGroupSelector:
karpenter.sh/discovery: my-clusterKarpenter optimiza los costos seleccionando el instance type óptimo para los requisitos de recursos del pod.
Resource Request and Limit Optimization
Optimizar los resource requests y limits de workloads en EKS es importante:
- Vertical Pod Autoscaler (VPA): Optimiza resource requests según el uso real de recursos del workload
- Goldilocks: Visualiza recomendaciones de VPA para apoyar la optimización de resource requests
- Resource Quotas: Limita el uso de recursos por namespace
# VPA example
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: frontend-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: frontend
updatePolicy:
updateMode: "Auto"Scheduling Best Practices
Mejores prácticas para optimizar scheduling en Kubernetes y EKS:
Set appropriate resource requests and limits:
- Establece resource requests según el uso real de recursos del workload
- Establece resource limits apropiados para workloads importantes
- Usa VPA para optimizar automáticamente resource requests
Workload distribution:
- Usa pod anti-affinity para distribuir workloads importantes entre múltiples nodes
- Usa topology spread constraints para distribuir workloads entre múltiples availability zones
- Usa node affinity para colocar workloads específicos en nodes específicos
Node resource optimization:
- Usa diversos instance types para proporcionar recursos apropiados para workloads
- Usa spot instances para optimizar costos
- Usa Karpenter para el aprovisionamiento automático de nodes apropiados para workloads
PDB configuration:
- Establece PDB para workloads importantes
- Selecciona valores de
minAvailableomaxUnavailableapropiados para las características del workload - Prueba regularmente la operación del PDB
Priority and preemption configuration:
- Establece priority classes altas para workloads importantes
- Usa priority classes
system-cluster-criticalosystem-node-criticalpara componentes del sistema - Comprende y prueba el impacto de preemption
Node taints and tolerations:
- Establece nodes dedicados para workloads especializados
- Aplica taints a nodes en mantenimiento
- Establece tolerations apropiadas
Conclusion
Los mecanismos de scheduling, preemption y eviction de Kubernetes desempeñan funciones importantes para gestionar eficientemente los recursos del cluster y mantener la disponibilidad de workloads. Al comprender y utilizar estas características, puedes optimizar y operar workloads de forma confiable en clusters Amazon EKS.
La optimización de scheduling es un proceso continuo, y los ajustes deben realizarse continuamente según las características del workload y el estado del cluster. Es importante rastrear el uso de recursos del cluster usando herramientas de monitoreo y ajustar las scheduling policies según sea necesario.
Quiz
Para comprobar lo que aprendiste en este capítulo, intenta el Scheduling, Preemption, and Eviction Quiz.