Hablemos de algunas de las mejores prácticas que deben seguirse al utilizar Kubernetes.

Kubernetes es una plataforma de orquestación de contenedores de código abierto que automatiza el despliegue de contenedores, el escalado continuo y el desescalado, el equilibrio de carga de contenedores y muchas cosas más.

Dado que la contenedorización se está utilizando en muchos servidores de producción con miles de contenedores, resulta muy importante gestionarlos bien, y eso es lo que hace Kubernetes.

Si utiliza Kubernetes, debe adoptar las mejores prácticas para una mejor orquestación de los contenedores.

He aquí una lista de algunas de las mejores prácticas de Kubernetes que debe seguir.

#1. Establezca solicitudes y límites de recursos

Cuando está desplegando una gran aplicación en un clúster de producción con recursos limitados en el que los nodos se quedan sin memoria o CPU, la aplicación dejará de funcionar. Este tiempo de inactividad de la aplicación puede tener un gran impacto en el negocio. Pero puede solucionarlo disponiendo de solicitudes y límites de recursos.

Las solicitudes y los límites de recursos son los mecanismos de Kubernetes para controlar el uso de recursos como la memoria y la CPU. Si un pod consume toda la CPU y la memoria, los demás pods se quedarán sin recursos y no podrán ejecutar la aplicación. Por lo tanto, es necesario establecer solicitudes y límites de recursos en los pods para aumentar la fiabilidad.

Para su información, el límite siempre será superior a la solicitud. Su contenedor no se ejecutará si la solicitud es superior al límite definido. Puede tener peticiones y límites definidos para cada contenedor en un pod. La CPU se define utilizando milicores, y la memoria se define utilizando bytes (megabyte/mebibyte).

A continuación se muestra un ejemplo en el que se establece un límite de 500 milicores de CPU y 128 mebibytes, y se fija una cuota para las peticiones de 300 milicores de CPU y 64 mebibytes.

contenedores:
- nombre: prodcontenedor1
    imagen: ubuntu
    recursos:
        peticiones:
            memoria "64Mi"
            cpu: "300m"
        límites:         
            memoria "128Mi"
            cpu: "500m"

#2. Utilice livenessProbe y readinessProbe

Las comprobaciones de estado son muy importantes en Kubernetes.

Proporciona dos tipos de comprobaciones de salud – Readiness probes y Liveness probes.

Las sondas de preparación se utilizan para comprobar si la aplicación está lista para empezar a servir tráfico o no. Esta sonda debe pasar en Kubernetes antes de que comience a enviar el tráfico al pod que ejecuta la aplicación dentro de un contenedor. Kubernetes dejará de enviar el tráfico al pod hasta que falle esta comprobación de estado de preparación.

Las sondas de disponibilidad se utilizan para comprobar si la aplicación sigue ejecutándose (viva) o se ha detenido (muerta). Si la aplicación se está ejecutando correctamente, Kubernetes no hace nada. Si la aplicación está muerta, Kubernetes lanzará un nuevo pod y ejecutará la aplicación en él.

Si estas comprobaciones no se realizan correctamente, los pods podrían terminar o empezar a recibir las solicitudes de los usuarios antes incluso de que estén listos.

Hay tres tipos de sondas que se pueden utilizar para las comprobaciones de liveness y readiness: HTTP, Command y TCP.

Permítame mostrarle un ejemplo de la más común que es la sonda HTTP.

Aquí su aplicación tendrá un servidor HTTP dentro de ella. Cuando Kubernetes haga ping a una ruta al servidor HTTP y obtenga una respuesta HTTP, marcará que la aplicación está sana, en caso contrario, que no lo está.

apiVersion: v1
tipo: Pod
metadatos:
 nombre: contenedor10
especificación:
 contenedores:
   - imagen: ubuntu
     nombre: contenedor10
     livenessProbe:
       httpGet:
         ruta: /prodhealth
         puerto 8080

#3. Construir imágenes de contenedores pequeños

Es preferible utilizar imágenes contenedoras más pequeñas porque ocupan menos espacio de almacenamiento y podrá extraer y construir las imágenes más rápidamente. Como el tamaño de la imagen será menor, las posibilidades de ataques de seguridad también serán menores.

Hay dos formas de reducir el tamaño del contenedor: utilizando una imagen base más pequeña y un patrón constructor. Actualmente, la última imagen base de NodeJS es de 345 MB, mientras que la imagen alpina de NodeJS es de sólo 28 MB, más de diez veces más pequeña. Por lo tanto, utilice siempre las imágenes más pequeñas y añada las dependencias necesarias para ejecutar su aplicación.

