Skip to content

External Secrets Operator (ESO)

Summary

External Secrets Operator is a CNCF Sandbox Kubernetes operator that syncs secrets from external stores (HashiCorp Vault, AWS Secrets Manager and Parameter Store, Azure Key Vault, GCP Secret Manager, and about 40 other providers) into native Kubernetes Secrets, and can push Secrets back out with PushSecret. Its core APIs have been GA at external-secrets.io/v1 since 2025, v1.0 shipped in November 2025, and the 2.x line releases a new minor about every three weeks. The latest version is 2.11.0 (2026-09-18). Only the newest minor is supported.

Overview

ESO is the de facto Kubernetes bridge for external secret stores. It watches ExternalSecret resources, fetches values through a SecretStore or ClusterSecretStore, renders optional Go templates, and creates or updates ordinary Kubernetes Secrets. Applications need no SDK, sidecar, or CSI driver. PushSecret reverses the flow, and generators mint values such as ECR tokens, Vault dynamic credentials, or random passwords. The trade-off is that secret values end up in etcd, and updates arrive by polling.

Key Facts

Attribute Detail
Website external-secrets.io
Repository external-secrets/external-secrets
Stars ~5k+
Latest Version 2.11.0 (2026-09-18), Helm chart 2.11.0
Release cadence New minor about every 3 weeks since 2.0; only the latest minor is supported
Tested Kubernetes 1.36 (for 2.11)
Stable APIs external-secrets.io/v1: ExternalSecret, ClusterExternalSecret, SecretStore, ClusterSecretStore
Alpha APIs external-secrets.io/v1alpha1: PushSecret, ClusterPushSecret; generators.external-secrets.io/v1alpha1: generators
Removed APIs v1alpha1 stores and ExternalSecrets (v0.16.0), v1beta1 no longer served (v0.17.0, 2025-05-14)
Language Go (multi-module since v1.0)
License Apache-2.0
Governance CNCF Sandbox (accepted 2022-07-26); five maintainers from different organizations
Install Helm chart external-secrets/external-secrets from https://charts.external-secrets.io

Evaluation

Pros Cons
About 40 providers behind one API; ten are stable Poll-based sync with lag (default refreshInterval 1h)
Native Kubernetes Secrets, so no application changes Secret values stored in etcd; needs encryption at rest
PushSecret for reverse sync (Vault, AWS, GCP, Azure, and more) Most providers are alpha and community-maintained
Generators for short-lived tokens and passwords PushSecret and generators are still v1alpha1 APIs
Go templating with Sprig and PKI helpers Only the latest minor is supported, so you must upgrade every few weeks
ClusterSecretStore with namespace conditions for multi-tenancy Controller holds cluster-wide Secret access; four notable CVEs in 2024-2026
Apache-2.0, CNCF, broad adoption (Red Hat ships a supported build) Maintainer shortage paused releases in mid-2025; bus factor still modest

Fits well when workloads run on Kubernetes, a central store already exists (a cloud secret manager or Vault), and GitOps should carry only references, never secret values. Fits poorly when you need secrets never to touch etcd (use the Secrets Store CSI Driver or Vault Agent injection), you have no external store (SOPS or Sealed Secrets are simpler), or you need sub-second propagation.

Architecture

The core controller reconciles ESO resources, calls provider APIs, and writes Kubernetes Secrets; a webhook and a cert controller support admission validation. Details are in Explanation.

flowchart LR
    subgraph K8s["Kubernetes cluster"]
        ES["ExternalSecret"]
        SS["SecretStore / ClusterSecretStore"]
        PS["PushSecret"]
        CTRL["ESO core controller"]
        WH["ESO webhook + cert controller"]
        SEC["Kubernetes Secret"]
        POD["Pods (env, envFrom, volume)"]
    end

    subgraph External["External providers"]
        VLT["HashiCorp Vault / OpenBao"]
        AWS["AWS Secrets Manager / Parameter Store"]
        GCP["GCP Secret Manager"]
        AZ["Azure Key Vault"]
    end

    ES -->|"what to fetch"| CTRL
    SS -->|"how to authenticate"| CTRL
    WH -.->|"validates"| SS
    CTRL -->|"fetch"| External
    CTRL -->|"create / update"| SEC
    SEC --> POD
    PS -->|"push"| CTRL
    CTRL -->|"write back"| VLT

    style CTRL fill:#1565c0,color:#fff

Core Resources

Resource API version Scope Purpose
SecretStore v1 Namespace Provider connection and auth config
ClusterSecretStore v1 Cluster Shared provider config, restrictable by namespace conditions
ExternalSecret v1 Namespace Defines which secrets to sync and how to shape them
ClusterExternalSecret v1 Cluster Stamps an ExternalSecret into selected namespaces
PushSecret v1alpha1 Namespace Pushes a Kubernetes Secret or generator output to a provider
ClusterPushSecret v1alpha1 Cluster Stamps a PushSecret into selected namespaces
Generators (Password, ECRAuthorizationToken, VaultDynamicSecret, ...) generators.external-secrets.io/v1alpha1 Namespace or cluster (ClusterGenerator) Produce values instead of fetching them

