Fase 3
HashiCorp Vault 1.16

HashiCorp Vault · Secrets Management

La Fase 3 introduce secrets management con HashiCorp Vault self-hosted en k3s. Vault centraliza el almacenamiento y acceso a credenciales, elimina secrets hardcodeados de los manifiestos y permite rotación sin redeploy. En el lab corre en modo dev — en Oracle Cloud se reemplaza por OCI Vault.

01

¿Por qué Vault?

Sin Vault, los secrets viven en ConfigMaps, variables de entorno o — peor — hardcodeados en los manifiestos. Con Vault, los secrets existen en un solo lugar, se acceden con autenticación y autorización, se auditan y se pueden rotar sin tocar los Deployments.

Centralización
Un solo source of truth para todos los secrets del stack. No más credenciales dispersas en ConfigMaps, env vars o archivos sueltos.
Sin hardcoding
Los pods reciben secrets en runtime via inyección. El Deployment no contiene credenciales — solo annotations declarando qué secrets necesita.
Rotación sin redeploy
Cambiar una contraseña en Vault no requiere reiniciar pods. El Vault Agent renueva el secreto y la app lo lee del archivo actualizado.
Auditabilidad
Cada acceso a un secret queda registrado. En producción, Vault envía audit logs a un backend externo para compliance.
02

Modo Dev vs Producción

El lab usa Vault en modo dev (vault server -dev). Es la forma más rápida de tener Vault corriendo, pero no es apto para producción. La tabla documenta exactamente qué cambia entre ambos modos — entender estas diferencias es parte del valor del proyecto.

Aspecto
Modo Dev (lab)
Producción
Almacenamiento
En memoria — se pierde al reiniciar el pod
Raft o Consul — persistente en disco
Unseal
Automático al iniciar
Manual — 3 de 5 unseal keys requeridas
Root token
Fijado por env var (dev-root-token)
Generado en vault operator init
TLS
Deshabilitado — HTTP plano
Obligatorio — certificados TLS
Audit logging
Deshabilitado
Recomendado — file/socket/syslog
HA
Single replica — no soporta clustering
Múltiples nodos con Raft leader election
El token dev-root-token es público. En modo dev, cualquiera con acceso al cluster puede leer este token del Deployment y usarlo para acceder a todos los secrets. En producción, el root token se genera con vault operator init y se almacena en un lugar seguro — nunca en un manifiesto.
03

Vault en k3s

Vault corre como un Deployment de una sola réplica en el namespace aiops. El binario oficial de HashiCorp se ejecuta con el flag -dev y expone su API en el puerto 8200 via un Service ClusterIP.

k3s/manifests/vault/deployment.yml (extracto)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vault
  namespace: aiops
spec:
  replicas: 1
  template:
    spec:
      serviceAccountName: vault
      containers:
        - name: vault
          image: hashicorp/vault:1.16.2
          command: ["vault", "server", "-dev"]
          securityContext:
            capabilities:
              add: ["IPC_LOCK"]     # Previene swap de memoria con secrets
          env:
            - name: VAULT_DEV_ROOT_TOKEN_ID
              value: "dev-root-token"
            - name: VAULT_DEV_LISTEN_ADDRESS
              value: "0.0.0.0:8200"
          ports:
            - containerPort: 8200
          readinessProbe:
            httpGet:
              path: /v1/sys/health
              port: 8200

El securityContext.capabilities.add: ["IPC_LOCK"] permite que Vault use mlock() para evitar que el kernel swapee memoria que contiene secrets a disco. En modo dev esto está deshabilitado internamente, pero el capability se mantiene por compatibilidad con el binario.

04

Dos Agentes, Dos Niveles

El proyecto usa dos mecanismos distintos para que los workloads accedan a Vault. Uno opera dentro de Kubernetes (Agent Injector), el otro a nivel de sistema operativo (Vault Agent via systemd). No compiten — cubren capas diferentes.

