昨天設定了 HPA,讓 todo-api 在 CPU 超過 50% 時自動擴容,並用壓測驗證了擴縮容的效果。今天要學 RBAC,設定不同角色的存取權限,控管誰能對 K8s 資源做什麼操作 !
目前用 kubectl 下的每個指令都有完整的叢集管理權限,可以建立、修改、刪除任何資源。在個人開發環境沒問題,但在多人協作或生產環境,這樣太危險:
RBAC(Role-Based Access Control)可以精確定義「誰能對哪些資源做什麼操作」。
Role 和 ClusterRole 都是用來定義「能對哪些資源做哪些操作」,差別只在範圍:
以下是一個 Role 的範例,允許讀取 dev Namespace 內的 Pod:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: dev
rules:
- apiGroups: [""] # "" 代表 core API group(Pod、Service 等)
resources: ["pods", "pods/log"] # 針對那些資源
verbs: ["get", "list", "watch"] # 允許哪些操作
verbs 決定允許哪些操作,常用的有:
get、list、watch:讀取create、update、patch:建立和修改delete:刪除光有 Role 還不夠,要透過 RoleBinding 把 Role 指派給特定對象,權限才會實際生效。RoleBinding 和 ClusterRoleBinding 都是做這件事,差別同樣在範圍:
以下範例把剛才的 pod-reader Role 指派給 todo-reader 這個 ServiceAccount:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: dev
subjects: # 誰能做 → 指定對象(User、Group、ServiceAccount)
- kind: ServiceAccount
name: todo-reader
namespace: dev
roleRef: # 引用上方建立的 pod-reader Role
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
subjects 支援三種對象:
kubectl 操作叢集)這篇的範例都用 ServiceAccount,因為情境是 CI/CD 系統操作 k8s。如果是要控制團隊成員的存取權限,就會改用 User 或 Group。
簡單總結四個資源的關係:
Role / ClusterRole → 定義「能做什麼」
RoleBinding / ClusterRoleBinding → 把「誰」和「能做什麼」綁在一起
今天目標:建立 todo-reader 和 cicd-deployer 兩個 ServiceAccount,分別設定對應的 Role 和 RoleBinding,並用 kubectl auth can-i 驗證權限有正確限制。
確認目前預設 Namespace 是 dev:
kubectl config view --minify --output "jsonpath={..namespace}"
如果不是 dev,先切換過去:
kubectl config set-context --current --namespace=dev
ServiceAccount 是 K8s 內部的帳號,給 Pod 或 CI/CD 系統使用,不是給真人用的帳號。
kubectl create serviceaccount todo-reader -n dev
建立 pod-reader-role.yaml,只允許讀取 Pod 和 Log:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: dev
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
kubectl apply -f pod-reader-role.yaml
建立 pod-reader-binding.yaml,把 Role 綁定給 ServiceAccount:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: todo-reader-binding
namespace: dev
subjects:
- kind: ServiceAccount
name: todo-reader
namespace: dev
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
kubectl apply -f pod-reader-binding.yaml
用 kubectl auth can-i 確認 ServiceAccount 有哪些權限:
# 確認可以 list pods
kubectl auth can-i list pods \
--as=system:serviceaccount:dev:todo-reader \
-n dev
# yes ← 有權限
# 確認不能刪除 pods
kubectl auth can-i delete pods \
--as=system:serviceaccount:dev:todo-reader \
-n dev
# no ← 沒有權限
# 確認不能讀取 secrets
kubectl auth can-i get secrets \
--as=system:serviceaccount:dev:todo-reader \
-n dev
# no ← 沒有權限
注意:
kubectl auth can-i查詢的是指定 Namespace 的權限,務必加上-n dev確保查詢結果正確。
實際工作中,CI/CD 系統(例如 GitHub Actions)需要部署權限。建立一個只有部署權限的 ServiceAccount:
建立 deployer-role.yaml:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer
namespace: dev
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services", "configmaps"]
verbs: ["get", "list", "create", "update", "patch"]
kubectl create serviceaccount cicd-deployer -n dev
kubectl apply -f deployer-role.yaml
建立 cicd-deployer-binding.yaml:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cicd-deployer-binding
namespace: dev
subjects:
- kind: ServiceAccount
name: cicd-deployer
namespace: dev
roleRef:
kind: Role
name: deployer
apiGroup: rbac.authorization.k8s.io
kubectl apply -f cicd-deployer-binding.yaml
ServiceAccount 除了給 CI/CD 用,也可以掛到 Pod 上,讓 Pod 裡的應用程式能呼叫 K8s API。
例如一個監控程式需要定期讀取所有 Pod 的狀態,可以幫它建立一個有讀取權限的 ServiceAccount,然後掛到 Pod 上:
spec:
serviceAccountName: todo-reader # 指定 ServiceAccount
containers:
- name: monitor
image: yourname/monitor:v1.0.0
Pod 裡的應用程式就能用 K8s API 讀取 Pod 資訊,而不需要把管理員憑證塞進 Pod 裡。
如果不指定 serviceAccountName,Pod 會自動使用 default ServiceAccount,它預設沒有任何額外權限。
今天學了 RBAC:
明天會學 NetworkPolicy,控制 Pod 之間的網路流量,讓 MySQL 只接受來自 todo-api 的連線 !