Secret Management: HashiCorp Vault vs AWS Secrets Manager vs Kubernetes Secrets
Compare Vault, AWS Secrets Manager, and Kubernetes Secrets. Learn about dynamic secrets, rotation, injection patterns, and when to use each tool.
Infrastructure engineer with 10+ years building production systems on AWS, GCP,…

Your Secrets Are Probably Less Secret Than You Think
Every application has secrets -- database passwords, API keys, TLS certificates, encryption keys. The question is where they live and who can access them. Secret management is the practice of storing, distributing, rotating, and auditing these credentials securely. Get it wrong, and a single leaked secret can compromise your entire infrastructure.
The three dominant approaches in 2026 are Kubernetes Secrets (convenient but dangerously basic), AWS Secrets Manager (managed and integrated), and HashiCorp Vault (powerful but complex). Each makes fundamentally different tradeoffs. Picking the wrong one wastes months of engineering time; picking the right one depends on your infrastructure, compliance requirements, and team size.
What Is Secret Management?
Definition: Secret management is the practice of securely storing, accessing, distributing, and rotating sensitive credentials such as API keys, database passwords, TLS certificates, and encryption keys. It encompasses access control, audit logging, automatic rotation, and encryption at rest to prevent unauthorized access to secrets.
Kubernetes Secrets: The Convenient Trap
Kubernetes Secrets are the default way to pass sensitive data to pods. They're built into the platform, require no additional infrastructure, and every K8s developer already knows how to use them. That convenience is exactly why they're dangerous.
How Kubernetes Secrets Work
- You create a Secret object in the cluster (via YAML manifest or
kubectl create secret). - The secret data is base64-encoded (not encrypted) and stored in etcd.
- Pods reference the secret as environment variables or mounted volumes.
- The kubelet fetches the secret from the API server and makes it available to the container.
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
namespace: production
type: Opaque
data:
username: YWRtaW4=
password: cDRzc3cwcmQ=
Watch out: Base64 is encoding, not encryption. Anyone with
kubectl get secret -o yamlpermissions can read every secret in a namespace. By default, etcd stores secrets in plaintext. You must enable etcd encryption at rest and restrict RBAC access to Secret objects to have any real security.
Hardening Kubernetes Secrets
- Enable encryption at rest for etcd using AES-CBC or KMS provider integration.
- Restrict RBAC: limit
getandliston Secret resources to only the service accounts that need them. - Use Sealed Secrets (Bitnami) or SOPS to encrypt secrets in Git, decrypted only at deploy time.
- Mount secrets as files, not environment variables -- environment variables leak into crash dumps, logs, and child processes.
AWS Secrets Manager: Managed and Integrated
AWS Secrets Manager is a fully managed service for storing and rotating secrets. It integrates natively with IAM, RDS, and other AWS services, making it the path of least resistance for AWS-heavy environments.
How AWS Secrets Manager Works
- You store a secret (key-value pair, JSON blob, or binary) via the console, CLI, or SDK.
- Secrets are encrypted at rest with KMS (you choose the key).
- Applications retrieve secrets at runtime via the AWS SDK or CLI.
- IAM policies control which identities can read which secrets.
- Automatic rotation can be configured with a Lambda function that updates the secret and the target service.
import boto3
import json
client = boto3.client('secretsmanager', region_name='us-east-1')
response = client.get_secret_value(SecretId='production/db-credentials')
secret = json.loads(response['SecretString'])
db_host = secret['host']
db_password = secret['password']
Automatic Rotation
Secrets Manager can rotate secrets on a schedule (e.g., every 30 days). For RDS databases, AWS provides pre-built Lambda rotation functions. For custom services, you write a Lambda that updates the secret and the target system in a multi-step process:
- createSecret -- Generate new credentials and store them as the pending version.
- setSecret -- Update the target service with the new credentials.
- testSecret -- Verify the new credentials work.
- finishSecret -- Promote the pending version to current.
HashiCorp Vault: Power and Complexity
Vault is the Swiss Army knife of secret management. It handles static secrets, dynamic secrets, encryption as a service, certificate issuance, and more. It's also the most complex option, requiring dedicated operational expertise.
Key Vault Capabilities
- Dynamic secrets -- Vault generates short-lived credentials on demand. Need a database password? Vault creates a temporary user with a TTL, and revokes it automatically. No shared passwords, no rotation headaches.
- Encryption as a service -- The Transit secrets engine encrypts/decrypts data without exposing keys. Your application sends plaintext; Vault returns ciphertext. The key never leaves Vault.
- PKI engine -- Vault acts as a certificate authority, issuing X.509 certificates with configurable TTLs. Integrates with service meshes for automatic mTLS.
- Leases and revocation -- Every secret has a lease. When it expires, Vault revokes the credentials. You can also revoke all secrets for a compromised path instantly.
# Enable the database secrets engine
vault secrets enable database
# Configure PostgreSQL connection
vault write database/config/production \
plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@db.example.com:5432/prod" \
allowed_roles="readonly" \
username="vault-admin" \
password="admin-password"
# Create a role that generates short-lived credentials
vault write database/roles/readonly \
db_name=production \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
# Get dynamic credentials
vault read database/creds/readonly
# Returns: username=v-token-readonly-abc123 password=xyz789 ttl=1h
Pro tip: Vault's dynamic secrets are its killer feature. Instead of rotating a shared password, every consumer gets unique, short-lived credentials. If one is compromised, you revoke it without affecting anyone else. This is a fundamentally better security model.
Comparison: Vault vs AWS Secrets Manager vs Kubernetes Secrets
| Feature | K8s Secrets | AWS Secrets Manager | HashiCorp Vault |
|---|---|---|---|
| Encryption at rest | Optional (etcd config) | Always (KMS) | Always (seal/unseal) |
| Dynamic secrets | No | No | Yes |
| Automatic rotation | No | Yes (Lambda-based) | Yes (lease-based) |
| Audit logging | API server audit logs | CloudTrail | Built-in audit device |
| Access control | RBAC | IAM policies | ACL policies + Sentinel |
| Multi-cloud | K8s only | AWS only | Any infrastructure |
| Operational burden | Minimal | Minimal | Significant |
| Cost | Free (included) | $0.40/secret/mo + $0.05/10K API calls | Free (OSS) or $1.58/hr (Enterprise) |
| Best for | Dev/staging | AWS-native production | Multi-cloud, compliance-heavy |
Decision Tree: Which Should You Choose?
- Are you running exclusively on AWS? Start with AWS Secrets Manager. It's managed, integrates with IAM, and handles rotation. You'll be productive in an afternoon.
- Do you need dynamic secrets or encryption as a service? Vault is the only option. The operational cost is justified when you need short-lived credentials or centralized key management.
- Are you multi-cloud or on-prem? Vault is cloud-agnostic. AWS Secrets Manager locks you in. For multi-cloud, Vault's flexibility outweighs its complexity.
- Is this a small team with simple needs? Use Kubernetes Secrets with etcd encryption and RBAC hardening. Add Sealed Secrets for GitOps. Graduate to Vault or a managed service when you outgrow it.
- Do you have compliance requirements (SOC 2, PCI, HIPAA)? You need audit logging and rotation. AWS Secrets Manager covers this for AWS workloads. Vault covers it for everything else.
Secret Injection Patterns
How secrets reach your application matters as much as where they're stored:
Environment Variables
The simplest approach. Secrets are injected as env vars at container startup. The downside: they're visible in /proc/<pid>/environ, can leak into logs, and persist in crash dumps. Use them only for non-critical configuration.
Mounted Volumes
Secrets are written to a tmpfs volume and mounted into the container. The application reads them from disk. Kubernetes does this natively. Vault's Agent Injector sidecar does the same with Vault secrets. This is safer than env vars because files don't leak into process metadata.
API-Based Retrieval
The application calls the secret manager's API directly at startup or on-demand. This gives you the most control -- you can cache, refresh, and handle errors explicitly. The trade-off is that your application code is now coupled to a specific secret manager SDK.
# Vault Agent Injector annotation for Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "api-server"
vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/readonly"
spec:
containers:
- name: api-server
image: api-server:latest
Frequently Asked Questions
Are Kubernetes Secrets encrypted?
Not by default. Kubernetes Secrets are base64-encoded and stored in etcd in plaintext unless you explicitly enable encryption at rest. Base64 is not encryption -- it's trivially reversible. Enable etcd encryption with an AES-CBC or KMS provider and restrict RBAC access to Secret objects.
What are dynamic secrets and why do they matter?
Dynamic secrets are credentials generated on-demand with a limited TTL. Instead of a shared database password that lives forever, each consumer gets unique, time-limited credentials. When the TTL expires, the credentials are automatically revoked. This eliminates shared secrets and limits the impact of credential theft.
How much does AWS Secrets Manager cost?
AWS Secrets Manager charges $0.40 per secret per month plus $0.05 per 10,000 API calls. For a team with 50 secrets accessed frequently, expect roughly $20-30/month. This is significantly cheaper than running and operating a Vault cluster, which requires dedicated infrastructure and engineering time.
Can I use Vault with Kubernetes?
Yes. Vault integrates with Kubernetes through the Vault Agent Injector (sidecar that writes secrets to shared volumes), the Vault CSI Provider (mounts secrets via the Container Storage Interface), or direct API calls from your application using Kubernetes service account authentication.
Should I store secrets in Git?
Never store plaintext secrets in Git. If you want secrets in version control for GitOps workflows, encrypt them first using tools like Sealed Secrets, SOPS (with KMS or age encryption), or git-crypt. The encrypted values are safe to commit; they're decrypted only at deploy time by a controller with the decryption key.
How often should I rotate secrets?
It depends on the secret's risk level and your compliance requirements. Database passwords should rotate every 30-90 days at minimum. API keys for third-party services should rotate quarterly. With dynamic secrets from Vault, rotation is continuous -- every credential has a 1-24 hour TTL by default. Shorter is better.
What happens if Vault goes down?
If Vault is unavailable, applications that cache secrets locally continue working until their leases expire. Applications that fetch secrets on every request will fail. Design for resilience: run Vault in HA mode (3-5 node Raft cluster), cache secrets in your application with a reasonable TTL, and have a fallback plan for Vault outages.
Get Your Secrets Under Control
The worst secret management strategy is the one you haven't implemented yet. If your secrets are in environment variables in a docker-compose file, in a .env file committed to Git, or in a shared password manager -- you have work to do. Start with the simplest tool that meets your security requirements. For most teams on AWS, that's Secrets Manager. For teams needing dynamic secrets or multi-cloud support, that's Vault. For small Kubernetes deployments, hardened K8s Secrets with Sealed Secrets for GitOps will get you surprisingly far. The important thing is to start.
Written by
Abhishek Patel
Infrastructure engineer with 10+ years building production systems on AWS, GCP, and bare metal. Writes practical guides on cloud architecture, containers, networking, and Linux for developers who want to understand how things actually work under the hood.
Related Articles
Network Firewalls vs WAFs: Understanding Your Defense Layers
Network firewalls filter by IP and port at Layer 3/4. WAFs inspect HTTP content at Layer 7. Learn when you need each and how to configure them together.
10 min read
SecurityCertificate Management at Scale: Let's Encrypt, ACME, and cert-manager
Automate TLS certificates with Let's Encrypt, ACME protocol, and cert-manager in Kubernetes. Covers HTTP-01, DNS-01, wildcards, private CAs, and expiry monitoring.
9 min read
SecuritySSRF Attacks: What They Are and Why Cloud Environments Make Them Dangerous
SSRF lets attackers reach internal services through your server. Learn how cloud metadata endpoints amplify the risk and how to defend against SSRF.
9 min read
Enjoyed this article?
Get more like this in your inbox. No spam, unsubscribe anytime.