- Published on
Vault 在 Kubernetes 上的部署指南:使用 AWS EFS 實現持久化存儲
Vault 服務部署說明
本文件提供在 AWS EKS Fargate 環境下部署 HashiCorp Vault 的詳細步驟,包含持久化儲存設定、自動解封、集群同步以及 Kubernetes 認證配置。部署完成後,Vault 可與 External Secrets Operator (ESO) 整合,用於管理帳號密碼。
環境需求
- AWS EKS Fargate 叢集
- AWS EFS 用於持久化儲存
- Helm 用於 Vault 安裝
- ArgoCD 用於應用程式部署
- kubectl 用於 Kubernetes 資源管理
- Vault CLI 用於初始化與配置
部署步驟
1. 安裝 AWS EFS CSI Driver
Vault 需要持久化儲存,在 EKS Fargate 中僅支援 AWS EFS。請先安裝 AWS EFS CSI Driver 以支援 EFS 掛載。
建立好 arn:aws:iam::xxxxxxxx:role/EKS_EFS_CSI_DriverRole
並增加對應的 turst policy 和 KS_EFS_CSI_Driver_Policy
helm upgrade --install aws-efs-csi-driver --namespace kube-system aws-efs-csi-driver/aws-efs-csi-driver \
--set controller.replicas=2 \
--set node.enabled=false \
--set sidecars.nodeDriverRegistrar.enabled=false \
--set controller.securityContext.privileged=false \
--set controller.containerSecurityContext.privileged=false \
--set serviceAccount.create=true \
--set serviceAccount.name=efs-csi-controller-sa
--set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"="arn:aws:iam::xxxxxxxxx:role/EKS_EFS_CSI_DriverRole"
詳見 https://github.com/kubernetes-sigs/aws-efs-csi-driver
2. 建立 StorageClass
透過 Helm 安裝 Vault 時,會自動建立 EFS 的 Access Point 以及 PersistentVolumeClaim (PVC) 和 PersistentVolume (PV)。無需手動定義,但需確保 StorageClass.yaml 已正確配置 EFS ID、GID 和 UID。
kubectl apply -f aws-deployment/vault-step/StorageClass.yaml
注意:請確認 StorageClass.yaml 中需要根據實際需求設定 EFS ID、GID 和 UID。
3. 建立 Vault Namespace
為 Vault 建立專屬命名空間:
kubectl create namespace vault
4. 配置 AWS KMS 自動解封
為 Vault 設定 AWS KMS 自動解封功能:
- 建立 KMS 資源並取得
kms_id。 - 將
kms_id填入aws-deployment/application/vault.yaml中seal "awskms"區段。
5. 部署 Vault 應用程式
使用 ArgoCD 部署 Vault,啟動三個 Pod(vault-0、vault-1、vault-2):
kubectl apply -f aws-deployment/application/vault.yaml
6. 檢查 Vault pod 狀態
確認三個 Vault Pod 均已啟動並運行:
kubectl get pods -n vault
出現這個問題可能是 pv, pvc 沒有刪除乾淨,請先刪除,它們會自動重建
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 10m fargate-scheduler Pod not supported on Fargate: volumes not supported: data not supported because: PVC data-vault-0 not bound
kubectl get pvc -n vault
kubectl delete pvc -n vault --all
kubectl get pv
kubectl delete pv pvc-1a5e124f-2df9-4d3d-9878-52a8e08ef594
7. 同步 Vault 集群
將 vault-1 和 vault-2 加入 vault-0 的 Raft 集群:
去其中一個 Pod 執行以下指令:
kubectl -n vault exec -it vault-0 -- /bin/sh
init 之後記下 key 跟 root token
vault operator init
初始化後會產生 5 個 Unseal Key 和 Root Token,請妥善記錄這些資訊。
接著做以下指令:
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN=hvs.XXXXXXXXXXXXXXX
vault operator raft list-peers
會出現以下訊息:
Node Address State Voter
---- ------- ----- -----
vault-0 vault-0.vault-internal:8201 leader true
去另外兩台做以下指令:
kubectl -n vault exec -it vault-1 -- /bin/sh
export VAULT_TOKEN=hvs.XXXXXXXXXXXXXXX
vault operator raft join http://vault-0.vault-internal:8200
vault operator unseal
Unseal Key (will be hidden): XXXXXX (輸入其中一組在第一台 init 時產生的 key)
vault operator raft list-peers
檢查集群狀態,確認所有 Pod 已正確加入 Raft 集群。會看到有 leader, followers:
Node Address State Voter
---- ------- ----- -----
vault-0 vault-0.vault-internal:8201 leader true
vault-1 vault-1.vault-internal:8201 follower true
vault-2 vault-2.vault-internal:8201 follower true
建立 ingress
kubectl apply -f aws-deployment/alb-ingress/vault/ingress.yaml
查地址
kubectl get ingress -n vault
預期輸出:
NAME CLASS HOSTS ADDRESS PORTS AGE
vault-ha-cluster-service-ingress alb * k8s-vault-vaulthac-0e9b13acef-2021229786.ap-east-2.elb.amazonaws.com 80 8s
8. 配置 Kubernetes 認證
為 Vault 設定 Kubernetes 認證,需取得以下三個值:
JWT_TOKEN:從 Secret 中取得。K8S_HOST:Kubernetes API 伺服器地址。K8S_CA_CERT:secret 的 CA 證書。
步驟:
- 建立 Service Account Secret:
kubectl apply -f aws-deployment/vault-step/vault-sa-token.yaml
- 提取認證所需值(在 Linux-like 環境下):
export VAULT_TOKEN=hvs.XXXXXXXXXXXXXXX
export VAULT_ADDR=http://127.0.0.1:8200
export JWT_TOKEN=$(kubectl get secret vault-sa-token -n vault -o jsonpath='{.data.token}' | base64 --decode)
export K8S_HOST=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
export K8S_CA_CERT=$(kubectl get secret vault-sa-token -n vault -o jsonpath='{.data.ca\.crt}' | base64 --decode)
echo $JWT_TOKEN # 顯示 JWT 內容
echo $K8S_HOST # 顯示 Kubernetes API 地址
echo $K8S_CA_CERT # 顯示 CA 證書內容
- 在 Vault 中配置 Kubernetes 認證:
kubectl -n vault exec -it vault-0 -- vault auth enable kubernetes
vault write auth/kubernetes/config \
token_reviewer_jwt=@/var/run/secrets/kubernetes.io/serviceaccount/token \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:$KUBERNETES_PORT_443_TCP_PORT" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
注意事項
- 確保 EFS CSI Driver 已正確安裝並配置,否則 Vault 無法持久化資料。
- 妥善保存初始化時產生的 Unseal Key 和 Root Token,遺失將無法恢復。
- 檢查 Vault 集群狀態,確保所有 Pod 正常運行並加入 Raft 集群。
- Kubernetes 認證配置需確保
vault-sa-tokenSecret 正確生成。