This guide explains how to deploy External Secrets with integrated provider deployments using the monolithic Helm chart.
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:
Set providers.enabled to true and define your providers in the providers.list array:
providers:
enabled: true
list:
- name: aws
type: aws
enabled: true
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 |
image:
repository: oci.external-secrets.io/external-secrets/provider-aws
pullPolicy: IfNotPresent
tag: "" # Defaults to chart appVersion
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
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:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 50m
memory: 64Mi
service:
type: ClusterIP
port: 8080
annotations: {}
# 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
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: 80
tls:
enabled: true
certPath: /etc/provider/certs
caSecretName: external-secrets-v2-ca
mountCA: true
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:
level: info # debug, info, warn, error
format: json # json, console
development: false
metrics:
enabled: true
port: 8081
serviceMonitor:
enabled: true
namespace: "" # Defaults to release namespace
interval: 30s
scrapeTimeout: 10s
labels: {}
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
# 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
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
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"
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
helm install external-secrets external-secrets/external-secrets \
-f values-with-providers.yaml
helm upgrade external-secrets external-secrets/external-secrets \
-f values-with-providers.yaml
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
kubectl get deployments -l app.kubernetes.io/component=provider
kubectl logs -l external-secrets.io/provider=aws -f
kubectl port-forward svc/external-secrets-provider-aws 8081:8081
curl http://localhost:8081/metrics
kubectl exec -it deployment/external-secrets-provider-aws -- sh
# Check if certificates are mounted
ls -la /etc/provider/certs
replicaCount >= 2 for production