跳至主要内容

Security - RBAC Authorization

Kubernetes 的認證、授權與准入控制

Triple-A

在 Kubernetes 中,安全性機制由 認證(Authentication)授權(Authorization)准入控制(Admission Control) 組成,共同確保叢集的安全性與可控性。


認證(Authentication)

在 Kubernetes 中,認證是保障系統安全的第一道防線,確保只有合法的用戶和服務能夠存取 API 伺服器。Kubernetes 支援多種認證方式來驗證身份,其中最常見的是普通使用者(User)服務帳號(ServiceAccount)

1. 普通使用者(User)

普通使用者是指直接與 Kubernetes API 伺服器交互的用戶或應用程式。這些使用者通常會使用 X.509 憑證、Token 或 OpenID Connect(OIDC)等方式進行身份認證。

  • 身份認證方式:普通使用者可使用 X.509 客戶端憑證或 Token 來進行身份驗證。也可以透過 OIDC 與外部身份提供者(如 Google、Azure AD)進行整合,實現單一登入(SSO)。
  • 用途:普通使用者一般是管理 Kubernetes 叢集的操作人員或開發者,他們會使用 kubectl 等工具來部署應用、管理資源、執行日常操作等。
  • 授權機制:普通使用者的權限通常透過角色基於存取控制(RBAC)來管理。管理員可根據使用者的角色來設定其對不同資源的訪問權限。

範例: 假設有一名開發者透過 X.509 憑證登錄 Kubernetes,這位開發者便可使用 kubectl 指令執行各種操作,但權限會受到 RBAC 配置的限制。

2. 服務帳號(ServiceAccount)

服務帳號是 Kubernetes 用來為 Pod 提供身份認證的機制,使得 Pod 能夠安全地與 Kubernetes API 互動。每個命名空間在建立時會自動創建一個名為 default 的服務帳號,並為該命名空間內的 Pod 提供一個 Token,用於身份驗證。

  • 身份認證:服務帳號會自動與一組憑證(如 JSON Web Token)關聯,這些憑證被 Pod 使用來與 API 伺服器進行交互,無需手動配置。
  • 作用範圍:服務帳號的作用範圍是基於命名空間。每個命名空間會自動創建 default 服務帳號,並將對應的 Token 提供給該命名空間中的 Pod 使用。
  • 用途:服務帳號主要用於 Pod 內的應用程式,當應用程式需要存取 Kubernetes API(例如讀取 ConfigMap 或創建資源)時,會使用服務帳號來進行身份驗證。
  • 授權機制:服務帳號的權限透過角色(Role)和角色綁定(RoleBinding)進行控制。每個服務帳號可以被賦予不同的角色,限制其可操作的資源範圍。

範例: 當 Pod 需要從 Kubernetes API 獲取一個 ConfigMap 時,它會自動使用該命名空間的 default 服務帳號進行身份驗證,並根據所配置的角色和角色綁定授予相應的權限。

身份驗證方式

  • X.509 客戶端憑證:這是最常見的方法,系統管理員可以使用 CA 簽署的憑證來驗證用戶身份。每個用戶會有獨立的憑證與私鑰,並透過 kubectl 設定。
  • 靜態 Token 文件:Kubernetes 允許透過 Token 文件來進行身份驗證,適用於簡單的測試環境。
  • OpenID Connect(OIDC):支援與外部身份提供者(如 Google、Azure AD、Keycloak)整合,適用於企業級 SSO(單一登入)。
  • Webhook 身份驗證:API 伺服器可透過 Webhook 方式,將身份驗證請求轉發至外部的認證服務。
  • 服務帳戶(ServiceAccount):專為 Pod 內的應用程式提供的身份驗證機制,使其能夠存取 Kubernetes API。

授權(Authorization)

身份驗證通過後,僅能代表當前的使用者允許與 Kubernetes API Server 溝通,但該使用者是否有權限請求什麼資源,就是由授權決定。

