Skip to main content

Command Palette

Search for a command to run...

Secrets Management for Containers: Parameter Store vs Secrets Manager vs HashiCorp Vault on AWS

Published
5 min read
Secrets Management for Containers: Parameter Store vs Secrets Manager vs HashiCorp Vault on AWS
G

I am experienced Cloud Devops Engineer I blog about Solutions, Cloud and DevOps Projects that boost your portfolio and provide troubleshooting guides on Cloud and DevOps

A hands-on comparison of the three leading secrets management solutions for containerized workloads on Amazon EKS


Introduction

Managing secrets in containerized environments is critical for cloud-native security. When running containers on AWS, you have three primary options:

  1. AWS Systems Manager Parameter Store — Simple, cost-effective storage

  2. AWS Secrets Manager — Purpose-built with rotation capabilities

  3. HashiCorp Vault — Enterprise-grade with dynamic secrets

This guide implements all three on Amazon EKS and helps you choose the right one.


Prerequisites

  • AWS Account with EKS cluster running

  • kubectl and Helm 3.x installed

  • IAM OIDC provider configured for IRSA

kubectl get nodes
kubectl create namespace demo


Quick Comparison

FeatureParameter StoreSecrets ManagerHashiCorp Vault
CostFree (standard)$0.40/secret/monthSelf-hosted
RotationManualAutomaticDynamic secrets
ComplexityLowLowMedium-High
Multi-cloudNoNoYes

Approach 1: External Secrets Operator (AWS Secrets Manager)

External Secrets Operator syncs AWS Secrets Manager into Kubernetes Secrets.

Install External Secrets Operator

helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets \
  --namespace external-secrets --create-namespace

Create Secrets in AWS

aws secretsmanager create-secret --name "myapp/database/credentials" \
  --secret-string '{"username":"dbadmin","password":"secure-pass","host":"db.example.com"}'

Configure ClusterSecretStore

apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
  name: aws-secrets-manager
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-east-1
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets
            namespace: external-secrets

Create ExternalSecret

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: database-credentials
  namespace: demo
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: database-credentials
  data:
    - secretKey: DB_PASSWORD
      remoteRef:
        key: myapp/database/credentials
        property: password

Verification

kubectl get externalsecrets -n demo
kubectl get secrets -n demo


Approach 2: Secrets Store CSI Driver (Parameter Store & Secrets Manager)

CSI Driver mounts secrets directly as files—no intermediate Kubernetes Secrets.

Install CSI Driver

helm install csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver \
  --namespace secrets-store-csi --create-namespace

kubectl apply -f https://raw.githubusercontent.com/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml

Create SecretProviderClass (Parameter Store)

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: aws-param-store-secrets
  namespace: demo
spec:
  provider: aws
  parameters:
    region: us-east-1
    objects: |
      - objectName: "/myapp/database/password"
        objectType: "ssmparameter"
      - objectName: "/myapp/api/key"
        objectType: "ssmparameter"

Create SecretProviderClass (Secrets Manager)

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: aws-secrets-manager-secrets
  namespace: demo
spec:
  provider: aws
  parameters:
    region: us-east-1
    objects: |
      - objectName: "myapp/database/credentials"
        objectType: "secretsmanager"
        jmesPath:
          - path: "username"
            objectAlias: "db-username"
          - path: "password"
            objectAlias: "db-password"

Deploy Application with CSI Volume

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-csi
  namespace: demo
spec:
  template:
    spec:
      containers:
        - name: app
          volumeMounts:
            - name: secrets
              mountPath: "/mnt/secrets"
              readOnly: true
      volumes:
        - name: secrets
          csi:
            driver: secrets-store.csi.k8s.io
            volumeAttributes:
              secretProviderClass: aws-param-store-secrets


Approach 3: HashiCorp Vault with CSI Driver

Vault provides dynamic secrets, comprehensive auditing, and multi-cloud support.

Install Vault

helm install vault hashicorp/vault --namespace vault --create-namespace \
  --set "server.standalone.enabled=true" \
  --set "csi.enabled=true"

Initialize and Unseal

kubectl exec -n vault vault-0 -- vault operator init -key-shares=1 -key-threshold=1
kubectl exec -n vault vault-0 -- vault operator unseal <UNSEAL_KEY>
kubectl exec -n vault vault-0 -- vault status

Configure Vault Secrets

kubectl exec -n vault vault-0 -- vault secrets enable -path=secret kv-v2

kubectl exec -n vault vault-0 -- vault kv put secret/database/credentials \
  username="dbadmin" password="vault-managed-password" host="db.example.com"

Configure Kubernetes Auth

kubectl exec -n vault vault-0 -- vault auth enable kubernetes

kubectl exec -n vault vault-0 -- vault write auth/kubernetes/role/demo-app \
  bound_service_account_names=vault-app \
  bound_service_account_namespaces=demo \
  policies=demo-app ttl=1h

Create Vault SecretProviderClass

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: vault-secrets-csi
  namespace: demo
spec:
  provider: vault
  parameters:
    vaultAddress: "http://vault.vault:8200"
    roleName: "demo-app"
    objects: |
      - objectName: "db-password"
        secretPath: "secret/data/database/credentials"
        secretKey: "password"


All Demos Running


Comparison: When to Use Each

Choose Parameter Store when:

  • ✅ Simple key-value configuration needed

  • ✅ Cost is a primary concern

  • ✅ No automatic rotation required

Choose Secrets Manager when:

  • ✅ Automatic secret rotation needed

  • ✅ Native RDS credential management

  • ✅ Prefer fully managed AWS service

Choose HashiCorp Vault when:

  • ✅ Dynamic secrets required (short-lived credentials)

  • ✅ Multi-cloud or hybrid environment

  • ✅ Comprehensive audit logging needed

  • ✅ Advanced features like PKI required


Best Practices

  1. Use IRSA — Never use static AWS credentials in pods

  2. Least Privilege — Grant minimum permissions required

  3. Enable Auditing — CloudTrail for AWS, audit device for Vault

  4. Rotate Regularly — Use automatic rotation when available

  5. Never Log Secrets — Configure apps to redact sensitive data


Conclusion

ScenarioRecommendation
Startups/Small TeamsAWS Secrets Manager + External Secrets
Enterprise/ComplianceHashiCorp Vault
Cost-SensitiveParameter Store for config, Secrets Manager for secrets
Multi-CloudHashiCorp Vault

Any of these solutions is infinitely better than hardcoded secrets. Choose based on your complexity tolerance and requirements.

Resources

More from this blog

G

Godstime Chisom

22 posts

Cloud Engineer • DevOps • SRE •
I am Devops Engineer, I blog about Solutions to Devops/SRE Tasks. Be sure to find help and troubleshooting guides for DevOps-related topics here