Skip to main content

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á.

  1. Kubectl envía la request al API de kubernetes.

  2. 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-controller ya está actuando detrás de escena, haciendo que el webhook tenga certificados válidos y rotados con seguridad.

  3. El external-secrets-webhook entra 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.
  4. 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ónSharding
< 100 ExternalSecrets❌ No necesita
100–500, latencia ok⚠️ Opcional
500+ secrets o backends lentos/throttling✅ Recomiendo
Multi-tenant clusters con muchos namespaces✅ Sí