授權機制

  • RBAC(Role-Based Access Control,基於角色的存取控制)
    • 透過 Role(角色)和 RoleBinding(角色綁定)來管理權限。
    • ClusterRoleClusterRoleBinding 適用於全域範圍。
    • RoleRoleBinding 限制在特定命名空間內。
  • ABAC(Attribute-Based Access Control,基於屬性的存取控制)
    • 採用策略文件來定義存取規則。
    • 需要啟用 --authorization-policy-file 參數。
  • Webhook 授權
    • 透過 Webhook 將授權決策委派給外部系統。
  • Node 授權
    • 用於控制節點(Node)層級的訪問權限,確保節點只能執行授權的操作。
    • 主要依賴於 NodeRestriction,確保只允許節點本身對特定資源(例如,Pod)進行操作。

查看是否有權限

我們可以通過auth can-i指令,來快速查看 API 是否有權限執行。

kubectl.exe auth can-i create deployments --namespace default
---

yes

准入控制(Admission Control)

准入控制(Admission Control)是在身份驗證與授權後的額外安全機制,能夠攔截、修改或拒絕 API 請求,確保叢集的運行符合安全策略。

准入控制器

  • NamespaceLifecycle:限制請求僅能作用於現有的命名空間,避免使用未經授權的命名空間。
  • LimitRanger:確保 Pod、Container、PersistentVolumeClaim 等資源不超出設定的限制範圍。
  • ResourceQuota:限制命名空間內可用的資源數量,例如 CPU、記憶體與儲存空間。
  • PodSecurityAdmission(取代舊版 PSP):根據 Pod Security Standards(PSS)規則來限制 Pod 佈署的安全性。
  • ValidatingAdmissionWebhook & MutatingAdmissionWebhook:允許透過 Webhook 來驗證與修改請求,例如強制執行公司安全策略或自動補充預設設定。

ValidatingWebhookConfiguration

  • 用途

    • 用於驗證 API 請求,確保請求的內容符合指定的安全規範或配置要求。
    • 這些 Webhook 可以攔截並拒絕不符合條件的 API 請求,確保叢集中的資源符合預期的標準。
  • 作用

    • 會在 API 請求 進入 Kubernetes API Server 之前進行驗證。
    • 如果請求未通過驗證,會 拒絕該請求,並返回錯誤訊息。
  • 範例

    • 驗證是否部署的 Pod 符合 安全性規範,例如確保容器鏡像來自受信任的來源。
    • 強制規定 Pod 必須包含特定標籤
  • 指令

    kubectl.exe get validatingwebhookconfigurations
    ---

    NAME WEBHOOKS AGE
    ingress-nginx-admission 1 15d
    keda-admission 3 14h

MutatingWebhookConfiguration

  • 用途

    • 用於修改 API 請求的內容。當請求進入 Kubernetes API Server 之前,Webhook 會自動修改或增加資源的某些屬性。
    • 這種方式可用於自動補充或調整請求中的資源配置。
  • 作用

    • 會在 API 請求進入 Kubernetes API Server 之前進行修改。
    • 能夠自動將某些預設配置添加到 Pod 或其他資源中,從而減少人工干預。
  • 範例

    • 自動為 Pod 加上預設標籤預設的資源限制(如 CPU、記憶體)。
    • 注入 Sidecar 容器(例如,Istio 或監控代理)。
  • 指令

    kubectl.exe get mutatingwebhookconfigurations
    ---

    NAME WEBHOOKS AGE
    vpa-webhook-config 1 14h

使用 VM 安裝 Kubernetes

因為 docker-desktop 沒有辦法取得內部的 ca 憑證,因此以下會利用 VM 從頭安裝一次 kubernetes cluster。

建立一個 Ubuntu VM

  1. 首先我們使用 Oracle VM VirtualBox 來安裝我們的 ubuntu,創立一個 VM。

create-vm-iso

  1. 接下來設定帳號和密碼,等一下安裝好登入要用到,不能忘記呦~

