En Kubernetes, los volúmenes (Volumes) son una forma de proporcionar almacenamiento persistente y compartido a los Pods y contenedores.
👉 Por defecto, los contenedores usan un sistema de archivos efímero: cuando el contenedor se reinicia o el Pod se destruye, los datos se pierden.
- Para resolver esto, Kubernetes introduce los volúmenes, que permiten:
- Persistencia de datos más allá de la vida de un contenedor.
- Compartir datos entre varios contenedores de un mismo Pod.
📂 Tipos de volúmenes más comunes
emptyDir
- Un directorio vacío que se crea cuando el Pod inicia.
- Se borra cuando el Pod muere.
- Útil para almacenamiento temporal o intercambio de archivos entre contenedores en un mismo Pod.
hostPath
- Monta un directorio del nodo host dentro del contenedor.
- Útil para acceder a logs del nodo o sockets del sistema.
- Poco recomendado en producción por dependencia con el nodo.
configMap / secret
-
Permite montar configuraciones o credenciales como archivos en el contenedor.
nfs
-
Conecta el Pod a un servidor NFS externo para compartir datos entre múltiples Pods.
persistentVolumeClaim (PVC)
- Es la forma estándar de Kubernetes para pedir almacenamiento persistente.
- Se asocia a un PersistentVolume (PV) que puede ser provisto por discos locales, NFS o nubes (EBS en AWS, PD en GCP, AzureDisk, etc.).
Ejemplo de volumenes
Volumen efímero compartido en el mismo Pod (No recomendado)
Para este ejemplo trabajaremos con el volumen mas simple que es emptyDir
apiVersion: v1
kind: Pod
metadata:
name: pod-con-dos-contenedores
spec:
containers:
- name: escritor
image: busybox
command: ["sh", "-c", "echo 'Hola desde el contenedor 1' > /datos/mensaje.txt && sleep 3600"]
volumeMounts:
- name: volumen-compartido
mountPath: /datos
- name: lector
image: busybox
command: ["sh", "-c", "cat /datos/mensaje.txt && sleep 3600"]
volumeMounts:
- name: volumen-compartido
mountPath: /datos
volumes:
- name: volumen-compartido
emptyDir: {}
🔎 Aquí:
- El contenedor escritor guarda un archivo en
/datos/mensaje.txt
. - El contenedor lector lo lee desde el mismo volumen
emptyDir
. - Como ambos están en el mismo Pod, sí pueden compartir el volumen efímero.
Ejecutamos
kubectl apply -f pod-volumen.yaml
kubectl get pods
Respuesta
NAME READY STATUS RESTARTS AGE
pod-con-dos-contenedores 2/2 Running 0 10s
Entrar al contenedor lector
kubectl exec -it pod-con-dos-contenedores -c lector -- sh
- -c lector → especifica el contenedor llamado lector.
- Ahora tendrás una terminal dentro del contenedor lector.
Dentro del contenedor lector ejecutamos
cat /datos/mensaje.txt
Respuesta: Hola desde el contenedor 1
Volumen hostPath
Un volumen hostPath en Kubernetes monta un directorio o archivo del nodo host dentro de un contenedor.
👉 Esto significa que lo que guardes en el contenedor queda físicamente en el nodo, y otros Pods que usen el mismo hostPath pueden acceder a esos datos.
⚠️ Importante antes de usar hostPath
- Es útil en pruebas o entornos de desarrollo.
- No es recomendado en producción, porque acopla tu Pod a un nodo específico.
- Si el Pod se mueve a otro nodo, no encontrará esos datos.
Procedemos a crear el archivo pod-con-hostpath
apiVersion: v1
kind: Pod
metadata:
name: pod-con-hostpath
spec:
containers:
- name: escritor
image: busybox
command: ["sh", "-c", "echo 'Hola desde hostPath' > /datos/mensaje.txt && sleep 3600"]
volumeMounts:
- name: volumen-host
mountPath: /datos
volumes:
- name: volumen-host
hostPath:
path: /mnt/data # Ruta en el nodo
type: DirectoryOrCreate # Si no existe, Kubernetes la crea
🔎 Qué hace este Pod
- Monta el directorio /mnt/data del nodo en /datos dentro del contenedor.
- Escribe un archivo /datos/mensaje.txt (que en realidad será /mnt/data/mensaje.txt en el nodo).
- Si otro Pod monta el mismo hostPath, podrá leer el archivo.
Luego procedemos a crear pod-lector-hostpath
apiVersion: v1
kind: Pod
metadata:
name: pod-lector-hostpath
spec:
containers:
- name: lector
image: busybox
command: ["sh", "-c", "cat /datos/mensaje.txt && sleep 3600"]
volumeMounts:
- name: volumen-host
mountPath: /datos
volumes:
- name: volumen-host
hostPath:
path: /mnt/data
type: Directory
Luego procedemos a crear
kubectl apply -f pod-con-hostpath.yaml
kubectl apply -f pod-lector-hostpath.yaml
Entra al Pod lector y verifica el archivo:
kubectl exec -it pod-lector-hostpath -- cat /datos/mensaje.txt
Respuesta: Hola desde hostPath
📌 En resumen:
- hostPath = montar un directorio/archivo del nodo host en un contenedor.
- Útil para logs, sockets, pruebas rápidas o cuando quieres que varios Pods en el mismo nodo compartan archivos.
Volumen NFS
Para realizar esta prueba, debemos tener un servidor NFS corriendo (puede ser en otra máquina o dentro del mismo cluster con un Pod NFS server). Revisa el post NFS Network File System
En ese servidor, haber exportado un directorio (/mnt/nfs_share
) y darle permisos de acceso a los nodos de Kubernetes.
Procedemos a crear el pod pod-escritor-nfs donde colocamos:
apiVersion: v1
kind: Pod
metadata:
name: pod-con-nfs
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo 'Hola desde NFS' > /datos/mensaje.txt && sleep 3600"]
volumeMounts:
- name: volumen-nfs
mountPath: /datos
volumes:
- name: volumen-nfs
nfs:
server: 192.168.1.100 # IP del servidor NFS
path: /srv/nfs/kubedata # Carpeta exportada por NFS
Procedemos a crear el pod pod-lector-nfs donde colocamos:
apiVersion: v1
kind: Pod
metadata:
name: pod-lector-nfs
spec:
containers:
- name: lector
image: busybox
command: ["sh", "-c", "cat /datos/mensaje.txt && sleep 3600"]
volumeMounts:
- name: volumen-nfs
mountPath: /datos
volumes:
- name: volumen-nfs
nfs:
server: 192.168.1.100
path: /srv/nfs/kubedata
Luego creamos los pods
kubectl apply -f pod-escritor-nfs.yaml
kubectl apply -f pod-lector-nfs.yaml
Entra al Pod lector y revisa el archivo:
kubectl exec -it pod-lector-nfs -- cat /datos/mensaje.txt
Respuesta: Hola desde NFS
Volumen con persistentVolumeClaim (PVC)
- PV (PersistentVolume): Recurso que representa un pedazo de almacenamiento disponible en el cluster.
- PVC (PersistentVolumeClaim): Petición de almacenamiento que hacen los pods.
- Pod + PVC: El pod monta el PVC como un directorio, y allí puede leer/escribir datos persistentes.
Creamos el archivo mi-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mi-pv
spec:
capacity:
storage: 1Gi # tamaño del volumen
accessModes:
- ReadWriteOnce # solo un nodo puede montar en modo lectura/escritura
hostPath:
path: /mnt/data # carpeta en el nodo donde se guardarán los datos
📌 Aquí le estamos diciendo a Kubernetes:
- Tengo un volumen de 1GB de capacidad.
- Se puede usar en modo lectura/escritura por un solo pod.
- Se almacena en la ruta /mnt/data del nodo.
Luego, creamos mi-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mi-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Mi # el pod pide medio giga
📌 El PVC pide 500MB de almacenamiento.
Kubernetes busca un PV que cumpla:
- accessModes compatible (ReadWriteOnce ✅).
- storage suficiente (PV tiene 1Gi, PVC pide 500Mi ✅).
Entonces este PVC se une al PV mi-pv.
Por ultimo, creamos pod-con-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-con-pvc
spec:
containers:
- name: app
image: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: volumen-web
volumes:
- name: volumen-web
persistentVolumeClaim:
claimName: mi-pvc
📌 Explicación:
- El contenedor corre nginx.
- Montamos el PVC en la carpeta /usr/share/nginx/html.
- Todo lo que pongamos en /mnt/data en el nodo aparecerá dentro del contenedor en esa ruta (¡y se conserva aunque el pod se borre y se recree!).
Procedemos a ejecutar
kubectl apply -f .\mi-pv.yaml
kubectl apply -f .\mi-pvc.yaml
kubectl apply -f .\pod-con-pvc.yaml