Skip to content

Secrets Management Comparison — Vault vs ESO vs SOPS

Canonical comparison of the three dominant Kubernetes secrets management approaches.

Quick Reference

Dimension HashiCorp Vault External Secrets Operator SOPS
Type Centralized secrets platform K8s sync operator File encryption tool
Latest Version v1.21.4 (Mar 2026) v2.2.0 (Mar 2026) CNCF Sandbox
Architecture Client-server (standalone) K8s controller (bridges providers) CLI (no daemon)
Dynamic secrets ✅ Yes (auto-generated, short-lived) ❌ (fetches static secrets)
Encryption-as-a-service ✅ Transit engine
PKI / Cert management
License ⚠️ BSL 1.1 Apache 2.0 MPL 2.0
Operational cost High (deploy + manage cluster) Low (K8s operator) Minimal (CLI only)

How They Work Together

flowchart LR
    SOPS_C["SOPS\n(encrypt secrets\nin Git)"] -->|"encrypted YAML\nin Git repo"| GitOps["GitOps\n(Flux / ArgoCD)"]
    GitOps -->|"deploy\nExternalSecret CRDs"| ESO_C["ESO\n(sync to K8s Secrets)"]
    ESO_C -->|"fetch dynamic\ncredentials"| Vault_C["Vault\n(generate secrets)"]
    Vault_C -->|"short-lived\nDB creds"| App["Application"]

    style SOPS_C fill:#2e7d32,color:#fff
    style ESO_C fill:#1565c0,color:#fff
    style Vault_C fill:#000,color:#fff

Key insight: These tools are complementary, not competitive. The gold-standard pattern is: SOPS encrypts configs in Git → ESO syncs external secrets to K8s → Vault generates dynamic credentials.

Feature Matrix

Feature Vault ESO SOPS
Secret storage ✅ (KV, databases, cloud) ❌ (bridges external stores) ✅ (encrypted in Git)
Dynamic secrets ✅ (DB, AWS, GCP, Azure)
Secret rotation ✅ Automatic ✅ (poll-based sync) ❌ Manual
Audit logging ✅ Comprehensive
K8s native ⚠️ (needs Vault agent/CSI) ✅ Native K8s Secrets ❌ (pre-deployment)
GitOps compatible ⚠️ (not stored in Git) ✅ CRDs in Git ✅ Encrypted files in Git
Multi-provider N/A (is the provider) ✅ (Vault, AWS, GCP, Azure) ✅ (age, AWS KMS, GCP KMS)
Complexity High Low–Medium Low

Decision Guide

Scenario Recommendation
Simple GitOps secrets SOPS — encrypt in Git, decrypt on deploy
Multi-provider K8s secret sync ESO — bridges any external provider to K8s
Dynamic DB credentials Vault — auto-generated, short-lived, auto-revoked
PKI / certificate management Vault — full CA, intermediate CAs
Small team, low complexity SOPS + ESO
Enterprise, regulated Vault + ESO
Full gold-standard stack SOPS (Git) + ESO (sync) + Vault (generate)

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 decrypts them on-cluster before applying.

sequenceDiagram
    participant Dev as Developer
    participant Git as Git Repository
    participant Flux as Flux Source Controller
    participant Kust as Kustomize Controller
    participant SOPS as SOPS Decryption
    participant K8s as Kubernetes API

    Dev->>Dev: sops --encrypt secret.yaml
    Dev->>Git: git push (encrypted YAML)
    Flux->>Git: Pull encrypted manifests
    Flux->>Kust: Forward to Kustomize Controller
    Kust->>SOPS: Detect SOPS metadata, decrypt
    SOPS->>K8s: Apply plaintext Secret

Key configuration:

  • Create .sops.yaml in repo root defining creation_rules with encrypted_regex and public key
  • Store the age/GPG private key as a K8s Secret in the flux-system namespace
  • Configure Kustomization CRD with spec.decryption.provider: sops
  • Use age over PGP for simplicity; graduate to cloud KMS (AWS KMS, GCP KMS) for production

Never apply encrypted Secrets with kubectl

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

ESO + Vault with Kubernetes Auth

ESO bridges Vault's dynamic secrets engine to native Kubernetes Secrets. The Kubernetes auth method is the recommended production pattern.

sequenceDiagram
    participant ESO as ESO Controller
    participant K8s as K8s API (ServiceAccount)
    participant Vault as Vault Server
    participant App as Application Pod

    ESO->>K8s: Read ServiceAccount JWT
    ESO->>Vault: POST /auth/kubernetes/login (JWT)
    Vault->>Vault: Validate JWT against K8s API
    Vault-->>ESO: Return Vault token
    ESO->>Vault: GET /secret/data/myapp (KV v2)
    Vault-->>ESO: Return secret payload
    ESO->>K8s: Create/Update Kubernetes Secret
    App->>K8s: Mount Secret as env/volume

Key configuration:

  • Enable Vault Kubernetes auth: vault auth enable kubernetes
  • Bind ESO ServiceAccount to a Vault role with scoped policy
  • Create SecretStore CRD referencing Vault server URL + K8s auth mount
  • Create ExternalSecret CRD mapping Vault paths to K8s Secret keys
  • Set refreshInterval (e.g., 1h) for automatic rotation sync

Full Stack: SOPS + ESO + Vault

The "gold standard" pattern combines all three tools, each handling what it does best:

Layer Tool Responsibility
Git encryption SOPS Encrypt non-sensitive configs and ESO CRDs in Git
K8s sync ESO Sync external secrets to native K8s Secrets
Secret generation Vault Generate dynamic, short-lived credentials (DB, cloud)

