Afinidad de Nodos en Kubernetes

nodeaffinity en kubernetes

nodeaffinity en kubernetes


En esta nueva entrada de Afinidad de Nodos en Kubernetes vamos a ver como aplicar y trabajar con la afinidad de nodos. Este artículo es una continuación del anterior sobre Selector de Nodos en Kubernetes.

¿Qué es la afinidad de Nodos en Kubernetes?

Tanto la afinidad de nodos como el selector de nodos buscan una misma finalidad pero de maneras diferentes, mientras en el Selector de Nodos se restringe en qué nodos va a funcionar haciendo uso de etiquetas. En la afinidad de nodos se establecen una serie de reglas para determinar donde establecer y asignar esos Pods. Es decir, permite especificar una «afinidad» para colocar un grupo de pods en un nodo. Y en ningún momento el nodo tendrá control sobre ese Pod.

Configuración de Afinidad de Nodos en Kubernetes

La mejor manera de ver el funcionamiento de la afinidad de Nodos en Kubernetes es ver la configuración de un Pod.

Para realizar la afinidad de nodos podemos utilizar dos tipos de reglas «preferred rule» (o preferida) o «required rule» (o requerida) o ambas. Teniendo en cuenta que si usamos la opción de ambas, primero se configurará la opción de «preferred rule». A continuación vamos a ver un ejemplo con required rule:

apiVersion: v1
kind: Pod
metadata:
  name: node-affinity
spec:
  affinity:
    nodeAffinity:  1
      requiredDuringSchedulingIgnoredDuringExecution: 2
        nodeSelectorTerms:
        - matchExpressions:
          - key: size
            operator: NotIn 4
            values:
            - very-big 3
            - very-small 3
  containers:
  - name: node-affinity
    image: nginx
  1. Se establece la propiedad nodeaffinity.
  2. Definición de una required rule.
  3. Clave/valor que debe conincidir para aplicar la regla
  4. El operador que se va a aplicar y representa la relación entre la etiqueta del nodo y el cojunto de valores que harán match en la especificación del Pod. Este valor puede ser InNotInExists, or DoesNotExistLt, or Gt.

Tipos de afinidad de Nodo

Anteriormente hemos hablado de dos tipos de afinidad de nodo diferentes preferred y required.

Estos tipos de nodo sirven para decirle como se tiene que programar el Pod. En el caso de Required la regla debe ser conocida antes de que un pod pueda ser planificado en un nodo.

Configurar un nodo Required

En el ejemplo anterior hemos definido un nodo de este tipo, a continuación vamos a describir los pasos con más detalle:

spec:
  affinity:
    nodeAffinity:  
      requiredDuringSchedulingIgnoredDuringExecution: 
        nodeSelectorTerms:
        - matchExpressions:
          - key: size
            operator: NotIn 
            values:
            - very-big 
            - very-small 
  containers:
  - name: node-affinity
    image: nginx

En el pode anterior especificamos el tipo de afinidad de nodo añadiendo el parámetro requiredDuringSchedulingIgnoredDuringExecution.

Una vez específicamos el tipo de nodo, debemos de asignar la clave y el valor, que se puede ver en el ejemplo con key: size y values.

Finalmente, asignamos el operador que queremos utilizar en este caso hemos dicho NotIn, para decir que no este en el nodo.

Si esta clave/valor que hemos definido, no se encontrará en el nodo, este Pod no será programado en el Nodo. Es decir, el estado será erróneo.

Configurar un Nodo Preferred

En este tipo de Nodos se específica que el programador intentará hacer cumplir la regla, pero en ningún momento garantiza su cumplimiento.

A continuación vamos a ver un ejemplo de configuración:

      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: e2e-az-name
            operator: In
            values:
            - e2e-az3

En este nodo añadimos el parámetro preferredDuringSchedulingIgnoredDuringExecution.

A continuación definimos un weight, es decir, un peso al nodo. Este número va de 1 a 100, siendo el valor más alto el más preferido.

Una vez definido el peso añadimos al igual que en el nodo tipo required la clave y el valor.

Si al hacer uso de preferredDuringSchedulingIgnoredDuringExecution, no hiciese match con la etiqueta del nodo, el pod se ejecutará ya que prevalece la carga del pod.

Ejemplo de Afinidad de Nodos en Kubernetes

Una vez hemos explicado los diferentes nodos y como funcionan vamos a ver un ejemplo paso a paso. En el que tendremos un nodo en el que las etiquetas van a coincidir

  • Listar nodos:
kubectl get nodes
  • Asignar etiqueta al nodo seleccionado:
kubectl label nodes <node-name> <label-key>=<label-value>

En nuestro caso vamos a trabajar sobre el siguiente nodo:

Labels:             alpha.eksctl.io/cluster-name=eks-dev-cluster
                    alpha.eksctl.io/instance-id=i-0100bdd9c9bd76461
                    alpha.eksctl.io/nodegroup-name=mixed-instances-stateless
                    beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/instance-type=c5.2xlarge
                    beta.kubernetes.io/os=linux
                    failure-domain.beta.kubernetes.io/region=us-east-1
                    failure-domain.beta.kubernetes.io/zone=us-east-1c
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=ip-192-168-143-94.ec2.internal
                    kubernetes.io/os=linux
                    node.kubernetes.io/instance-type=c5.2xlarge
                    nodegroup-instances=mixed-instances-stateless
                    nodegroup-type=microservices
                    topology.kubernetes.io/region=us-east-1
                    topology.kubernetes.io/zone=us-east-1c

Y a este nodo le vamos a asignar una afinida de nodos a un deployment con la etiqueta microservices:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: locations
  namespace: microservices
spec:
  selector:
    matchLabels:
      app: locations
  replicas: 1
  template:
    metadata:
      labels:
        app: locations
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: nodegroup-type
                    operator: In
                    values:
                      - microservices
      containers:
        - name: locations
          image: locations:latest
          resources:
            requests:
              memory: "512Mi"
              cpu: "500m"
            limits:
              memory: "512Mi"
              cpu: "500m"
          ports:
            - containerPort: 8080
          livenessProbe:
            httpGet:
              path: /actuator/health
              port: 8080
            initialDelaySeconds: 240
            periodSeconds: 5
    

Con el deployment anterior lo que vamos a hacer es asginar una afinidad de nodos por la etiqueta microservices.

¿Qué pasaría si la etiqueta en la afinidad de nodo no existe?

Al haber elegido la opción requiredDuringSchedulingIgnoredDuringExecution, entonces al no hacer match con la etiqueta, se quedaría en estado de pending al crear el pod. Si por el contrario hubiesemos elegido la etiqueta referredDuringSchedulingIgnoredDuringExecution, aunque no haga match daría preferencia a la carga del Pod y se asingaría al nodo.

Conclusión

En esta entrada sobre Afinidad de Nodos en Kubernetes, hemos visto como podemos hacer que un pod se despliegue en uno o en otro nodo en función una etiqueta. Esta suele ser una práctica muy utilizada dentro de kubernetes ya que los nodos suelen tener diferentes características y nos ayudará a distribuir nuestros Pods.

Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com y te ayudaremos encantados!


No te olvides de seguirnos en nuestras redes sociales Facebook o Twitter para estar actualizado.


2 pensamientos sobre “Afinidad de Nodos en Kubernetes

Deja una respuesta

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