Managing secrets in Kubernetes using default Secret objects is, frankly, a security risk. They are only base64 encoded, not encrypted, meaning anyone with access to the namespace can practically read your DB passwords in plain text. In my experience building secure pipelines, moving to a dedicated secrets manager is the single biggest security win you can achieve.

If you’re wondering how to setup HashiCorp Vault on Kubernetes, you’ve come to the right place. I’ve deployed Vault across various environments—from small staging clusters to high-availability production setups—and I’ve learned that the ‘easy way’ usually leads to pain during the first scaling event. In this guide, I’ll show you the robust way to get it running using Helm.

Prerequisites

Step 1: Adding the HashiCorp Helm Repository

The most reliable way to deploy Vault is via the official Helm chart. It handles the complex deployment logic and provides a standardized way to manage versions. First, let’s add the repository and update your local charts:

helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update

Step 2: Configuring the Value File

Running Vault in ‘standalone’ mode is great for learning, but for anything serious, you want Integrated Storage (Raft). I always recommend creating a values.yaml file instead of passing flags via the CLI to ensure your configuration is version-controlled.

Create a file named vault-values.yaml with the following configuration:

# vault-values.yaml
server:
  # Use Raft integrated storage for better reliability
  ha:
    enabled: true
    raft:
      enabled: true
      setNodeId: true
      config: |
        cluster_addr = "[[ raft.cluster_addr ]]"
        retry_join {
          leader_api_addr = "[[ raft.leader_api_addr ]]"
        }

  # Expose Vault via a LoadBalancer for initial setup
  service:
    type: LoadBalancer

As we move toward a production environment, you’ll likely need to consider scaling HashiCorp Vault in production to handle higher request volumes and ensure zero downtime.

Step 3: Deploying Vault

Now, let’s deploy Vault into its own dedicated namespace. This keeps your security tooling isolated from your application logic.

kubectl create namespace vault

helm install vault hashicorp/vault \
  --namespace vault \
  -f vault-values.yaml

You can verify the deployment by checking the pods. Note that the pods will be in a 0/1 Ready state—this is normal because Vault starts in a sealed state. It requires a set of unseal keys to decrypt its master key before it can serve requests.

Here is how your terminal should look once the pods are deployed, as shown in the image below:

Terminal output showing successful Helm installation of HashiCorp Vault on Kubernetes
Terminal output showing successful Helm installation of HashiCorp Vault on Kubernetes

Step 4: Initializing and Unsealing Vault

Since Vault is sealed, we need to initialize it. I’ll exec into the first pod to run the init command:

kubectl exec -it vault-0 -n vault -- vault operator init

CRITICAL: This command will output 5 Unseal Keys and an Initial Root Token. Save these in a password manager immediately. If you lose these, your data is gone forever. There is no ‘forgot password’ button in Vault.

To unseal the vault, run the following command three times, using a different unseal key each time:

kubectl exec -it vault-0 -n vault -- vault operator unseal [YOUR_UNSEAL_KEY]

Once the Sealed status changes to false, you can log in using the root token:

kubectl exec -it vault-0 -n vault -- vault login [YOUR_ROOT_TOKEN]

Step 5: Enabling the Kubernetes Auth Method

The real magic happens when you let your Kubernetes pods authenticate with Vault using their own Service Accounts. This eliminates the need to store a ‘Vault Token’ inside your app’s environment variables.

Run these commands inside the Vault pod to enable K8s auth:

# Enable the auth method
vault auth enable kubernetes

# Configure Vault to talk to the K8s API
vault write auth/kubernetes/config \
    kubernetes_host="https://kubernetes.default.svc:443"

If you’re debating whether this complexity is worth it compared to simpler cloud-native options, check out my deep dive on AWS Secrets Manager vs HashiCorp Vault to see which fits your stack better.

Pro Tips for Vault on K8s

Troubleshooting Common Issues

Vault Pods Stuck in Pending

This is usually a PVC (Persistent Volume Claim) issue. Ensure your cluster has a default StorageClass configured. If you’re on a bare-metal cluster, you might need to manually create the PVs.

Authentication Failures (403 Forbidden)

Double-check that the ServiceAccount used by your application pod is exactly the same one mapped in the Vault role. A common mistake is forgetting to specify the namespace in the Vault role configuration.

What’s Next?

Now that you’ve mastered how to setup HashiCorp Vault on Kubernetes, the next step is to move away from the Root Token. I recommend creating a custom policy for your apps and mapping it to a specific Kubernetes Service Account. This follows the principle of least privilege, ensuring that if one pod is compromised, the attacker can’t steal every secret in your organization.