Para mantener las imágenes contenedoras aún más pequeñas, puede utilizar un patrón constructor. El código se construye en el primer contenedor y luego el código compilado se empaqueta en el contenedor final sin todos los compiladores y herramientas necesarios para hacer el código compilado, lo que hace que la imagen del contenedor sea aún más pequeña.

#4. Conceder niveles seguros de acceso (RBAC)

Disponer de un clúster Kubernetes seguro es muy importante.

El acceso al clúster debe estar bien configurado. Debe definir el número de solicitudes por usuario por segundo/minuto/hora, las sesiones concurrentes permitidas por dirección IP, el tamaño de la solicitud y el límite de rutas y nombres de host. Esto le ayudará a mantener el cluster a salvo de ataques DDoS.

Los ingenieros de desarrollo y DevOps que trabajan en un clúster Kubernetes deben tener un nivel de acceso definido. La función de control de acceso basado en roles (RBAC) de Kubernetes es útil en este caso. Puede utilizar Roles y ClusterRoles para definir los perfiles de acceso. Para facilitar la configuración de RBAC, puede utilizar rbac-managers de código abierto disponibles para ayudarle en la simplificación de la sintaxis o utilizar Rancher, ya que proporciona RBAC por defecto.

apiVersion: rbac.authorization.k8s.io/v1
tipo: ClusterRole
metadatos:
  name: cluster-role
reglas:
- apiGrupos: [""]
  recursos: ["pods"]
  verbos: ["get", "list"]

Kubernetes Secrets almacena información confidencial como tokens de autenticación, contraseñas y claves ssh. Nunca debe consultar Kubernetes Secrets en el repositorio IaC, de lo contrario, quedará expuesto a quienes tengan acceso a su repositorio git.

DevSecOps es una palabra de moda ahora que habla de DevOps y Seguridad. Las organizaciones están adoptando esta tendencia ya que comprenden su importancia.

#5. Manténgase al día

Se recomienda tener siempre instalada la última versión de Kubernetes en el clúster.

La última versión de Kubernetes incluye nuevas funciones, actualizaciones de funciones anteriores, actualizaciones de seguridad, correcciones de errores, etc. Si utiliza Kubernetes con un proveedor en la nube, actualizarlo resulta muy sencillo.

#6. Utilice espacios de nombres

Kubernetes incluye tres espacios de nombres diferentes: default, kube-system y kube-public.

Estos espacios de nombres desempeñan un papel muy importante en un clúster Kubernetes para la organización y la seguridad entre los equipos.

Tiene sentido utilizar el espacio de nombres por defecto si se trata de un equipo pequeño que trabaja con sólo 5-10 microservicios. Pero un equipo en rápido crecimiento o una gran organización tendrá varios equipos trabajando en un entorno de prueba o de producción, por lo que cada equipo necesita tener un espacio de nombres separado para facilitar la gestión.

Si no lo hacen, pueden acabar sobrescribiendo o interrumpiendo accidentalmente la aplicación/función de otro equipo sin ni siquiera darse cuenta. Se sugiere crear varios espacios de nombres y utilizarlos para segmentar sus servicios en trozos manejables.

He aquí un ejemplo de creación de recursos dentro de un espacio de nombres:

apiVersion: v1
tipo: Pod
metadatos:
   nombre: pod01
espacio de nombres: prod
   etiquetas:
      imagen: pod01
espec:
   contenedores:
- nombre: prod01
  Imagen: ubuntu

#7. Utilizar etiquetas

A medida que crezcan sus despliegues de Kubernetes, incluirán invariablemente múltiples servicios, pods y otros recursos. Hacer un seguimiento de estos puede llegar a ser engorroso. Aún más difícil puede ser describir en Kubernetes cómo interactúan estos diversos recursos, cómo desea que se repliquen, escalen y reciban servicio. Las etiquetas en Kubernetes son muy útiles para resolver estas cuestiones.

Las etiquetas son pares clave-valor que se utilizan para organizar los elementos dentro de la interfaz de Kubernetes.

Por ejemplo, app: kube-app, phase: test, role: front-end. Se utilizan para describir en Kubernetes el funcionamiento conjunto de los distintos objetos y recursos del clúster.

apiVersion: v1
tipo: Pod
metadatos:
 nombre: test-pod
 etiquetas:
   entorno: testing
   equipo: test01
especificación
 contenedores:
   - nombre: test01
     imagen: "Ubuntu"
     recursos:
       límites:
        cpu: 1