create-vm-username-password

  1. 記憶體和 CPU 可以多給一點,但不要給到整台電腦的量,避免原本的電腦當機,後續可以再調整。

create-vm-memory-cpu

  1. 硬碟大小可以給大,因為設定之後就不能調整了,而且他不會一次就要滿全部的量,用多少佔多少,所以可以多一點,避免未來想要的時候反而調不動。

create-vm-disk

  1. 按下完成就建立好了,它會自動執行,進行安裝。

create-vm-overview

  1. 完成安裝之後,就會進到登入畫面。

ubuntu-login


設定 SSH 連線

  1. 接下來我不想要直接操作 VM 的 UI,首先按下ctrl+alt+F3,登入 root,密碼是剛剛設定的密碼。

ubuntu-terminal-login

  1. 接著將我們剛剛創立的帳號增加 sudoer 的權限,exit 之後就可以用自己的帳號再登入了。
sudo usermod -aG sudo <username>
  1. 先進行系統的更新與安裝。
sudo apt-get update && sudo apt-get upgrade -y
  1. 安裝 openssh-server,另外需要安裝 net-tools 和 vim,等一下要來查看 IP 位置,安裝好後將 ubuntu 關機。
sudo apt-get install openssh-server -y
sudo apt-get install net-tools -y
sudo apt-get install vim -y
sudo shutdown -h 0
  1. 之後,要設定網路讓本機可以連到虛擬機,虛擬機也能連到外網,因此點選左上角的工具,在僅限主機需要創立一個。

create-vm-network-host-only-adapter

  1. 接著將 VM 設定裡面的網路介面卡添加僅限主機這個介面卡到介面 2,混和模式記得要選擇允許 VM,確定後就可開機了。

setting-vm-network-host-only-adapter

  1. 接著我們登入 ubuntu 之後,去修改 netplan 的 yaml 檔案,並執行他,就會看到可以取得 IP 了。
sudo vim /etc/netplan/01-network-manager-all.yaml
network:
version: 2
ethernets:
enp0s3:
dhcp4: true
enp0s8:
dhcp4: false
addresses:
- 192.168.182.2/24 # 我們剛剛建立的Host-Only Adapter是192.168.182.1/24,所以選擇192.168.182.2~255都可以
sudo netplan apply
ifconfig
---

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255

enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.182.2 netmask 255.255.255.0 broadcast 192.168.182.255

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
  1. 接著我們將 VM 縮小,用本機的 terminal 連線到 192.168 上面的那個 IP,就可以成功登入。
ssh calvin@192.168.182.2
---

calvin@k8s-cluster:~$

禁用 SWAP、載入 kernel module

  1. 首先我們透過上面的 SSH 連到 VM 裡面,接著我們要對 Ubuntu 禁用 Swap,這樣 Kubernetes 才能正常運作。
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
  1. 接下來啟動 Kuberntes 需要的 Linux kernel module,並寫到設定檔之中,每次都會啟用。
sudo modprobe overlay
sudo modprobe br_netfilter
sudo tee /etc/modules-load.d/k8s.conf <<EOF
overlay
br_netfilter
EOF
  1. 設定 IP 轉發的參數供 kernel 使用,一樣也是要寫到設定檔之中。
sudo tee /etc/sysctl.d/kubernetes.conf <<EOT
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOT
  1. 透過指令載入這些參數。
sudo sysctl --system

安裝 Containerd

  1. Containerd 是 kubernetes 提供容器運行,首先我們安裝取得 Containerd 套件的工具。
sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
  1. 增加 Containerd 的 repo。
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/containerd.gpg
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
  1. 更新 repo 以及安裝 Containerd。
sudo apt update && sudo apt install containerd.io -y
  1. 設定 Containerd 的 Config,並使用 SystemdCgroup 來執行命令。
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
  1. 重啟 Containerd 的服務,讓上面的更改生效。
sudo systemctl restart containerd

