Aplicaciones Stateful en Kubernetes – Statefulset
En esta entrada vamos a tratar sobre aplicaciones Stateful en Kubernetes – Statefulset, el cual es un tipo de recurso que nos ofrece Kubernetes. Statefulset es un recurso que controla y gestiona en kubernetes uno o más Pods, pero entonces por qué no usar un Deployment te estarás preguntando?, entonces antes de continuar es mejor que veas las diferencias entre Stateful y Stateless en una arquitectura.
Diferencia entre Statefulset y Deployment en Kubernetes
Para entender por qué aplicar un objeto de tipo Statefulset en lugar de Deployment, antes de nada necesitamos conocer las diferencias básicas entre Stateless y Stateful.
Una aplicación stateless es aquella que no tiene estado, a la que no le importa la red en la que se esta ejecutando, o que no necesita un almacenamiento permanente, su información puede ser efímera y estar contenida en su Pod. Un ejemplo de esto puede ser un Tomcat, o un Apache o un Nginx. Este tipo es el más usado dentro de Kubernetes.
Por otro lado, tenemos todas aquellas aplicaciones stateful, que son las que tienen estado, que nos importa conocer la red o la instancia en la que se ejecuta o se está ejecutando, por lo general este tipo de aplicaciones suelen corresponder a Bases de Datos. Algún ejemplo son PostgreSql, MongoDB, Elasticsearch, kafka, etc… .
Vamos a intentar explicar una aplicación Stateful con un ejemplo con PostgreSQL funcionando en alta disponibilidad (HA). Imágina que tenemos ejecutando un único master (escritura) con una o más replicas (lecturas). Como cada nodo que desplegamos tienen que estar identificados para saber quién es master y cuál es réplica y conocer su estado. De esta manera sabemos que nodo escribe y cuál lee además si el master se cae tenemos que elegir su sucesor. Por lo que, necesitamos que se desplieguen de manera Stateful, por lo que utilizaremos un StatefulSet para el despliegue.
Por lo que el motivo para elegir un StatefulSet, en general, en lugar de un deployment, suele ser que necesitamos conocer el Pod, al cual se le asigna una identidad única, y con un Deployment pueden ser intercambiables, y además poder otorgar persistencia a la aplicación.
¿Cómo funciona un Statefulset en Kubernetes?
Cuando decidimos hacer uso del tipo de objeto Statefulset en kubernetes es debido, por lo general, a que los pods que desplegemos tienen que ser únicos y estar identificados. Por lo que cuando creamos este tipo de objeto de manera automática se crearán Pods que se encontrarán identificados.
Cuando trabajamos con Kubernetes se suele crear un servicio, que podríamos definirlo como una capa de abstración para nuestros Pods, se llama o se realiza una petición al servicio y este redirecciona a cualquier Pod. Pero cuando trabajamos con un tipo de Objeto Statefulset el Pod al que se redirija la llamada es importante, por lo que este hecho implica a Headless Service. El cuál no tiene un clúster de IP’s asignadas a unos Pod’s, sino que tiene varios endpoints con unos registros de DNS, y cada uno a un Pod diferentes.
Por lo que detrás de un objeto Statefulset de Kubernetes, la capa servicio que tiene asociada, tendrá una serie de endpoints para atacar directamente al Pod que se requiera.
Cómo desplegar una aplicación Stateful en Kubernetes con un objeto Statefulset?
A continuación vamos a hacer la definición de un objeto Statefulset, para ello vamos a realizar el ejemplo con unas imágenes de cassandra.
Desplegar cassandra en HA en kubernetes
Lo primero que vamos a hacer es definir un Headless Service, que tal y como hemos comentado antes no irá un clusterIp asociado:
apiVersion: v1 kind: Service metadata: labels: app: cassandra name: cassandra spec: clusterIP: None ports: - port: 9042 selector: app: cassandra
y una vez creado el fichero lo ejecutamos de la siguiente manera:
kubectl apply -f cassandra-service.yml
A continuación creamos el objeto Statefulset con el que vamos a crear 2 Pods de cassandra, ya que establecemos replicas 2.
apiVersion: apps/v1 kind: StatefulSet metadata: name: cassandra labels: app: cassandra spec: serviceName: cassandra replicas: 2 selector: matchLabels: app: cassandra template: metadata: labels: app: cassandra spec: terminationGracePeriodSeconds: 1800 containers: - name: cassandra image: gcr.io/google-samples/cassandra:v13 imagePullPolicy: Always ports: - containerPort: 7000 name: intra-node - containerPort: 7001 name: tls-intra-node - containerPort: 7199 name: jmx - containerPort: 9042 name: cql resources: limits: cpu: "500m" memory: 1Gi requests: cpu: "500m" memory: 1Gi securityContext: capabilities: add: - IPC_LOCK lifecycle: preStop: exec: command: - /bin/sh - -c - nodetool drain env: - name: MAX_HEAP_SIZE value: 512M - name: HEAP_NEWSIZE value: 100M - name: CASSANDRA_SEEDS value: "cassandra-0.cassandra.default.svc.cluster.local" - name: CASSANDRA_CLUSTER_NAME value: "K8Demo" - name: CASSANDRA_DC value: "DC1-K8Demo" - name: CASSANDRA_RACK value: "Rack1-K8Demo" - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP readinessProbe: exec: command: - /bin/bash - -c - /ready-probe.sh initialDelaySeconds: 15 timeoutSeconds: 5 volumeMounts: - name: cassandra-data mountPath: /cassandra_data volumeClaimTemplates: - metadata: name: cassandra-data spec: accessModes: [ "ReadWriteOnce" ] storageClassName: fast resources: requests: storage: 1Gi
y a continuación vamos a crear el StorageClass. En esta caso vamos a específicar que tipo de almacenamiento necesitamos y nos proporciona nuestro cloud. Como en nuestro caso usamos minikube, se nos proporciona k8s.io/minikube-hostpath y el tip de parámetro añadimos pd-ssd aunque también puede ser standard.
Si quieres ver el tipo de StorageClass que tienes puedes ejecutar por línea de comando kubectl get sc.
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: fast provisioner: k8s.io/minikube-hostpath parameters: type: pd-ssd
A continuación vamos a ver como se han asignado numéricamente los Pods mediante el comando describe:
Podemos ver como se han asignado los pods con cassandra-0 y cassandra-1.
Una vez finalizado podemos realizar pruebas con Cassandra mediante una aplicación Spring Boot que explícamos en un artículo pasado.
Conclusión
En esta entrada Aplicaciones Stateful en Kubernetes – Statefulset, hemos visto como y por qué crear una aplicación statefulset en Kubernetes.
Vamos a hacer un pequeño resumen sobre lo visto en el artículo:
- Un objeto StatefulSet es un tipo de objeto dentro de Kubernetes que se encarga de gestionar los Pods, pero que esta pensado para las aplicaciones stateful.
- Las aplicaciones stateful en kubernetes requieren Pods con una identidad única.
- Para poder trabajar y que nuestras aplicaciones stateful funcionen correctamente en Kubernetes, necesitamos un Headless Service. La cual expone varios endpoints.
- Un objeto StatefulSet necesita almacenamiento, por lo que usaremos los objetos de kubernetes que nos lo proporcionan.
Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com y te ayudaremos encantados!
No te olvides de seguirnos en nuestras redes sociales Facebook o Twitter para estar actualizado.
1 pensamiento sobre “Aplicaciones Stateful en Kubernetes – Statefulset”