一個共用 admin 帳號的災難
某公司新進工程師第一天上班,主管丟了一個 \config\ 檔給他:
「這是 K8s 的 kubeconfig,所有環境都用這個。」
新人為了清測試環境的舊資源,下了:
\\\bash\
kubectl delete namespace prod
\\
整個生產環境消失了。為什麼?因為那個 kubeconfig 是 cluster-admin,所有人共用。
K8s 怎麼避免這種事?答案是 RBAC(Role-Based Access Control)。
RBAC 的邏輯就三個字
誰 + 能做什麼 + 綁定起來
| 概念 | K8s 物件 |
|---|---|
| 誰 | User / Group / ServiceAccount |
| 能做什麼 | Role / ClusterRole |
| 綁定起來 | RoleBinding / ClusterRoleBinding |
四個物件,先記範圍
| 物件 | 作用範圍 | 用途 |
|---|---|---|
| Role | 單一 Namespace | 定義「能對什麼資源做什麼動作」 |
| ClusterRole | 整個叢集 | 同上,但跨 Namespace |
| RoleBinding | 單一 Namespace | 把 Role 綁到某人身上 |
| ClusterRoleBinding | 整個叢集 | 把 ClusterRole 綁到某人身上 |
- Role = 門禁卡(只能進 3F 研發部)
- ClusterRole = 萬能卡(所有樓層都能進)
- RoleBinding = 把門禁卡發給某個人
- ClusterRoleBinding = 把萬能卡發給某個人
ServiceAccount = Pod 的身份
人類用 \kubectl\ 是透過 User 認證。Pod 呢?
Pod 也常常需要呼叫 K8s API(如 ingress-controller、Prometheus、ArgoCD 等)。Pod 的身份就是 ServiceAccount。
\\\bash\
# 每個 Namespace 預設都有一個 default
kubectl get sa
# NAME SECRETS AGE
# default 1 5d
\\
Role YAML:拆解 verbs
\\\yaml\
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-viewer
rules:
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"] # 只能查不能改
\\
關鍵欄位:
| 欄位 | 說明 |
|---|---|
\apiGroups: [""]\ | 空字串代表 core API(Pod, Service, ConfigMap) |
\apiGroups: ["apps"]\ | apps 群組(Deployment, StatefulSet) |
\resources\ | 哪些資源(pods, services, deployments...) |
\verbs\ | 動作:get / list / watch / create / update / delete |
create / delete\,這個 Role 就是只讀的。
實作:從零做一個 viewer 帳號
完整 YAML(一份檔案搞定 SA + Role + Binding):
\\\yaml\
# rbac-viewer.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: viewer-sa
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-viewer
rules:
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-viewer-binding
namespace: default
subjects:
name: viewer-sa
namespace: default
roleRef:
kind: Role
name: pod-viewer
apiGroup: rbac.authorization.k8s.io
\\
\\\bash\
kubectl apply -f rbac-viewer.yaml
\\
驗證:用 \--as\ 模擬身份
\--as\ 讓 kubectl 假裝自己是某個 SA,不用真的去切 kubeconfig。
應該成功的:
\\\bash\
kubectl get pods --as=system:serviceaccount:default:viewer-sa
# 正常顯示 Pod 清單 ✅
\\
應該被擋的:
\\\bash\
kubectl run test --image=nginx \\
--as=system:serviceaccount:default:viewer-sa
# Error from server (Forbidden): pods is forbidden:
# User "system:serviceaccount:default:viewer-sa" cannot create resource "pods"
\\
\\\bash\
kubectl delete deployment nginx \\
--as=system:serviceaccount:default:viewer-sa
# Error: deployments.apps is forbidden ✅
\\
這就是 RBAC 在保護你——viewer-sa 只能查不能改,Role 沒寫的權限通通沒有。
更實用:給人用的 kubeconfig
上面只是用 \--as\ 模擬。真實情境是給工程師一份 kubeconfig:
\\\bash
# 為 viewer-sa 建立 token(K8s 1.24+)
TOKEN=$(kubectl create token viewer-sa)
# 從現有 kubeconfig 拿 cluster CA
CA=$(kubectl config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
SERVER=$(kubectl config view --raw -o jsonpath='{.clusters[0].cluster.server}')
# 寫一份只讀的 kubeconfig
cat <
apiVersion: v1
kind: Config
clusters:
certificate-authority-data: $CA
server: $SERVER
name: local
contexts:
cluster: local
user: viewer-sa
name: local
current-context: local
users:
user:
token: $TOKEN
EOF
\\\
把 \viewer.kubeconfig\ 給工程師,他用:
\\\bash\
KUBECONFIG=viewer.kubeconfig kubectl get pods # OK
KUBECONFIG=viewer.kubeconfig kubectl delete pod # Forbidden
\\
內建 ClusterRole 速查
K8s 已經幫你準備好幾個常用的 ClusterRole,先用內建的,不要自己寫:
| ClusterRole | 用途 |
|---|---|
\view\ | 唯讀(除了 Secret) |
\edit\ | 可改但不能管權限 |
\admin\ | Namespace 內全權 |
\cluster-admin\ | 上帝視角(很危險) |
\\\bash\
kubectl create clusterrolebinding alice-view \\
--clusterrole=view \\
--serviceaccount=default:alice-sa
\\
重點整理
- RBAC = 誰 + 能做什麼 + 綁定起來
- Role / RoleBinding 只在一個 Namespace;ClusterRole / ClusterRoleBinding 跨叢集
- ServiceAccount = Pod 的身份;每個 Namespace 都有 default
- 沒寫的權限就是沒有——白名單機制
- \
--as\模擬身份最快驗證權限 - 內建 view / edit / admin / cluster-admin 多數情況夠用
下一步
權限管好了——但 K8s 預設 Pod 之間網路全通。前端 Pod 可以直連資料庫 Pod、開發 namespace 可以打到生產 namespace。
下一篇:NetworkPolicy — 讓 Pod 之間有防火牆
📅 下一篇:NetworkPolicy:讓 Pod 之間有防火牆
預設 Pod 全通——這篇教你怎麼把生產/開發切開,前端不能直連 DB。
📚 完整系列總覽:K8s 系列教學首頁(共 40 課,按學習路徑順序排)