安裝 Kubernetes 元件 (Kubeadm、kubelet、kubectl)

  1. 因為 Ubuntu 24.04 預設的 repo 不能使用,我們首先要先添加 repo,以下以 kubernetes 1.30 為範例。
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/k8s.gpg
echo 'deb [signed-by=/etc/apt/keyrings/k8s.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/k8s.list
  1. 更新套件後,我們就可以來安裝 kubernetes 的三元件。
sudo apt update
sudo apt install kubelet kubeadm kubectl -y

安裝 Kubernetes

1. 上面所有的元件都安裝好後,我們就可以開始安裝 Kuberentes,我們在 master 的節點上執行kubeadm指令,用來初始化 Kubernetes 集群,control-plane-endpoint 就是我們之前創立 VM 的名字,他會記錄在/etc/hosts。

sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --control-plane-endpoint=k8s-cluster
---

Your Kubernetes control-plane has initialized successfully!
  1. 安裝成功之後,我們照著他的指示,將設定檔放到自己的家目錄底下。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
  1. 如果有其他 makter 或 worker 可以透過上面給的指令來增加 node(我們這邊沒有)。
kubeadm join k8s-cluster:6443 --token lzqq9n.7jvhkyj5qugtvm9l \
--discovery-token-ca-cert-hash sha256:bf6a379f7cb0ce846a90cfe9a3a1b6661ed68f93cded0a4ff5ab315b88ffc54f \
--control-plane
---
kubeadm join k8s-cluster:6443 --token lzqq9n.7jvhkyj5qugtvm9l \
--discovery-token-ca-cert-hash sha256:bf6a379f7cb0ce846a90cfe9a3a1b6661ed68f93cded0a4ff5ab315b88ffc54f

安裝 Calico Network Add-on Plugin

  1. 因為我們在虛擬機上安裝,因此我選擇 Manifest based 的方法來安裝 Calico,首先先把設定檔下載下來。
wget https://docs.projectcalico.org/manifests/calico.yaml
  1. 用編輯器打開文件,並且在--cluster-cidr 底下的兩行取消註解。
vim calico.yaml

---
# no effect. This should fall within `--cluster-cidr`.
- name: CALICO_IPV4POOL_CIDR
value: "192.168.0.0/16"
  1. 因為我們是使用虛擬機,網卡不是 eth 開頭,因此需要找尋有 IP 的地方,然後在他下面加上兩行。
vim calico.yaml

---
>> search
- name: IP
value: "autodetect"
>> add
- name: IP_AUTODETECTION_METHOD
value: "interface=enp0s3" (多網卡用","分隔)

# first-found會去找主機的第一張網卡,但預設是找"eth*",所以VM的網卡為ens就會失敗
  1. 透過指令來創建 calico 所有的服務。
kubectl create -f calico.yaml
  1. 等數分鐘至數十分鐘,我們可以觀察到所有 kube-system 底下的 pod 都順利運行。
kubectl get pods -n kube-system
---

NAME READY STATUS RESTARTS AGE
calico-kube-controllers-5b9b456c66-2r99b 1/1 Running 0 30m
calico-node-bxjr6 1/1 Running 0 30m
coredns-55cb58b774-52nk6 1/1 Running 0 41m
coredns-55cb58b774-cxrzg 1/1 Running 0 41m
etcd-k8s-cluster 1/1 Running 3 (25m ago) 42m
kube-apiserver-k8s-cluster 1/1 Running 3 (25m ago) 42m
kube-controller-manager-k8s-cluster 1/1 Running 2 (25m ago) 42m
kube-proxy-5grwt 1/1 Running 1 (25m ago) 41m
kube-scheduler-k8s-cluster 1/1 Running 3 (25m ago) 42m
  1. 這個時候查看 node 的狀態就會從 NotReady 變成 Ready,代表成功運行囉!
kubectl get nodes
---

NAME STATUS ROLES AGE VERSION
k8s-cluster Ready control-plane 43m v1.30.9

實作一個 RBAC

