Install
La instalación es bastante simple y podemos hacerla usando helm para el external secret operator. Lo que cambia y trae un poco más de complejidad es configurar el proveedor y hacer el mapeo de las configuraciones.
El Operator instala los Custom Resource Definitions que harán la extensión de la API y realizará el despliegue (deployment) del external secrets que es el controller que gestiona los objetos definidos.
helm install external-secrets \
external-secrets/external-secrets \
-n external-secrets \
--create-namespace \
Verificando lo que tenemos en el clúster.
❯ k get all -n external-secrets
NAME READY STATUS RESTARTS AGE
pod/external-secrets-547987d945-d88xw 1/1 Running 0 6h45m
pod/external-secrets-cert-controller-f79f56cf4-7r2mx 1/1 Running 0 6h45m
pod/external-secrets-webhook-6cb79956f4-6gqn2 1/1 Running 0 6h45m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/external-secrets-webhook ClusterIP 172.20.142.40 <none> 443/TCP 6h45m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/external-secrets 1/1 1 1 6h45m
deployment.apps/external-secrets-cert-controller 1/1 1 1 6h45m
deployment.apps/external-secrets-webhook 1/1 1 1 6h45m
NAME DESIRED CURRENT READY AGE
replicaset.apps/external-secrets-547987d945 1 1 1 6h45m
replicaset.apps/external-secrets-cert-controller-f79f56cf4 1 1 1 6h45m
replicaset.apps/external-secrets-webhook-6cb79956f4 1 1 1 6h45m
Podemos observar 3 pods.
- external-secrets: El núcleo del external secrets operator. Este es el pod que realmente busca los datos del Secrets Manager o SSM.
- Busca los secretos en los backends (AWS, GCP, Vault, etc).
- Concilia los ExternalSecret con los Secret de K8s.
- Aplica refreshInterval, dataFrom, target.creationPolicy, etc.
- Queda monitoreando los recursos del tipo ExternalSecret/SecretStore/ClusterSecretStore
- external-secrets-cert-controller: Gestiona los certificados internos del ESO
- Crear y renovar los certificados TLS usados internamente por los webhooks del ESO.
- Garantiza que la comunicación entre el K8s API Server y los webhooks sea segura (vía certificados).
- Crea un Certificate e Issuer usando cert-manager o con self-signed.
- external-secrets-webhook: Validación y seguridad
Validar los manifiestos antes de aplicar (ValidatingWebhook y MutatingWebhook)
- Agregar valores por defecto (como default refreshInterval, creationPolicy, etc).
- Hacer verificaciones como:
- "¿El tipo del backend es soportado?"
- "¿El recurso está bien formado?"
- Actúa en el momento en que creas o alteras un recurso (tipo kubectl apply).
Si ejecutamos entonces el comando kubectl apply -f external-secret.yaml (un manifiesto del tipo ExternalSecret por ejemplo) el flujo será.
-
Kubectl envía la request al API de kubernetes.
-
Después de la autenticación y autorización que el kube-api hace, una tercera etapa es el admission controller. El kube-api server verifica si existe algún webhook de validación/mutación registrado para el Custom Resource ExternalSecret. El webhook es un servicio y en ese momento el
external-secrets-cert-controllerya está actuando detrás de escena, haciendo que el webhook tenga certificados válidos y rotados con seguridad. -
El
external-secrets-webhookentra en acción- El API Server hace una llamada HTTPS al pod external-secrets-webhook.
- El webhook hace:
- Validación de campos obligatorios
- Verifica si el tipo de backend es válido (aws, gcp, vault, etc)
- Agrega valores por defecto si olvidaste (ej: refreshInterval: 1h)
- Si todo está bien, el webhook devuelve un 200 OK y el recurso se persiste en el etcd.
-
El
external-secrets (controller)detecta la creación- El controller está "viendo" todos los ExternalSecret, SecretStore, etc, vía watch en K8s.
- Cuando detecta un nuevo ExternalSecret, él:
- Resuelve el SecretStore/ClusterSecretStore
- Usa las credenciales configuradas (IAM, accessKey, IRSA, etc)
- Accede al backend (ej: AWS SSM, Secrets Manager)
- Busca los valores usando:
- data
- dataFrom
- Construye un Secret de K8s con los valores obtenidos
¿Cuándo escalar el external-secrets-controller?
- Muchos secretos (~miles) siendo reconciliados frecuentemente.
- Latencia muy alta para buscar datos en backends.
- Uso multi-tenant pesado con muchos ExternalSecret ejecutándose por segundo.
Ahí puedes escalar el external-secrets controller con más réplicas y usar la funcionalidad de sharding (tiene soporte).
El external-secrets-cert-controller ejecuta solamente tareas periódicas de certificado, no necesita escala. El webhook es bastante simple, solo recibe llamadas del API Server, es de baja carga, entonces como máximo 2 pods si es necesario, pero no por carga, sino por resiliencia.
Lo que sería un values.yaml productivo.
replicaCount: 2 # Alta disponibilidad del controller
resources:
limits:
cpu: 250m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
# Agrega probes de health check
controllerManager:
container:
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
# Tolerations para permitir ejecución en nodos específicos, como nodes de infra
# tolerations:
# - key: "dedicated"
# operator: "Equal"
# value: "infra"
# effect: "NoSchedule"
# Si quieres ejecutar solo en nodes con un label específico
# nodeSelector:
# node-role.kubernetes.io/infra: "true"
# Prioridad para el controller (evitar preempción)
priorityClassName: "system-cluster-critical"
# Webhook config
webhook:
replicaCount: 2
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 50m
memory: 64Mi
# Cert controller
certController:
replicaCount: 1
resources:
limits:
cpu: 50m
memory: 64Mi
requests:
cpu: 25m
memory: 32Mi
installCRDs: false
# (Opcional) Sharding — divide los ExternalSecrets entre réplicas
sharding:
enabled: true
replicaCount: 2 # Debe coincidir con controllerManager.replicaCount
# Metrics habilitadas
metrics:
serviceMonitor:
enabled: true # Requiere Prometheus Operator
# Leader election para HA
# Es un mecanismo donde solo uno de los pods es el líder activo, y los otros quedan en standby.
# Este líder es el único que ejecuta la reconciliación de los ExternalSecrets (o el sharding, si está activo).
leaderElection:
enabled: true
Qué es el Sharding
Es la capacidad del ESO de dividir automáticamente la carga de reconciliación de ExternalSecrets entre varias réplicas del controller.
Cuando tienes muchos ExternalSecrets (ej: centenas o miles), una única réplica del ESO puede:
- Quedar sobrecargada
- Tener delays en el refreshInterval
- Generar throttling en AWS/GCP/Vault
Con sharding, esparces la carga entre los pods, manteniendo rendimiento y confiabilidad.
Cada ExternalSecrets es hasheado con base en metadata.name + namespace. Ese hash es usado para determinar cuál controller va a cuidar de cuál recurso. Así, cada réplica procesa solamente una porción del universo total.
Flujo con replicaCount: 3 y sharding.enabled: true Imagina que tienes 3 pods del ESO:
Pod 1 → procesa ExternalSecrets cuyo hash termina en 0
Pod 2 → hash termina en 1
Pod 3 → hash termina en 2
Cada pod procesa solo lo que es "suyo", e ignora el resto.
| Situación | Sharding |
|---|---|
< 100 ExternalSecrets | ❌ No necesita |
| 100–500, latencia ok | ⚠️ Opcional |
| 500+ secrets o backends lentos/throttling | ✅ Recomiendo |
| Multi-tenant clusters con muchos namespaces | ✅ Sí |