K8s by Example: External Secrets

External Secrets Operator syncs secrets from AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager, Azure Key Vault, etc. Secrets stay in your vault, synced to Kubernetes automatically.

external-secret.yaml

ExternalSecret defines which secrets to sync. refreshInterval controls sync frequency. secretStoreRef points to the provider. remoteRef specifies the secret path and property.

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-secrets
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: app-secrets
  data:
    - secretKey: DATABASE_URL
      remoteRef:
        key: my-app/database
        property: url
secret-store.yaml

ClusterSecretStore defines the connection to your secrets provider. Typically one per cluster or environment. SecretStore is namespace-scoped alternative. Uses IRSA/Workload Identity for auth.

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: aws-secrets-manager
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-west-2
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets
            namespace: external-secrets
---
kind: SecretStore
metadata:
  name: team-vault
  namespace: my-team
spec:
  provider:
    vault:
      server: "https://vault.example.com"
      path: "secret"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "my-team"
external-secret-aws.yaml

AWS Secrets Manager provider. Store secrets as JSON, extract specific properties. Works with IRSA for secure authentication without access keys.

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-secrets
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: app-secrets
  data:
    - secretKey: DATABASE_URL
      remoteRef:
        key: my-app/prod
        property: db_url
    - secretKey: API_KEY
      remoteRef:
        key: my-app/prod
        property: api_key
external-secret-vault.yaml

HashiCorp Vault provider. Supports KV v1, KV v2, and other secret engines. Use Kubernetes auth for secure Pod authentication.

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: vault
spec:
  provider:
    vault:
      server: "https://vault.example.com:8200"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "external-secrets"
          serviceAccountRef:
            name: external-secrets
            namespace: external-secrets
---
kind: ExternalSecret
spec:
  secretStoreRef:
    name: vault
    kind: ClusterSecretStore
  data:
    - secretKey: password
      remoteRef:
        key: apps/my-app
        property: password
external-secret-datafrom.yaml

Sync all keys from a secret with dataFrom. Each key in the remote secret becomes a key in the Kubernetes Secret. Useful for secrets with many keys.

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-secrets
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: app-secrets
  dataFrom:
    - extract:
        key: my-app/production
external-secret-template.yaml

Target options control the created Secret. Set labels, annotations, type, and creation policy. Use templates for complex transformations.

spec:
  target:
    name: app-secrets
    creationPolicy: Owner
    template:
      type: kubernetes.io/tls
      metadata:
        labels:
          app: my-app
        annotations:
          description: "Synced from AWS"
      data:
        tls.crt: "{{ .cert }}"
        tls.key: "{{ .key }}"
  data:
    - secretKey: cert
      remoteRef:
        key: my-app/tls-cert
    - secretKey: key
      remoteRef:
        key: my-app/tls-key
secret-store-cloud.yaml

GCP Secret Manager and Azure Key Vault providers. Use Workload Identity (GCP) or Azure AD Pod Identity for secure authentication.

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: gcp-secrets
spec:
  provider:
    gcpsm:
      projectID: my-project-123
      auth:
        workloadIdentity:
          clusterLocation: us-central1
          clusterName: my-cluster
          serviceAccountRef:
            name: external-secrets
            namespace: external-secrets
---
kind: ClusterSecretStore
metadata:
  name: azure-keyvault
spec:
  provider:
    azurekv:
      vaultUrl: "https://my-vault.vault.azure.net"
      authType: WorkloadIdentity
      serviceAccountRef:
        name: external-secrets
        namespace: external-secrets
terminal

Check sync status and troubleshoot issues. ExternalSecret creates a regular Kubernetes Secret that Pods use normally. Force sync by annotating. Common issues: SecretStore auth failure (check IAM/RBAC), secret not found (check remote key path), property not found (check JSON structure).

$ kubectl get externalsecret
NAME          STORE                  REFRESH   STATUS
app-secrets   aws-secrets-manager    1h        SecretSynced

$ kubectl describe externalsecret app-secrets
Status:
  Conditions:
    Type:   Ready
    Status: True
  Refresh Time: 2024-01-15T10:30:00Z

$ kubectl get secret app-secrets -o yaml

$ kubectl annotate externalsecret app-secrets \
    force-sync=$(date +%s) --overwrite

$ kubectl logs -n external-secrets \
    -l app.kubernetes.io/name=external-secrets

Index | GitHub | Use arrow keys to navigate |