Así, puede reducir el dolor de la producción de Kubernetes etiquetando siempre los recursos y objetos.

#8. Registro de auditoría

Para identificar las amenazas en el clúster Kubernetes, la auditoría de los registros es muy importante. La auditoría ayuda a responder a preguntas como qué ocurrió, por qué ocurrió, quién lo hizo, etc.

Todos los datos relacionados con las solicitudes realizadas a kube-apiserver se almacenan en un archivo de registro llamado audit.log. Este archivo de registro está estructurado en formato JSON.

En Kubernetes, por defecto, el registro de auditoría se almacena en <em>/var/log/audit.log</em> y la política de auditoría está presente en <em>/etc/kubernetes/audit-policy.yaml</em>.

Para habilitar el registro de auditoría, inicie el kube-apiserver con estos parámetros:

--audit-policy-file=/etc/kubernetes/audit-policy.yaml --audit-log-path=/var/log/audit.log

A continuación se muestra un ejemplo de archivo audit. log configurado para registrar los cambios en los pods:

apiVersion: audit.k8s.io/v1
tipo: Política
omitStages:
  - "SolicitudRecibida"
reglas
  - level: SolicitudRespuesta
    recursos:
    - grupo: ""
      recursos: ["pods"]
   - nivel: Metadatos
     recursos:
     - grupo: ""
      recursos: ["pods/log", "pods/status"]

Siempre puede volver atrás y comprobar los registros de auditoría en caso de que se produzca algún problema en el clúster de Kubernetes. Le ayudará a restaurar el estado correcto del clúster.

#9. Aplicar reglas de afinidad (Nodo/Pod)

Existen dos mecanismos en Kubernetes para asociar mejor los pods con los nodos: afinidad Pod y afinidad Node. Se recomienda utilizar estos mecanismos para obtener un mejor rendimiento.

Utilizando la afinidad de nodo, puede programar pods en los nodos basándose en criterios definidos En función de los requisitos del pod, se selecciona y asigna el nodo correspondiente en un clúster Kubernetes.

apiVersion: v1
tipo: Pod
metadatos
  nombre: ubuntu
spec:
  afinidad
    nodeAffinity:    
preferredDuringSchedulingIgnoredDuringExecution:
      - peso: 2
        preferencia:        
matchExpressions:
          - clave: disktype
            operador: En
            valores:
            - ssd   
  contenedores:
  - nombre: ubuntu
    imagen: ubuntu
    imagePullPolicy: IfNotPresent

Utilizando la afinidad de pods, puede programar múltiples pods en el mismo nodo (para mejorar la latencia) o decidir mantener los pods en nodos separados (para alta disponibilidad) para aumentar el rendimiento.

apiVersion: v1
tipo: Pod
metadatos:
  nombre: ubuntu-pod
spec:
  afinidad:
    podAffinity:
     
requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
         
matchExpressions:
          - clave: seguridad
            operador: En
            valores:
            - S1
        topologyKey: fallo-dominio.beta.kubernetes.io/zona
  contenedores:
  - nombre: ubuntu-pod
    imagen: ubuntu

Tras analizar la carga de trabajo de su clúster, debe decidir qué estrategia de afinidad utilizar.

#10. Terminación de Kubernetes

Kubernetes termina los pods cuando ya no son necesarios. Puede iniciarlo mediante un comando o una llamada a la API, los pods seleccionados pasan al estado de terminación y no se envía tráfico a esos pods. A continuación, se envía un mensaje SIGTERM a esos pods, tras lo cual los pods se apagan.

Los pods se terminan con gracia, por defecto el periodo de gracia es de 30 segundos. Si los pods siguen funcionando, Kubernetes envía un mensaje SIGKILL que apaga los pods por la fuerza. Finalmente, estos pods son eliminados por Kubernetes del servidor API en la máquina maestra.

En caso de que sus pods estén tardando siempre más de 30 segundos, puede aumentar este periodo de gracia a 45 o 60 segundos.

apiVersion: v1
tipo: Pod
metadatos:
 nombre: contenedor10
especificación:
 contenedores:
   - imagen: ubuntu
     nombre: contenedor10
  terminaciónGracePeriodSeconds: 60

Conclusión

Espero que estas mejores prácticas le ayuden en una mejor orquestación de contenedores utilizando Kubernetes. Siga adelante e intente implementarlas en su clúster Kubernetes para obtener mejores resultados.

A continuación, explore las mejores herramientas de Kubernetes para el éxito de DevOps.