PROVIDERS.md 10 KB

Provider Deployment Guide

This guide explains how to deploy External Secrets with integrated provider deployments using the monolithic Helm chart.

Overview

The External Secrets Helm chart now supports deploying one or multiple secret providers alongside the controller in a single installation. Each provider runs as an independent deployment with its own configuration, allowing you to:

  • Deploy multiple providers simultaneously (AWS, GCP, Azure, Vault, etc.)
  • Configure each provider independently with specific resource limits, security contexts, and authentication
  • Scale providers independently based on workload requirements
  • Enable high availability with pod disruption budgets and anti-affinity rules

Basic Configuration

Enable Provider Deployments

Set providers.enabled to true and define your providers in the providers.list array:

providers:
  enabled: true
  list:
    - name: aws
      type: aws
      enabled: true

Provider Structure

Each provider in the list supports the following configuration:

Field Type Description Required
name string Unique name for this provider instance Yes
type string Provider type (aws, gcp, azure, vault, etc.) Yes
enabled boolean Enable/disable this provider Yes
replicaCount int Number of replicas (default: 2) No

Configuration Sections

Image Configuration

image:
  repository: oci.external-secrets.io/external-secrets/provider-aws
  pullPolicy: IfNotPresent
  tag: ""  # Defaults to chart appVersion

Service Account

serviceAccount:
  create: true
  annotations:
    # Example: AWS IRSA
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/eso-provider-aws
    # Example: GCP Workload Identity
    # iam.gke.io/gcp-service-account: eso-provider@project.iam.gserviceaccount.com
    # Example: Azure Workload Identity
    # azure.workload.identity/client-id: "00000000-0000-0000-0000-000000000000"
  name: ""  # Auto-generated if empty
  automount: true

Security Contexts

podSecurityContext:
  enabled: true
  runAsNonRoot: true
  runAsUser: 65532
  fsGroup: 65532
  seccompProfile:
    type: RuntimeDefault

securityContext:
  enabled: true
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  runAsNonRoot: true
  runAsUser: 65532
  capabilities:
    drop:
    - ALL

Resources

resources:
  limits:
    cpu: 200m
    memory: 256Mi
  requests:
    cpu: 50m
    memory: 64Mi

Service Configuration

service:
  type: ClusterIP
  port: 8080
  annotations: {}

High Availability

# Pod Disruption Budget
podDisruptionBudget:
  enabled: true
  minAvailable: 1
  # maxUnavailable: 1

# Affinity rules for spreading pods
affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 100
      podAffinityTerm:
        labelSelector:
          matchLabels:
            app.kubernetes.io/component: provider
            external-secrets.io/provider: aws
        topologyKey: kubernetes.io/hostname

# Topology spread constraints
topologySpreadConstraints:
- maxSkew: 1
  topologyKey: topology.kubernetes.io/zone
  whenUnsatisfiable: ScheduleAnyway
  labelSelector:
    matchLabels:
      external-secrets.io/provider: aws

Auto-scaling

autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80
  targetMemoryUtilizationPercentage: 80

TLS Configuration

tls:
  enabled: true
  certPath: /etc/provider/certs
  caSecretName: external-secrets-v2-ca
  mountCA: true

Provider-Specific Configuration

Use the config section to pass provider-specific settings:

config:
  # AWS provider example
  region: us-east-1
  authMethod: irsa
  assumeRoleARN: ""
  externalID: ""
  
  # GCP provider example
  # projectID: my-project
  
  # Azure provider example
  # vaultURL: https://my-vault.vault.azure.net
  # tenantID: "00000000-0000-0000-0000-000000000000"
  
  # Vault provider example
  # vaultAddr: https://vault.example.com
  # authMethod: kubernetes

Logging

logging:
  level: info  # debug, info, warn, error
  format: json  # json, console
  development: false

Metrics

metrics:
  enabled: true
  port: 8081
  serviceMonitor:
    enabled: true
    namespace: ""  # Defaults to release namespace
    interval: 30s
    scrapeTimeout: 10s
    labels: {}

Health Checks

health:
  port: 8082
  livenessProbe:
    enabled: true
    initialDelaySeconds: 10
    periodSeconds: 20
    timeoutSeconds: 5
    failureThreshold: 3
  readinessProbe:
    enabled: true
    initialDelaySeconds: 5
    periodSeconds: 10
    timeoutSeconds: 5
    failureThreshold: 3

Extra Configuration

# Additional environment variables
extraEnv:
- name: CUSTOM_VAR
  value: "custom-value"
- name: SECRET_VAR
  valueFrom:
    secretKeyRef:
      name: my-secret
      key: password

# Additional volumes
extraVolumes:
- name: custom-config
  configMap:
    name: provider-config

# Additional volume mounts
extraVolumeMounts:
- name: custom-config
  mountPath: /etc/config
  readOnly: true

