為什麼要談安全#

在 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 view
apiVersion: 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