External Secrets Operator: From Git-Tracked Secrets to Cloud-Native Secret Management
The Evolution of Kubernetes Secret Management
For years, the conventional wisdom was simple: never store secrets in etcd. This led to elaborate workarounds—encrypted secrets in Git repositories, Vault clusters requiring dedicated teams, or custom sidecars that injected secrets from cloud providers. While security teams slept better, developers wrestled with complex workflows just to get a database password into their pods.
The landscape has fundamentally changed. Modern Kubernetes secret management has matured from "avoid etcd at all costs" to "sync from authoritative external stores with encryption-at-rest." This shift was enabled by three key developments:
- Kubernetes encryption-at-rest became standard (KMS integration on EKS, GKE, AKS)
- Workload identity patterns (IRSA, Workload Identity, Managed Identity) eliminated the need for static credentials
- Operator-based sync patterns emerged that treat external secret stores as the source of truth
External Secrets Operator (ESO) sits at the convergence of these trends: a lightweight controller that continuously syncs secrets from cloud providers into Kubernetes Secret objects, using cloud-native identity, with minimal operational overhead. It's neither a heavyweight secret vault requiring specialized teams, nor a static encryption scheme requiring manual rotations. It's secret synchronization done right for cloud-native infrastructure.
The Maturity Spectrum: Kubernetes Secret Management Approaches
Let's examine how teams manage secrets in Kubernetes, from anti-patterns to production-ready solutions.
Level 0: The Anti-Pattern
Base64-Encoded Secrets in Git — Some teams still commit Kubernetes Secret manifests directly to Git, relying on base64 encoding as "security." This is fundamentally broken: base64 is encoding, not encryption. Anyone with repository access has plaintext secrets.
Verdict: Never do this. Base64 provides zero security and creates a nightmare of secret sprawl, rotation, and audit trails.
Level 1: Encrypted Secrets in Git
Sealed Secrets (Bitnami) and similar tools encrypt secrets using a cluster-specific key, allowing you to safely store encrypted Secret manifests in Git. Developers commit sealed secrets, and a controller decrypts them at runtime.
Strengths:
- Pure GitOps workflow: all secrets are code-reviewed and versioned
- No external runtime dependencies
- Simple mental model
Limitations:
- Secret rotation requires re-encrypting and committing new sealed secrets
- No dynamic secret generation (database credentials with short TTLs)
- Secrets are effectively static configuration, not runtime data
- Disaster recovery requires backing up cluster private keys
When to use: Small teams with configuration-type secrets that rarely change, strong GitOps culture, and no compliance requirements around dynamic rotation.
Level 2: Sidecar Injection from Cloud Providers
Cloud-Specific CSI Drivers (AWS Secrets Store CSI, GCP Secret Manager CSI, Azure Key Vault CSI) mount secrets as volumes directly into pods using native cloud identity.
Strengths:
- Secrets never touch etcd—mounted as ephemeral volumes
- Cloud-native: maintained by providers, tight IAM integration
- Automatic updates when volume remounts
Limitations:
- Secrets aren't Kubernetes Secret objects—incompatible with Helm charts expecting
existingSecretreferences - Application code must read from file paths, not environment variables (without additional configuration)
- Single-cloud focus: multi-cloud setups require multiple CSI drivers
- Volume mounts don't work well for init containers or job-style workloads
When to use: Strict compliance requirements prohibiting secrets in etcd, applications designed for file-based secret injection, single-cloud environments.
Level 3: Full-Featured Secret Management (Vault)
HashiCorp Vault with Vault Agent Injector or CSI driver provides enterprise-grade secret management: dynamic secrets, detailed audit logs, advanced policies, and automatic rotation.
Strengths:
- Dynamic secret generation (database credentials rotated every few hours)
- Fine-grained access policies and comprehensive audit trails
- Secrets-as-a-service for the entire organization
- Short-lived credentials reduce exposure window
Limitations:
- Significant operational overhead: running Vault clusters (HA setup, backups, upgrades)
- Requires dedicated expertise: Vault administrators become a specialization
- Complexity can slow down development velocity
- Many teams only need 20% of Vault's features but pay 100% of the operational cost
When to use: Large enterprises already invested in Vault infrastructure, compliance requirements mandating detailed audit trails, need for dynamic secret generation across the organization.
Level 4: The Modern Pragmatic Solution
External Secrets Operator (ESO) bridges the gap between simplicity and production readiness. It treats cloud provider secret stores as the source of truth, continuously syncing them into Kubernetes Secret objects.
How it works:
- Secrets live in AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, or 20+ other providers
- ESO runs as a lightweight controller (50m CPU, 100Mi memory)
- Developers define
ExternalSecretcustom resources that reference external secrets - ESO pulls secrets using cloud-native identity (IRSA, Workload Identity, Managed Identity)
- Kubernetes Secret objects are created/updated automatically at configurable intervals
Strengths:
- Cloud-native identity: No static credentials—uses IRSA (EKS), Workload Identity (GKE), Managed Identity (AKS)
- Multi-cloud by design: Single controller handles AWS + GCP + Azure + Vault simultaneously
- Kubernetes-native UX: Secrets end up as standard Secret objects—compatible with all Helm charts and applications
- Minimal overhead: One lightweight operator per cluster, no specialized infrastructure
- Operational maturity: Apache 2.0 licensed, CNCF sandbox project, production-proven at scale
- Rotation-friendly: Update secret in cloud provider → ESO syncs automatically within configured interval
Trade-offs:
- Secrets are stored in etcd (mitigated by Kubernetes encryption-at-rest with KMS)
- Polling-based updates (configurable intervals from minutes to hours)
- Not designed for extremely short-lived secrets (minute-scale TTLs—use Vault for that)
When to use: Cloud-native teams using AWS/GCP/Azure, need for simple secret sync without heavyweight infrastructure, multi-cloud environments, teams wanting standard Kubernetes Secret objects rather than sidecar injection.
Comparison: ESO vs. Alternatives
| Approach | Secrets in etcd? | Dynamic Secrets? | Multi-Cloud? | Operational Overhead | GitOps-Friendly? |
|---|---|---|---|---|---|
| Sealed Secrets | Yes (encrypted) | No | Yes | Very Low | Excellent |
| CSI Drivers | No (volume mount) | No | Single-cloud per driver | Low | Good |
| Vault | Depends on mode | Yes | Yes | High | Fair |
| ESO | Yes (encrypted at rest) | No* | Excellent | Low | Excellent |
*ESO can sync dynamically-generated Vault secrets, but doesn't generate them itself.
Licensing & Maturity:
- ESO: Apache 2.0, CNCF Sandbox, 6K+ GitHub stars, v1.0+ Helm chart
- Sealed Secrets: Apache 2.0, stable, widely deployed
- Vault: MPL 2.0 (Enterprise features require commercial license)
- CSI Drivers: Provider-specific (typically Apache/MIT)
The Project Planton Choice: External Secrets Operator
Project Planton defaults to External Secrets Operator for Kubernetes secret management. This decision is grounded in three principles:
1. Cloud-Native by Default
Modern cloud platforms provide excellent secret stores (AWS Secrets Manager, GCP Secret Manager, Azure Key Vault) with built-in encryption, audit trails, and IAM integration. ESO leverages these native capabilities rather than reinventing secret storage.
2. Open-Source and Production-Proven
ESO is Apache 2.0 licensed with no proprietary tiers. It's mature enough for production (v1.0+ chart, CNCF sandbox) yet lightweight enough to run in every cluster without specialized teams.
3. Developer Experience Matters
Developers get standard Kubernetes Secret objects that work with any Helm chart or application. No file-path injection, no custom sidecars, no reading from specialized volume mounts. Just secretKeyRef in pod specs—the Kubernetes-native pattern everyone already knows.
Project Planton Abstractions:
The ExternalSecrets API focuses on the essential 20%:
message ExternalSecretsSpec {
// Target cluster (any K8s cluster—EKS, GKE, AKS, or on-prem)
KubernetesAddonTargetCluster target_cluster = 1;
// Poll interval (balance freshness vs. cloud API costs)
uint32 poll_interval_seconds = 2; // default: 10 seconds
// Resource tuning (CPU/memory for controller)
ExternalSecretsSpecContainer container = 3;
// Provider-specific configuration (exactly one)
oneof provider_config {
ExternalSecretsGkeConfig gke = 100; // GCP + Workload Identity
ExternalSecretsEksConfig eks = 101; // AWS + IRSA
ExternalSecretsAksConfig aks = 102; // Azure + Managed Identity
}
}
What we handle for you:
- Installing ESO Helm chart with production defaults (HA mode, leader election)
- Configuring cloud provider authentication (IRSA role creation for EKS, Workload Identity binding for GKE, etc.)
- Setting up ClusterSecretStore resources for the configured provider
- Resource tuning and namespace isolation
What you control:
- Which secrets to sync (via
ExternalSecretcustom resources in your namespaces) - Poll intervals (balance secret freshness vs. cloud API costs)
- Provider-specific IAM policies (which secrets ESO can access)
Multi-Provider Support
One ESO instance can sync secrets from multiple providers simultaneously. A single cluster might pull:
- Database credentials from AWS Secrets Manager
- API keys from GCP Secret Manager
- TLS certificates from Azure Key Vault
- Internal credentials from HashiCorp Vault
Define multiple SecretStore resources (one per provider) and ExternalSecret resources reference the appropriate store. ESO handles the rest.
Production Considerations
Security Best Practices
Least-Privilege IAM:
- EKS: Create IRSA roles limited to specific secret paths (
prod/analytics/*) - GKE: Grant GCP Service Accounts only
Secret Manager Secret Accessoron needed secrets - AKS: Use Managed Identities with Key Vault access policies scoped to specific keys
RBAC on ExternalSecret CRDs:
Treat ExternalSecret and SecretStore custom resources as sensitive. Only allow developers to create ExternalSecrets in their own namespaces, referencing pre-configured ClusterSecretStores. Restrict ClusterSecretStore creation to cluster admins.
Network Policies: Limit ESO pod egress to cloud provider API endpoints and Kubernetes API. No unrestricted internet access.
Pod Security: ESO adheres to Kubernetes restricted Pod Security Standard by default (non-root, read-only filesystem, dropped capabilities).
High Availability
Production deployments run ESO with:
- Multiple replicas (2-3) with leader election (only one actively syncs, others standby)
- Pod anti-affinity to spread replicas across nodes
- Resource limits to prevent memory leaks from affecting cluster
Project Planton configures this automatically.
Monitoring & Operational Health
Key Metrics (Prometheus):
externalsecret_sync_calls_total— total syncsexternalsecret_sync_calls_error— failed syncs (alert on this)externalsecret_status_condition— per-secret health gauge
Alerts to Configure:
- Any ExternalSecret in error state for >10 minutes
- Sync error rate spike (could indicate IAM issues or provider outage)
- No successful syncs for a canary ExternalSecret (ESO health check)
Troubleshooting Common Issues:
- Error: AccessDenied → Check IAM policy on cloud provider
- Error: Secret not found → Verify
remoteRef.keymatches secret name in provider - ExternalSecret stuck in "Pending" → Check ESO controller logs for authentication errors
- Secret not updating after external change → Verify poll interval hasn't elapsed; consider shorter interval or manual trigger
Cost Optimization
Poll Interval Tuning:
- Longer intervals (1-4 hours) for rarely-changed secrets (TLS certificates, API keys)
- Shorter intervals (15-30 minutes) for frequently-rotated credentials
- Very short intervals (<5 minutes) only for critical secrets—beware cloud API costs
Example Cost Math:
- 100 secrets polled every hour = 2,400 API calls/day = ~72,000/month
- AWS Secrets Manager: $0.05 per 10,000 API calls → ~$0.36/month
- Scale this by your secret count and poll frequency
Most teams find polling costs negligible, but avoid "poll everything every minute" anti-patterns.
Secret Rotation
ESO's polling model handles rotation elegantly:
- Rotate secret in cloud provider (AWS, GCP, Azure)
- ESO fetches new value at next poll interval
- Kubernetes Secret object updates automatically
- Pods using Secret via environment variables require restart (standard K8s behavior)
- Pods mounting Secret as volume get updated content (kubelet sync delay applies)
For zero-downtime rotations: Stage new credentials, update ExternalSecret to create a new Secret, update deployment to reference new Secret, cut over, delete old Secret.
Migration Path: From Static Secrets to ESO
Existing clusters with static Kubernetes Secrets can migrate incrementally:
- Install ESO (via Project Planton or directly)
- Populate external store with current secret values
- Create ExternalSecret resources with
creationPolicy: Merge(doesn't overwrite existing secrets) - Validate sync — ensure ESO-synced values match existing secrets
- Switch to Owner mode — change
creationPolicy: Ownerso ESO fully manages the Secret - Remove static definitions from Git/Helm/Terraform
One secret at a time, one namespace at a time. No big-bang migration required.
Common Anti-Patterns to Avoid
❌ Overly Frequent Polling
Setting poll intervals to seconds wastes cloud API calls and increases costs. Most secrets change infrequently—hourly polling is usually sufficient.
❌ Shared ClusterSecretStore Without RBAC Controls
One ClusterSecretStore with broad credentials accessible to all namespaces violates least-privilege. Use namespace-scoped SecretStores or add ClusterSecretStore conditions restricting namespace access.
❌ Hardcoding Cloud Credentials in Kubernetes
Storing AWS access keys or GCP service account JSON keys in Kubernetes Secrets defeats the purpose. Use IRSA, Workload Identity, or Managed Identity—never static credentials in production.
❌ Running Single Replica in Production
One ESO pod is a single point of failure. Run 2-3 replicas with leader election for high availability.
❌ No Monitoring on Sync Failures
Secrets are critical infrastructure. Always alert on ExternalSecret sync errors—a failed sync can lead to outages during rotations.
Conclusion: The Right Tool for Modern Cloud-Native Teams
External Secrets Operator represents a pragmatic middle ground in Kubernetes secret management. It's not as heavyweight as running Vault clusters, nor as limited as sealed secrets in Git. It leverages what cloud providers already do well (secret storage, encryption, audit) while giving you standard Kubernetes primitives (Secret objects) that work with existing tooling.
For teams running workloads on EKS, GKE, or AKS, ESO is the natural choice: cloud-native identity, minimal overhead, production-proven, and open-source. Project Planton's integration makes it even simpler—define your provider configuration, and we handle the installation, authentication setup, and best-practice defaults.
The result? Developers reference secrets naturally via secretKeyRef, operations teams manage them in cloud provider UIs (or Terraform), and security teams get audit trails and rotation without custom infrastructure. Secret management that just works.
Further Reading:
Next article