Implementando en Kubernetes: Deployment vs StatefulSet vs DaemonSet
Kubernetes (K8s) es un orquestador de contenedores de código abierto orientado a automatizar la implementación, escalado y administración de aplicaciones en contenedores Docker o CRI-O.
Kubernetes proporciona un recurso base llamado Pod (cápsula). Es la unidad más pequeña para Kubernetes, que en realidad es un conjunto de contenedores y volúmenes con características similares.
Un pod puede tener uno o más contenedores y puede pasarles diferentes configuraciones como variables de entorno, montar volúmenes, realizar pruebas de estado, etc.
Para más información revisar Pod
Ésta publicación muestra tres formas diferentes de implementar una aplicación en pods de Kubernetes. Cada una con sus características, ventajas y desventajas.
- Deployment
- StatefulSets
- DaemonSets
“Hay otro, el ReplicationController pero Kubernetes ahora apunta a Deployment que automáticamente crea ReplicaSets”
Para conocer las diferencias detalladas entre los 3 recursos, se implementará una aplicación contador, que guarda e incrementa el número desde un archivo de contador como 1,2,3,4 … Estoy usando el archivo contador en un volumen persistente (Persistent Volume — PV) para detallar las diferencias entre Deployment, StatefulSets y DaemonSets. Los YAML se pueden encontrar en el link de la aplicación contador.
Deployment (Stateless)
Es el recurso más fácil y más utilizado para implementar su aplicación. Es un controlador de Kubernetes que hace coincidir el estado actual de su clúster (Current State) con el estado deseado mencionado en el YAML (Desired State).
Si creamos una Deployment con 1 réplica, primero se crea un ReplicaSet que compara el estado deseado con el estado actual, si el DESIRED es 1 y el CURRENT es 0, se crea un POD para igualar ambos valores. (deseado y actual)
Deployment > ReplicaSet > Pod | con más detalle:
Si creamos un deployment con el nombre counter, éste creará un ReplicaSet con el nombre counter-<replica-set-id>, que creará a su vez un pod con el nombre counter-<pod-id>.
alias k=kubectl
Los Deployment generalmente se usan para aplicaciones volátiles (stateless). Sin embargo, se puede guardar el estado del deployment adjuntando un Volumen Persistente (PV) y hacerlo persistente (stateful), cabe destacar que todos los pods de un deployment compartirán el mismo Volumen y los datos en todos ellos serán los mismos.
pv = PersistentVolume (Volumen Persistente)
pvc = PersistentVolumeClaim (Solicitud de Volumen Persistente)
Para implementar la aplicación contador usando un deployment, puedes copiar el archivo YAML a continuación y guardándolo en un archivo llamado deployment.yaml (o cualquier otro nombre) y luego aplicarlo:
kubectl apply -f deployment.yaml
Si despliega el deployment y vemos los logs del pod, veremos el contador en acción 1,2,3,…
Los logs del primer pod (k como alias de kubectl)
Ahora, se escala el deployment a 3 pods, ejecutando
kubectl scale deployment counter — replicas=3
Puedes ver dos nuevos pod recién creados, si revisamos los logs de un pod nuevo, sus conteo no comenzarán desde 1 sino que comenzará desde el último número del primer pod.
Si revisamos los logs (kubectl logs counter545d84d64bXXX), están comenzando desde 73, significa que el pod anterior había escrito hasta 72 en el archivo y ambos comparten el mismo volumen y los datos son consistentes en todos los pods de un deployment . Además, solo se creará un PVC que compartirán todos pods del deployment.
Las deployments, como se discutió, crean un ReplicaSet que luego crea un Pod, por lo que cada vez que actualiza el deployment utilizando la estrategia RollingUpdate (predeterminada), se crea un nuevo ReplicaSet y el deployment mueve los Pods del ReplicaSet anterior al nuevo a una velocidad controlada.
La actualización continua (RollingUpdate) significa que el ReplicaSet anterior no se escala a 0 a menos que el nuevo ReplicaSet esté en funcionamiento y garantice un tiempo de actividad del 100%. Si se produce un error durante la actualización, el nuevo ReplicaSet nunca estará en estado READY, por lo que el viejo ReplicaSet no se eliminará, nuevamente asegurando un tiempo de actividad del 100% en caso de una actualización fallida.
En deployments, se puede retroceder manualmente a un ReplicaSet anterior, si es necesario en caso de que su nueva configuración no funcione como se esperaba.
StatefulSets (Stateful)
StatefulSet (estable-GA en v1.9 K8S) es un recurso de Kubernetes utilizado para gestionar aplicaciones persistentes (stateful). Gestiona el despliegue y la ampliación de un conjunto de Pods, y proporciona garantía sobre el orden y la exclusividad de estos Pods.
StatefulSet también es un controlador, pero a diferencia del deployment, no crea ReplicaSet sino que crea el Pod directamente con una nomenclatura única. Por ejemplo, si creamos un StatefulSet con el nombre counter, se creará un pod con el nombre counter-0, y para múltiples réplicas de un StatefulSet, sus nombres se incrementarán como counter-0, counter-1, counter-2, counter-3, etc.
Cada réplica del pod tendrá su propio volumen, y cada uno creará su propio PVC (PersistentVolumeClaim). Por lo tanto, un conjunto StatefulSet con 3 réplicas creará 3 pods, cada uno con su propio volumen, por lo que da un total de 3 PVC.
Para implementar la aplicación counter utilizando un conjunto con estado, utilizaremos el siguiente manifiesto. puede implementarlo copiando el manifiesto a continuación y guardándolo en un archivo, por ejemplo, statefulset.yaml, y luego aplicando mediante
kubectl apply -f statefulset.yaml
Si implementamos un StatefulSet y revisamos los logs del Pod, vemos el conteo como 1,2,3,4..
Los logs del primer pod. El nombre del pod es counter-0.
Aquí, puede ver que los registros comienzan desde 1. Ahora cambiamos el StatefulSet a 3 réplicas:
kubectl scale statefulsets counter — replicas=3
Primero se creará un nuevo pod counter-1, y una vez que el pod está listo (READY), entonces se empieza a crear el otro pod counter-2.
Los nuevos pods tendrán su propio Volumen PVC y si vemos los logs, el conteo comenzará nuevamente desde 1 para cada pod, a diferencia del deployment como vimos anteriormente.
Los logs del segundo pod. Su el nombre es counter-1.
Aquí, los logs vuelven a comenzar desde 1, ya que este pod tiene su propio Volumen, por lo que no lee el archivo del primer pod. Y si vemos los PVC, serán 3 PVC creadas ya que habíamos escalado las réplicas a 3.
Los StatefulSets no crean ReplicaSet ni nada por el estilo, por lo que no puede revertir un StatefulSet a una versión anterior (Rollback). Solo se puede eliminar, ampliar o reducir.
Si actualizamos un StatefulSet, también realiza un RollingUpdate, es decir, un pod de réplica se eliminará y el pod actualizado aparecerá, luego el próximo pod de réplica se reducirá de la misma manera, por ejemplo:
Si aplicaramos un nuevo StatefulSet éste se implementará tipo cascada:
kubectl apply -f new_statefulset.yaml #example
El counter-2 terminará y una vez que termine por completo, entonces se recrea el counter-2, si se recrea bien el counter-2, luego termina también el counter-1 y es recreado, y así hasta el counter-0.
Si se produce un error durante el escalado, solo el contador 2 estará inactivo, el counter-1 y el counter-0 seguirán activos, ejecutando en la versión estable anterior.
DaemonSet
Un DaemonSet es un controlador que garantiza que el pod se ejecute en todos los nodos del clúster. Si se agrega / elimina un nodo del clúster, DaemonSet agrega / elimina automáticamente el pod respectivo.
Algunos casos de uso típicos de un DaemonSet es ejecutar aplicaciones de nivel de clúster :
- Monitoreo: Para supervisar todos los nodos de un clúster deberás ejecutar un monitor en todos los nodos del clúster del tipo NodeExporter.
- Daemon para colección de logs: recopilación de logs de todos los nodos, por lo que necesitaría un DaemonSet de recopilador de logs como Fluentd para exportar logs de todos sus nodos.
Sin embargo, Daemonset no se ejecuta automáticamente en los nodos que tienen una mancha (Taint), por ejemplo, Master. Deberá especificar que es tolerante en el pod.
Los taints son una forma de decirle a los nodos que repelen a ciertos pods, es decir, no se asignan pod en este nodo a menos que el pod lo tolere. El nodo Master por defecto no tolera pods, para que el demonio se ejecute en todos los nodos (incluyendo el Master), se tiene que especificar ésta tolerancia en el POD
Taint y Tolerance es un tema aparte
Para implementar la aplicación contador usando un DaemonSet, usaremos el siguiente YAML. Se puede implementar copiando el manifiesto a continuación y guardándolo en un archivo, por ejemplo, daemonset.yaml, y luego aplicandolo
kubectl apply -f daemonset.yaml
Cuando implementamos el daemonset, creará pods iguales al número de nodos. En términos de volúmenes, se comportará igual que las deployment, es decir, todos los pods compartirán el mismo volumen persistente y pvc.
Estos son los logs de un grupo de DaemonSet, podemos ver que el conteo no está en orden, pasa del 16 al 25, y del 26 al 30 lo que significa que todos los grupos comparten el mismo Volumen. Además, solo se creará un PVC que compartirán todos los pods.
Cuando se actualiza un DaemonSet, también se hace mediante un RollingUpdate, es decir, un pod(v1) se desactivará y otro pod(v2) actualizado se activará, luego el próximo pod réplica se recreará, por ejemplo, si cambio la imagen del DaemonSet a una anterior, se recreará un pod, aparecer con la nueva imagen, sólo entonces el próximo pod se actualizará y así sucesivamente.
Si se produce un error durante la actualización, un sólo pod estará inactivo, todos los demás pod seguirán activos, ejecutándose en la versión estable anterior.
A diferencia del deployment, no puede revertir su DaemonSet a una versión anterior.
Hasta aquí llegamos, estos son los principales recursos para implementar sus aplicaciones (contenedores) en Kubernetes.
FUENTE: https://medium.com/stakater/k8s-deployments-vs-statefulsets-vs-daemonsets-60582f0c62d4