Vault Agent Injector
Kubernetes — admission webhook
Cómo funciona: Intercepta creación de pods con annotations vault.hashicorp.com/agent-inject. Modifica el pod spec para agregar un init container que recupera secrets de Vault.
Cuándo se usa: Pods en k3s que necesitan secrets de Vault en runtime. El desarrollador solo agrega annotations al Deployment — el Injector hace el resto.
Vault Agent (systemd)
Sistema operativo — servicio systemd
Cómo funciona: Binario vault ejecutándose como daemon en la VM. Se autentica con AppRole y cachea tokens y secrets en disco. Renderiza templates HCL como archivos locales.
Cuándo se usa: Procesos del host fuera de k3s: scripts de monitoreo, tareas cron, backups. En modo dev tiene utilidad limitada — es referencia para producción.
En el lab actual, el Vault Agent de systemd tiene utilidad limitada. Vault está en modo dev con almacenamiento en memoria — los datos se pierden al reiniciar el pod. El Agent Injector es el mecanismo principal para el lab. El Agent de systemd se incluye como referencia para la transición a producción con almacenamiento persistente.
05

Flujo de Inyección de Secrets

El Vault Agent Injector modifica pods en tiempo de creación para que reciban secrets de Vault sin que el desarrollador escriba una sola línea de código de autenticación. Siete pasos desde la annotation hasta el secret en disco.

1
Developer
Agrega annotations de Vault al pod spec (vault.hashicorp.com/agent-inject: "true")
2
kubectl
Envía el Deployment a la API de Kubernetes
3
API Server
Envía AdmissionReview al Vault Agent Injector (Mutating Admission Webhook)
4
Injector
Lee las annotations del pod. Modifica el spec: agrega volumen compartido + init container (vault-agent-init)
5
API Server
Crea el pod modificado con el init container inyectado
6
vault-agent-init
Se autentica con Vault usando el ServiceAccount token del pod. Recupera los secrets. Los escribe en archivos del volumen compartido.
7
App Container
Arranca y lee los secrets desde los archivos en /vault/secrets/
annotations en un Deployment
# El desarrollador solo agrega esto al pod spec:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-secret-db: "secret/data/db"
vault.hashicorp.com/role: "myapp"
# El Injector hace el resto automáticamente.
# El contenedor lee el secret de /vault/secrets/db
06

Métodos de Autenticación

Vault soporta múltiples métodos de autenticación. El proyecto usa Kubernetes Auth para pods y AppRole para procesos del SO. Los tokens directos se evitan por diseño — son el equivalente a passwords hardcodeadas.

Kubernetes Pods en uso
El pod presenta su ServiceAccount token. Vault valida el token contra la API de Kubernetes. Si es válido, Vault asigna una política al pod según su ServiceAccount.
AppRole Máquinas/procesos en uso
Role ID (identidad pública) + Secret ID (credencial secreta). Ideal para servicios fuera de Kubernetes. El Vault Agent de systemd usa este método.
Token Humanos/root
Token directo generado por Vault. El root token (dev-root-token) usa este método. Los pods nunca deberían usar tokens directos.
07

Vault Self-Hosted → OCI Vault

Una de las decisiones de arquitectura más importantes del proyecto: en el lab local, Vault es self-hosted. En Oracle Cloud, se reemplaza por OCI Vault — el servicio gestionado.

Lab Local
HashiCorp Vault self-hosted
El equipo gestiona el servidor Unseal keys bajo responsabilidad propia Políticas ACL manuales Alta disponibilidad manual (Raft)
Oracle Cloud
OCI Vault (managed)
Oracle gestiona la infraestructura HA y backup automáticos IAM policies en lugar de ACL Integración nativa con OCI services

El valor del proyecto no está en usar un Vault u otro — está en entender la diferencia operacional entre self-hosted y managed. Poder explicar cuándo elegir cada uno y qué implicaciones tiene (disponibilidad, responsabilidad, costo) es fundamental para tomar decisiones de arquitectura informadas.

Siguiente: Vault Agent Injector

La siguiente página profundiza en el mecanismo de inyección de secrets: cómo funciona el Mutating Admission Webhook, qué annotations necesita un pod y cómo se configura el Injector en k3s.

Vault Agent Injector