為什麼需要 Secret#
ConfigMap 雖然方便,但它是以「明碼」儲存資料,並不適合放置 API Key、金鑰等敏感資訊。Kubernetes 提供 Secret 作為對應的選擇 — 用法與 ConfigMap 接近,但對敏感資料多了一層保護,避免隨意暴露。
不過要先講清楚:Secret 並沒有想像中那麼「安全」,後面會說明為什麼。
什麼是 Secret#
Secret 在基本操作上與 ConfigMap 大致相同,但定位不同:它是 Kubernetes 提供給開發者用來儲存敏感資料的機制。Kubernetes 自己也使用相同機制儲存 Access Token,控制 API 的存取權限。
Secret 主要有三種類型:
Service Account:由 Kubernetes 自動建立並掛載到 Pod,用來存取 Kubernetes API。位於/run/secret/kubernetes.io/serviceaccount。Opaque:以 base64 編碼的 Secret,用來存放密碼、金鑰等。docker-registry:當映像檔存放於私有 Registry 時使用,省去每次都要docker login的麻煩。
在 Pod 中存取 Secret 常見的方式:
- 把 Secret 當作環境變數注入。
- 把 Secret 以檔案形式掛載到 Pod 中的某個路徑。
- 加入
docker-registry類型的 Secret,讓 Kubernetes 自動處理私有 Registry 的登入。
建立 Secret#
建立 Secret 時,值必須先用 base64 編碼,掛載成功後 Kubernetes 會自動還原為原始值。
1. 將內容轉成 base64#
echo -n 'my-account' | base64
echo -n 'my-password' | base64得到例如:
bXktYWNjb3VudA==
bXktcGFzc3dvcmQ=2. 撰寫 Secret yaml#
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: test-secret
data:
username: bXktYWNjb3VudA==
password: bXktcGFzc3dvcmQ=kubectl apply -f secret.yaml3. 查看結果#
kubectl get secret test-secretNAME TYPE DATA AGE
test-secret Opaque 2 15skubectl describe secret test-secretdescribe 只會顯示 key 名稱與大小,不會直接印出值。
4. 直接用 kubectl 建立#
如果不想寫 yaml,也可以直接用指令:
kubectl create secret generic test-secret \
--from-literal='username=my-account' \
--from-literal='password=my-password'generic 這個子命令表示使用本地資源或 key-value 建立 Secret。
在 Pod 中使用 Secret#
把剛剛建立的 test-secret 以檔案形式掛載:
# secret-test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-test-pod
spec:
containers:
- name: test-container
image: nginx
volumeMounts:
- name: secret-volume
mountPath: /etc/secret-volume
volumes:
- name: secret-volume
secret:
secretName: test-secret部署並確認:
kubectl apply -f secret-test-pod.yaml
kubectl get pod secret-test-pod進入容器查看:
kubectl exec -it secret-test-pod -- sh
ls /etc/secret-volume會看到 username 與 password 兩個檔案:
cat /etc/secret-volume/username
# my-account
cat /etc/secret-volume/password
# my-password可以看到掛載到容器中時,內容是「已經自動 base64 解碼後的原值」。
關於 Secret 並沒有想像中安全這件事#
從上面流程可以發現,只要擁有相關權限,就能輕易看到 Secret 的原值。雖然 Secret 在 etcd 中是以 base64 編碼存放,但 base64 並不是加密,本質上等同於明文。
因此:
- 原生 Secret 並不適合直接拿來作為大型企業內保存高度敏感資料的方案。
- 對 RBAC(角色權限)的設計挑戰也較高。
要讓原生 Secret 真的「安全」,通常需要同時做到:
- etcd 加密。
- API Server 嚴格的權限控制。
- 強化 Node 權限與系統安全。
這些措施缺一不可,整體成本相當高。社群與雲端服務商因此提供了許多更進階的方案可以參考:
- AWS Key Management Service(KMS)
- Google Cloud KMS
理解 Secret 的限制有助於我們在不同情境下做出合理取捨:對於中小型應用,原生 Secret 足夠;對於高度敏感的場景,則應考慮搭配雲端 KMS 或專屬的 Secret 管理方案。
小結#
- Secret 與 ConfigMap 用法相近,但定位是「敏感資料」的容器。
- 內容以 base64 編碼,並非加密。
- 真正落地時需要搭配 etcd 加密、RBAC 與外部 KMS 等機制,才能達到合適的安全等級。
原文出處#
- GitHub:https://github.com/MikeHsu0618/2022-ithelp/tree/main/Day19
- iThome:https://ithelp.ithome.com.tw/articles/10293943