Recent Developments

  • 2.x cadence (2026): 2.0 (2026-02-06) removed the unmaintained Alibaba and Device42 providers; later minors added a dedicated OpenBao provider and syncWindows (2.7), CreateOrMerge and an AWS Certificate Manager provider (2.8), Conjur PushSecret and GitHub Dependabot secrets (2.10), and Barbican application credentials (2.11).
  • v1.0 GA (2025-11-07): stable APIs and a Go multi-module layout (/apis, /runtime, per-provider and per-generator modules).
  • Release pause and recovery (2025): maintainers paused releases on 2025-07-30 over burnout, and the CNCF TOC opened a health review. New maintainers joined and releases resumed with v0.20.0 on 2025-09-22. See Explanation.
  • API migration (2025): v0.16.0 promoted v1, and v0.17.0 stopped serving v1beta1. The upgrade path is in How-to Guides.
  • Security: CVE-2026-22822 (cross-namespace getSecretKey, fixed in 1.2.0) and CVE-2026-34984 (DNS exfiltration via getHostByName, fixed after 2.2.0) both came from template functions. See Reference.

Alternatives

Alternative How it differs
SOPS Encrypts secrets in Git and decrypts at deploy; needs no external store
Sealed Secrets Controller-held key pair decrypts SealedSecret into a Secret; no external store
Vault Secrets Operator HashiCorp's Vault-specific operator with similar CRD-to-Secret sync
Secrets Store CSI Driver Mounts secrets as files directly from the provider; can avoid etcd entirely
Vault Agent injector Sidecar renders secrets into the pod; Vault only

Topic Map

  • How-to Guides: install, upgrade and v1beta1 migration, provider setup (AWS, Vault, GCP), templates, generators, PushSecret, hardening, troubleshooting
  • Reference: release and support matrix, API versions, field and policy values, provider stability, generators, flags, Helm values, metrics, ports, CVEs, hardening checklist
  • Explanation: components, reconciliation loop, provider interface, template engine, history and governance, scaling, threat model

Sources

Questions

Answered

  • Q: Can ESO push secrets to providers? Yes. The PushSecret CRD (v1alpha1) reverses the normal flow and pushes data from Kubernetes Secrets or generators to providers such as AWS Secrets Manager, HashiCorp Vault, or GCP Secret Manager. updatePolicy (Replace or IfNotExists) and deletionPolicy (None or Delete) control provider-side behavior. Only providers that implement the write path support it.

  • Q: How does ESO differ from Sealed Secrets? Sealed Secrets encrypts secrets client-side and decrypts them in-cluster using a controller-managed key pair. ESO does not encrypt secrets itself. It synchronizes secrets from external management systems (Vault, AWS SM, and more) into native Kubernetes Secrets, so it delegates trust to the external provider rather than managing its own encryption.

  • Q: What happens if the external provider is unavailable? ESO leaves the last successfully synced Kubernetes Secret in place. The ExternalSecret's Ready condition switches to SecretSyncedError, and with the flood gate enabled (the default), ExternalSecrets whose store is unhealthy are skipped until the store's health check passes. Once the provider recovers, the next reconcile updates the Secret. retrySettings (maxRetries, retryInterval) on the store tunes HTTP retries to the provider.

  • Q: Can ESO manage secrets across multiple clusters? Yes. Each cluster runs its own ESO; point every cluster's stores at the same provider, or use the Kubernetes provider (beta) to read Secrets from a remote cluster's API server. PushSecret with a shared provider can publish a Secret from one cluster for others to consume. ClusterExternalSecret only distributes across namespaces within one cluster.

  • Q: How does the template engine work? ESO renders Go templates in spec.target.template with engine v2, the only engine since v0.16. Templates can use Sprig functions (b64enc, b64dec, fromJson, toJson, upper, and 200+ more, minus env and expandenv) and ESO helpers for PKCS#12, PEM and JWK. The old v1 names such as base64encode no longer exist. The template context holds all fetched values.

  • Q: What is the difference between SecretStore and ClusterSecretStore? SecretStore is namespaced and can only be referenced by ExternalSecrets in the same namespace. ClusterSecretStore is cluster-scoped and can be referenced from any namespace unless conditions (namespaces, namespaceSelector, namespaceRegexes) restrict it.

  • Q: Is the project still maintained after the 2025 pause? Yes. Releases resumed on 2025-09-22, v1.0 shipped on 2025-11-07, and twelve 2.x minors followed through 2026-09-18.

  • Q: How does ESO handle secret rotation notifications to workloads? ESO updates the Kubernetes Secret when the external value changes. Environment variables in running pods never change, and volume-mounted Secrets update only after the kubelet sync delay, so the application must re-read the file. Use a restart controller such as Stakater Reloader or kubectl rollout restart. See How-to Guides.

  • Q: Will out-of-tree (gRPC) providers land? Not on any current plan. PR #3634 (a gRPC-endpoint provider proposal) was closed unmerged as stale on 2024-12-27, and the follow-up tracking issue #5218 ("Out of Tree Providers", opened 2025-08-28) was closed as not planned (checked 2026-09-28).

Open

  • Q: What is the performance impact of running many ExternalSecrets? Each ExternalSecret reconciles at its refreshInterval, so thousands of them can exhaust provider API quotas before ESO itself runs out of resources. Upstream publishes no benchmarks (the estimates in Reference are unsourced). No public controlled test at 1k, 5k, and 10k ExternalSecrets was found (checked 2026-09-28).
  • Q: Will ESO apply for CNCF incubation, and when? A user asked in issue #4232 (2024-12-20), which is now closed without a stated plan. As of 2026-09-28 the project is still Sandbox, the TOC's tracked item is the health issue #1819 (opened 2025-08-13), and no incubation application issue was found.
  • Q: Will PushSecret and generators graduate from v1alpha1? No timeline is published: the roadmap lists only the four core CRDs as stable v1 (checked 2026-09-28).