Workflow: Developer commits SOPS-encrypted ExternalSecret CRDs to Git. Flux decrypts and applies them. ESO reads the ExternalSecret, fetches the actual credential from Vault, and creates a K8s Secret. The application consumes the K8s Secret normally.

Start simple, add layers as needed

Most teams should start with SOPS only (simplest). Add ESO when you need multi-provider sync or rotation. Add Vault when you need dynamic credentials or PKI. Do not adopt the full stack on day one.

Operational Overhead

Dimension Vault ESO SOPS
Deployment Helm chart + HA backend (Raft or Consul) Single Helm chart (one controller + CRDs) CLI binary (no deployment)
Infrastructure 3-5 node cluster (HA), dedicated storage Runs as K8s Deployment (1-3 replicas) None
Init/unseal Manual unseal or auto-unseal via cloud KMS N/A N/A
Maintenance Regular: rotate root token, audit policies, manage leases, certificate renewal Low: monitor CRD sync status, upgrade operator Minimal: rotate encryption keys periodically
Backup Raft snapshots + storage backend backups CRDs in Git (self-recovering) Keys in secure storage; encrypted files in Git
Team skill requirement High — needs dedicated platform team Low-Medium — K8s operator familiarity Low — CLI/GitOps familiarity
On-call burden High — unsealing, lease management, audit log review Low — controller restart resolves most issues Near-zero — no running processes
Estimated FTE 0.25-0.5 FTE for operations 0.05 FTE ~0 FTE

Cost Analysis

Licensing

Tool License Open Source? Notes
Vault Community BSL 1.1 Source-available (not OSI-approved) Free for internal use; cannot host as competing service
Vault Enterprise Proprietary No Adds namespaces, DR replication, HSM, Sentinel
ESO Apache 2.0 Yes Fully open source, CNCF-affiliated
SOPS MPL 2.0 Yes CNCF Sandbox project

Infrastructure Costs

Scenario Vault (self-hosted) Vault (HCP Dedicated) ESO SOPS
Small (< 10 services) 3 EC2 t3.medium (~$100/mo) ~$450/mo (dev cluster) Free (runs in existing K8s) Free
Medium (50 services) 3 EC2 m5.large (~$300/mo) ~$5,000/mo (Essentials + per-client fees) Free Free
Large (200+ services) 5 EC2 m5.xlarge (~$700/mo) Custom pricing (negotiate) Free Free

HCP Vault per-client fees add up fast

HCP Vault Dedicated charges $72.92/month per client (any unique authenticating service/user) on Essentials and Standard tiers. At 50 clients, per-client fees alone cost $3,646/month — on top of cluster costs. Self-hosted Vault avoids this but requires operational expertise.

Total Cost by Team Size

Team Size Recommended Stack Estimated Annual Cost
1-5 engineers SOPS only ~$0 (just key management)
5-20 engineers SOPS + ESO ~$0 infrastructure + team time
20-50 engineers ESO + Vault (self-hosted) ~$5,000-15,000/yr infrastructure
50+ engineers, regulated Full stack (SOPS + ESO + Vault Enterprise) $50,000-150,000/yr (Vault Enterprise license)

Multi-cluster Secret Distribution

Capability Vault ESO SOPS
Architecture Single Vault cluster serves all K8s clusters ESO instance per cluster, all pointing to same provider Encrypted files in shared Git repo
Cross-cluster sync Native — each cluster authenticates independently Per-cluster ESO + shared SecretStore backend Git-based — each cluster decrypts independently
PushSecret N/A (pull model) ESO PushSecret CRD pushes to remote clusters N/A
Consistency Strong — single source of truth in Vault Eventual (poll interval, default 1h) Manual — requires Git push + Flux reconcile
Secret scoping Vault namespaces + policies per cluster Namespace-scoped SecretStore per tenant .sops.yaml creation rules per path
Failure mode Cluster loses access if Vault is down Secrets persist in K8s; no updates until ESO reconnects Secrets persist; no updates until Git sync

Multi-cluster Patterns

Centralized Vault (hub-and-spoke):

  • Single Vault cluster with Kubernetes auth enabled per target cluster
  • Each cluster's ESO authenticates via its own ServiceAccount
  • Vault policies scope access per cluster/namespace
  • Best for: regulated environments needing centralized audit

Distributed ESO with shared backend:

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

Git-centric (SOPS + Flux):

  • Encrypted secrets in a shared Git repo with per-cluster overlays
  • Each cluster runs Flux and decrypts with its own age key
  • Best for: teams that want everything in Git, no external dependencies

Compliance Considerations

Framework Vault ESO SOPS
SOC 2 Strong — comprehensive audit logging, access controls, encryption at rest/transit, lease management Partial — inherits audit from backend provider; add K8s audit logging Partial — Git commit log as audit trail; no runtime audit
HIPAA Strong — encryption-as-a-service (Transit engine), dynamic credentials, automatic rotation, detailed audit logs Depends on backend — if backed by Vault or AWS SM, inherits their HIPAA posture Weak — no automatic rotation, no access audit, manual key management
PCI-DSS Strong — key management (HSM support in Enterprise), access controls, tokenization via Transit engine Partial — no native key management; depends on backend Weak — no key ceremony support, no runtime access controls
FedRAMP HCP Vault Dedicated is FedRAMP authorized (via AWS GovCloud) N/A — not an independent service N/A
GDPR Supports data residency via Vault namespaces Depends on backend provider's data residency Encryption keys can be region-scoped via cloud KMS

Compliance does not mean just one tool

No single tool satisfies all compliance requirements alone. Vault provides the strongest audit and key management story, but your compliance posture also depends on K8s RBAC, network policies, cloud provider controls, and organizational processes. Use ESO and SOPS to complement Vault, not replace it.

Sources