iT邦幫忙

2026 iThome 鐵人賽

DAY 19
0

昨天設定了 HPA,讓 todo-api 在 CPU 超過 50% 時自動擴容,並用壓測驗證了擴縮容的效果。今天要學 RBAC,設定不同角色的存取權限,控管誰能對 K8s 資源做什麼操作 !


為什麼需要權限控制

目前用 kubectl 下的每個指令都有完整的叢集管理權限,可以建立、修改、刪除任何資源。在個人開發環境沒問題,但在多人協作或生產環境,這樣太危險:

  • 開發人員應該能看 Pod log,但不應該能刪除 Production 的 Deployment
  • CI/CD 系統只需要部署特定 Namespace 的權限,不需要讀取 Secret
  • 不同團隊只應該能操作自己負責的 Namespace

RBAC(Role-Based Access Control)可以精確定義「誰能對哪些資源做什麼操作」。


RBAC 的四個核心資源

Role 和 ClusterRole

Role 和 ClusterRole 都是用來定義「能對哪些資源做哪些操作」,差別只在範圍:

  • Role:只在某個 Namespace 內有效
  • ClusterRole:適用於整個叢集,不限 Namespace,也能操作叢集層級的資源(如 Node、PV)

以下是一個 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:刪除

RoleBinding 和 ClusterRoleBinding

光有 Role 還不夠,要透過 RoleBinding 把 Role 指派給特定對象,權限才會實際生效。RoleBinding 和 ClusterRoleBinding 都是做這件事,差別同樣在範圍:

  • RoleBinding:在某個 Namespace 內授予權限
  • 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 支援三種對象:

  • ServiceAccount:給程式或系統使用(例如 Pod、CI/CD pipeline)
  • User:給個人使用(例如開發者用 kubectl 操作叢集)
  • Group:給一群人使用(例如整個開發團隊共用同一套權限)

這篇的範例都用 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

Step1: 建立 ServiceAccount

ServiceAccount 是 K8s 內部的帳號,給 Pod 或 CI/CD 系統使用,不是給真人用的帳號。

kubectl create serviceaccount todo-reader -n dev

Step2: 建立 Role

建立 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

Step3: 建立 RoleBinding

建立 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

Step4: 驗證權限

用 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 確保查詢結果正確。

Step5: 建立 CI/CD 專用的 ServiceAccount

實際工作中,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 在 Pod 裡的用途

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:

  • Role / ClusterRole:定義能對哪些資源做哪些操作
  • RoleBinding / ClusterRoleBinding:把 Role 綁定給使用者或 ServiceAccount
  • ServiceAccount:K8s 內部帳號,給 Pod 和 CI/CD 系統使用
  • 最小權限原則:只給剛好需要的權限,不多給

明天會學 NetworkPolicy,控制 Pod 之間的網路流量,讓 MySQL 只接受來自 todo-api 的連線 !


上一篇
Day 18|HPA
系列文
從零學 K8s|30 天核心概念 × 實作,新手也能真正掌握 Kubernetes 共 19 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言