Install Hashicorp Vault to Kubernetes

ติดตั้ง KMS สำหรับจัดการ credential ใน Kubernetes ด้วย Hashicorp vault

สร้าง script สำหรับติดตั้ง install-vault.sh

Shell
#!/bin/bash
# 1. Add the HashiCorp Helm Repository
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
# 2. Create a dedicated namespace
kubectl create namespace vault
# 3. Deploy Vault in High Availability (HA) mode with Raft storage
# We use a custom values file for production-like settings
cat <<EOF > vault-values.yaml
server:
ha:
enabled: true
raft:
enabled: true
setNodeId: true
config: |
ui = true
listener "tcp" {
tls_disable = 1
address = "[::]:8200"
cluster_address = "[::]:8201"
}
storage "raft" {
path = "/vault/data"
}
service_registration "kubernetes" {}
EOF
helm install vault hashicorp/vault \
--namespace vault \
-f vault-values.yaml

ตรวจสอบว่า Vault ได้ install และมี status Running ดังรูป โดย status จะยังเป็น 0/1 Ready เพราะว่าต้องทำการ Initial และ Unseal ก่อน pod ถึงจะทำงาน

nutanix@harbor ~]$ kubectl get pod -n vault
NAME READY STATUS RESTARTS AGE
vault-0 0/1 Running 0 19m
vault-1 0/1 Running 0 19m
vault-2 0/1 Running 0 19m
vault-agent-injector-5b7dd85f5c-cht5p 1/1 Running 0 19m

เข้าไปที่ vault-0. เพื่อทำการ initial ด้วยคำสั่ง

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

คำสั่ง init จะทำการสร้าง Unseal Keys และ Initial Root Token ซึ่งจะต้องเก็บผลลัพธ์ไว้ เพราะต้องใช้ในการ unseal ในกรณี pod restart ถ้าข้อมูลนี้หายจะไม่สามารถ unseal และดึงข้อมูลที่เก็บใน vault ได้

Unseal Key 1: n80kTk1a0QUsd5XJIVQ+SVF+cmjDj5H0AX8HkDd4xgZg
Unseal Key 2: pu2+W0CZWOHcl6xyD77mzip1BeUZOcq9aRW8NwXx5m10
Unseal Key 3: 9vGGqh02ZnOvc7T7P45EpPyFeX+KMEYGhv69B/qERaBL
Unseal Key 4: 8gbpjijpBLViLDXnfJF7me32ts2pborEyiOH5wHLIHef
Unseal Key 5: 0YaO4FKto4I+5ZyV2VGtQrUHJFpLS73bYsQeU153J39I
Initial Root Token: hvs.SMpvYTqteXW6Vjup8HWIB972
Vault initialized with 5 key shares and a key threshold of 3. Please securely
distribute the key shares printed above. When the Vault is re-sealed,
restarted, or stopped, you must supply at least 3 of these keys to unseal it
before it can start servicing requests.
Vault does not store the generated root key. Without at least 3 keys to
reconstruct the root key, Vault will remain permanently sealed!
It is possible to generate new unseal keys, provided you have a quorum of
existing unseal keys shares. See "vault operator rekey" for more information.

ทำตามขั้นตอนข้างต้นกับ vault-1 และ vault-2

ขั้นตอนการ Unseal ใช้คำสั่งดังนี้

# Repeat this 3 times with different keys for each pod
kubectl exec -it vault-0 -n vault -- vault operator unseal <YOUR_UNSEAL_KEY>
kubectl exec -it vault-1 -n vault -- vault operator unseal <YOUR_UNSEAL_KEY>
kubectl exec -it vault-2 -n vault -- vault operator unseal <YOUR_UNSEAL_KEY>

จำต้องทำคำสั่งข้างบน ด้วยการใช้ Unseal key โดยแต่ละ pod จะต้องทำ 3 ครั้งโดยใช้ Unseal Key ที่แตกต่างกัน และเมื่อทำครบแล้วจะได้ผลลัพธ์ดังตัวอย่าง

[nutanix@harbor ~]$ kubectl exec -it vault-2 -n vault -- vault operator unseal
Unseal Key (will be hidden):
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 5
Threshold 3
Version 1.21.2
Build Date 2026-01-06T08:33:05Z
Storage Type raft
Cluster Name vault-cluster-0f5e0570
Cluster ID b4922833-5b45-50ee-3f29-b6639ae0ef16
Removed From Cluster false
HA Enabled true
HA Cluster https://vault-2.vault-internal:8201
HA Mode active
Active Since 2026-02-05T10:58:54.132265118Z
Raft Committed Index 37
Raft Applied Index 37

และเมื่อกลับมาดู status ของ pod อีกครั้งจะพบว่า pod ได้ทำงานครบตามจำนวน

[nutanix@harbor ~]$ kubectl get pod -n vault
NAME READY STATUS RESTARTS AGE
vault-0 1/1 Running 0 23m
vault-1 1/1 Running 0 23m
vault-2 1/1 Running 0 23m
vault-agent-injector-5b7dd85f5c-cht5p 1/1 Running 0 23m

คำสั่งที่ใช้สำหรับ ตรวจสอบ status, login และ access ui

kubectl exec -it vault-0 -n vault -- vault status
kubectl exec -it vault-0 -n vault -- vault login <ROOT_TOKEN>
kubectl port-forward service/vault 8200:8200 -n vault (Visit http://localhost:8200)

ตรวจสอบ status ของ cluster

# Login first
kubectl exec -it vault-0 -n vault -- vault login <YOUR_ROOT_TOKEN>
# Check Raft members
kubectl exec -it vault-0 -n vault -- vault operator raft list-peers

สิ่งที่ควรต้องพิจารณา

  1. Storage ที่ใช้ใน Script จะต้องมี StorageClass เพื่อ provision persistent volume
  2. การ Auto-Unseal สามารถใช้ Cloud KMS (AWS KMS, GCP KMS หรือ Azure Key Vault) ให้ช่วยขั้นตอนการ unseal ได้ ในกรณีที่ pod มีการ restart โดยไม่ต้องทำแบบ manual
  3. TLS ใน script install ทำการ disable ไว้ (tls_disable =1) เพื่อความง่ายในการติดตั้ง สำหรับ production ต้อง integrate กับ cert-manager เพื่อจัดการ life cycle ของ certificate

ตัวอย่างการสร้าง secret

ssh เข้าไปที่ vault instance

kubectl exec -it vault-0 -n vault -- sh

Login ด้วย root token

# Ensure you are logged in first
vault login hvs.SMpvYTqteXW6Vjup8HWIB972
# Enable the KV-v2 engine at the path 'secret'
vault secrets enable -path=secret kv-v2

สร้าง secret

# vault kv put <PATH> <KEY>=<VALUE>
vault kv put secret/my-app/db-creds password="YourSuperSecurePassword123!"

ตรวจสอบ secret ว่าสามารถเรียกดูได้ถูกต้อง

vault kv get secret/my-app/db-creds
======= Secret Path =======
secret/data/my-app/db-creds
======= Metadata =======
Key Value
--- -----
created_time 2026-02-05T11:13:56.470489651Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
password password123