Kubernetes使用Secrets Store CSI Driver掛載Vault Secret
如何透過 Vault CSI 驅動實現 Kubernetes 工作負載的動態密鑰管理。該筆記涵蓋 Vault CSI 的架構、安裝配置步驟,以及實際案例展示如何安全地將密鑰或機密資料掛載至 Pod,從而提升應用程式的安全性與合規性。
先決條件
在開始之前,請確保您的 macOS 環境已經具備以下軟體:
-
Homebrew:macOS 的套件管理工具,用來安裝其他必要軟體。
-
KinD: 一種基於 Docker 的本地 Kubernetes 集群工具,用於在本地開發與測試 Kubernetes 工作負載。 可以透過 Homebrew 安裝:
brew install kind
更多詳細說明可參考 在本機用 KinD 建立 Kubernetes。
-
Helm: Kubernetes 的應用程式包管理工具,用於簡化應用部署與管理。可以透過 Homebrew 安裝
brew install helm
安裝 Vault Helm Chart
在 Kubernetes 中安裝 HashiCorp Vault,可以透過 Helm Chart 簡化部署流程。
以下是安裝步驟:
1. 新增 HashiCorp 的 Helm Chart 儲存庫:
首先,將 HashiCorp 的官方 Helm Chart 儲存庫加入本地 Helm 設定:
helm repo add hashicorp https://helm.releases.hashicorp.com
成功後會顯示以下類似訊息
"hashicorp" has been added to your repositories
2. 更新 Helm Chart 儲存庫
確保您擁有最新的 Chart 資料:
helm repo update hashicorp
成功後會顯示以下類似訊息
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "hashicorp" chart repository
Update Complete. ⎈Happy Helming!⎈
3. 安裝 Vault
使用 Helm Chart 安裝 Vault 至指定的命名空間,例如 vault:
helm install vault hashicorp/vault \
--set "server.dev.enabled=true" \
--set "injector.enabled=false" \
--set "csi.enabled=true" \
--namespace vault --create-namespace
成功後會顯示以下類似訊息
NAME: vault
LAST DEPLOYED: Sat Nov 16 19:26:31 2024
NAMESPACE: vault
STATUS: deployed
REVISION: 1
NOTES:
Thank you for installing HashiCorp Vault!
Now that you have deployed Vault, you should look over the docs on using
Vault with Kubernetes available here:
https://developer.hashicorp.com/vault/docs
Your release is named vault. To learn more about the release, try:
$ helm status vault
$ helm get manifest vault
4. 驗證部署
確認 Vault Pod 是否成功啟動:
kubectl -n vault get pod
成功後會顯示以下類似訊息
NAME READY STATUS RESTARTS AGE
vault-0 1/1 Running 0 10m
vault-csi-provider-nkvpw 2/2 Running 0 10m
在 Vault 中設定 Secret
完成 Vault 部署後,可以開始設定 Secret。以下是設定 Secret 的基本流程:
1. 進入Vault Pod中
首先,啟動一個互動式的 shell session,進入 vault-0
Pod:
kubectl -n vault exec -it vault-0 -- /bin/sh
成功進入後,提示字元會變為:
/ $
2. 在 Vault 中新增 Secret
在路徑 secret/db-pass 建立一個包含密碼的 Secret:
vault kv put secret/db-pass password="db-secret-password"
執行後會顯示成功的輸出:
=== Secret Path ===
secret/data/db-pass
======= Metadata =======
Key Value
--- -----
created_time 2024-11-16T14:54:08.929095439Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
3. 驗證 Secret 是否成功儲存
vault kv get secret/db-pass
執行後會顯示儲存的密鑰內容:
=== Secret Path ===
secret/data/db-pass
======= Metadata =======
Key Value
--- -----
created_time 2024-11-16T14:54:08.929095439Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
password db-secret-password
在 Vault 中配置 Kubernetes 驗證
Vault 支援 Kubernetes 驗證方法,允許 Kubernetes 的 Service Account 使用其 Token 與 Vault 進行認證。以下在 vault-0
Pod中配置步驟:
1. 啟用 Kubernetes 驗證方法
在 Vault 中啟用 Kubernetes 驗證方法:
vault auth enable kubernetes
成功後會顯示以下類似訊息
Success! Enabled kubernetes auth method at: kubernetes/
2. 配置 Kubernetes 驗證
設定 Kubernetes 驗證方法,使用 Vault Pod 自身的 Service Account Token:
vault write auth/kubernetes/config \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443"
成功後會顯示以下類似訊息
Success! Data written to: auth/kubernetes/config
$KUBERNETES_PORT_443_TCP_ADDR 是 Kubernetes 主機的內部網址。
如果是外部Vault就依照實際狀況改成實際Vault的網址
3. 建立存取策略
建立一個名為 internal-app 的策略,授權讀取 secret/data/db-pass:
vault policy write internal-app - <<EOF
path "secret/data/db-pass" {
capabilities = ["read"]
}
EOF
成功後會顯示以下類似訊息
Success! Uploaded policy: internal-app
4. 建立 Kubernetes 驗證角色
建立一個名為 database 的 Kubernetes 驗證角色,綁定到指定的 Service Account 和策略:
vault write auth/kubernetes/role/database \
bound_service_account_names=webapp-sa \
bound_service_account_namespaces=default \
policies=internal-app \
ttl=20m
成功後會顯示以下類似訊息
Success! Data written to: auth/kubernetes/role/database
此角色將 Service Account webapp-sa(位於 default 命名空間)與 Vault 策略 internal-app 綁定,並設定 Token 的有效期為 20 分鐘。 完成以上步驟後,Vault 已經成功設定 Secret 並啟用 Kubernetes 驗證,供 Kubernetes 工作負載安全地存取所需的密鑰或敏感資訊。
最後,確認沒問題後離開 Pod:
exit
安裝 Secrets Store CSI Driver
Secrets Store CSI Driver (secrets-store.csi.k8s.io
) 允許 Kubernetes 將外部密鑰管理系統中的多個 Secrets、金鑰和憑證以 Volume 的形式掛載到 Pod。
1. 新增 Helm 儲存庫
helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
成功後會顯示以下類似訊息
"secrets-store-csi-driver" has been added to your repositories
2. 安裝 Secrets Store CSI Driver
使用 Helm 安裝最新版本的 Secrets Store CSI Driver:
helm install csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver -n kube-system
成功後會顯示以下類似訊息
NAME: csi-secrets-store
LAST DEPLOYED: Sat Nov 16 23:18:30 2024
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The Secrets Store CSI Driver is getting deployed to your cluster.
To verify that Secrets Store CSI Driver has started, run:
kubectl --namespace=kube-system get pods -l "app=secrets-store-csi-driver"
Now you can follow these steps https://secrets-store-csi-driver.sigs.k8s.io/getting-started/usage.html
to create a SecretProviderClass resource, and a deployment using the SecretProviderClass.
3. 驗證安裝是否成功
kubectl -n kube-system get pods -l "app=secrets-store-csi-driver"
成功後會顯示以下類似訊息
NAME READY STATUS RESTARTS AGE
csi-secrets-store-secrets-store-csi-driver-xf4jj 3/3 Running 0 42s
驗證 Vault CSI Provider 是否運行
kubectl -n vault get pod
NAME READY STATUS RESTARTS AGE
vault-0 1/1 Running 0 28m
vault-csi-provider-6zxmz 2/2 Running 0 28m
確認 Vault-csi-provider Pod 運行Container全部準備就緒
定義 SecretProviderClass 資源
1. 建立 SecretProviderClass
cat > spc-vault-database.yaml <<EOF
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: vault-database
spec:
provider: vault
parameters:
vaultAddress: "http://vault.vault:8200"
roleName: "database"
objects: |
- objectName: "db-password"
secretPath: "secret/data/db-pass"
secretKey: "password"
EOF
套用此配置:
kubectl apply -f spc-vault-database.yaml
成功後會顯示以下類似訊息
secretproviderclass.secrets-store.csi.x-k8s.io/vault-database created
2. 驗證配置是否成功
kubectl describe SecretProviderClass vault-database
成功後會顯示以下類似訊息
Name: vault-database
Namespace: default
Labels: <none>
Annotations: <none>
API Version: secrets-store.csi.x-k8s.io/v1
Kind: SecretProviderClass
Metadata:
Creation Timestamp: 2024-11-16T15:25:00Z
Generation: 1
Resource Version: 3536
UID: 0225ef39-7761-4966-bdcd-d51f3f271bb1
Spec:
Parameters:
Objects: - objectName: "db-password"
secretPath: "secret/data/db-pass"
secretKey: "password"
Role Name: database
Vault Address: http://vault.default:8200
Provider: vault
Events: <none>
建立 Pod 並掛載 Secret
1. 創建 Service Account
使用名為 webapp-sa 的 Service Account:
kubectl create serviceaccount webapp-sa
成功後會顯示以下類似訊息
serviceaccount/webapp-sa created
2. 定義 WebApp Pod
創建一個 Pod,將 Secrets Volume 掛載至 /mnt/secrets-store:
cat > webapp-pod.yaml <<EOF
kind: Pod
apiVersion: v1
metadata:
name: webapp
spec:
serviceAccountName: webapp-sa
containers:
- image: polinhou/golang-http-headers:latest
name: webapp
volumeMounts:
- name: secrets-store-inline
mountPath: "/mnt/secrets-store"
readOnly: true
volumes:
- name: secrets-store-inline
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"
EOF
套用此配置:
kubectl apply -f webapp-pod.yaml
成功後會顯示以下類似訊息
pod/webapp created
3. 驗證 Pod 是否成功啟動
kubectl get pods
成功後會顯示以下類似訊息
pod/webapp created
成功後會顯示以下類似訊息
NAME READY STATUS RESTARTS AGE
webapp 1/1 Running 0 3s
驗證掛載的 Secret
在 Pod 中檢查掛載的 Secret 文件內容:
kubectl exec webapp -- cat /mnt/secrets-store/db-password
成功後會顯示以下類似訊息
db-secret-password