Vault Secrets Not Injecting into Kubernetes Pod Fix (2026)
Vault Agent Injector not mounting secrets into your pod? Here's how to debug and fix Vault secret injection issues in Kubernetes step by step.
vault.hashicorp.com/agent-inject annotations set but secrets not appearing in your pod? Here's the systematic fix.
How Vault Injection Works (Quick Overview)
The Vault Agent Injector is a mutating admission webhook. When a pod is created with Vault annotations, the injector:
- Intercepts the pod creation request
- Injects a
vault-agent-initinit container and avault-agentsidecar - The init container authenticates to Vault using Kubernetes auth
- Secrets are written to a shared in-memory volume at
/vault/secrets/
If any step fails, secrets don't appear.
Step 1: Check If the Injector Is Running
# Find the injector pod
kubectl get pods -n vault -l component=webhook
# Or check for agent-injector
kubectl get pods -A | grep agent-injector
# Check logs
kubectl logs -n vault -l component=webhook --tail=50If the injector pod is not running, no secrets will ever inject.
Step 2: Check Pod Annotations
The annotations must be on the pod template, not just the Deployment metadata:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
metadata:
annotations: # ← HERE, inside template
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "my-app-role"
vault.hashicorp.com/agent-inject-secret-config: "secret/data/my-app/config"
spec:
containers:
...Common mistake: annotations on metadata at the top level instead of spec.template.metadata.
Step 3: Check Init Container Logs
# Get pod name
kubectl get pods -n my-namespace
# Check init container logs
kubectl logs -n my-namespace my-app-pod -c vault-agent-init
# If pod is running, check sidecar logs
kubectl logs -n my-namespace my-app-pod -c vault-agentThe init container logs will tell you exactly why authentication or secret fetch failed.
Fix 1: Kubernetes Auth Not Configured
The most common error:
Error authenticating: error looking up token:
Error making API request.
URL: PUT http://vault:8200/v1/auth/kubernetes/login
Code: 403. Errors:
* permission denied
Fix — configure Kubernetes auth in Vault:
# Enable Kubernetes auth (if not enabled)
vault auth enable kubernetes
# Configure with cluster details
vault write auth/kubernetes/config \
kubernetes_host="https://kubernetes.default.svc:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
token_reviewer_jwt=@/var/run/secrets/kubernetes.io/serviceaccount/token
# Create a policy for your app
vault policy write my-app-policy - <<EOF
path "secret/data/my-app/*" {
capabilities = ["read"]
}
EOF
# Create a role binding the K8s service account to the policy
vault write auth/kubernetes/role/my-app-role \
bound_service_account_names=my-app-sa \
bound_service_account_namespaces=my-namespace \
policies=my-app-policy \
ttl=1hFix 2: Service Account Mismatch
The pod's service account must match what's in the Vault role:
# Check which service account the pod uses
kubectl get pod my-app-pod -n my-namespace -o jsonpath='{.spec.serviceAccountName}'
# Verify the Vault role allows this service account
vault read auth/kubernetes/role/my-app-role
# Look at: bound_service_account_names, bound_service_account_namespacesIf they don't match, update the Vault role or the pod's serviceAccountName.
Fix 3: Secret Path Is Wrong
Error reading secret: Error making API request.
URL: GET http://vault:8200/v1/secret/data/my-app/config
Code: 403 or 404
KV v2 secrets have data/ in the path:
# KV v2 (most common) — path includes 'data'
vault.hashicorp.com/agent-inject-secret-config: "secret/data/my-app/config"
# KV v1 — no 'data' in path
vault.hashicorp.com/agent-inject-secret-config: "secret/my-app/config"Verify the path exists:
vault kv get secret/my-app/config # KV v2
vault read secret/my-app/config # KV v1Fix 4: Injector Webhook Not Targeting Your Namespace
The Vault injector may have namespace selectors that exclude your namespace:
# Check webhook configuration
kubectl get mutatingwebhookconfiguration vault-agent-injector-cfg -o yaml | grep -A10 namespaceSelectorIf your namespace lacks the required label:
# Add the label
kubectl label namespace my-namespace vault-injection=enabled
# Or check what label the webhook requires and add itFix 5: Secret Template Formatting
If secrets appear but are malformatted, check your template:
annotations:
vault.hashicorp.com/agent-inject-secret-config: "secret/data/my-app/config"
vault.hashicorp.com/agent-inject-template-config: |
{{- with secret "secret/data/my-app/config" -}}
DB_HOST={{ .Data.data.db_host }}
DB_PASS={{ .Data.data.db_password }}
{{- end }}Without a template, Vault writes JSON to the file. With a template, you control the format.
Access the secret in your app:
# Inside the pod
cat /vault/secrets/configFix 6: Vault Is Sealed or Unreachable
# Check Vault is unsealed and reachable from the pod namespace
kubectl run vault-test --image=curlimages/curl --restart=Never \
-n my-namespace -- \
curl -s http://vault.vault.svc.cluster.local:8200/v1/sys/health
# Expected: {"initialized":true,"sealed":false,...}If Vault is sealed → unseal it. If unreachable → check Service/NetworkPolicy.
Full Annotation Example (Working)
spec:
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-status: "update"
vault.hashicorp.com/role: "my-app-role"
vault.hashicorp.com/agent-inject-secret-config: "secret/data/my-app/config"
vault.hashicorp.com/agent-inject-template-config: |
{{- with secret "secret/data/my-app/config" -}}
export DB_HOST="{{ .Data.data.db_host }}"
export DB_PASS="{{ .Data.data.db_password }}"
{{- end }}
spec:
serviceAccountName: my-app-sa # must match Vault role
containers:
- name: my-app
image: my-app:latest
command: ["/bin/sh", "-c"]
args: ["source /vault/secrets/config && ./start.sh"]Quick summary:
- Init container failing → check init container logs
- 403 permission denied → Vault Kubernetes auth not configured or service account mismatch
- 404 not found → wrong secret path (check KV v1 vs v2)
- Webhook not triggering → namespace label missing
- Vault unreachable → check NetworkPolicy and Vault seal status
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
cert-manager Certificate Not Ready: Causes and Fixes
cert-manager Certificate stuck in a non-Ready state is a common Kubernetes TLS issue. This guide covers every root cause — DNS challenges, RBAC, rate limits, and issuer problems — with step-by-step fixes.
Kubernetes Admission Webhook Error Fix (2026)
Getting 'admission webhook denied the request' or webhook timeout errors in Kubernetes? Here's how to debug and fix admission webhook issues step by step.
AWS EKS Pods Stuck in Pending State: Causes and Fixes
Pods stuck in Pending on EKS are caused by a handful of known issues — insufficient node capacity, taint mismatches, PVC problems, and more. Here's how to diagnose and fix each one.