Gestión de Cargas de Trabajo en Kubernetes. Bloque 2. Tema 2.1 del CKA.
Cuando hablamos de cargas de trabajo (Workloads) en Kubernetes, no solo nos referimos a aplicaciones ejecutándose en contenedores. Nos referimos a un ecosistema completo que gestiona de manera automatizada el ciclo de vida de esas aplicaciones, desde su creación, escalado, hasta su recuperación ante fallos. Kubernetes se encarga de que cada carga de trabajo sea gestionada de forma eficiente, asegurando que los procesos críticos como el escalado, la actualización continua y la tolerancia a fallos se realicen sin intervención manual constante.
Kubernetes no solo ejecuta contenedores, sino que también proporciona una serie de herramientas avanzadas que permiten gestionar aplicaciones de todo tipo. Estas aplicaciones pueden escalar sin perder datos, ser robustas ante fallos y operar en entornos distribuidos sin afectar su rendimiento o disponibilidad. Ya sea que se trate de aplicaciones sin estado (stateless) que pueden escalar fácilmente, o aplicaciones con estado (stateful) que requieren una gestión cuidadosa del almacenamiento persistente, Kubernetes ofrece los recursos necesarios para garantizar que se mantengan operativas y resilientes en todo momento.
Entre los recursos más utilizados para gestionar cargas de trabajo en Kubernetes encontramos los Deployments, StatefulSets, DaemonSets, Jobs y CronJobs, cada uno con un propósito específico para cubrir las distintas necesidades de las aplicaciones. Además, Kubernetes incluye potentes estrategias de actualización, como RollingUpdate, que permiten implementar nuevas versiones sin interrupciones en el servicio.
Entender estos conceptos no solo es fundamental para aquellos que se preparan para el examen CKA (Certified Kubernetes Administrator), sino también para cualquier administrador que busque gestionar aplicaciones en Kubernetes de manera eficaz y segura. Kubernetes simplifica lo complejo, automatiza lo repetitivo y proporciona las herramientas para mantener aplicaciones de misión crítica funcionando sin problemas, sin importar la escala o la complejidad del entorno.
¿Qué es una Carga de Trabajo en Kubernetes?
En el mundo de Kubernetes, una carga de trabajo es simplemente una aplicación que ha sido contenedorizada y está lista para ser ejecutada dentro de este poderoso sistema de orquestación. Lo interesante aquí es que Kubernetes no se limita a ejecutar estos contenedores; va un paso más allá. Los contenedores que conforman estas aplicaciones se agrupan en pods, los cuales siguen un ciclo de vida bien definido. Este ciclo incluye capacidades como la autorreparación (self-healing), lo que significa que, si un pod falla, Kubernetes automáticamente lo reiniciará o reemplazará, asegurando que la aplicación siga funcionando sin problemas.
Controlando el Ciclo de Vida de los Pods
A menudo, la gestión directa de los pods no es lo más eficiente, y es aquí donde Kubernetes brilla. Para aliviar esta carga, Kubernetes ofrece recursos avanzados como Deployments y StatefulSets. Estos recursos automatizan gran parte del trabajo, desde la creación de nuevos pods hasta su actualización sin interrupciones. Imagina que tienes una aplicación crítica funcionando: ¿no sería genial poder actualizarla sin detener el servicio? Aquí entra en juego la estrategia RollingUpdate, que reemplaza gradualmente los pods antiguos con nuevos, sin afectar la disponibilidad.
Además, si lo que necesitas es algo más drástico, Kubernetes también ofrece la estrategia Recreate, que reemplaza todos los pods de golpe. Esto puede ser útil en situaciones donde los cambios son tan grandes que no puedes permitir que convivan pods de versiones diferentes.
Recursos API Principales para Cargas de Trabajo: (Pulsa aquí para más información)
Dependiendo del tipo de aplicación que estés gestionando, Kubernetes ofrece diferentes recursos API que se adaptan a las necesidades específicas de tus cargas de trabajo. Aquí te explico los más comunes:
1. Deployment: Qué es y cómo funciona:
Un Deployment es un recurso de Kubernetes que se utiliza para gestionar la creación y la actualización de un grupo de pods. Es el recurso más utilizado cuando se trata de aplicaciones sin estado (stateless) que pueden ejecutarse sin necesidad de mantener información entre reinicios. Por ejemplo, una aplicación web o una API que simplemente procesa solicitudes puede ejecutarse sin necesidad de recordar qué ocurrió en ejecuciones anteriores.
Los Deployments proporcionan características como:
- Escalabilidad: Puedes ajustar fácilmente el número de pods que ejecutan tu aplicación en función de la carga.
- Actualización continua (Rolling Updates): Kubernetes permite actualizar tu aplicación sin tener que detenerla. El Deployment se encargará de reemplazar gradualmente los pods antiguos con los nuevos.
- Rollback (Reversión): Si una actualización falla, puedes volver a la versión anterior de manera sencilla.
Ejemplo de un Deployment:
apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 1 template: metadata: labels: app: my-app spec: containers: - name: my-app image: nginx:1.18 ports:- containerPort: 80
Explicación:
- replicas: Define cuántos pods quieres que Kubernetes mantenga en ejecución. En este caso, tres.
- template: Aquí defines cómo se verá cada pod. En este ejemplo, estás ejecutando tres instancias del contenedor
nginx:1.17
en los pods. - selector: Es el criterio que Kubernetes usará para identificar qué pods pertenecen a este deployment.
2. ReplicaSet: Asegurar el número de réplicas
Un ReplicaSet es un recurso de Kubernetes que garantiza que siempre haya un número específico de pods en ejecución en el clúster. Es importante entender que los Deployments usan ReplicaSets de forma implícita para gestionar los pods.
Por sí mismo, un ReplicaSet solo asegura que haya un número fijo de réplicas corriendo en el clúster. Si algún pod falla, el ReplicaSet lo reemplazará automáticamente. Sin embargo, un ReplicaSet no maneja actualizaciones ni rollbacks; esas características están asociadas a los Deployments.
Nota: Aunque puedes crear un ReplicaSet directamente, la práctica común es utilizar un Deployment, ya que este último ofrece más control sobre actualizaciones y versiones.
Ejemplo de un ReplicaSet:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:1.17
ports:
- containerPort: 80
Explicación:
- Es similar al Deployment, pero aquí el recurso es un ReplicaSet que se encargará de mantener tres réplicas activas en todo momento.
- selector: Al igual que en un Deployment, el selector identifica los pods gestionados por este ReplicaSet.
Actualizaciones con Deployments: Rolling Update y Rollback
Una de las principales ventajas de usar un Deployment sobre un ReplicaSet es que los Deployments gestionan actualizaciones. Existen dos métodos clave:
Rolling Update: Cuando actualizas la imagen de una aplicación (por ejemplo,
nginx:1.17
anginx:1.18
), Kubernetes no derriba todos los pods de golpe. En cambio, realiza un despliegue gradual donde elimina algunos pods antiguos y los reemplaza por los nuevos de forma controlada, lo que asegura que no haya tiempo de inactividad.Puedes ajustar el comportamiento del Rolling Update definiendo cuántos pods pueden estar fuera de servicio o cuántos nuevos pueden arrancar simultáneamente.
Rollback: Si una actualización provoca errores, Kubernetes guarda el estado anterior del Deployment. Esto te permite hacer un rollback para revertir los cambios y volver a la versión anterior de la aplicación sin complicaciones.
Ejemplo de Actualización Continua en un Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:1.18
ports:
- containerPort: 80
Explicación:
- strategy: Aquí definimos que usaremos una actualización continua (RollingUpdate).
- maxUnavailable: Solo un pod puede estar fuera de servicio durante la actualización.
- maxSurge: Solo un pod adicional puede ser lanzado mientras la actualización se lleva a cabo.
Si algo sale mal, puedes revertir fácilmente a la versión anterior con:
kubectl rollout undo deployment my-deployment
Diferencias Clave entre Deployment y ReplicaSet:
Deployment:
- Abstrae y gestiona los ReplicaSets.
- Permite realizar actualizaciones continuas (rolling updates) y volver a versiones anteriores (rollback).
- Proporciona mayor flexibilidad y control en la administración de aplicaciones sin estado.
ReplicaSet:
- Garantiza que un número específico de réplicas esté siempre corriendo.
- No maneja actualizaciones ni versiones anteriores por sí mismo.
- Se utiliza principalmente en el contexto de un Deployment.
Cuándo Usar un Deployment o un ReplicaSet
Deployment: Se utiliza cuando necesitas administrar aplicaciones stateless y necesitas control sobre las actualizaciones. La mayoría de las aplicaciones modernas que no necesitan mantener el estado entre reinicios usan Deployments.
ReplicaSet: Es útil si simplemente necesitas asegurar que un conjunto de pods esté siempre disponible, pero no necesitas gestionar versiones ni realizar actualizaciones. Aun así, la práctica común es trabajar directamente con Deployments, ya que gestionan los ReplicaSets automáticamente.
3. StatefulSet
Los StatefulSets en Kubernetes son el recurso adecuado cuando necesitas gestionar aplicaciones que requieren persistencia de datos y mantener una identidad única a lo largo del tiempo. Son especialmente útiles para aplicaciones con estado, como bases de datos (MySQL, Cassandra, etc.) o sistemas distribuidos que necesitan conservar la información cuando los Pods se reinician, se escalan o se reemplazan.
¿Cómo funcionan los StatefulSets?
Identidad única para cada Pod:
- A diferencia de los Deployments y ReplicaSets, donde los Pods son intercambiables, en un StatefulSet cada Pod tiene una identidad única y persistente. Esta identidad se basa en un nombre ordinal secuencial (por ejemplo,
my-app-0
,my-app-1
,my-app-2
), que no cambia aunque el Pod sea reiniciado o eliminado. - Esto es clave para aplicaciones que dependen de identificadores constantes, como bases de datos, donde cada nodo tiene un rol único dentro del clúster.
- A diferencia de los Deployments y ReplicaSets, donde los Pods son intercambiables, en un StatefulSet cada Pod tiene una identidad única y persistente. Esta identidad se basa en un nombre ordinal secuencial (por ejemplo,
Volúmenes persistentes:
- Cada Pod en un StatefulSet tiene un volumen persistente asociado. Estos volúmenes garantizan que, incluso si un Pod falla o es recreado, sus datos sigan siendo accesibles y estén vinculados al mismo nodo de la aplicación.
- Los volúmenes no se comparten entre Pods, lo que es esencial para mantener la integridad de los datos y evitar conflictos en aplicaciones con estado.
Orden de creación y eliminación:
- Los Pods en un StatefulSet se crean de manera secuencial. Kubernetes asegura que se inicie el Pod
my-app-0
antes de crear el Podmy-app-1
, y así sucesivamente. - De la misma manera, cuando se eliminan o reinician, lo hacen en orden inverso, asegurando que siempre se mantenga la consistencia del sistema.
- Este comportamiento es crítico en aplicaciones distribuidas o clústeres de bases de datos donde el orden de inicio es importante para la sincronización de los nodos.
- Los Pods en un StatefulSet se crean de manera secuencial. Kubernetes asegura que se inicie el Pod
Escalabilidad controlada:
- Aunque puedes escalar un StatefulSet, Kubernetes garantiza que los nuevos Pods se creen uno a la vez y en orden. Esto es crucial para mantener la consistencia en aplicaciones que dependen de la replicación de datos o la sincronización entre nodos.
Cuándo usar StatefulSet
- Bases de datos: Si estás ejecutando aplicaciones como MySQL, Cassandra, o Redis en Kubernetes, donde cada nodo debe almacenar y preservar datos, un StatefulSet es la opción correcta.
- Sistemas distribuidos: Aplicaciones como Apache Kafka o Zookeeper, donde los nodos se comunican entre sí y deben tener un rol específico dentro del clúster.
- Aplicaciones que dependen de la persistencia de datos: Si un Pod requiere mantener su información de forma constante en el disco y no perder datos entre reinicios o escalados, un StatefulSet es la mejor opción.
Ejemplo básico de StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-statefulset
spec:
serviceName: "my-service"
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-database-image
volumeMounts:
- name: my-persistent-storage
mountPath: /data/db
volumeClaimTemplates:
- metadata:
name: my-persistent-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
Explicación del manifiesto:
- Pod identidad: Los Pods generados por este StatefulSet tendrán nombres como
my-statefulset-0
,my-statefulset-1
, etc., y estos nombres se mantendrán sin importar cuántas veces sean recreados. - Volúmenes persistentes: Cada Pod tiene un volumen persistente (
my-persistent-storage
) que almacena los datos en el directorio/data/db
. Este volumen se mantendrá asociado a su Pod, incluso si el Pod es destruido y recreado. - Escalabilidad: Se definen 3 réplicas (
replicas: 3
), lo que significa que habrá tres Pods creados secuencialmente. Cada Pod tendrá un identificador único y no intercambiable.
Ventajas de usar StatefulSets:
- Identidad garantizada: Los Pods conservan su identidad única, lo que es esencial en sistemas que dependen de nodos individuales con roles específicos.
- Persistencia de datos: Los volúmenes persistentes aseguran que los datos sobrevivan a reinicios o eliminaciones de Pods, lo que es crucial para la integridad de las aplicaciones con estado.
- Control del orden: Kubernetes controla el orden de creación y destrucción de los Pods, asegurando que se mantenga la consistencia en sistemas distribuidos.
En resumen, StatefulSets son esenciales cuando trabajas con aplicaciones que dependen de la persistencia de datos y necesitan garantizar una identidad única para cada Pod.
Comentarios
Publicar un comentario