Storing Secrets in Kubernetes with OpenBao: Agent Injector vs CSI Provider vs External Secrets Operator
Compare the three main patterns for injecting OpenBao secrets into Kubernetes workloads — Vault Agent Injector, the Secrets Store CSI Driver, and External Secrets Operator — on security, overhead, rotation, and setup complexity.
Quick Navigation
Difficulty: Intermediate
Estimated Time: 15-20 minutes
Prerequisites: Basic Kubernetes knowledge, An OpenBao or Vault cluster reachable from the cluster, Familiarity with Kubernetes Secrets and RBAC
What You'll Learn
This guide compares the three dominant patterns for getting OpenBao secrets into Kubernetes workloads:
- Agent Injector - Sidecar-based secret delivery with in-memory rotation
- CSI Provider - Volume-mounted secrets via the Secrets Store CSI Driver
- External Secrets Operator (ESO) - Syncing OpenBao secrets into native Kubernetes Secrets
- Comparison Matrix - Security, overhead, rotation, complexity, and scalability side by side
- Scoring - A weighted score for each option
- Recommendations - Which pattern fits which workload, and why production clusters often combine them
Prerequisites
- Basic Kubernetes cluster administration experience
- An OpenBao (or Vault) cluster reachable from the Kubernetes cluster
- Familiarity with Kubernetes Secrets, RBAC, and CRDs
Related Tutorials
- Main Tutorials Hub - Step-by-step implementation guides
- Kubernetes Tutorials - Container orchestration guides
- Kubernetes Security Best Practices - Hardening guidance for clusters handling sensitive data
Introduction
OpenBao — the open-source fork of HashiCorp Vault — is increasingly the secrets backend of choice for teams that want a vendor-neutral, community-governed store for credentials, PKI material, and encryption keys. The harder question is rarely "which secrets engine," it's "how do secrets actually get from OpenBao into a running pod." Three patterns dominate: an Agent Injector sidecar, the Secrets Store CSI Driver, and External Secrets Operator (ESO). Each makes a different trade-off between zero-trust security, operational overhead, and how much an existing application has to change to use it.
The Three Patterns
Agent Injector
A mutating webhook adds an init container and a sidecar to every annotated pod. The sidecar authenticates to OpenBao directly, renders secrets to an in-memory tmpfs volume as files, and keeps watching for renewal — reloading the file in place when a lease rotates, without the application needing to know anything about OpenBao. Secrets never pass through etcd and never sit on the API server.
CSI Provider
The Secrets Store CSI Driver runs as a per-node DaemonSet. A SecretProviderClass custom resource tells the driver's OpenBao provider what to fetch, and the driver mounts the result as a read-only volume backed by tmpfs at pod start. There's no per-pod sidecar — the driver is shared across every pod on the node — but there's also no built-in file-reload-on-rotation without an optional sync-to-Kubernetes-Secret add-on, and the application still needs a restart or a file-watcher to pick up rotated values.
External Secrets Operator (ESO)
A cluster-wide controller polls OpenBao (or Vault) on an interval defined by an ExternalSecret custom resource and writes the result into a native Kubernetes Secret object. Applications consume it exactly like any other Kubernetes Secret — as an env var or a mounted volume — with zero code or packaging changes. The trade-off is that the secret now exists in etcd, so its protection depends entirely on etcd encryption-at-rest and tight RBAC on the Secret resource.
Comparison Matrix
| Critère | Agent Injector | CSI Provider | External Secrets Operator |
|---|---|---|---|
| Principe | Sidecar dans chaque pod | Volume monté via CSI driver | Sync vers K8s Secret natifs |
| Overhead ressources | Élevé (1 sidecar/pod, +50-100MB RAM/pod) | Faible (pas de sidecar, driver partagé au niveau node) | Faible (1 controller central) |
| Sécurité / Zero-trust | Secrets jamais dans etcd, rotation en mémoire | Secrets en tmpfs (RAM), pas dans etcd | Secrets stockés en clair dans etcd (sauf chiffrement at-rest) |
| Rotation automatique | Native, agent watch + reload | Dépend du polling interval, pas de reload auto app | Polling périodique, nécessite restart pod pour reload |
| Complexité setup | Webhook + annotations par pod | Driver + SecretProviderClass CRD | CRD ExternalSecret + SecretStore |
| Compat apps existantes | App doit lire des fichiers (pas toujours natif) | Idem, montage fichier | App consomme un Secret K8s standard, zero refactor |
| Latence démarrage pod | Init container ajoute délai | Rapide, driver déjà résident | Secret déjà sync avant déploiement |
| Observabilité/Debug | Logs sidecar par pod | Logs driver niveau node | Controller centralisé, events K8s clairs |
| Scalabilité (many pods) | Coût linéaire (1 agent/pod) | Driver partagé, plus léger à l'échelle | Un seul controller, très scalable |
| Maturité écosystème OpenBao | Injector Vault mature, portage OpenBao récent | Provider generic-CSI, dépend du support OpenBao | ESO supporte Vault/OpenBao provider officiellement |
| Risque exposition secrets | Faible (mémoire pod uniquement) | Faible (tmpfs) | Moyen-élevé (etcd, sauf encryption-at-rest + RBAC strict) |
Score Global
Scored out of 10, weighted toward security and practicality:
| Injector | CSI | ESO | |
|---|---|---|---|
| Score | 8/10 | 7.5/10 | 7/10 |
The Injector leads on the security axis that matters most for a secrets pipeline — secrets never touch etcd — at the cost of a sidecar on every pod. CSI closes most of that resource gap while keeping the same tmpfs-only guarantee. ESO trades some of that isolation for near-zero application friction, which is why it still scores well despite depending on etcd encryption-at-rest to match the other two.
Recommendations by Context
- Sécurité maximale, apps modernes → Agent Injector : meilleur choix si les apps peuvent lire des fichiers, et que le coût sidecar est acceptable.
- Beaucoup de pods, besoin d'efficacité → CSI Provider : bon compromis sécurité/performance à l'échelle, sans sidecar par pod.
- Legacy apps, besoin de simplicité, équipe déjà familière avec K8s Secrets → External Secrets Operator : le plus simple à adopter mais attention à chiffrer etcd at-rest et limiter le RBAC sur les Secret.
In many production setups, teams don't pick just one: ESO covers legacy and simple applications, while Injector or CSI handles sensitive workloads — payment processing, PII, cryptographic key material — where the extra operational cost buys a real reduction in blast radius.
Conclusion
There's no single right answer to "how should OpenBao secrets reach my pods" — the three patterns sit on a spectrum between zero-trust isolation and zero-friction adoption. Agent Injector and the CSI Provider both keep secrets out of etcd entirely, which matters most for regulated or high-value workloads; External Secrets Operator trades that isolation for compatibility with any application that already reads a Kubernetes Secret, provided etcd encryption-at-rest and RBAC are locked down. Most mature platform teams end up running more than one pattern side by side, matching the tool to the sensitivity of the workload rather than standardizing on a single mechanism cluster-wide.
Tags: #OpenBao #Vault #Kubernetes #SecretsManagement #CSIDriver #ExternalSecretsOperator #ZeroTrust #DevSecOps