Skip to content

Secrets Management Comparison — Vault vs ESO vs SOPS

Summary

Canonical comparison of the three most common approaches to secrets for Kubernetes and GitOps: a central secrets platform (HashiCorp Vault), a sync operator (External Secrets Operator), and file encryption in Git (SOPS). They solve different layers and are usually combined rather than chosen exclusively. OpenBao, the MPL-2.0 fork of Vault, is covered as an alternative inside the Vault topic (Vault and OpenBao at a Glance).

Quick Reference

Dimension HashiCorp Vault External Secrets Operator SOPS
Type Centralized secrets platform Kubernetes sync operator File encryption CLI and Go library
Latest Version 2.1.1 (2026-09-16) 2.11.0 (2026-09-18) 3.13.3 (2026-07-23)
Architecture Client-server cluster (Integrated Storage / Raft) Kubernetes controller (three Deployments: core, webhook, cert controller) CLI (no daemon)
Dynamic secrets Yes (database, cloud, SSH, PKI; auto-revoked leases) Partly, via generators (VaultDynamicSecret, ECRAuthorizationToken, Password, v1alpha1) No
Encryption as a service Yes (Transit engine) No No (encrypts files, not a service)
PKI / certificates Yes (root and intermediate CAs, ACME) No No
License BSL 1.1 (source-available; Enterprise commercial) Apache-2.0 MPL-2.0
Governance IBM (HashiCorp acquisition closed 2025-02-27) CNCF Sandbox CNCF Sandbox; TOC health review open since 2026-03 (cncf/toc#2098)
Open-source alternative OpenBao 2.7.0 (MPL-2.0, OpenSSF) Vault Secrets Operator (Vault-only), Secrets Store CSI Driver Sealed Secrets
Operational cost High (HA cluster, unseal, upgrades, audit) Low (operator; upgrade often, only the newest minor is supported) Minimal (CLI; key distribution is on you)

Which One Should I Pick?

The decision usually starts from where secrets live today and whether you need credentials generated on demand.

flowchart TD
    Q1{"Need dynamic credentials,<br/>PKI or encryption as a service?"}
    Q1 -->|"Yes"| Q2{"Strict OSI open-source<br/>license required?"}
    Q2 -->|"Yes"| BAO["OpenBao<br/>(MPL-2.0 Vault fork)"]
    Q2 -->|"No"| VAULT["HashiCorp Vault<br/>(CE, Enterprise or HCP)"]
    Q1 -->|"No"| Q3{"Secrets already in a cloud<br/>secret manager or Vault?"}
    Q3 -->|"Yes"| Q4{"Consumers run on<br/>Kubernetes?"}
    Q4 -->|"Yes"| ESO["External Secrets Operator<br/>(sync into K8s Secrets)"]
    Q4 -->|"No"| SDK["Provider SDK / CLI<br/>or Vault Agent"]
    Q3 -->|"No"| Q5{"Want secrets versioned<br/>in Git with no server?"}
    Q5 -->|"Yes"| SOPS["SOPS<br/>(age or cloud KMS)"]
    Q5 -->|"No"| CLOUD["Adopt a cloud secret manager,<br/>then add ESO"]
    VAULT -.->|"deliver to pods"| K8S["ESO, VSO or CSI provider"]
    BAO -.->|"deliver to pods"| K8S
Scenario Recommendation
Simple GitOps secrets, small team SOPS with age: encrypt in Git, Flux decrypts on-cluster
Secrets already in AWS SM, GCP SM, Azure Key Vault ESO with a ClusterSecretStore per provider
Dynamic database or cloud credentials Vault (or OpenBao): short-lived, auto-revoked leases
Internal PKI / certificate authority Vault PKI engine (or OpenBao)
Application-level encryption, signing, HMAC Vault Transit
Strict OSI license requirement for the central store OpenBao instead of Vault
Enterprise, regulated, central audit of every read Vault (Enterprise or HCP) + ESO or VSO
Secrets must never be stored in etcd Secrets Store CSI Driver or Vault Agent injection (not ESO or SOPS-to-Secret)
Layered stack SOPS (bootstrap secrets in Git) + ESO (sync) + Vault (generate)

How They Work Together

The layered pattern uses each tool for what it does best: SOPS protects the few bootstrap credentials that must live in Git, ESO carries references (not values) through GitOps, and Vault issues the real credentials.

flowchart LR
    DEV["Developer"] -->|"sops encrypt<br/>(bootstrap creds)"| GIT["Git repository"]
    DEV -->|"ExternalSecret manifests<br/>(references only)"| GIT
    GIT --> FLUX["Flux kustomize-controller<br/>(decrypts SOPS)"]
    FLUX -->|"apply"| ESO_C["ESO core controller"]
    ESO_C -->|"Kubernetes auth,<br/>read KV or lease creds"| VAULT_C["Vault<br/>(KV, database engine)"]
    ESO_C -->|"create / update"| SEC["Kubernetes Secret"]
    SEC -->|"env or volume"| APP["Application Pod"]

    style ESO_C fill:#1565c0,color:#fff
    style VAULT_C fill:#000,color:#fff

Complementary, not competitive

These tools sit at different layers. ExternalSecret manifests contain only references, so they can be committed in plaintext; SOPS is needed only for values that must be in Git (for example, the credentials a SecretStore uses when workload identity is unavailable).

Feature Matrix

Feature Vault ESO SOPS
Secret storage Yes (KV v2, versioned) No (bridges external stores) Yes (encrypted files in Git)
Dynamic secrets Yes (database, AWS, GCP, Azure, SSH, Kubernetes) Partly (generators, v1alpha1) No
Secret rotation Automatic for dynamic secrets and database static roles; KV not rotated Propagates provider changes on refreshInterval (default 1h) Manual (updatekeys + rotate)
Audit logging Yes, audit devices log every request No own audit log; relies on provider logs and Kubernetes audit Via KMS / Key Vault / Vault-OpenBao Transit logs; optional PostgreSQL decrypt log; none for age or PGP
Kubernetes integration Kubernetes auth, Agent injector, CSI provider, Vault Secrets Operator (VSO), or ESO Native Kubernetes Secrets via CRDs Flux native; Argo CD via KSOPS or helm-secrets
GitOps compatible Values not in Git; config via Terraform Yes (CRDs in Git hold references only) Yes (encrypted files in Git)
Providers / key backends Is the provider; auto-unseal via cloud KMS or HSM About 40 providers (ten stable), including Vault, OpenBao, AWS, GCP, Azure age (incl. SSH, plugin, post-quantum), PGP, AWS KMS, GCP KMS, Azure Key Vault, Vault/OpenBao Transit, HuaweiCloud KMS
Push to provider Enterprise secrets sync to cloud secret managers PushSecret (v1alpha1) No
Complexity High Low to medium Low

Integration Patterns

SOPS + Flux GitOps Pipeline

The most common GitOps secrets pattern. SOPS encrypts secret values in YAML (keys remain plaintext for readable diffs), and Flux's kustomize-controller decrypts them on-cluster before applying. Details: SOPS GitOps decryption models.

sequenceDiagram
    participant Dev as Developer
    participant Git as Git Repository
    participant Src as Flux source-controller
    participant Kust as Flux kustomize-controller
    participant K8s as Kubernetes API

    Dev->>Dev: sops encrypt secret.yaml (age recipient)
    Dev->>Git: git push (encrypted YAML)
    Src->>Git: Fetch revision
    Src-->>Kust: Artifact ready
    Kust->>Kust: Detect sops metadata, decrypt with age key Secret or KMS identity
    Kust->>K8s: Server-side apply plaintext Secret

Key configuration:

  • Create .sops.yaml in the repository root with creation_rules (path_regex, encrypted_regex: ^(data|stringData)$, recipients).
  • Store the age private key as a Kubernetes Secret in flux-system, or use cloud KMS / OpenBao workload identity.
  • Set spec.decryption.provider: sops on the Flux Kustomization.
  • Prefer age over PGP (the SOPS docs recommend age; PGP is not deprecated). Move to cloud KMS when you need central revocation and audit.

Never apply encrypted Secrets with kubectl

SOPS-encrypted Secrets are designed for consumption by kustomize-controller. Applying them directly with kubectl apply creates a Secret containing ciphertext, not plaintext.

ESO + Vault with Kubernetes Auth

ESO reads static secrets from Vault KV through a SecretStore, and can request dynamic credentials through the VaultDynamicSecret generator. Kubernetes auth is the usual production pattern. Details: ESO how-to guides and the ESO Vault provider.

sequenceDiagram
    participant ESO as ESO core controller
    participant K8s as Kubernetes API
    participant Vault as Vault server
    participant App as Application Pod

    ESO->>K8s: Request ServiceAccount token (TokenRequest)
    ESO->>Vault: POST /v1/auth/kubernetes/login (JWT, role)
    Vault->>K8s: TokenReview (validate JWT)
    Vault-->>ESO: Vault token with policies
    ESO->>Vault: GET /v1/secret/data/myapp (KV v2)
    Vault-->>ESO: Secret payload
    ESO->>K8s: Create or update Kubernetes Secret
    App->>K8s: Consume Secret as env or volume

Key configuration:

  • Enable Vault Kubernetes auth: vault auth enable kubernetes.
  • Bind the ESO ServiceAccount to a Vault role with a scoped policy.
  • Create a SecretStore (or ClusterSecretStore with namespace conditions) with the Vault URL and Kubernetes auth mount.
  • Create ExternalSecret resources mapping Vault paths to Secret keys, with a refreshInterval (for example, 1h).
  • Alternative: HashiCorp's own Vault Secrets Operator provides similar CRD-to-Secret sync, for Vault only.

Layered Stack: SOPS + ESO + Vault

Layer Tool Responsibility
Git encryption SOPS Encrypt the few bootstrap values that must live in Git
Kubernetes sync ESO Turn ExternalSecret references into native Kubernetes Secrets
Secret generation and storage Vault Store KV secrets; issue dynamic, short-lived credentials (database, cloud)

Workflow: a developer commits plaintext ExternalSecret manifests (references only) and, if needed, SOPS-encrypted bootstrap credentials. Flux decrypts and applies them. ESO fetches the actual values from Vault and creates Kubernetes Secrets, which the application consumes normally.

Start simple, add layers as needed

Many teams start with SOPS only. Add ESO when a central store exists or multi-cluster sync is needed. Add Vault (or OpenBao) when you need dynamic credentials, PKI, or central audit. Avoid adopting the full stack on day one.

Operational Overhead

Dimension Vault ESO SOPS
Deployment Helm chart or packages; Integrated Storage (Raft) recommended, Consul legacy Helm chart: core controller, webhook and cert controller Deployments + CRDs Single binary (no deployment)
Infrastructure 3 or 5 Raft voters (5 across 3 zones for production), SSD storage Runs in the existing cluster; HA needs replicaCount > 1 and leaderElect: true None
Init / unseal Shamir unseal or auto-unseal via cloud KMS (HSM in Enterprise) N/A N/A
Maintenance Upgrades (CE patches only the newest line), policies, leases, audit devices, snapshots Upgrade every few weeks (only the newest minor is supported); monitor sync status Key distribution and rotation; updatekeys / rotate after staff changes
Backup Raft snapshots (test restores) CRDs in Git; values live in the provider Keys in secure storage; encrypted files in Git
Team skill High: needs a platform team Low to medium: Kubernetes operator familiarity Low: CLI and GitOps familiarity
On-call burden High: quorum, unseal, lease exhaustion, audit device failures Low: provider outages leave the last synced Secret in place Near zero: no running process
Estimated FTE (estimate, unsourced) 0.25-0.5 ~0.05 ~0

Cost Analysis

Licensing

Tool License OSI open source? Notes
Vault Community BSL 1.1 (1.15.0 and later; each release converts to MPL 2.0 after four years) No (source-available) Free to use; BSL restricts offering competing hosted products
Vault Enterprise Commercial No Namespaces, DR and performance replication, HSM, Sentinel, secrets sync; IBM Support Cycle-2 lifecycle since 2.0
OpenBao MPL 2.0 Yes Linux Foundation / OpenSSF; namespaces included, no DR/performance replication
ESO Apache-2.0 Yes CNCF Sandbox; Red Hat ships a supported OpenShift build
SOPS MPL-2.0 Yes CNCF Sandbox; licensing is the subject of the open TOC health review

Infrastructure Costs

Rough estimates

The self-hosted figures below are order-of-magnitude estimates (instance counts follow HashiCorp's 3 or 5 voter guidance and hardware sizing), not quotes. HCP Vault Dedicated is billed as an hourly cluster base cost plus, on Essentials and Standard, a per-client charge; check the official pricing page for current numbers.

Scenario Vault (self-hosted, estimate) Vault (HCP Dedicated) ESO SOPS
Small (< 10 services) 3 small VMs (~$100/mo) Development tier (single node, 25-client limit, no SLA) or Essentials Free (runs in existing cluster) Free
Medium (50 services) 3 mid-size VMs (~$300/mo) Essentials: cluster base + per-client fees Free Free
Large (200+ services) 5 larger VMs (~$700/mo) Standard or contract pricing Free Free

HCP Vault per-client fees

Infisical's Vault pricing guide (2026 edition, checked 2026-09-28) lists $72.92 per client per month on Essentials and Standard, on top of about $1,152 per month for an Essentials cluster. HashiCorp's tiers and features page confirms that Essentials adds a flat hourly cost per Vault client, counted once per monthly billing period. A client is any unique entity that authenticates (application, service, or user), so per-client fees can exceed the cluster cost at modest scale. Self-hosted Community Edition has no per-client fee but needs operational expertise.

Total Cost by Team Size

These are illustrative estimates (unsourced) to show relative scale, not budgets.

Team size Typical stack Estimated annual cost
1-5 engineers SOPS only ~$0 (key management time)
5-20 engineers SOPS + ESO (+ cloud secret manager) Cloud secret manager fees + team time
20-50 engineers ESO + Vault CE or OpenBao (self-hosted) ~$5,000-15,000/yr infrastructure (estimate)
50+ engineers, regulated SOPS + ESO + Vault Enterprise or HCP License or HCP fees dominate. Not published for self-managed Vault Enterprise ("Contact sales" on hashicorp.com/pricing); HCP Vault Dedicated bills per cluster-hour plus, on Essentials and Standard, a per-client charge (HCP pricing definitions, checked 2026-09-28)

Multi-cluster Secret Distribution

Capability Vault ESO SOPS
Architecture One Vault cluster serves many Kubernetes clusters ESO per cluster, all pointing to the same provider Encrypted files in a shared Git repository
Cross-cluster access Each cluster authenticates via its own Kubernetes auth mount Per-cluster ESO + shared backend, or the Kubernetes provider (beta) reading a remote cluster Each cluster decrypts independently
Push model Pull model; Enterprise secrets sync pushes to cloud secret managers PushSecret (v1alpha1) writes to a provider, including a remote cluster via the Kubernetes provider N/A
Consistency Single source of truth Eventual (per refreshInterval, default 1h) Git push + GitOps reconcile
Secret scoping Policies per auth role; namespaces (Enterprise or OpenBao) Namespaced SecretStore, ClusterSecretStore conditions .sops.yaml creation rules per path
Failure mode New reads fail if Vault is unreachable; existing leases run to TTL Last synced Secret stays; no updates until the provider recovers Secrets persist; no updates until Git sync

Multi-cluster Patterns

Centralized Vault (hub and spoke):

  • One Vault cluster with a Kubernetes auth mount per target cluster.
  • Each cluster's ESO (or VSO) authenticates with its own ServiceAccount.
  • Vault policies scope access per cluster and namespace.
  • Best for: regulated environments that need centralized audit.

Distributed ESO with a shared backend:

  • ESO in every cluster, each with a ClusterSecretStore pointing to the same provider (AWS SM, GCP SM, Azure Key Vault).
  • Secrets are defined once in the provider and synced everywhere.
  • Best for: cloud-native teams using managed secret stores.

Git-centric (SOPS + Flux):

  • Encrypted secrets in a shared Git repository with per-cluster overlays.
  • Each cluster runs Flux and decrypts with its own age key or KMS identity.
  • Best for: teams that want everything in Git and no external dependency.

Compliance Considerations

This table summarizes capabilities relevant to common frameworks; it is not a compliance attestation.

Framework Vault ESO SOPS
SOC 2 Strong: audit device logs every request, ACL policies, encryption at rest and in transit, leases Partial: inherits audit from the backend; add Kubernetes audit logging Partial: Git history plus KMS logs; no runtime audit with age or PGP
HIPAA Strong: Transit, dynamic credentials, audit logs Depends on the backend (Vault, AWS SM, etc.) Weak: no automatic rotation; access audit only with a KMS backend
PCI-DSS Strong: HSM (Enterprise), access controls; tokenization via the Transform engine (Enterprise ADP) Partial: no own key management; depends on the backend Weak: no key ceremony support, no runtime access controls
FedRAMP No FedRAMP authorization announced for HCP Vault Dedicated; FedRAMP was a roadmap item in 2024 (TechTarget), with nothing newer found (checked 2026-09-28). Self-managed Vault Enterprise offers FIPS builds N/A (not a service) N/A
GDPR Data residency follows where clusters run; namespaces (Enterprise) separate tenants Depends on the backend's data residency Region-scoped cloud KMS keys

Compliance does not mean just one tool

No single tool satisfies a framework on its own. Vault provides the strongest audit and key management story, but the overall posture also depends on Kubernetes RBAC, etcd encryption at rest, network policies, cloud controls, and process. ESO and SOPS complement a central store; they do not replace its audit trail.

Sources