Los controladores de Pod son proporcionados por el componente kube-controller-manager del nodo maestro. Entre los controladores más comunes se encuentran ReplicationController, ReplicaSet, Deployment, DaemonSet, StatefulSet, Job y CronJob. Cada uno gestiona los objetos Pod de manera distinta.
- Controlador ReplicaSet
(1) Introducción a ReplicaSet
Conocido como RS, es una implementación de controlador de Pod que garantiza que la cantidad de réplicas de un Pod coincida exactamente con el número esperado en todo momento. El controlador RS busca en el clúster los objetos Pod que coincidan con su selector de etiquetas. Si la cantidad de objetos activos no coincide con la esperada, elimina los sobrantes o crea nuevos a partir de una plantilla para alcanzar el número deseado. Una vez que se cumple la cantidad esperada, entra en el siguiente ciclo de reconciliación.
Las propiedades de RS, como el número de réplicas, el selector de etiquetas y la plantilla de Pod, se pueden modificar en cualquier momento. Sin embargo, modificar solo el número esperado de réplicas afecta directamente a los Pod existentes. Cambiar el selector de etiquetas puede hacer que los Pod existentes ya no coincidan, y el controlador RS simplemente dejará de contarlos. Además, una vez creado, RS no se preocupa por el contenido real del Pod, por lo que los cambios en la plantilla solo afectan a los nuevos Pod creados posteriormente. En comparación con la creación y gestión manual de Pods, RS ofrece las siguientes funcionalidades:
- Garantizar la cantidad de Pods: RS se asegura de que el número de réplicas de Pod bajo su control coincida con el valor esperado definido en la configuración. Si no es así, añade los que faltan o elimina los sobrantes.
- Monitoreo de Pods: Si detecta que un Pod bajo su control no está disponible debido a una falla en el nodo de trabajo, solicita al planificador que cree un Pod de reemplazo en otro nodo.
- Escalado elástico: Ante fluctuaciones en la carga de trabajo, se puede ajustar dinámicamente la cantidad de Pods a través del controlador RS. Incluso se puede usar el controlador HPA (HorizontalPodAutoscaler) para un escalado automático.
(2) Creación de un ReplicaSet
Al igual que los Pods, la creación de un controlador RS se define mediante un archivo de manifiesto en formato YAML o JSON, y luego se utiliza el comando correspondiente para crearlo.
replicas: Número esperado de réplicas de Pod.selector: Selector de etiquetas para emparejar los Pods que controla. SoportamatchLabelsymatchExpressions.template: Plantilla de Pod utilizada para crear réplicas cuando sea necesario.minReadySeconds: Tiempo mínimo que un Pod recién creado debe estar funcionando sin fallos para ser considerado listo. El valor predeterminado es 0 segundos.
Ejemplo:
~]# cat rs-ejemplo.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-ejemplo
spec:
replicas: 2
selector:
matchLabels:
app: rs-demo
template:
metadata:
labels:
app: rs-demo
spec:
containers:
- name: miapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
~]# kubectl apply -f rs-ejemplo.yaml
~]# kubectl get replicaset -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
rs-ejemplo 2 2 2 5m20s miapp ikubernetes/myapp:v1 app=rs-demo
(3) Pods bajo el control de RS
Existen varias situaciones que pueden provocar que la cantidad de Pods difiera del valor esperado, como la eliminación accidental de un Pod, el cambio de etiquetas de un Pod, la modificación del selector de etiquetas del controlador o una falla en un nodo de trabajo. El ciclo de reconciliación de RS monitorea estas anomalías y actúa en consecuencia.
a. Falta de réplicas de Pod
Cualquier pérdida de Pods relacionados se solventa automáticamente mediante el controlador RS.
Por ejemplo, al eliminar manualmente un Pod:
~]# kubectl delete pods rs-ejemplo-c5k89
pod "rs-ejemplo-c5k89" deleted
~]# kubectl get pods -l app=rs-demo -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
rs-ejemplo-679xq 1/1 Running 0 52s 10.244.1.9 node01.ilinux.io <none>
rs-ejemplo-sxq7x 1/1 Running 0 9m56s 10.244.3.7 node03.ilinux.io <none>
</none></none>
Por ejemplo, al modificar las etiquetas de un Pod:
~]# kubectl label pods rs-ejemplo-679xq app= --overwrite
pod/rs-ejemplo-679xq labeled
~]# kubectl get pods -l app=rs-demo -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
rs-ejemplo-d9j9z 1/1 Running 0 2m1s 10.244.2.25 node02.ilinux.io <none>
rs-ejemplo-sxq7x 1/1 Running 0 17m 10.244.3.7 node03.ilinux.io <none>
</none></none>
b. Exceso de réplicas de Pod
Si la cantidad de Pods seleccionados por el selector supera el valor esperado, los sobrantes se eliminan automáticamente. Esto significa que cualquier Pod creado de forma independiente o por otro controlador, cuyas etiquetas cambien para coincidir con un controlador que ya tiene suficientes réplicas, será eliminado.
~]# kubectl label pods pod-ejemplo app=rs-demo
c. Visualización de eventos relacionados con Pods
~]# kubectl describe replicasets/rs-ejemplo
(4) Actualización del controlador ReplicaSet
Los componentes principales de RS son el selector de etiquetas, la cantidad de réplicas y la plantilla de Pod. Las actualizaciones suelen centrarse en los campos replicas y template. Modificar la plantilla de Pod no afecta a los Pod existentes, pero al eliminar los antiguos, se pueden crear nuevos basados en la nueva plantilla. Cambiar la cantidad de réplicas implica escalar la aplicación.
a. Cambio de plantilla de Pod: Actualización de aplicación
La plantilla de Pod de RS se puede modificar en cualquier momento, pero solo afecta a los nuevos Pods creados posteriormente.
~]# cat rs-ejemplo-v2.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-ejemplo
spec:
replicas: 2
selector:
matchLabels:
app: rs-demo
template:
metadata:
labels:
app: rs-demo
spec:
containers:
- name: nginx
image: ikubernetes/myapp:v2
ports:
- name: http
containerPort: 80
~]# kubectl replace -f rs-ejemplo-v2.yaml
Tras esto, se deben eliminar manualmente los Pods existentes para que el controlador cree nuevos basados en la plantilla actualizada. Sin embargo, para un control más avanzado, se recomienda usar el controlador Deployment.
b. Escalado
Modificar la propiedad replicas en la configuración de RS hace que el controlador ajuste la cantidad de Pods en tiempo real. También se puede usar el comando kubectl scale.
Ejemplo: aumentar las réplicas a 5
~]# kubectl scale replicasets rs-ejemplo --replicas=5
replicaset.extensions/rs-ejemplo scaled
~]# kubectl get replicasets rs-ejemplo
NAME DESIRED CURRENT READY AGE
rs-ejemplo 5 5 5 3h25m
Para reducir:
~]# kubectl scale replicasets rs-ejemplo --replicas=3
c. Eliminación de un ReplicaSet
Al eliminar un objeto RS con kubectl delete, también se eliminan los Pods que controla. Para evitar la eliminación en cascada, usa la opción --cascade=false.
~]# kubectl delete replicasets rs-ejemplo --cascade=false
Aunque RS es potente, en la práctica, Deployment es el controlador más utilizado.
- Controlador Deployment
Conocido como deploy, es otra implementación de controlador que se basa en ReplicaSet para proporcionar actualizaciones declarativas de Pods y RS. Ofrece funcionalidades adicionales:
- Visualización de eventos y estado: Permite ver el progreso y el estado detallado de una actualización.
- Rollback: Permite revertir a una versión anterior si se detectan problemas.
- Versionado: Cada operación sobre un Deployment se guarda en el historial para posibles rollbacks.
- Pausa y reanudación: Permite pausar y reanudar actualizaciones en cualquier momento.
- Estrategias de actualización: Soporta
Recreate(recreación completa) yRollingUpdate(actualización gradual).
(1) Creación de un Deployment
Un Deployment se construye sobre ReplicaSet e incluye campos como replicas, selector, template y minReadySeconds.
Ejemplo:
~]# cat miapp-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: miapp-deploy
spec:
replicas: 3
selector:
matchLabels:
app: miapp
template:
metadata:
labels:
app: miapp
spec:
containers:
- name: miapp
image: ikubernetes/myapp:v1
ports:
- containerPort: 80
name: http
~]# kubectl apply -f miapp-deploy.yaml --record
~]# kubectl get deployment
(2) Estrategias de actualización
Deployment soporta dos estrategias: RollingUpdate (predeterminada) y Recreate. Recreate elimina todos los Pods antiguos antes de crear los nuevos, útil cuando las versiones no son compatibles. RollingUpdate reemplaza gradualmente los Pods antiguos por nuevos, garantizando que el servicio no se interrumpa, pero requiere que la aplicación soporte ambas versiones simultáneamente.
En RollingUpdate, los Pods antiguos y nuevos se gestionan en dos ReplicaSets distintos. Se definen dos propiedades:
maxSurge: Número máximo de Pods por encima del valor esperado durante la actualización. Puede ser un número entero o un porcentaje.maxUnavailable: Número máximo de Pods no disponibles durante la actualización. Puede ser un número entero o un porcentaje. El valor predeterminado es 1.
Ambos valores no pueden ser 0 al mismo tiempo. La propiedad minReadySeconds controla la velocidad de la actualización, esperando un tiempo antes de iniciar el siguiente reemplazo.
(3) Actualización de un Deployment
Modificar la plantilla de Pod en un Deployment desencadena una actualización. Se recomienda usar kubectl apply, patch o set image.
Ejemplo: configurar el tiempo de espera y actualizar la imagen
~]# kubectl patch deployments miapp-deploy -p '{"spec": {"minReadySeconds": 5}}'
~]# kubectl set image deployments miapp-deploy miapp=ikubernetes/myapp:v2
Ver el progreso:
~]# kubectl rollout status deployment miapp-deploy
~]# kubectl get deployments miapp-deploy --watch
(4) Lanzamiento Canary
Deployment permite pausar una actualización para realizar un lanzamiento Canary. Se configura maxSurge y maxUnavailable, se inicia la actualización y se pausa inmediatamente después de crear los primeros Pods nuevos.
Ejemplo:
~]# kubectl patch deployments miapp-deploy -p '{"spec":{"strategy":{"rollingUpdate": {"maxSurge": 1, "maxUnavailable": 0} }}}'
~]# kubectl set image deployments miapp-deploy miapp=ikubernetes/myapp:v3 && kubectl rollout pause deployment miapp-deploy
Después de verificar, se reanuda la actualización:
~]# kubectl rollout resume deployments miapp-deploy
(5) Rollback de un Deployment
Para revertir una actualización, se usa kubectl rollout undo.
~]# kubectl rollout undo deployments miapp-deploy
~]# kubectl rollout history deployments miapp-deploy
~]# kubectl rollout undo deployments miapp-deploy --to-revision=2
El rollback se registra como una nueva actualización en el historial.
(6) Escalado
Modificar spec.replicas en un Deployment escala la aplicación. Se puede hacer mediante el archivo de configuración, kubectl edit o kubectl scale.
- Controlador DaemonSet
DaemonSet ejecuta una réplica de un Pod en todos los nodos del clúster. Los nuevos nodos que se unan al clúster crean automáticamente el Pod correspondiente, y al eliminar un nodo, el Pod se elimina. Se puede restringir a nodos con etiquetas específicas. Es útil para tareas a nivel de sistema, como:
- Ejecutar demonios de almacenamiento (glusterfs, ceph).
- Ejecutar agentes de recolección de logs (fluentd, logstash).
- Ejecutar agentes de monitoreo (Prometheus Node Exporter, collectd).
(1) Creación de un DaemonSet
Incluye selector, template y minReadySeconds, pero no replicas.
Ejemplo:
~]# cat filebeat-ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat-ds
labels:
app: filebeat
spec:
selector:
matchLabels:
app: filebeat
template:
metadata:
labels:
app: filebeat
spec:
containers:
- name: filebeat
image: ikubernetes/filebeat:5.6.5-alpine
env:
- name: REDIS_HOST
value: db.linux.io:6379
- name: LOG_LEVEL
value: info
~]# kubectl apply -f filebeat-ds.yaml
daemonset.apps/filebeat-ds created
(2) Actualización de un DaemonSet
Soporta RollingUpdate (predeterminado) y OnDelete. RollingUpdate actualiza los Pods uno por uno, usando maxUnavailable para controlar la disponibilidad.
- Controlador Job
Job gestiona Pods que ejecutan tareas únicas. Una vez que el proceso en el contenedor finaliza correctamente, el Pod pasa al estado Completed. Si falla, se puede configurar para reiniciar o no. Si el nodo falla, el Pod se reprograma.
Existen dos tipos de Job:
- Serial: Ejecuta tareas de forma secuencial hasta alcanzar el número deseado de finalizaciones.
- Paralelo: Permite ejecutar múltiples tareas en paralelo.
(1) Creación de un Job
El campo obligatorio es template. Es importante configurar restartPolicy como Never o OnFailure.
Ejemplo:
~]# cat job-ejemplo.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: job-ejemplo
spec:
template:
spec:
containers:
- name: mitrabajo
image: alpine
command: ["/bin/sh", "-c", "sleep 120"]
restartPolicy: Never
~]# kubectl apply -f job-ejemplo.yaml
~]# kubectl get jobs job-ejemplo
(2) Job Paralelo
Se configura con completions (número total de tareas) y parallelism (número de tareas concurrentes).
Ejemplo:
apiVersion: batch/v1
kind: Job
metadata:
name: job-multi
spec:
completions: 5
parallelism: 2
backoffLimit: 5
activeDeadlineSeconds: 100
template:
spec:
containers:
- name: mitrabajo
image: alpine
command: ["/bin/sh", "-c", "sleep 120"]
restartPolicy: OnFailure
(3) Escalado de un Job
Se puede cambiar la concurrencia con kubectl scale.
~]# kubectl scale jobs job-multi --replicas=2
(4) Eliminación de un Job
Los Jobs completados se pueden eliminar manualmente. Para controlar fallos, se usan activeDeadlineSeconds y backoffLimit.
- Controlador CronJob
CronJob gestiona la ejecución periódica de Jobs, similar a crontab en Linux.
(1) Creación de un CronJob
Campos principales:
jobTemplate: Plantilla del Job a ejecutar.schedule: Horario en formato cron.concurrencyPolicy: Política de concurrencia (Allow,Forbid,Replace).failedJobHistoryLimitysuccessfulJobHistoryLimit: Límite de historial.startingDeadlineSeconds: Tiempo de espera para iniciar un Job retrasado.
Ejemplo:
~]# cat cronjob-ejemplo.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: cronjob-ejemplo
labels:
app: micronjob
spec:
schedule: "*/2 * * * *"
jobTemplate:
metadata:
labels:
app: micronjob-jobs
spec:
parallelism: 2
template:
spec:
containers:
- name: mitrabajo
image: alpine
command:
- /bin/sh
- -c
- date; echo Hello from k8s cluster; sleep 10
restartPolicy: OnFailure
~]# kubectl apply -f cronjob-ejemplo
~]# kubectl get cronjobs cronjob-ejemplo
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob-ejemplo */2 * * * * False 0 <none> 22s
</none>
(2) Mecanismo de control de CronJob
CronJob gestiona Jobs. Si un Job anterior no ha finalizado cuando el siguiente debe comenzar, la política de concurrencia determina el comportamiento. Allow permite múltiples Jobs simultáneos, Forbid los evita y Replace detiene el anterior y comienza el nuevo.