HashiCorp Vault — Helm Chart Deployment
Deploy Vault on Kubernetes using the official HashiCorp Helm chart with Raft integrated storage for high availability.
Add Helm Repository
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
Development Mode
Quick deployment for testing:
helm install vault hashicorp/vault \
--set "server.dev.enabled=true"
This runs a single Vault server in dev mode (unsealed, root token = root).
Production HA Deployment
values.yaml
global:
enabled: true
tlsDisable: false
server:
# 3-node HA cluster
ha:
enabled: true
replicas: 3
raft:
enabled: true
config: |
ui = true
listener "tcp" {
tls_disable = 0
address = "[::]:8200"
cluster_address = "[::]:8201"
tls_cert_file = "/vault/userconfig/vault-tls/tls.crt"
tls_key_file = "/vault/userconfig/vault-tls/tls.key"
tls_client_ca_file = "/vault/userconfig/vault-tls/ca.crt"
}
storage "raft" {
path = "/vault/data"
}
service_registration "kubernetes" {}
# Resource limits
resources:
requests:
memory: 256Mi
cpu: 250m
limits:
memory: 512Mi
cpu: 500m
# Persistent storage
dataStorage:
enabled: true
size: 10Gi
storageClass: null # Uses default StorageClass
# Audit log storage
auditStorage:
enabled: true
size: 10Gi
# Extra volumes for TLS
extraVolumes:
- type: secret
name: vault-tls
# Pod annotations
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8200"
prometheus.io/path: "/v1/sys/metrics"
# Vault Agent Injector
injector:
enabled: true
replicas: 2
resources:
requests:
memory: 64Mi
cpu: 50m
limits:
memory: 128Mi
cpu: 100m
# Vault UI
ui:
enabled: true
serviceType: ClusterIP
Deploy
helm install vault hashicorp/vault \
--namespace vault \
--create-namespace \
-f values.yaml
Initialize and Unseal
# Wait for pods to be running
kubectl -n vault get pods -w
# Initialize the first node
kubectl -n vault exec vault-0 -- vault operator init \
-key-shares=5 \
-key-threshold=3 \
-format=json > vault-init.json
# Extract keys and root token
KEYS=$(cat vault-init.json | jq -r '.unseal_keys_b64[]')
ROOT_TOKEN=$(cat vault-init.json | jq -r '.root_token')
# Unseal vault-0 (need 3 of 5 keys)
kubectl -n vault exec vault-0 -- vault operator unseal $(echo "$KEYS" | sed -n '1p')
kubectl -n vault exec vault-0 -- vault operator unseal $(echo "$KEYS" | sed -n '2p')
kubectl -n vault exec vault-0 -- vault operator unseal $(echo "$KEYS" | sed -n '3p')
Join and Unseal Other Nodes
# Join vault-1 to the Raft cluster
kubectl -n vault exec vault-1 -- vault operator raft join \
http://vault-0.vault-internal:8200
# Unseal vault-1
kubectl -n vault exec vault-1 -- vault operator unseal $(echo "$KEYS" | sed -n '1p')
kubectl -n vault exec vault-1 -- vault operator unseal $(echo "$KEYS" | sed -n '2p')
kubectl -n vault exec vault-1 -- vault operator unseal $(echo "$KEYS" | sed -n '3p')
# Repeat for vault-2
kubectl -n vault exec vault-2 -- vault operator raft join \
http://vault-0.vault-internal:8200
kubectl -n vault exec vault-2 -- vault operator unseal $(echo "$KEYS" | sed -n '1p')
kubectl -n vault exec vault-2 -- vault operator unseal $(echo "$KEYS" | sed -n '2p')
kubectl -n vault exec vault-2 -- vault operator unseal $(echo "$KEYS" | sed -n '3p')
Verify Cluster
# Check Raft peers
kubectl -n vault exec vault-0 -- vault operator raft list-peers
# Check status
kubectl -n vault exec vault-0 -- vault status
Access Vault
# Port forward the UI
kubectl -n vault port-forward svc/vault 8200:8200
# In another terminal
export VAULT_ADDR=http://127.0.0.1:8200
vault login $ROOT_TOKEN
vault status
TLS Setup
Create TLS certificates before deploying:
# Create TLS secret (use Vault PKI, cert-manager, or manual certs)
kubectl -n vault create secret generic vault-tls \
--from-file=tls.crt=vault.crt \
--from-file=tls.key=vault.key \
--from-file=ca.crt=ca.crt
Quick Reference
| Command | Description |
|---|---|
helm install vault hashicorp/vault ... |
Deploy Vault |
helm upgrade vault hashicorp/vault ... |
Upgrade Vault |
helm uninstall vault -n vault |
Remove Vault |
kubectl -n vault exec vault-0 -- vault status |
Check Vault status |
Next: Kubernetes Auth