為什麼要談安全#
在 DevOps 議題中,安全(Security)是相對特殊的一塊:它不一定會在每天的開發中出場,卻是評估一個基礎建設成熟度的重要指標。小團隊往往把權限管理排在優先序的後段,但隨著團隊規模拉大、產品線同時並行,沒有清楚的權限切分會讓誤操作變成災難。
從職涯角度來看,越是規模大的公司,越會在意這塊;願意提早投資權限管理的能力,對任何一位工程師來說都是加分。
Kubernetes 的認證與授權流程#
任何與 Kubernetes 叢集(Cluster)的互動,最終都會打到 kube-apiserver 這個資源管理入口。每個進來的請求都會依序通過:
- Authentication(身份驗證)
- Authorization(授權)
- Admission Control(准入控制)
通過後,請求才會被持久化到 etcd。這篇先聚焦在「身份」這一層,下一篇再進到 RBAC(Role-Based Access Control)的授權設定。
什麼是 Kubernetes Context#
在 Kubernetes 中,一個 Context 像是 kubeconfig 用戶端的 Alias,紀錄「我要怎麼跟某個叢集溝通」的一組組合。切換到某個 Context 之後,後續所有 kubectl 指令都會以該 Context 對應的:
- Cluster
- Namespace
- User
去發送請求。
kube-apiserver 本身並不認識 Context 這個概念。Context 只在用戶端被解析、把對應的 cluster/user/namespace 轉成請求參數送出去而已。
先看一份典型的 kubeconfig 結構。
kubectl config viewapiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://kubernetes.docker.internal:6443
name: docker-desktop
contexts:
- context:
cluster: docker-desktop
user: docker-desktop
name: docker-desktop
current-context: docker-desktop
kind: Config
preferences: {}
users:
- name: docker-desktop
user:
client-certificate-data: REDACTED
client-key-data: REDACTED只想看當前 Context 的設定可以加上 --minify。
kubectl config view --minify從結構上可以歸納出三個區塊:
- Clusters:紀錄每個叢集的 URL 與認證資訊,告訴用戶端要怎麼連到該叢集的 kube-apiserver。
- Contexts:把 cluster、user、namespace 三者組合在一起的命名 Alias(namespace 沒填則預設為
default)。 - Users:使用者(User)定義,內含對應的認證資訊,例如 client certificate、bearer token、authenticating proxy 等。
一個用戶管理情境#
假設工作環境中有兩個叢集:production 與 development,兩個叢集中各以 namespace 切出 frontend 與 backend。我們希望:
- 前端開發者只能操作 frontend namespace。
- 後端開發者只能操作 backend namespace。
- 不論是 production 或 development 都套用同樣的限制。
對應的 kubeconfig 概念上長這樣:
apiVersion: v1
kind: Config
clusters:
- cluster:
name: development
- cluster:
name: production
users:
- name: backend-developer
- name: front-developer
contexts:
- context:
name: dev-backend
namespace: backend
cluster: development
user: backend-developer
- context:
name: prod-backend
namespace: backend
cluster: production
user: backend-developer
- context:
name: dev-frontend
namespace: frontend
cluster: development
user: frontend-developer
- context:
name: prod-frontend
namespace: frontend
cluster: production
user: frontend-developer切到哪個 Context,就以該 user 的身份在該 cluster 中對該 namespace 操作資源。
實際操作#
建立 Context#
# 通用語法
kubectl config set-context <CONTEXT_NAME> \
--namespace=<NAMESPACE_NAME> \
--cluster=<CLUSTER_NAME> \
--user=<USER_NAME>
# 依序建立四個 Context
kubectl config set-context prod-frontend --cluster=production --namespace=frontend --user=prod-frontend
kubectl config set-context prod-backend --cluster=production --namespace=backend --user=prod-backend
kubectl config set-context dev-frontend --cluster=development --namespace=frontend --user=dev-frontend
kubectl config set-context dev-backend --cluster=development --namespace=backend --user=dev-backend建立完之後,再次 kubectl config view 就會看到這些 Context 出現在 contexts 區塊裡。
切換 Context#
# 顯示當前使用中的 Context
kubectl config current-context
# 切換到指定的 Context
kubectl config use-context <CONTEXT_NAME>到這一步,「角色 → Context → 對應的權限與 namespace」這條鏈路就成立了:每個團隊成員只要切到自己的 Context,就會以正確的身份與範圍操作叢集。
刪除設定#
# 刪除 user
kubectl --kubeconfig=config-demo config unset users.<name>
# 刪除 cluster
kubectl --kubeconfig=config-demo config unset clusters.<name>
# 刪除 context
kubectl --kubeconfig=config-demo config unset contexts.<name>Context 中的 Cluster 與 User 從哪來#
Context 既然只是 Alias,那實際的 cluster 連線資訊與 user 認證資訊是怎麼進到 kubeconfig 的?
- 本機 docker-desktop 只能提供一個 cluster,所以多叢集通常出現在雲端託管環境(GKE、EKS 等)。
- 雲端服務多半會用自家 CLI 或 SDK 把 kubeconfig 設好,例如
gcloud會自動寫入一條使用 GCP auth-provider 的 user 與對應 cluster。
如果要自己手動建立,可以用:
# 建立/修改 cluster
kubectl config set-cluster \
<CLUSTER_NAME> \
--server=<SERVER_ADDRESS> \
--certificate-authority=<CLUSTER_CERTIFICATE>
# 建立/修改 user
kubectl config set-credentials \
<USER_NAME> \
--client-certificate=<USER_CERTIFICATE> \
--client-key=<USER_KEY>這裡是用憑證的方式進行驗證:--client-certificate 用來認證 user,--certificate-authority 用來認證 cluster。Kubernetes 還支援 token、OpenID、Webhook 等多種驗證方式。
小結#
Context 把「叢集 + 使用者 + 命名空間」打包成一個易切換的單位,一方面用在多人團隊的權限切分,一方面也保護自己不在錯誤的環境下手。但 Context 本身只解決「我是誰、在哪個叢集」的問題,至於這個 user 能做什麼,要靠下一篇的 RBAC 來決定。
原文出處#
- GitHub:https://github.com/MikeHsu0618/2022-ithelp/tree/main/Day28
- iThome:https://ithelp.ithome.com.tw/articles/10300175