¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
Conoce nuestra marca.¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
Conoce nuestra marca.dev
Fernando Cabadas 18/04/2022 Cargando comentarios…
Los contenedores llevan años despuntando en el desarrollo de aplicaciones. No es ningún secreto que Kubernetes se ha convertido en una gran plataforma para desarrollar las mejores aplicaciones. Hace un tiempo ya explicamos por qué todas las empresas apostaban por ellos y hoy ya nadie duda de su capacidad para aumentar la portabilidad y la agilidad al desplegar y gestionar aplicaciones.
Ya conocemos cuáles son sus características y las distintas plataformas según las necesidades. Ahora, en este post nos adentramos en el almacenamiento y persistencia de datos, pero antes de empezar haremos una pequeña introducción sobre Kubernetes.
Una definición muy simple sería decir que Kubernetes es un orquestador de contenedores, es decir, Kubernetes (K8S) se define como un sistema open-source para la automatización de despliegues, el escalado y la gestión de aplicaciones contenerizadas.
Esta plataforma ofrece un entorno de administración centrado en contenedores y orquesta la infraestructura de cómputo, redes y almacenamiento para que las cargas de trabajo de los usuarios no tengan que hacerlo. Estos son algunos conceptos importantes:
Hemos contado en la introducción la definición de Pod, pero lo que no hemos contado es que los Pods por defecto son efímeros y cuando se destruyen se pierde toda la información que contenían. Para poder conservar esa información tenemos que hablar de cómo persistir esos datos.
En Kubernetes un volumen se puede considerar como un directorio al que pueden acceder los contenedores de un pod. Tenemos diferentes tipos de volúmenes y ese tipo define cómo se crea el volumen y su contenido.
Los volúmenes no se limitan a ningún contenedor. Soportan cualquiera o todos los contenedores desplegados dentro del pod de Kubernetes.
Una ventaja clave del volumen en Kubernetes es que admite diferentes tipos de almacenamiento en los que el pod puede utilizar varios de ellos al mismo tiempo.
Existen muchos tipos de volúmenes en Kubernetes, entre ellos: awselasticblockstore, azuredisk, azurefile, cephfs, cinder, configmap, downwardapi, emptydir, fc, flocker, gcepersistentdisk, gitrepo, glusterfs, hostpath, iscsi, local, nfs, persistentvolumeclaim, portworxvolume, projected, quobyte, rbd, secret, vspherevolume.
A continuación ponemos un ejemplo del tipo de volumen emptyDir.
Un volumen emptyDir se crea por primera vez cuando se asigna un Pod a un nodo, y existe mientras ese Pod se esté ejecutando en ese nodo. Como su nombre indica, el volumen emptyDir está inicialmente vacío. Todos los contenedores del Pod pueden leer y escribir los mismos archivos en el volumen emptyDir, aunque ese volumen puede ser montado en la misma o diferente ruta en cada contenedor. Cuando un Pod es eliminado de un nodo por cualquier razón, los datos en el emptyDir son borrados permanentemente.
Este es el contenido del fichero yml para crear un pod con un volumen:
apiVersion: v1
kind: Pod
metadata:
name: mivolumepod
namespace: paradigma
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /tmp/nginx
name: k8svolume
- name: ubuntu
image: ubuntu:20.04
command: ['sh', '-c', 'while true; do sleep 30; done;']
volumeMounts:
- mountPath: /tmp/ubuntu
name: k8svolume
volumes:
- name: k8svolume
emptyDir: {}
Podemos ver cómo existe un volumen llamado k8svolume indicado en la etiqueta volumes y que es de tipo emptyDir:
volumes:
- name: k8svolume
emptyDir: {}
También vemos cómo asignar a cada contenedor el volumen e indicar la ruta con el contenido que queremos almacenar en el volumen.
En el contenedor nginx almacenamos la ruta /tmp/nginx:
volumeMounts:
- mountPath: /tmp/nginx
name: k8svolume
En el contenedor ubuntu almacenamos la ruta /tmp/ubuntu:
volumeMounts:
- mountPath: /tmp/ubuntu
name: k8svolume
Creamos el pod a partir del fichero .yml que hemos creado anteriormente con el siguiente comando.
kubectl apply -f volumePod.yml
Para ver el resultado del Pod que hemos creado ejecutamos el siguiente comando:
kubectl get pods -n paradigma
Comprobamos que no existen datos en ninguna de las carpetas de cada contenedor listando las carpetas.
kubectl exec -it mivolumepod -c ubuntu -n paradigma -- ls -l /tmp/ubuntu
kubectl exec -it mivolumepod -c nginx -n paradigma -- ls -l /tmp/nginx
Creamos un fichero en alguna de las carpetas, podemos hacerlo en cualquiera de los contenedores. Y, en este caso, lo haremos sobre el contenedor de ubuntu:
kubectl exec -it mivolumepod -c ubuntu -n paradigma -- touch /tmp/ubuntu/test.json
Por último, listamos las carpetas en ambos contenedores y vemos que el fichero que hemos creado en uno de los contenedores es accesible desde ambos.
kubectl exec -it mivolumepod -c ubuntu -n paradigma -- ls -l /tmp/ubuntu
kubectl exec -it mivolumepod -c nginx -n paradigma -- ls -l /tmp/nginx
De esta manera hemos visto cómo compartir información entre contenedores dentro de un mismo Pod.
Ya os hemos contado que cuando un Pod es eliminado de un nodo por cualquier razón, los datos del volumen son borrados permanentemente. Para evitar que los datos se pierdan, Kubernetes nos permite implementar el almacenamiento persistente utilizando PersistentVolume y PersistentVolumeClaims.
Los PVCs se vincularán automáticamente a un PV que tenga StorageClass
y accessModes compatibles.
Si creamos un PVC con un storageClass:fast y un accessModes:RWO va a
buscar un PV con esas características y que esté disponible y automáticamente
se enlaza con él y es el PVC el que configuraremos al crear el YML del pod.
Vamos a explicar las etiquetas importantes del PV:
A continuación el contenido del fichero yml para crear un PersistentVolume.
apiVersion: v1
kind: PersistentVolume
metadata:
name: mipv
spec:
storageClassName: local-storage
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
Creamos el PersistentVolume a partir del fichero .yml que hemos creado anteriormente con el siguiente comando.
kubectl apply -f persistentVolume.yml
Para ver el resultado del PersistentVolume ejecutamos el siguiente comando.
kubectl get pv
Aunque vemos cómo se ha creado el volumen y el Status es Available, todavía no está asociado.
Para asociarlo a un Pod necesitamos un PVC (PersistentVolumeClaim) que os contamos a continuación.
¿Cuáles son las labels importantes del PVC?
A continuación el contenido del fichero yml para crear un PersistentVolumeClaim.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mipvc
namespace: paradigma
spec:
storageClassName: local-storage
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 512Mi
Como comentamos anteriormente, al crear el PVC si queremos que se enlace automáticamente al PV tiene que tener definido el mismo storageClassName y el mismo accessMode. En este caso lo hemos definido así: el PersistentVolumeClaim a partir del fichero .yml que hemos creado anteriormente con el siguiente comando.
kubectl apply -f persistentVolumeClaim.yml
Si quieres el resultado del PersistentVolumeClaim:
kubectl get pvc -n paradigma
Aquí ya visualizamos cómo se ha creado el PVC y se ha enlazado con el volume mipv. También podemos ver de nuevo el volumen para ver que también nos indica el enlace.
kubectl get pv
Observamos como en la columna CLAIM nos muestra el PVC al que se ha enlazado.
Por último, nos quedaría asignar este PV y PVC a un pod. Este es el contenido del fichero yml para crear un Pod asignándole el PVC que hemos creado:
apiVersion: v1
kind: Pod
metadata:
name: mipvcpod
namespace: paradigma
spec:
containers:
- name: ubuntu
image: ubuntu:18.04
command: ["/bin/sh", "-c", "while true; do sleep 3600; done"]
volumeMounts:
- mountPath: "/mnt/storage"
name: mivolume
volumes:
- name: mivolume
persistentVolumeClaim:
claimName: mipvc
Se añade la siguiente información:
volumes:
- name: mivolume
persistentVolumeClaim:
claimName: mipvc
En ella indicamos que el volumen viene asociado a un PersistentVolumeClaim.
Luego, se crea el Pod a partir del fichero .yml (que tenemos de antes) con el siguiente comando:
kubectl apply -f persistentVolumePod.yml
Si queremos ver el resultado, ejecutamos el siguiente comando:
kubectl get pods -n paradigma
Y para finalizar, podemos comprobar que se ha asignado correctamente el PV al Pod ejecutamos el siguiente comando:
kubectl describe pod mipvcpod -n paradigma
En el apartado de Volumes observaremos que se ha asignado correctamente el Volumen. Al ser un PersistentVolume si eliminamos el Pod, el PV permanece y puede ser utilizado por cualquier Pod utilizando el PVC que le corresponde, en este caso mipvc.
Como hemos visto, los Pods son efímeros y al destruirlos pierden toda la información que tenían, por eso es importante poder almacenar y conservar esa información gracias a la persistencia de datos.
En este post hemos conocido el paso a paso para realizar el almacenamiento y persistencia de datos configurando Pods.
El ciclo de vida del Persistent Volume (PV) es independiente de cualquier contenedor particular en el cluster. Las Persistent Volume Claim (PVC) son una petición realizada por un usuario o aplicación de contenedor para un tipo específico de almacenamiento. Al crear un PV, la documentación de Kubernetes recomienda lo siguiente:
El almacenamiento persistente de Kubernetes ofrece a las aplicaciones una forma conveniente de solicitar y consumir recursos de almacenamiento. PVC y PV son equivalentes a las interfaces e implementaciones orientadas a objetos. El Pod creado por el usuario declara el PVC, y Kubernetes encontrará un PV con el que emparejarlo. Si no hay un PV con el que emparejarse, va a la StorageClass correspondiente, le ayuda a crear un PV, y luego completa la unión con el PVC. El PV recién creado necesita crear un disco remoto para el host a través del nodo maestro vinculado y luego montar el disco remoto vinculado al directorio del host a través del componente kubelet de cada nodo.
Los PVs son ideales si tiene datos que tienen que ser compartidos entre Pods o que deben sobrevivir a los reinicios. Los PVs pueden ser definidos y enlazados a un Pod específico.
¿Te has quedado con alguna duda? ¡Déjanos un comentario!
Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.
Cuéntanos qué te parece.