Orquestadores
Kubernetes
Logo de Kubernetes
La adopción de Kubernetes se motiva principalmente por la necesidad de administrar de manera eficiente y escalable múltiples contenedores distribuidos en diversos servidores. Kubernetes facilita la orquestación de estos contenedores a través de una infraestructura declarativa, en la que los usuarios definen la configuración deseada en un manifiesto (un archivo de configuración) que se procesa mediante la API de Kubernetes. La plataforma asume la responsabilidad de distribuir la carga de trabajo entre los nodos disponibles y de administrar los recursos requeridos por los contenedores.
Kubernetes también posibilita la construcción de pipelines ETL utilizando herramientas como Spark o Airflow, y se emplea extensamente en el entrenamiento de modelos de aprendizaje automático, como se evidencia en su uso con Kubeflow. Al gestionar la infraestructura de cómputo, redes y almacenamiento, Kubernetes simplifica la implementación y administración de aplicaciones en contenedores a gran escala.
Componentes de Kubernetes
Kubectl es una interfaz de línea de comandos que facilita la interacción con un clúster de Kubernetes, permitiendo la gestión de objetos como pods, servicios y despliegues.
Para la creación de un clúster de Kubernetes en un entorno local, se utiliza
Minikube. Esta herramienta permite la ejecución de Kubernetes de manera local para
fines de prueba o desarrollo, creando un clúster con uno o varios nodos virtualizados.
Por defecto, Minikube crea un clúster que contiene un nodo. Para inicializar el clúster
se utiliza el comando minikube start, y para verificar su estado, minikube status.
Nodos
Un nodo representa la unidad más pequeña dentro de un clúster de Kubernetes. Puede ser una máquina física o una máquina virtual donde se ejecutan las aplicaciones. Kubernetes abstrae el hardware subyacente, permitiendo una gestión eficiente de los requisitos de recursos. Si un nodo no puede proporcionar más recursos o falla, Kubernetes redistribuye las cargas de trabajo a otros nodos disponibles. Existen diferentes tipos de nodos: los nodos bajo demanda (on-demand nodes), que se crean cuando los recursos requeridos son elevados (CPU, GPU, RAM), y los nodos al mejor precio (spot nodes), que son más económicos pero pueden ser retirados en cualquier momento.
Pods
Un pod es la unidad mínima de ejecución en Kubernetes y puede contener uno o más contenedores que comparten los mismos recursos y red local. Todos los contenedores dentro del mismo pod pueden comunicarse entre sí y comparten el mismo entorno de red. Al escalar un pod, todos los contenedores dentro de él se escalan conjuntamente.
Clúster
Un clúster es un conjunto de nodos, también conocidos como workers, que se ejecutan en Kubernetes. La relación entre las aplicaciones que se ejecutan en cada nodo es independiente. Por ejemplo, si se dispone de un servidor de Proxmox con dos máquinas virtuales, VM1 y VM2, a pesar de que cuenten con diferentes pods, si todos están gestionados por Kubernetes, ambos forman parte del mismo clúster.
StatefulSet y volúmenes
Dado que no se puede garantizar el lugar de ejecución de una aplicación, el uso del disco local para almacenar datos resulta inviable, siendo útil únicamente para almacenamiento temporal como caché. Kubernetes emplea volúmenes persistentes que, a diferencia de otros recursos como la CPU, GPU y RAM gestionados por los clústeres, deben adjuntarse al propio clúster desde unidades locales o en la nube. Estos volúmenes no se asocian a un nodo en particular.
StatefulSet permite la creación de pods con volúmenes persistentes, garantizando la integridad de los datos incluso si el pod se reinicia o se elimina. A continuación se muestra un ejemplo:
Para verificar el estado de los volúmenes y los StatefulSets se utilizan los comandos
kubectl get pvc (para consultar la asignación del volumen, capacidad y otros detalles)
y kubectl get sts (para consultar los StatefulSets).
Manifiestos
Un manifiesto es un archivo en formato YAML o JSON que especifica cómo desplegar una aplicación en un clúster de Kubernetes. Este archivo se conoce como un registro de intención, donde se le indica a Kubernetes el estado deseado del clúster.
Un concepto importante asociado es el de namespace, que constituye la división lógica
del clúster de Kubernetes y permite separar la carga del clúster. Se pueden crear
políticas para separar tráfico entre namespaces, aunque por defecto los datos de un
namespace son visibles desde otro. Para obtener los namespaces del clúster se utiliza
kubectl get ns, para obtener los pods de un namespace específico se emplea
kubectl -n nombre_namespace get pods -o wide (la opción -o wide proporciona
información adicional como la IP del pod y el nodo), y para eliminar un pod se usa
kubectl -n nombre_namespace delete pod nombre_pod.
A continuación se muestra un ejemplo de manifiesto para crear un pod simple:
Para aplicar el manifiesto se ejecuta kubectl apply -f nombre.yaml, y para consultar el
estado del pod, kubectl get pods.
El siguiente ejemplo muestra un manifiesto más complejo que incluye variables de entorno, solicitudes y límites de recursos, así como readiness probe y liveness probe:
En este manifiesto, la sección resources.requests define los recursos garantizados que
la instancia debe tener disponibles para poder realizar el despliegue, medidos en
milicores para CPU (donde 1000 milicores equivalen a 1 core). La sección
resources.limits establece el límite máximo de recursos que el pod puede consumir. Si
se excede dicho límite, el kernel de Linux finaliza el proceso y el pod se reinicia.
La readiness probe indica a Kubernetes que el pod está listo para recibir tráfico,
mientras que la liveness probe confirma que el pod sigue activo y no debe ser
eliminado.
Despliegue y gestión de réplicas
Un despliegue (deployment) permite declarar el número de réplicas de pods y asegurar que el estado deseado se mantenga, monitorizándolos de forma continua:
DaemonSet
Un DaemonSet es una forma de despliegue que garantiza que un pod se ejecute en todos los nodos del clúster, con exactamente un pod por nodo. No se especifica el número de réplicas, ya que depende del número de nodos. Se utiliza habitualmente para servicios de monitoreo:
Exponer aplicaciones
Tipos de servicios
Los servicios en Kubernetes permiten acceder a los pods desde dentro y fuera del clúster. Existen varios tipos de servicios según las necesidades de exposición.
ClusterIP proporciona una dirección IP virtual única a nivel de clúster, facilitando la comunicación y el balanceo de carga entre pods de forma interna.
NodePort crea un puerto en cada nodo que recibe el tráfico y lo redirige a los pods correspondientes, permitiendo que la aplicación sea accesible desde fuera del clúster. Suele utilizar puertos dentro del rango 30000 a 32767:
LoadBalancer está orientado a proveedores de la nube y crea un balanceador de carga que proporciona una IP estable para el servidor, facilitando su acceso desde Internet:
Ingress
Ingress administra el acceso externo a los servicios del clúster, típicamente HTTP. Proporciona balanceo de carga y terminación SSL, y permite el acceso al servicio mediante paths. Suele requerirse un controlador Ingress-Nginx que se instala por separado.
Networking y almacenamiento
Cada pod en Kubernetes tiene su propia dirección IP, y para comunicar pods en diferentes nodos se utiliza el Cloud Cluster Networking Interface. En cuanto al almacenamiento, etcd es un almacén de datos clave-valor distribuido utilizado para guardar datos de configuración, estado y metadatos del clúster.