我們想要基於 Role 的概念來建立訪問權限,用來調節使用者對 kubernetes API Server 的訪問方法, 以超級管理者為例,這個角色與瀏覽者有著極大的權限差距,為了保護內部的重要基礎建設,不希望每個使用著都可以建立或刪除資源, 因此我們實現將 權限(Permission) 綁定在普通使用著以及服務帳號的概念上,將複雜的業務權限做輕量化,並遵從權限最小化原則。

建立一個以 X.509 憑證驗證的普通使用者

  1. 首先我們需要以自身的 kubernetes 作為 CA 發送方,來發送一個 CA 憑證,並產生一組私鑰,名稱叫做 pod-viewer.key。
openssl genrsa -out pod-viewer.key 2048
  1. 我們透過 pod-viewer.key 去產生 CSR (憑證簽名請求),檔案名稱叫做 pod-viewer.csr,kubernetes 會使用憑證中的 subject 的通用名稱(Common Name)欄位來確定使用者名稱。
openssl req -new -key pod-viewer.key -out pod-viewer.csr -subj "/CN=pod-viewer/O=app"
  1. 有了 CSR,我們就可以把它交給叢集管理者(這裡也是我們)透過叢集 CA 簽署客戶端憑證。

  2. 進到 master 的 node 裡面(也就是我們所在的 VM),我們可以將 CA 根憑證取出來,複製一份到目前的工作目錄,為了來簽屬所有需要通訊的憑證。

sudo cp /etc/kubernetes/pki/ca.crt .
sudo cp /etc/kubernetes/pki/ca.key .
sudo chown $(id -u):$(id -g) ca.crt ca.key
ls
---

ca.crt ca.key pod-viewer.csr pod-viewer.key
  1. 接著我們拿根憑證來產生一個被叢集 CA 簽署過的憑證,並且可以看到他的 CN 是 kubernetes。
openssl x509 -req -in pod-viewer.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out pod-viewer.crt -days 365
---

Certificate request self-signature ok
subject=CN = pod-viewer, O = app
openssl x509 -noout -text -in pod-viewer.crt
---

Certificate:
Data:
Version: 1 (0x0)
Serial Number:
11:88:92:5c:a6:04:26:5f:6b:1b:c8:55:9a:4d:43:e0:82:cc:e6:80
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = kubernetes
Validity
Not Before: Feb 6 17:38:44 2025 GMT
Not After : Feb 6 17:38:44 2026 GMT
Subject: CN = pod-viewer, O = app
  1. 有了憑證之後可以來建立 Context 和 User 了,使用 pod-viewer 建立一個普通的 User。
kubectl config set-credentials pod-viewer \
--client-certificate=pod-viewer.crt \
--client-key=pod-viewer.key \
--embed-certs=true

---
User "pod-viewer" set.
  1. 接著我們建立一個 Context 叫做 only-view,並且指定 Cluster 是 kubernetes,User 是剛剛建立的 pod-viewer。
kubectl config set-context only-view --cluster=kubernetes --user=pod-viewer
---

Context "only-view" created.
kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://k8s-cluster:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
- context:
cluster: kubernetes
user: pod-viewer
name: only-view
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
- name: pod-viewer
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
  1. 於是我們就可以切換 Context 到 pod-viewer,當我們試圖查看 pod 的時候會發現沒有權限,這是正常的,因為還不能通過 Authorization。
kubectl config use-context only-view
---

Switched to context "only-view".
kubectl get pod
---

Error from server (Forbidden): pods is forbidden: User "pod-viewer" cannot list resource "pods" in API group "" in the namespace "default"

使用 RBAC 授權給普通使用者

Kubernetes 自 v1.8 起引入了 Authorization 機制,用於管制對 Kubernetes API 的訪問。 管理者可透過 rbac.authorization.k8s.io API 群組進行動態管理設定,其中 RBAC(Role-Based Access Control,基於角色的存取控制)機制允許管理員透過定義角色(Role)與角色綁定(RoleBinding), 來管控用戶、組件或服務帳戶的權限,確保資源的安全性與管理效率。

