--- title: "Cómo gestionar secretos de Kubernetes con HashiCorp Vault" description: "Instala HashiCorp Vault en Kubernetes con Helm, configura la autenticación de Kubernetes e inyecta secretos en tus pods con el Agent Injector y el driver CSI." category: "Kubernetes Avanzado" language: es source: https://cubepath.com/es/docs/kubernetes-avanzado/gestion-de-secretos-de-kubernetes-con-vault updated: 2026-09-25 --- # Cómo gestionar secretos de Kubernetes con HashiCorp Vault Los `Secret` nativos de Kubernetes se guardan en etcd codificados en base64, que no es cifrado, y cualquiera con permiso de lectura sobre el namespace puede verlos. HashiCorp Vault centraliza los secretos, los cifra, controla quién accede a cada uno mediante políticas y registra cada acceso. En este tutorial instalarás Vault en un clúster de Kubernetes con Helm, guardarás un secreto en el motor KV, permitirás que los pods se autentiquen con su ServiceAccount y entregarás ese secreto a una aplicación de dos formas: con el Vault Agent Injector y con el driver CSI de Secrets Store. ## Requisitos previos Para seguir esta guía necesitas: - Un clúster de Kubernetes 1.29 o superior con al menos un nodo worker con 2 GB de RAM libres, por ejemplo uno desplegado sobre VPS de CubePath. - Una StorageClass por defecto, ya que Vault guarda sus datos en un volumen persistente. Compruébalo con `kubectl get storageclass`. - Una estación de trabajo (tu portátil o un servidor Ubuntu 24.04) con `kubectl` configurado contra el clúster, [Helm](https://helm.sh/docs/intro/install/) 3 o superior y `jq` (`sudo apt install jq`). Todos los comandos se ejecutan desde esa estación de trabajo. ## Paso 1: Instalar Vault con Helm HashiCorp publica un chart oficial que despliega el servidor de Vault, el Agent Injector (un webhook que añade un contenedor de Vault a los pods que lo piden) y, opcionalmente, el proveedor CSI. Añade el repositorio: ```bash helm repo add hashicorp https://helm.releases.hashicorp.com helm repo update ``` Instala Vault en su propio namespace. Por defecto el chart crea un único servidor en modo standalone con almacenamiento en disco, que es suficiente para este tutorial. Activa también el proveedor CSI, que usarás en el paso 7: ```bash helm install vault hashicorp/vault \ --namespace vault --create-namespace \ --set csi.enabled=true ``` Comprueba los pods: ```bash kubectl get pods -n vault ``` ```output NAME READY STATUS RESTARTS AGE vault-0 0/1 Running 0 45s vault-agent-injector-7d8b5c9f4d-x2kqp 1/1 Running 0 45s vault-csi-provider-8h4tw 2/2 Running 0 45s ``` `vault-0` aparece como `0/1`: es normal, la sonda de readiness falla mientras Vault no esté inicializado y desbloqueado. ## Paso 2: Inicializar y desbloquear Vault Al inicializar Vault se genera la clave maestra, dividida en varias claves de desbloqueo (unseal keys), y un token root. Para este tutorial usarás una sola clave: ```bash kubectl exec -n vault vault-0 -- vault operator init \ -key-shares=1 -key-threshold=1 -format=json > vault-keys.json ``` > Advertencia: `vault-keys.json` contiene la única forma de desbloquear Vault y un token con acceso total. Guárdalo en un gestor de contraseñas y bórralo del disco al terminar. En producción usa varias claves (por ejemplo `-key-shares=5 -key-threshold=3`) repartidas entre personas distintas, o el auto-unseal con un KMS. Desbloquea Vault con la clave generada: ```bash VAULT_UNSEAL_KEY=$(jq -r '.unseal_keys_b64[0]' vault-keys.json) kubectl exec -n vault vault-0 -- vault operator unseal "$VAULT_UNSEAL_KEY" ``` En la salida, `Sealed` debe valer `false`: ```output Key Value --- ----- Seal Type shamir Initialized true Sealed false Total Shares 1 Threshold 1 ... ``` Pasados unos segundos, `kubectl get pods -n vault` mostrará `vault-0` como `1/1`. Cada vez que el pod se reinicie volverá a arrancar sellado y tendrás que repetir el `unseal`. ## Paso 3: Guardar un secreto en el motor KV Muestra el token root para iniciar sesión: ```bash jq -r '.root_token' vault-keys.json ``` Abre una shell dentro del pod de Vault. Los pasos 3, 4 y 5 se ejecutan en esta shell: ```bash kubectl exec -it -n vault vault-0 -- /bin/sh ``` Inicia sesión pegando el token root cuando te lo pida: ```bash vault login ``` Activa el motor de secretos KV versión 2 en la ruta `secret/` y guarda las credenciales de ejemplo de una aplicación llamada `webapp`. Sustituye los valores por los tuyos: ```bash vault secrets enable -path=secret kv-v2 vault kv put secret/webapp/config username="webapp" password="your_strong_password" ``` Léelo para confirmar que se ha guardado: ```bash vault kv get secret/webapp/config ``` ```output ====== Secret Path ====== secret/data/webapp/config ... ====== Data ====== Key Value --- ----- password your_strong_password username webapp ``` Fíjate en la ruta real, `secret/data/webapp/config`: en KV v2 las políticas y las anotaciones usan siempre el segmento `data/`. ## Paso 4: Activar la autenticación de Kubernetes El método de autenticación `kubernetes` permite que un pod presente el token de su ServiceAccount y reciba a cambio un token de Vault. Vault valida ese token contra la API de Kubernetes. Como Vault corre dentro del propio clúster, basta con indicarle la dirección de la API; usará su propia ServiceAccount y el certificado de la CA montados en el pod: ```bash vault auth enable kubernetes vault write auth/kubernetes/config \ kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" ``` ```output Success! Enabled kubernetes auth method at: kubernetes/ Success! Data written to: auth/kubernetes/config ``` ## Paso 5: Crear una política y un rol Una política define qué rutas puede leer quien la tenga. Crea una de solo lectura para el secreto de `webapp`: ```bash vault policy write webapp - < -c vault-agent-init`. Un error `permission denied` suele indicar que la ServiceAccount o el namespace del pod no coinciden con `bound_service_account_names` y `bound_service_account_namespaces` del rol. - **El pod no recibe el sidecar.** Comprueba que el injector está en ejecución (`kubectl get pods -n vault`) y que las anotaciones están en `spec.template.metadata.annotations`, no en los metadatos del Deployment. - **`vault-0` vuelve a `0/1` tras un reinicio.** Vault arranca sellado. Repite el `vault operator unseal` del paso 2. - **El pod CSI falla con `failed to mount secrets store objects`.** Ejecuta `kubectl describe pod webapp-csi` y revisa que `secretPath` incluye `data/` y que `secretKey` existe en el secreto. ## Conclusión Tienes Vault funcionando en Kubernetes, con los secretos cifrados fuera de etcd y cada aplicación limitada a sus propias rutas mediante políticas y roles ligados a su ServiceAccount. Los pods reciben las credenciales como ficheros, ya sea por el Agent Injector o por el driver CSI. Como siguientes pasos, puedes desplegar Vault en alta disponibilidad con almacenamiento Raft integrado (`server.ha.enabled=true` y `server.ha.raft.enabled=true` en el chart), configurar el auto-unseal y activar el motor `database` para generar credenciales de base de datos dinámicas que caducan solas.