Introducción
La gestión de los permisos de volumen en Kubernetes puede ser un desafío para los desarrolladores y administradores de sistemas. Cuando los contenedores necesitan leer o escribir en volúmenes persistentes, a menudo surgen problemas de permisos debido a discrepancias entre los IDs de usuario del contenedor y la propiedad del volumen. Estos desafíos pueden causar fallos en las aplicaciones y problemas de acceso a los datos.
Este laboratorio le guiará a través de los problemas comunes de permisos de volumen en Kubernetes y le proporcionará soluciones prácticas para resolverlos. Aprenderá a configurar correctamente los contextos de seguridad, a utilizar contenedores de inicialización (init containers) y a implementar las mejores prácticas para la gestión de permisos de volumen en sus implementaciones de Kubernetes.
Comprensión de los Volúmenes de Kubernetes
En este paso, exploraremos los volúmenes de Kubernetes y comprenderemos cómo funcionan. Los volúmenes de Kubernetes proporcionan una forma para que los contenedores almacenen y accedan a datos de forma persistente, incluso cuando los contenedores se reinician o se reprograman.
Tipos de Volúmenes de Kubernetes
Kubernetes admite varios tipos de volúmenes:
- EmptyDir: Un directorio vacío simple que existe durante la vida útil de un pod.
- HostPath: Monta un archivo o directorio del sistema de archivos del nodo host en su pod.
- PersistentVolume: Un recurso de almacenamiento aprovisionado por un administrador con un ciclo de vida independiente de cualquier pod.
- ConfigMap y Secret: Proporcionan una forma de inyectar datos de configuración e información sensible.
Creación de su Primer Volumen
Creemos un pod simple con un volumen EmptyDir:
- Cree un archivo YAML para la configuración de nuestro pod:
cd ~/project/k8s-volume-demo
nano emptydir-pod.yaml
- Copie el siguiente contenido en el archivo:
apiVersion: v1
kind: Pod
metadata:
name: emptydir-pod
spec:
containers:
- name: container-1
image: ubuntu:22.04
command:
[
"/bin/bash",
"-c",
"while true; do echo $(date) >> /data/log.txt; sleep 10; done"
]
volumeMounts:
- name: data-volume
mountPath: /data
volumes:
- name: data-volume
emptyDir: {}
Guarde el archivo (presione Ctrl+X, luego Y, luego Enter).
Cree el pod en su clúster de Kubernetes:
kubectl apply -f emptydir-pod.yaml
- Espere a que el pod esté listo:
kubectl get pods
La salida debería mostrar su pod en estado de ejecución:
NAME READY STATUS RESTARTS AGE
emptydir-pod 1/1 Running 0 30s
- Comprobemos el contenido de nuestro volumen:
kubectl exec emptydir-pod -- cat /data/log.txt
Debería ver una lista de marcas de tiempo, lo que demuestra que nuestro contenedor está escribiendo en el volumen:
Mon Jan 1 12:34:56 UTC 2023
Mon Jan 1 12:35:06 UTC 2023
Mon Jan 1 12:35:16 UTC 2023
Comprensión de los Montajes de Volumen
En el ejemplo anterior:
- Definimos un volumen llamado
data-volumede tipoemptyDir - Montamos este volumen en el contenedor en la ruta
/data - El contenedor escribe marcas de tiempo en un archivo en este volumen
Esto demuestra el concepto básico de los volúmenes de Kubernetes: proporcionan almacenamiento al que los contenedores de un pod pueden acceder. El volumen EmptyDir existe durante la vida útil del pod, por lo que si el pod se elimina, los datos se pierden.
Limpieza
Eliminemos el pod que creamos:
kubectl delete pod emptydir-pod
En el siguiente paso, exploraremos cómo pueden surgir problemas de permisos al usar volúmenes y cómo identificarlos.
Identificación de Problemas de Permisos de Volumen
En este paso, crearemos un escenario que demuestre los problemas comunes de permisos de volumen en Kubernetes. Estos problemas suelen ocurrir al usar volúmenes HostPath o volúmenes persistentes donde los permisos del sistema de archivos no coinciden con el ID de usuario que se ejecuta en el contenedor.
Comprensión del Problema
Cuando un contenedor se ejecuta como un usuario no root pero intenta acceder a un volumen propiedad de root (u otro usuario), pueden ocurrir errores de "permiso denegado". Este es un problema común en entornos de producción donde ejecutar contenedores como usuarios no root es una práctica recomendada de seguridad.
Creación de un Volumen HostPath con Problemas de Permisos
Creemos un pod que intente acceder a un volumen HostPath con propiedad root:
- Cree un archivo YAML para la configuración de nuestro pod:
cd ~/project/k8s-volume-demo
nano hostpath-pod.yaml
- Copie el siguiente contenido en el archivo:
apiVersion: v1
kind: Pod
metadata:
name: hostpath-pod
spec:
containers:
- name: container-1
image: ubuntu:22.04
command:
[
"/bin/bash",
"-c",
"while true; do echo 'Trying to write' >> /data/output.txt; sleep 10; done"
]
volumeMounts:
- name: host-data
mountPath: /data
securityContext:
runAsUser: 1000 ## Run as non-root user
volumes:
- name: host-data
hostPath:
path: /home/labex/project/k8s-volume-demo/data
type: Directory
Guarde el archivo (presione Ctrl+X, luego Y, luego Enter).
Cree el pod en su clúster de Kubernetes:
kubectl apply -f hostpath-pod.yaml
- Espere un momento, luego verifique el estado del pod:
kubectl get pods
- Debería ver que el pod se está ejecutando, pero si verificamos los registros, podríamos ver errores:
kubectl logs hostpath-pod
Podría ver errores de "permiso denegado" como:
bash: /data/output.txt: Permission denied
- Confirmemos el problema verificando los permisos en nuestro directorio host:
ls -la ~/project/k8s-volume-demo/data
Debería ver una salida como:
total 12
drwxr-xr-x 2 root root 4096 Jan 1 12:00 .
drwxr-xr-x 3 labex labex 4096 Jan 1 12:00 ..
-rw-r--r-- 1 root root 19 Jan 1 12:00 test.txt
El directorio y los archivos son propiedad de root, pero nuestro contenedor se está ejecutando como el ID de usuario 1000. Esta discrepancia causa los errores de "permiso denegado".
Comprensión de los IDs de Usuario y Grupo en Contenedores
En Kubernetes, los contenedores pueden ejecutarse como IDs de usuario específicos a través de la configuración securityContext. En nuestro ejemplo:
securityContext:
runAsUser: 1000 ## Run as non-root user
Esto le dice a Kubernetes que ejecute el proceso del contenedor como el ID de usuario 1000, que no tiene permiso para escribir en los archivos propiedad de root.
Limpieza
Antes de pasar al siguiente paso, eliminemos el pod:
kubectl delete pod hostpath-pod
En el siguiente paso, exploraremos soluciones a estos problemas de permisos.
Solución de Problemas de Permisos con Security Context
En este paso, exploraremos cómo usar el SecurityContext de Kubernetes para resolver problemas de permisos de volumen. SecurityContext define la configuración de privilegios y control de acceso para pods y contenedores.
Uso de fsGroup para Solucionar Permisos
La configuración fsGroup en un SecurityContext puede ayudar a resolver problemas de permisos. Cuando se especifica, Kubernetes cambia la propiedad del grupo del volumen para que coincida con el ID de grupo especificado, y establece el permiso para que el volumen sea legible y escribible por ese grupo.
Creemos un pod con un security context adecuado:
- Cree un archivo YAML para la configuración de nuestro pod:
cd ~/project/k8s-volume-demo
nano fixed-pod.yaml
- Copie el siguiente contenido en el archivo:
apiVersion: v1
kind: Pod
metadata:
name: fixed-pod
spec:
securityContext:
fsGroup: 2000 ## Set group ID for all containers in the pod
containers:
- name: container-1
image: ubuntu:22.04
command:
[
"/bin/bash",
"-c",
"while true; do echo $(date) >> /data/output.txt; cat /data/test.txt; sleep 10; done"
]
volumeMounts:
- name: host-data
mountPath: /data
securityContext:
runAsUser: 1000 ## Run as non-root user
volumes:
- name: host-data
hostPath:
path: /home/labex/project/k8s-volume-demo/data
type: Directory
Guarde el archivo (presione Ctrl+X, luego Y, luego Enter).
Cree el pod en su clúster de Kubernetes:
kubectl apply -f fixed-pod.yaml
- Espere a que el pod esté listo:
kubectl get pods
- Ahora, verifiquemos los registros para ver si nuestro problema de permisos se ha resuelto:
kubectl logs fixed-pod
Debería ver las marcas de tiempo que se escriben correctamente, lo que demuestra que el contenedor ahora puede escribir en el volumen:
This is a test file
Mon Jan 1 12:45:06 UTC 2023
This is a test file
Mon Jan 1 12:45:16 UTC 2023
- Examinemos qué sucedió con los permisos del volumen:
## Get into the container
kubectl exec -it fixed-pod -- bash
## Inside the container, check the permissions
ls -la /data
## Exit the container
exit
Debería ver que los archivos en el volumen ahora son accesibles por el contenedor porque Kubernetes aplicó la configuración fsGroup.
Comprensión de la Configuración de Security Context
- runAsUser: Especifica el ID de usuario con el que se ejecutarán los procesos del contenedor.
- fsGroup: Controla el ID de grupo utilizado para el acceso al volumen. Todos los procesos en el pod serán parte de este grupo suplementario.
- runAsGroup: Especifica el ID de grupo principal para todos los procesos dentro de los contenedores (opcional).
Estas configuraciones ayudan a garantizar que sus contenedores puedan acceder correctamente a los datos del volumen mientras mantienen las mejores prácticas de seguridad de no ejecutarse como root.
Limpieza
Eliminemos el pod que creamos:
kubectl delete pod fixed-pod
En el siguiente paso, exploraremos otro enfoque para solucionar problemas de permisos utilizando contenedores de inicialización (init containers).
Uso de Contenedores de Inicialización (Init Containers) para Solucionar Permisos
En algunas situaciones, el uso de fsGroup podría no ser suficiente o posible. Por ejemplo, al usar ciertos tipos de volumen o al ejecutarse en versiones anteriores de Kubernetes. En estos casos, se pueden usar contenedores de inicialización para establecer los permisos correctos antes de que se inicie el contenedor principal.
¿Qué son los Contenedores de Inicialización?
Los contenedores de inicialización se ejecutan antes que los contenedores principales en un pod. Pueden realizar tareas de inicialización como configurar permisos, descargar contenido o esperar dependencias. Los contenedores de inicialización son particularmente útiles para la gestión de permisos, ya que pueden ejecutarse con privilegios elevados para cambiar la propiedad y los permisos de los archivos del volumen.
Creación de un Pod con un Contenedor de Inicialización
Creemos un pod que use un contenedor de inicialización para solucionar los permisos:
- Cree un archivo YAML para la configuración de nuestro pod:
cd ~/project/k8s-volume-demo
nano init-pod.yaml
- Copie el siguiente contenido en el archivo:
apiVersion: v1
kind: Pod
metadata:
name: init-pod
spec:
initContainers:
- name: permission-fixer
image: ubuntu:22.04
command:
["/bin/bash", "-c", "chown -R 1000:1000 /data && chmod -R 755 /data"]
volumeMounts:
- name: host-data
mountPath: /data
securityContext:
runAsUser: 0 ## Run as root to change permissions
containers:
- name: main-container
image: ubuntu:22.04
command:
[
"/bin/bash",
"-c",
"while true; do echo $(date) >> /data/init-output.txt; cat /data/test.txt; sleep 10; done"
]
volumeMounts:
- name: host-data
mountPath: /data
securityContext:
runAsUser: 1000 ## Run as non-root user
volumes:
- name: host-data
hostPath:
path: /home/labex/project/k8s-volume-demo/data
type: Directory
Guarde el archivo (presione Ctrl+X, luego Y, luego Enter).
Cree el pod en su clúster de Kubernetes:
kubectl apply -f init-pod.yaml
- Espere a que el pod esté listo. El pod permanecerá en el estado "Init" hasta que el contenedor de inicialización se complete:
kubectl get pods
- Una vez que el pod esté en estado de ejecución, verifique los registros del contenedor principal:
kubectl logs init-pod
Debería ver las marcas de tiempo que se escriben correctamente, lo que demuestra que el contenedor ahora puede escribir en el volumen:
This is a test file
Mon Jan 1 13:05:06 UTC 2023
This is a test file
Mon Jan 1 13:05:16 UTC 2023
- Examinemos qué sucedió con los permisos del volumen:
## Check the content of the data directory
ls -la ~/project/k8s-volume-demo/data
Notará que la propiedad del archivo ha cambiado para reflejar el ID de usuario especificado en el comando del contenedor de inicialización.
Comprensión del Enfoque del Contenedor de Inicialización
En este ejemplo:
- El contenedor de inicialización se ejecuta con privilegios de root (
runAsUser: 0) - Cambia la propiedad y los permisos del contenido del volumen
- Después de que el contenedor de inicialización se completa, se inicia el contenedor principal
- El contenedor principal se ejecuta como un usuario no root (
runAsUser: 1000) - El contenedor principal ahora puede leer y escribir en el volumen
Esta técnica es particularmente útil cuando:
- Necesita preparar volúmenes con patrones de propiedad específicos
- Está trabajando con volúmenes que no admiten
fsGroup - Necesita realizar una lógica de configuración de permisos compleja
Limpieza
Eliminemos el pod que creamos:
kubectl delete pod init-pod
En el siguiente paso, exploraremos las mejores prácticas y aprenderemos a combinar estos enfoques para una gestión robusta de permisos de volumen.
Mejores Prácticas y Enfoque Combinado
En escenarios del mundo real, es posible que deba combinar múltiples enfoques para manejar los permisos de volumen de manera efectiva. En este paso final, exploraremos las mejores prácticas y crearemos un ejemplo completo que implemente una solución robusta.
Mejores Prácticas para los Permisos de Volumen
Aquí hay algunas de las mejores prácticas clave para administrar los permisos de volumen en Kubernetes:
- Ejecute los contenedores como usuarios no root siempre que sea posible.
- Use el usuario con el menor privilegio necesario para que su aplicación funcione.
- Aproveche los contextos de seguridad tanto a nivel de pod como de contenedor.
- Estandarice los valores de UID/GID en toda su organización.
- Use contenedores de inicialización para escenarios de configuración complejos.
- Implemente un manejo de errores adecuado para problemas de permisos.
Creación de una Solución Completa
Creemos un despliegue que combine nuestro aprendizaje en una solución robusta:
- Cree un archivo YAML para nuestro despliegue:
cd ~/project/k8s-volume-demo
nano best-practice-deployment.yaml
- Copie el siguiente contenido en el archivo:
apiVersion: apps/v1
kind: Deployment
metadata:
name: volume-best-practices
labels:
app: volume-demo
spec:
replicas: 1
selector:
matchLabels:
app: volume-demo
template:
metadata:
labels:
app: volume-demo
spec:
## Pod-level security context
securityContext:
fsGroup: 2000
## Init container for advanced preparation
initContainers:
- name: volume-permissions
image: ubuntu:22.04
command:
- /bin/bash
- -c
- |
## Create directory structure if it doesn't exist
mkdir -p /data/app /data/logs /data/config
## Set appropriate permissions
chmod 755 /data
chmod 775 /data/app /data/logs
chmod 755 /data/config
## Set ownership (belt and suspenders approach)
chown -R 1000:2000 /data
echo "Volume prepared successfully"
volumeMounts:
- name: data-volume
mountPath: /data
securityContext:
runAsUser: 0 ## Run as root for setup
## Application containers
containers:
- name: app-container
image: ubuntu:22.04
command:
- /bin/bash
- -c
- |
echo "Starting application with user $(id)"
while true; do
echo "$(date) - Application running" >> /data/logs/app.log
echo "Writing to app directory" >> /data/app/status.txt
echo "Reading from config"
cat /data/config/test.txt || echo "No config found"
sleep 10
done
volumeMounts:
- name: data-volume
mountPath: /data
securityContext:
runAsUser: 1000 ## Run as non-root user
runAsGroup: 2000 ## Use the same group as fsGroup
allowPrivilegeEscalation: false ## Prevent privilege escalation
volumes:
- name: data-volume
hostPath:
path: /home/labex/project/k8s-volume-demo/data
type: Directory
Guarde el archivo (presione Ctrl+X, luego Y, luego Enter).
Cree el despliegue en su clúster de Kubernetes:
kubectl apply -f best-practice-deployment.yaml
- Espere a que el despliegue esté listo:
kubectl get pods -l app=volume-demo
- Verifiquemos los registros del contenedor de inicialización:
## Get the pod name
POD_NAME=$(kubectl get pods -l app=volume-demo -o jsonpath='{.items[0].metadata.name}')
## Check the init container logs
kubectl logs $POD_NAME -c volume-permissions
Debería ver un mensaje que indica que el volumen se preparó con éxito.
- Ahora, verifique los registros del contenedor de la aplicación:
kubectl logs $POD_NAME -c app-container
Debería ver que la aplicación se está ejecutando y puede leer y escribir en el volumen.
- Examinemos los archivos creados por nuestro despliegue:
ls -la ~/project/k8s-volume-demo/data
Debería ver la estructura de directorios creada por el contenedor de inicialización, con los permisos y la propiedad adecuados.
Comprensión de la Solución Completa
Esta solución combina múltiples mejores prácticas:
- Contexto de seguridad a nivel de pod con
fsGrouppara establecer permisos base. - Contenedor de inicialización para la configuración compleja de la estructura de directorios.
- Contexto de seguridad a nivel de contenedor para ejecutarse como no root.
- Alineación de grupo adecuada entre
fsGroupyrunAsGroup. - Seguridad mejorada con
allowPrivilegeEscalation: false.
Este enfoque garantiza:
- La aplicación tiene los permisos necesarios para funcionar.
- Se sigue el principio del mínimo privilegio.
- La solución es robusta en diferentes entornos.
Limpieza
Limpiemos todos los recursos creados durante este laboratorio:
kubectl delete deployment volume-best-practices
rm -rf ~/project/k8s-volume-demo/data/app ~/project/k8s-volume-demo/data/logs ~/project/k8s-volume-demo/data/config
Ahora ha aprendido múltiples enfoques para resolver problemas de permisos de volumen en Kubernetes e implementado una solución completa siguiendo las mejores prácticas.
Resumen
En este laboratorio, ha aprendido a identificar y resolver problemas de permisos de volumen de Kubernetes a través de varios enfoques:
- Primero, obtuvo una comprensión de cómo funcionan los volúmenes de Kubernetes y creó un ejemplo simple de volumen EmptyDir.
- Luego, identificó problemas comunes de permisos de volumen al crear un volumen HostPath con permisos de usuario no coincidentes.
- Implementó una solución utilizando el SecurityContext de Kubernetes con
fsGrouppara establecer los permisos de volumen apropiados. - Exploró un enfoque alternativo utilizando contenedores de inicialización para establecer explícitamente los permisos antes de que se inicie el contenedor principal.
- Finalmente, combinó estas técnicas en una solución integral de mejores prácticas que proporciona una forma robusta de administrar los permisos de volumen en Kubernetes.
Estas habilidades le ayudarán a garantizar que sus aplicaciones en contenedores puedan acceder correctamente al almacenamiento persistente mientras mantienen las mejores prácticas de seguridad. Al aplicar la combinación correcta de contextos de seguridad, contenedores de inicialización y técnicas de gestión de permisos, puede evitar problemas comunes de permisos en sus implementaciones de Kubernetes.