RBAC 主要由四個核心物件組成:

  • Role
  • ClusterRole
  • RoleBinding
  • ClusterRoleBinding
  1. 首先我們先切回來原本的 Context,然後建立一個 Role 定義在 default 命名空間,名稱是 pod-viewer。
kubectl config use-context kubernetes-admin@kubernetes
---

Switched to context "kubernetes-admin@kubernetes".
role.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default # 定義在default命名空間
name: pod-viewer # Role的名稱
rules:
- apiGroups: [''] # '' 預設代表 apiversion: v1
resources: ['pods']
verbs: ['get', 'list', 'watch']
kubectl apply -f role.yaml
---

role.rbac.authorization.k8s.io/pod-viewer created
  1. 我們有了 user 名稱叫做 pod-viewer,另外也有了 role,他定義這個 role 可以讀取那些資源和權限,名稱叫做 pod-viewer,接下來我們要定義 RoleBinding,讓 user 和 role 做綁定。
role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-viewer-rolebinding
namespace: default # 授權的命名空間為default
subjects:
- kind: User
name: pod-viewer # 連結 user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-viewer # 連結 role
apiGroup: rbac.authorization.k8s.io
kubectl apply -f role-binding.yaml
---

rolebinding.rbac.authorization.k8s.io/pod-viewer-rolebinding created
  1. 接下來我們切換到 only-view 這個 context,他可以正確取得 pod 的資訊,但阻止看到其他 namespace 的資源。
kubectl config use-context only-view
---

Switched to context "only-view".
kubectl get pods -n default
---

No resources found in default namespace.
kubectl get pods -n kube-system
---

Error from server (Forbidden): pods is forbidden: User "pod-viewer" cannot list resource "pods" in API group "" in the namespace "kube-system"

Kubernetes RBAC Example

RBAC-overview


Role 與 ClusterRole

Role

Role 是在 命名空間(Namespace)範圍內 定義的權限集合。它只影響該命名空間內的資源,無法管理整個集群(Cluster)級別的資源。

特點

  • 限定在單一命名空間內。
  • 授權細粒度的資源存取,例如 Pod、ConfigMap、Secret 等。
  • 不能直接控制 Cluster 範圍的資源,如 Node、PersistentVolume(PV)等。

適用場景

  • 需要針對不同命名空間設置不同權限的應用場景。
  • 限制某些使用者或服務帳戶僅能存取特定命名空間內的資源。

範例:

role.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default # 定義在default命名空間
name: pod-viewer # Role的名稱
rules:
- apiGroups: [''] # '' 預設代表 apiversion: v1
resources: ['pods']
verbs: ['get', 'list', 'watch']

參數:

1. apiGroups

apiGroups 定義資源所屬的 API Group。Kubernetes 的資源可以劃分為不同的 API Group。Core 資源(例如 pods)屬於空的 API Group (apiGroups: ['']),而其他資源(例如 deploymentsservices)則屬於特定的 API Group(如 appsbatch 等)。

2. resources

resources 定義角色可以操作的具體 Kubernetes 資源類型。例如:

  • pods:表示 Pod 資源。
  • services:表示 Service 資源。
  • deployments:表示 Deployment 資源。

使用 * 可以表示所有資源類型。

3. verbs

verbs 定義了該角色可以對指定資源執行的操作。常見的動作包括:

  • get:查看資源的詳細資料。
  • list:列出資源的集合。
  • create:創建新的資源。
  • update:更新資源。
  • delete:刪除資源。
  • watch:監控資源的變化。

ClusterRole

ClusterRole 與 Role 類似,但它的權限適用於 整個集群(Cluster),而不侷限於特定命名空間,如果系統管理員沒有 ClusterRole 的權限,代表他需要將每個 namespace 一一綁定叢集等級使用者,那真的是惡夢。

