Volúmenes en Kubernetes


Aprenderemos con ejemplos como crear volúmenes con kubernetes, trabajaremos con emptyDir

oscar Escrito por oscar 29 August 2025 159 0

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

Comentario

Debe aceptar antes de enviar