1. Deploy Vault trên Kubernetes bằng Helm
Các mode deploy
| Mode | Mô tả | Use case |
|---|---|---|
| Dev | Single pod, in-memory storage | Development, testing |
| Standalone | Single pod, persistent storage | Small deployments |
| HA | Multi-pod, Integrated Storage (Raft) | Production |
| External | Vault chạy ngoài K8s, chỉ deploy Agent Injector | External Vault server |
Helm Install (HA Mode)
# Add Helm repo
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
# Install Vault HA với Integrated Storage
helm install vault hashicorp/vault \
--namespace vault \
--create-namespace \
--set server.ha.enabled=true \
--set server.ha.replicas=3 \
--set server.ha.raft.enabled=true \
--set server.dataStorage.size=10Gi \
--set server.resources.requests.memory=256Mi \
--set server.resources.requests.cpu=250m \
--set server.resources.limits.memory=512Mi \
--set server.resources.limits.cpu=500m \
--set ui.enabled=true \
--set ui.serviceType=ClusterIP
Custom Values
# values-production.yaml
server:
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"
}
storage "raft" {
path = "/vault/data"
retry_join {
leader_api_addr = "https://vault-0.vault-internal:8200"
leader_ca_cert_file = "/vault/userconfig/vault-tls/ca.crt"
}
retry_join {
leader_api_addr = "https://vault-1.vault-internal:8200"
leader_ca_cert_file = "/vault/userconfig/vault-tls/ca.crt"
}
retry_join {
leader_api_addr = "https://vault-2.vault-internal:8200"
leader_ca_cert_file = "/vault/userconfig/vault-tls/ca.crt"
}
}
service_registration "kubernetes" {}
dataStorage:
size: 20Gi
storageClass: gp3
extraVolumes:
- type: secret
name: vault-tls
resources:
requests:
memory: 512Mi
cpu: 500m
limits:
memory: 1Gi
cpu: 1000m
ingress:
enabled: true
hosts:
- host: vault.company.com
ui:
enabled: true
injector:
enabled: true
replicas: 2
# Install với custom values
helm install vault hashicorp/vault \
--namespace vault \
--create-namespace \
-f values-production.yaml
Init và Unseal
# Init trên vault-0
kubectl exec -n vault vault-0 -- vault operator init \
-key-shares=5 \
-key-threshold=3 \
-format=json > vault-init.json
# Unseal vault-0
kubectl exec -n vault vault-0 -- vault operator unseal <key-1>
kubectl exec -n vault vault-0 -- vault operator unseal <key-2>
kubectl exec -n vault vault-0 -- vault operator unseal <key-3>
# Join vault-1 và vault-2 vào Raft cluster
kubectl exec -n vault vault-1 -- vault operator raft join \
https://vault-0.vault-internal:8200
kubectl exec -n vault vault-2 -- vault operator raft join \
https://vault-0.vault-internal:8200
# Unseal vault-1 và vault-2
kubectl exec -n vault vault-1 -- vault operator unseal <key-1>
# ... (repeat for each node)
2. Vault Secrets Operator (VSO)
VSO là Kubernetes operator chính thức, tự động sync secrets từ Vault vào Kubernetes Secrets. Đây là phương pháp recommended cho Kubernetes-native secret management.
Install VSO
helm install vault-secrets-operator hashicorp/vault-secrets-operator \
--namespace vault-secrets-operator-system \
--create-namespace
Custom Resources
# 1. VaultConnection — kết nối đến Vault server
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultConnection
metadata:
name: vault-connection
namespace: app
spec:
address: https://vault.company.com:8200
skipTLSVerify: false
caCertSecretRef: vault-ca-cert
---
# 2. VaultAuth — xác thực với Vault
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: vault-auth
namespace: app
spec:
vaultConnectionRef: vault-connection
method: kubernetes
mount: kubernetes
kubernetes:
role: webapp
serviceAccount: webapp-sa
---
# 3. VaultStaticSecret — sync KV secret
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: app-db-secret
namespace: app
spec:
vaultAuthRef: vault-auth
mount: secret
type: kv-v2
path: production/db
refreshAfter: 60s
destination:
name: app-db-credentials
create: true
labels:
app: webapp
transformation:
excludeRaw: true
templates:
connection-string:
text: "postgresql://{{ .Secrets.username }}:{{ .Secrets.password }}@{{ .Secrets.host }}:5432/{{ .Secrets.database }}"
---
# 4. VaultDynamicSecret — dynamic database credentials
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultDynamicSecret
metadata:
name: app-dynamic-db
namespace: app
spec:
vaultAuthRef: vault-auth
mount: database
path: creds/app-role
renewalPercent: 67
destination:
name: app-dynamic-db-credentials
create: true
---
# 5. VaultPKISecret — auto-issue certificates
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultPKISecret
metadata:
name: app-tls-cert
namespace: app
spec:
vaultAuthRef: vault-auth
mount: pki
role: app-cert
commonName: app.company.com
altNames:
- app.internal.company.com
ttl: 24h
expiryOffset: 1h
destination:
name: app-tls
create: true
Sử dụng trong Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
namespace: app
spec:
template:
spec:
serviceAccountName: webapp-sa
containers:
- name: webapp
image: myapp:latest
envFrom:
- secretRef:
name: app-db-credentials
volumeMounts:
- name: tls
mountPath: /etc/tls
readOnly: true
volumes:
- name: tls
secret:
secretName: app-tls
3. Vault CSI Provider
Vault CSI Provider sử dụng Secrets Store CSI Driver để mount secrets trực tiếp vào Pod volumes, không tạo Kubernetes Secrets.
# SecretProviderClass
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: vault-db-creds
namespace: app
spec:
provider: vault
parameters:
vaultAddress: "https://vault.company.com:8200"
roleName: "webapp"
objects: |
- objectName: "db-username"
secretPath: "secret/data/production/db"
secretKey: "username"
- objectName: "db-password"
secretPath: "secret/data/production/db"
secretKey: "password"
# Optionally sync to K8s Secret
secretObjects:
- secretName: app-db-synced
type: Opaque
data:
- objectName: db-username
key: username
- objectName: db-password
key: password
---
# Pod sử dụng CSI volume
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
serviceAccountName: webapp-sa
containers:
- name: webapp
image: myapp:latest
volumeMounts:
- name: secrets
mountPath: /mnt/secrets
readOnly: true
volumes:
- name: secrets
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: vault-db-creds
4. Vault Agent Injector
Agent Injector sử dụng Kubernetes Mutating Webhook để tự động inject Vault Agent sidecar vào Pods bằng annotations.
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "webapp"
vault.hashicorp.com/agent-inject-secret-db.txt: "secret/data/production/db"
vault.hashicorp.com/agent-inject-template-db.txt: |
{{- with secret "secret/data/production/db" -}}
DB_HOST={{ .Data.data.host }}
DB_USER={{ .Data.data.username }}
DB_PASS={{ .Data.data.password }}
{{- end }}
spec:
serviceAccountName: webapp-sa
containers:
- name: webapp
image: myapp:latest
# Secrets available at /vault/secrets/db.txt
5. So sánh VSO vs CSI vs Agent Injector
| Tiêu chí | VSO | CSI Provider | Agent Injector |
|---|---|---|---|
| Mechanism | Operator + CRDs | CSI Driver | Mutating Webhook |
| K8s Secrets | Tạo K8s Secrets | Optional sync | Không |
| Dynamic secrets | ✅ (VaultDynamicSecret) | Hạn chế | ✅ (templates) |
| PKI certificates | ✅ (VaultPKISecret) | Hạn chế | ✅ (templates) |
| Auto-rotation | ✅ (refreshAfter) | Cấu hình riêng | ✅ (sidecar) |
| Sidecar required | Không | Không | Có |
| Resource overhead | Thấp (operator chung) | Thấp | Cao (1 sidecar/pod) |
| Recommendation | ✅ Recommended | OK cho simple | Legacy |
6. Best Practices cho Kubernetes
Ưu tiên VSO cho deployments mới — native K8s experience, ít overhead
Sử dụng dedicated ServiceAccount cho mỗi workload
Enable Auto-unseal với Cloud KMS cho production
Cấu hình Pod Security cho Vault pods (non-root, read-only filesystem)
Sử dụng NetworkPolicy để restrict access đến Vault
Mount secrets vào emptyDir (memory-backed) thay vì persistent volume
7. Tổng kết
Helm chart — deploy Vault HA với Integrated Storage trên K8s
VSO — recommended, CRD-based, tự động sync secrets vào K8s Secrets
CSI Provider — mount secrets trực tiếp vào Pod volumes
Agent Injector — legacy, sidecar-based, annotation-driven
Phần tiếp theo sẽ tập trung vào tích hợp Vault với các ứng dụng thực tế — Spring Boot, Node.js, Terraform, Ansible và CI/CD pipelines.