Here’s the updated Vault + Kubernetes Auth Setup Documentation with detailed explanations in each section to help you understand what you're doing and why:
# 🛡️ HashiCorp Vault with Kubernetes Auth - Local Minikube Setup (Dev Mode)
This guide shows how to run Vault on Minikube using HA mode (with Raft storage) and enable Kubernetes-based authentication to securely inject secrets into workloads.
---
## 1. Install Vault via Helm
**Explanation**: Helm is the recommended way to deploy Vault in Kubernetes. This configuration enables:
- **HA mode**: Multiple Vault pods, using Raft as internal storage backend.
- **Vault UI**: So you can access Vault in the browser.
Create the custom values file:
```yaml
# vault-values.yml
server:
ha:
enabled: true
raft:
enabled: true
setNodeId: true
ui:
enabled: true
Install with:
helm repo add hashicorp https://helm.releases.hashicorp.com
helm install vault hashicorp/vault -n vault --create-namespace -f vault-values.yml
2. Initialize and Unseal Vault
Explanation: Vault starts sealed for security. You need to initialize it to generate keys and then unseal it using one of them.
Initialize Vault and store keys:
kubectl exec -n vault vault-0 -- vault operator init -key-shares=1 -key-threshold=1 -format=json > keys.json
Extract and use the unseal key:
export UNSEAL=$(jq -r .unseal_keys_b64[0] keys.json)
kubectl exec -n vault vault-0 -- vault operator unseal $UNSEAL
Note: For HA, repeat unseal for
vault-1
,vault-2
as well.
3. Login to Vault (CLI)
Explanation: To configure Vault, you must authenticate. Here we use the root token generated during initialization.
Set the Vault address and login:
export VAULT_ADDR=http://localhost:8200
export VAULT_TOKEN=$(jq -r .root_token keys.json)
vault login $VAULT_TOKEN
You’re now authenticated as a root user in CLI.
4. Enable KV Secrets and Kubernetes Auth Methods
Explanation:
- The
kv
(key-value) secrets engine stores arbitrary secrets. - The
kubernetes
auth method allows K8s pods to authenticate to Vault via service accounts.
vault secrets enable -path=secret kv-v2
vault auth enable kubernetes
5. Configure Kubernetes Auth Method
Explanation: Vault needs to connect to the Kubernetes API to validate ServiceAccount tokens. You supply:
- Kubernetes Host URL
- JWT: Vault uses this to verify tokens.
- CA cert: Ensures HTTPS communication.
Extract credentials from Vault pod (recommended in Minikube):
kubectl exec -n vault -ti vault-0 -- sh
# Inside the pod
TOKEN_REVIEWER=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CA_CERT=$(cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt)
K8S_HOST=https://$KUBERNETES_PORT_443_TCP_ADDR:443
# Then configure Vault
vault write auth/kubernetes/config \
kubernetes_host="$K8S_HOST" \
token_reviewer_jwt="$TOKEN_REVIEWER" \
kubernetes_ca_cert="$CA_CERT"
Why this matters: Vault now knows how to validate tokens from Kubernetes pods using its API.
6. Create Policy and Role
Explanation:
- Policies define what a client (e.g., pod) can access.
- Roles bind a Kubernetes service account to a Vault policy.
Define a webapp
policy that allows reading one path:
vault policy write webapp - <<EOF
path "secret/data/webapp/config" {
capabilities = ["read"]
}
EOF
Create a role to bind the policy to a service account:
vault write auth/kubernetes/role/webapp \
bound_service_account_names=webapp-sa \
bound_service_account_namespaces=default \
policies=webapp \
ttl=1h
Add a sample secret to test:
vault kv put secret/webapp/config username="demo" password="pwd123"
7. Create Kubernetes ServiceAccount
Explanation: A pod must use a specific service account (SA) to authenticate to Vault. Vault checks if the pod’s SA matches the role.
Create the SA in the default
namespace:
kubectl create serviceaccount webapp-sa
Ensure this name matches the
bound_service_account_names
in the Vault role.
(Optional): Create vault-auth
SA and bind it with permissions so Vault can verify tokens.
kubectl create serviceaccount vault-auth -n vault
kubectl create clusterrolebinding vault-auth-delegator \
--clusterrole=system:auth-delegator \
--serviceaccount=vault:vault-auth
8. Create a Test Pod Using That SA
Explanation: Now test if a pod using webapp-sa
can authenticate to Vault and fetch secrets.
Use this manifest:
apiVersion: v1
kind: Pod
metadata:
name: test-auth
spec:
serviceAccountName: webapp-sa
containers:
- name: busybox
image: busybox
command: [ "/bin/sh", "-c", "sleep 3600" ]
Apply:
kubectl apply -f testpod.yaml
Access it:
kubectl exec -it test-auth -- sh
9. Authenticate to Vault from Inside the Pod
Explanation: The pod now has access to a ServiceAccount JWT. You use this JWT to login to Vault and receive a Vault token.
Inside the pod:
JWT=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -s --request POST \
--data '{"jwt":"'"$JWT"'","role":"webapp"}' \
http://vault.vault.svc.cluster.local:8200/v1/auth/kubernetes/login | jq
You’ll get a Vault client token in the response. Use it to access secrets:
curl \
-H "X-Vault-Token: <vault_token>" \
http://vault.vault.svc.cluster.local:8200/v1/secret/data/webapp/config | jq
✅ Summary
Component | Purpose |
---|---|
Vault Helm Chart | Deploys Vault into Kubernetes |
Init & Unseal | Starts and unlocks Vault |
Auth Method | Lets K8s pods authenticate to Vault |
ServiceAccount | Identity that Vault binds to |
Policy & Role | Grant and scope permissions |
Pod Test | Validate if secrets can be fetched |
🔒 Next Steps (Optional)
- Use Vault Agent Sidecar Injector for auto token and secret injection.
- Setup TLS for Vault instead of dev HTTP.
- Rotate secrets with dynamic secrets engines (e.g., DB, AWS).
---
Would you like me to export this as a `.md` file or add **Vault Agent Injector** setup next?
Pod Secret Injection Example
🛠️ Injecting Vault Secrets as Environment Variables in Kubernetes Pod
This guide explains how to inject secrets (e.g., DB credentials) stored in HashiCorp Vault into a Kubernetes Pod's environment variables, replacing traditional ConfigMap or Kubernetes Secret-based workflows.
We'll use:
- Vault Agent Sidecar Injector (mutating webhook)
- Vault Kubernetes Auth Method
- A sample BusyBox pod that consumes the secrets
1. Prerequisites
- Vault is installed via Helm in Minikube (HA mode with Raft)
- Kubernetes Auth Method is enabled and configured
vault.kube.auth
is set up and reachable
2. Enable Vault Agent Injector
Explanation: The Vault Agent Injector automatically injects a sidecar into your pods to authenticate and write secrets to memory or env.
Enable it:
helm upgrade --install vault hashicorp/vault \
-n vault \
-f vault-values.yml \
--set injector.enabled=true
Verify:
kubectl get pods -n vault -l app.kubernetes.io/name=vault-agent-injector
3. Add DB Credentials in Vault
vault kv put secret/db-creds username=dbuser password=dbpass123
4. Define a Vault Policy
vault policy write dbapp - <<EOF
path "secret/data/db-creds" {
capabilities = ["read"]
}
EOF
5. Create Vault Role for Pod
vault write auth/kubernetes/role/dbapp \
bound_service_account_names=dbapp-sa \
bound_service_account_namespaces=default \
policies=dbapp \
ttl=24h
6. Create a Kubernetes Service Account
kubectl create serviceaccount dbapp-sa
7. Annotate Pod with Vault Instructions
Here's a full manifest:
apiVersion: v1
kind: Pod
metadata:
name: vault-env-busybox
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "dbapp"
vault.hashicorp.com/agent-inject-secret-DB_USER: "secret/data/db-creds"
vault.hashicorp.com/agent-inject-template-DB_USER: |
{{ with secret "secret/data/db-creds" }}
export DB_USER={{ .Data.data.username }}
export DB_PASS={{ .Data.data.password }}
{{ end }}
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/agent-inject-command: ["/bin/sh", "-c", "source /vault/secrets/DB_USER && env"]
vault.hashicorp.com/log-level: debug
spec:
serviceAccountName: dbapp-sa
containers:
- name: busybox
image: busybox
command: ["/bin/sh", "-c"]
args:
- |
echo "Starting Busybox with Vault Secrets";
source /vault/secrets/DB_USER;
env;
sleep 3600
8. Apply and Test
kubectl apply -f vault-env-busybox.yaml
Then check:
kubectl logs vault-env-busybox
You should see:
DB_USER=dbuser
DB_PASS=dbpass123
✅ Summary
- No
.env
or Kubernetes Secrets used - Secrets dynamically pulled from Vault
- Sidecar handles token auth and injection
- Environment variables set via shell sourcing
🔒 Notes
- The secrets are mounted at
/vault/secrets/<NAME>
- You can also mount as plain files or config using templates
- Ideal for 12-factor apps, security-sensitive environments