特點

  • 可以管理 Cluster 級別的資源,如 Node、PersistentVolume、Namespace。
  • 也可以用來授權跨所有命名空間的權限。
  • 適用於具有集群範圍權限的使用者或應用程式。

適用場景

  • 需要管理整個 Kubernetes 集群的資源。
  • 監控系統、運維工具等需要存取所有命名空間的資源。
  • 授權給 Kubernetes 組建(如 kubelet)以管理 Cluster 資源。

範例:

cluster-role.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
# ClusterRole 沒有命名空間字段
name: cluster-admin
rules:
- apiGroups: ['']
resources: ['pods']
verbs: ['get', 'list', 'watch']

RoleBinding 與 ClusterRoleBinding

RoleBinding.

RoleBinding

RoleBinding 用於 將 Role 指派給特定的使用者、群組或服務帳戶,但僅限於某個特定的命名空間。

特點

  • 綁定的 Role 只能影響其所屬的命名空間。
  • 可以綁定 Kubernetes 使用者、群組或服務帳戶。
  • 允許將 ClusterRole 綁定至特定命名空間內的使用者,以限制 ClusterRole 的作用範圍。

適用場景

  • 為不同的開發團隊或應用程式提供命名空間級別的權限管理。
  • 控制特定服務帳戶在命名空間內的操作權限。

範例:

role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-viewer-rolebinding
namespace: defaul # 授權的命名空間為default
subjects:
- kind: User
name: pod-viewer # 連結 user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-viewer # 連結 role
apiGroup: rbac.authorization.k8s.io

subject 參數:

1. User

User 指的是一個具名的使用者帳戶。這通常是指 Kubernetes 認證的個別使用者,可以是經由認證系統(如 LDAP 或 OpenID)登入的使用者。

範例:這表示授權名稱為 pod-viewer 的使用者。

subjects:
- kind: User
name: pod-viewer
apiGroup: rbac.authorization.k8s.io

2. Service Account

ServiceAccount 是 Kubernetes 中的服務帳戶,通常用於授權應用程式或服務進行自動化操作。服務帳戶會被綁定到特定的命名空間,並且它們通常用來執行特定的 Pod 或者在命名空間內執行的操作。

範例:這表示授權名稱為 default 的服務帳戶。

subjects:
- kind: ServiceAccount
name: default
namespace: default # 指定服務帳戶所屬命名空間

3. Group

Group 用來指定一個群組,這個群組中的所有成員都會被授予該角色的權限。群組通常與用戶管理系統(例如 LDAP)中的群組相關聯。

範例:

# 對於"qa"命名空間中的所有服務帳號
subjects:
- kind: Group
name: system: serviceaccounts: qa
apiGroup: rbac.authorization.k8s.io
# 對於所有用戶
subjects:
- kind: Group
name: system: authenticated
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system: unauthenticated
apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding

ClusterRoleBinding 允許將 ClusterRole 綁定至 整個集群範圍內的使用者、群組或服務帳戶,確保這些主體擁有跨命名空間的權限。

特點

  • 可將 ClusterRole 賦予所有命名空間內的主體,或對集群級別的資源賦權。
  • 適用於集群管理員、監控工具、基礎設施自動化工具等。

適用場景

  • 需要跨命名空間或集群級別存取權限的服務帳戶或應用程式。
  • 為 Kubernetes 核心組件(如 Controller、Scheduler)提供管理權限。

範例:

role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-admin-binding
subjects:
- kind: User
name: admin # 連結 user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin # 連結 cluster role
apiGroup: rbac.authorization.k8s.io

RoleClusterRoleRoleBindingClusterRoleBinding
作用範圍單一命名空間整個集群單一命名空間整個集群
管理對象Pod、Secret、ConfigMap 等Node、Namespace、PersistentVolume 等使用者、群組、服務帳戶(僅影響單一命名空間)使用者、群組、服務帳戶(影響所有命名空間)
適用場景應用於特定命名空間的權限控制需跨命名空間或集群範圍的權限限制特定使用者或服務帳戶的權限需全域存取權限的應用