K8s · 維運與部署 · 第 33 課 · · 11min read

K8s RBAC 教學:建一個只讀帳號給工程師查問題

admin 權限給每個工程師太危險。RBAC 用 Role + RoleBinding 把權限綁到使用者:你只能 get pod、不能刪、不能改。這篇實作只讀帳號完整流程。

#Kubernetes #RBAC #權限 #Role #ServiceAccount
章節目錄 · 11

一個共用 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:

  • apiGroups: [""] # core API(Pod, Service 這些)
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:

  • apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-viewer-binding
namespace: default
subjects:
  • kind: ServiceAccount
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 < viewer.kubeconfig
apiVersion: v1
kind: Config
clusters:

  • cluster:
certificate-authority-data: $CA
server: $SERVER
name: local
contexts:
  • context:
cluster: local
user: viewer-sa
name: local
current-context: local
users:
  • name: viewer-sa
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\上帝視角(很危險)
例如要給某人「所有 Namespace 唯讀」:

\\\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 課,按學習路徑順序排)