# Pod annotations
podAnnotations:
  prometheus.io/scrape: "true"

# Pod labels
podLabels:
  environment: production

# Node selector
nodeSelector:
  cloud.provider/instance-type: standard

# Tolerations
tolerations:
- key: "provider-workload"
  operator: "Equal"
  value: "true"
  effect: "NoSchedule"

# Priority class
priorityClassName: high-priority

Examples

AWS Provider with IRSA

providers:
  enabled: true
  list:
    - name: aws-us-east-1
      type: aws
      enabled: true
      replicaCount: 3
      
      image:
        repository: oci.external-secrets.io/external-secrets/provider-aws
      
      serviceAccount:
        create: true
        annotations:
          eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/eso-provider-aws
      
      resources:
        limits:
          cpu: 300m
          memory: 512Mi
        requests:
          cpu: 100m
          memory: 128Mi
      
      config:
        region: us-east-1
        authMethod: irsa
      
      podDisruptionBudget:
        enabled: true
        minAvailable: 2
      
      metrics:
        enabled: true
        serviceMonitor:
          enabled: true

Multiple Providers

providers:
  enabled: true
  list:
    # AWS Provider
    - name: aws
      type: aws
      enabled: true
      replicaCount: 2
      image:
        repository: oci.external-secrets.io/external-secrets/provider-aws
      serviceAccount:
        annotations:
          eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/eso-aws
      config:
        region: us-east-1
        authMethod: irsa
    
    # GCP Provider
    - name: gcp
      type: gcp
      enabled: true
      replicaCount: 2
      image:
        repository: oci.external-secrets.io/external-secrets/provider-gcp
      serviceAccount:
        annotations:
          iam.gke.io/gcp-service-account: eso@project.iam.gserviceaccount.com
      config:
        projectID: my-project
    
    # Azure Provider
    - name: azure
      type: azure
      enabled: true
      replicaCount: 2
      image:
        repository: oci.external-secrets.io/external-secrets/provider-azure
      serviceAccount:
        annotations:
          azure.workload.identity/client-id: "00000000-0000-0000-0000-000000000000"
      podLabels:
        azure.workload.identity/use: "true"
      config:
        vaultURL: https://my-vault.vault.azure.net
        tenantID: "00000000-0000-0000-0000-000000000000"

Provider with Custom Authentication Secret

providers:
  enabled: true
  list:
    - name: vault
      type: vault
      enabled: true
      
      image:
        repository: oci.external-secrets.io/external-secrets/provider-vault
      
      config:
        vaultAddr: https://vault.example.com
        authMethod: token
      
      extraEnv:
      - name: VAULT_TOKEN
        valueFrom:
          secretKeyRef:
            name: vault-token
            key: token
      
      extraVolumes:
      - name: vault-ca
        secret:
          secretName: vault-ca-cert
      
      extraVolumeMounts:
      - name: vault-ca
        mountPath: /etc/vault/ca
        readOnly: true

Installation

Install with providers

helm install external-secrets external-secrets/external-secrets \
  -f values-with-providers.yaml

Upgrade existing installation

helm upgrade external-secrets external-secrets/external-secrets \
  -f values-with-providers.yaml

Install with specific provider enabled

helm install external-secrets external-secrets/external-secrets \
  --set providers.enabled=true \
  --set providers.list[0].name=aws \
  --set providers.list[0].type=aws \
  --set providers.list[0].enabled=true \
  --set providers.list[0].replicaCount=2 \
  --set providers.list[0].image.repository=oci.external-secrets.io/external-secrets/provider-aws

Troubleshooting

Check provider deployment status

kubectl get deployments -l app.kubernetes.io/component=provider

View provider logs

kubectl logs -l external-secrets.io/provider=aws -f

Check provider metrics

kubectl port-forward svc/external-secrets-provider-aws 8081:8081
curl http://localhost:8081/metrics

Verify TLS connectivity

kubectl exec -it deployment/external-secrets-provider-aws -- sh
# Check if certificates are mounted
ls -la /etc/provider/certs

Best Practices

  1. High Availability: Always use replicaCount >= 2 for production
  2. Resource Limits: Set appropriate resource limits based on your workload
  3. Pod Disruption Budgets: Enable PDBs to prevent all replicas from being evicted
  4. Anti-Affinity: Use pod anti-affinity to spread replicas across nodes/zones
  5. Monitoring: Enable metrics and ServiceMonitor for observability
  6. Authentication: Use workload identity (IRSA, Workload Identity) instead of static credentials
  7. TLS: Keep TLS enabled for secure provider-controller communication
  8. Auto-scaling: Use HPA for dynamic scaling based on load
  9. Health Checks: Enable liveness and readiness probes for better reliability
  10. Security Context: Use restrictive security contexts (non-root, read-only filesystem)