Kubernetes Scheduling Parte 1
Kubernetes Scheduling parte 1 es el primero de una serie de artículos en los que trataré todo lo referente a cómo el cluster asigna los Pods en uno o más nodos.
Si te has topado con la necesidad de trabar con un cluster de múltiples nodos y deseas controlar cuáles de ellos deben o no deben correr ciertos Pods, entonces este artículo es para ti.
Acerca del Scheduling
El término scheduling se puede traducir al castellano como «programación» o «asignación». La idea principal es el criterio de cómo organizar y/o distribuir ciertas cargas de trabajo sobre un grupo de recursos disponibles.
Kubernetes Scheduler
El Kubernetes Scheduler es un componente fundamental de Kubernetes que se encarga de asignar los pods a los nodos adecuados dentro de un clúster.
Proceso de Scheduling
El scheduling en Kubernetes es el proceso automático de asignar pods a los nodos adecuados dentro de un cluster.
Esta tarea, aparentemente simple, es fundamental para garantizar un uso eficiente de los recursos, un alto rendimiento y una alta disponibilidad de las aplicaciones desplegadas.
Un scheduling eficaz es esencial para evitar cuellos de botella, maximizar el aprovechamiento de los recursos y garantizar la escalabilidad de las aplicaciones en entornos dinámicos y complejos.
Cómo funciona
- Creación de un pod: Cuando se crea un nuevo pod, el scheduler lo evalúa.
- Selección de nodos candidatos: El scheduler busca en el clúster todos los nodos que cumplen los requisitos del pod (recursos disponibles, etiquetas, tolerancias, etc.).
- Clasificación de nodos: Los nodos candidatos se clasifican según una serie de prioridades y ponderaciones.
- Asignación del pod: El scheduler selecciona el nodo con la puntuación más alta y asigna el pod a él.
Cluster de pruebas
Antes de iniciar con la parte práctica sobre Scheduling, es importante contar con acceso a un cluster que tenga dos o más nodos Worker.
Hay muchas opciones para probar Kubernetes, ya sea en la nube (EKS, AKS, GKE, etc.) o localmente (Minikube, Kind, k3d, microk8s, etc.). De hecho, tengo dos artículos introductorios sobre las opciones que prefiero:
En mi caso personal, optaré por trabajar con k3d en este artículo, pero el lector puede usar cualquier otra alternativa de su preferencia.
Por ello, empezaré con la creación de un cluster de 3 nodos:
k3d cluster create demo -a 3
Mi cluster se llama «demo». El nombre es lo de menos.
Ahora listo los nodos:
kubectl get node
Verifico que tengo 3 nodos worker:
Scheduling manual de Pods
Esta es la forma más básica de asignar un único Pod hacia un nodo particular. Esto es posible a través del atributo spec.nodeName
en el objeto Pod.
Crear un Pod
Primero, veamos cómo se crea un Pod manualmente con un archivo de manifiesto:
# pod-manual.yaml --- apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: nginx:latest name: nginx
Si la memoria te falla al recordar la estructura y atributos del manifiesto YAML, esta otra puede ser una alternativa:
kubectl run nginx --image nginx:latest --dry-run=client -o yaml > pod-cli.yaml
Ahora solo nos toca editar el archivo pod-cli.yaml creado con el comando anterior.
Especificaciones del Pod
Los atributos de un Pod son muchos, pero solo unos pocos los mínimos requeridos. Es necesario revisar la documentación extensa sobre la especificación de Pods en Kubernetes, pero esta es una tarea que algo laboriosa.
Otra opción más a nuestro alcance está en la misma línea de comandos, como sigue:
kubectl explain pod.spec
Al navegar sobre la documentación mostrada, podemos ver el atributo nodeName
:
Entonces, ahora consultamos más detalles sobre ese atributo específico:
kubectl explain pod.spec.nodeName
La explicación es clara: «NodeName es una petición para asignar este pod en un nodo específico. Si este campo no está vacío, el scheduler simplemente asigna este pod en ese nodo, asumiendo que cumple con los requisitos de recursos.»
Pruebas de creación de Pod con asignación manual
Primero, probemos crear el pod desde el archivo de manifiesto pero sin usar el atributo spec.nodeName:
kubectl apply -f pod-manual.yaml
Ahora reviso la lista de Pods en ejecución para ver en qué nodo se asignó automáticamente:
kubectl get pods -o wide
Verifico que mi único pod está corriendo en el primer nodo worker:
Ahora, eliminaré el pod antes de realizar la segunda prueba. Hago esto porque spec.nodeName
no es un atributo que pueda ser modificado en un pod existente.
kubectl delete -f pod-manual.yaml
Esta vez voy a probar la asignación del pod al tercer nodo worker k3d-demo-agent-2, para lo cual debo editar el manifiesto YAML como sigue:
# pod-manual.yaml --- apiVersion: v1 kind: Pod metadata: name: nginx spec: nodeName: k3d-demo-agent-2 # Agrego esta linea containers: - image: nginx:latest name: nginx
Luego, procedo a aplicar los cambios y ver la lista detallada de pods:
kubectl apply -f pod-manual.yaml kubectl get pods -o wide
Aquí se verifica que el Pod fue ejecutado en el nodo que le indiqué:
Conclusión
En este artículo he mostrado la primera y más básicas de las formas de asignar un Pod a cierto nodo específico, el cual lo tuve que definir por su nombre dentro del archivo de manifiesto.
Si bien se hizo pruebas con la creación de un Pod, lo mostrado líneas arriba es aplicable de igual manera para otros objetos como Deployments o DaemonSets. Aquí un ejemplo:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: nodeName: k3d-demo-agent-2 # Nodo especifico deseado containers: - image: nginx name: nginx
Esta manera de asignar Pods en base al atributo spec.nodeName es la más sencilla de comprender, pero también la más limitada de todas. No es posible reasignar el Pod a otro nodo si el primero al cual fue asignado fallase (en dicho caso el Pod se quedará en estado Pending). Tampoco es posible elegir automáticamente uno o más nodos worker apropiados según diversos criterios. Pero tal vez, solo para necesidades muy básicas esta forma de asignación es más que suficiente.
En un próximo artículo compartiré una segunda forma de asignar Pods a nodos: basado en el uso de selectores de labels o etiquetas.
Deja un comentario