Home » Kubernetes Scheduling Parte 2
Kubernetes scheduling

Kubernetes Scheduling Parte 2

Elegir pods con el atributo nodeName es facil pero muy limitado. Ahora, usando nodeSelector podemos elegir entre uno o más nodos disponibles segun el valor de los labels.

Kubernetes Scheduling parte 2 es la continuación del tema referente a cómo asignar Pods en nodos. Si eres nuevo en el tema, te recomiendo que primero leas Kubernetes Scheduling parte 1.

Acerca de los labels

Los labels en Kubernetes son como pequeñas etiquetas que asignamos a los objetos de la plataforma, como pods, servicios, nodos, etc. Estas etiquetas son pares clave-valor (key-value) que nos permiten organizar y filtrar estos objetos de manera flexible.

¿Para qué sirven los labels?

  • Organización: Nos permiten agrupar objetos que comparten características comunes, como por ejemplo todos los pods que pertenecen a una misma aplicación.
  • Selección: Los labels son la base para los selectores, que nos permiten seleccionar un conjunto de objetos basados en sus etiquetas. Esto es fundamental para muchas operaciones en Kubernetes, como:
    • Deployments: Desplegar aplicaciones en un conjunto específico de nodos.
    • Servicios: Exponer servicios a un conjunto de pods con ciertas etiquetas.
    • ReplicaSets: Asegurar que se mantenga un número determinado de réplicas de un pod con ciertas etiquetas.
  • Automatización: Los labels permiten crear reglas de automatización basadas en las características de los objetos, lo que facilita la gestión de grandes entornos Kubernetes.

Labels en los nodos

Como vimos antes, a los nodos también se les pueden asignar labels. Así es como se los nodos con el detalle de sus labels cada uno:

kubectl get node --show-labels
Listado de nodos worker con sus labels

Una de las razones principales de asignar labels a los nodos worker es para poder configurar reglas de asignación de pods. Precisamente ese es el tema que veremos a continuación.

Scheduling de Pods con nodeSelector

La especificación de los Pods soporta el atributo nodeSelector. Puede consultarse su documentación así:

kubectl explain pod.spec.nodeSelector
Documentación del atributo nodeSelector de los Pods

La explicación es corta y no brinda ejemplos, pero sí una referencia a la documentación de Kubernetes donde se debe buscar el enlace que habla sobre nodeSelector.

El uso de este atributo es la forma más básica de asignar pods a nodos según el valor de uno o más labels de estos últimos. Existen otras formas de asignación basado también en el uso de labels pero que son más flexibles pero complejas y lo revisaremos en un próximo artículo.

Consulta de nodos y creación sencilla de Pod

Recordemos del artículo anterior que tenemos ya creado un cluster con al menos 3 nodos. Aquí está el mío:

Listado de nodos worker

Todos tienen varios labels asignados, pero me interesa mostrar el valor de un label particular, como sigue:

kubectl get node -L aplicacion
Listado de nodos por label aplicacion

Elegí un label arbitrario como «aplicacion», el cual nadie lo tiene asignado. Por eso esa columna aparece vacía.

Ahora, voy a crear un Pod común y corriente y luego revisaré en qué nodo aleatorio fue colocado:

kubectl run nginx2 --image nginx
kubectl get pods -o wide
Pod asignado a un nodo aleatorio

Como se ve, el pod fue asignado al nodo k3d-demo-agent-2. Fue uno cualquiera y pudo quizá haber sido otro distinto. El Scheduler de Kubernetes simplemente colocó el pod en cualquier nodo.

Creación de Pod con nodeSelector

Ahora la prueba consiste en crear el Pod pero definiendo uno o más labels en el atributo nodeSelector.

Para eso, primero creamos el archivo de manifiesto de un nuevo Pod:

kubectl run nginx3 --image=nginx --dry-run=client -o yaml > nginx3-pod.yaml

Así luce el archivo de manifiesto creado (nginx3-pod.yaml):

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx3
  name: nginx3
spec:
  containers:
  - image: nginx
    name: nginx3
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

Editamos el archivo para que quede así (agregamos spec.nodeSelector):

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx3
  name: nginx3
spec:
  nodeSelector:
    aplicacion: demo
  containers:
  - image: nginx
    name: nginx3
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

Ahora, procedemos a crear el pod desde el archivo de manifiesto y luego de unos segundos, consultamos la lista de Pods:

kubectl apply -f nginx3-pod.yaml
sleep 10
kubectl get pods -o wide

Tras esperar varios segundos o minutos, vemos que el estado del Pod es «Pending»:

Pod nginx3 en estado Pending

Una mirada más detallada del pod permite conocer por qué no ha sido aún asignado a ningún nodo y se mantiene en «Pending»:

kubectl describe pod nginx3
Vista detallada del pod nginx3

Dado que ningún nodo worker tiene un label aplicacion=demo, el Scheduler de Kubernetes no asigna el pod a ningún nodo.

La solución es asignar dicho label y valor a por lo menos uno de los nodos. Luego de unos segundos, se comprueba que el Pod fue asignado al mismo nodo al cual le asignamos el label.

kubectl label nodes k3d-demo-agent-0 aplicacion=demo
kubectl get node -L aplicacion
sleep 10
kubectl get pods -o wide
Comprobacion de pod nginx3 asignado al nodo deseado

¿Notaste cómo el pod fue asignado al mismo nodo worker al cual le aplicamos el label?

Múltiples labels con nodeSelector

No estamos limitados a especificar un único label con el atributo nodeSelector. Aquí un ejemplo de cómo indicar al pod que encuentre un nodo con los 3 labels indicados debajo:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx4
  name: nginx4
spec:
  nodeSelector:
    aplicacion: demo
    entorno: dev
    capa: frontend
  containers:
  - image: nginx
    name: nginx4
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

En este caso, obligatoriamente tiene que existir al menos un nodo worker que tenga los 3 labels aplicacion=demo, entorno=dev y capa=frontend. Cumplir solo 1 o 2 de los labels no es suficiente: debe cumplirlos todos.

Conclusión

En este artículo vimos una forma adicional de seleccionar nodos para los Pods a través del uso de labels y el atributo nodeSelector. Esto es más flexible que el uso básico del atributo nodeName, pues este selecciona un único nodo.

El uso de nodeSelector permite poder elegir entre uno o más nodos disponibles, siempre que cumplan con los criterios de los labels definidos.

Si bien se hizo la explicación sobre cómo hacerlo con pods, la misma configuración se hace con deployments (ver ejemplo debajo):

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx5
  name: nginx5
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx5
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx5
    spec:
      nodeSelector:
        aplicacion: demo
      containers:
      - image: nginx
        name: nginx5
        resources: {}
status: {}

Espero esta información te haya sido de más utilidad en tu uso diario de Kubernetes. En el siguiente artículo explicaré cómo asignar pods con reglas de afinidad.

Post navigation

Deja un comentario

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *