使用 RBAC 授權

基於角色的訪問控制(Role-based access control, RBAC)是一種根據組織內各個使用者的角色來調節對計算機或網路資源的訪問的方法。

RBAC 授權使用 `rbac.authorization.k8s.io` API 組來驅動授權決策,允許你透過 Kubernetes API 動態配置策略。

要啟用 RBAC,啟動 API 伺服器時,將 `authorization-config` 標誌設定為包含 `RBAC` 授權器的檔案;例如:

apiVersion: apiserver.config.k8s.io/v1
kind: AuthorizationConfiguration
authorizers:
  ...
  - type: RBAC
  ...

或者,啟動 API 伺服器時,將 `authorization-mode` 標誌設定為逗號分隔的列表,其中包含 `RBAC`;例如:

kube-apiserver --authorization-mode=...,RBAC --other-options --more-options

API 物件

RBAC API 聲明瞭四種 Kubernetes 物件:**Role**、**ClusterRole**、**RoleBinding** 和 **ClusterRoleBinding**。你可以使用 `kubectl` 等工具描述或修改 RBAC 物件,就像操作任何其他 Kubernetes 物件一樣。

Role 和 ClusterRole

RBAC **Role** 或 **ClusterRole** 包含表示一組許可權的規則。許可權是純粹疊加的(沒有“拒絕”規則)。

Role 始終在特定的名稱空間中設定許可權;當你建立 Role 時,必須指定其所屬的名稱空間。

相比之下,ClusterRole 是一種非名稱空間資源。這些資源具有不同的名稱(Role 和 ClusterRole),因為 Kubernetes 物件始終必須是名稱空間的或非名稱空間的;它不能兩者兼具。

ClusterRole 有多種用途。你可以使用 ClusterRole 來

  1. 定義對名稱空間資源的許可權,並授予對單個名稱空間(或多個名稱空間)的訪問許可權
  2. 定義對名稱空間資源的許可權,並授予對所有名稱空間的訪問許可權
  3. 定義對叢集範圍資源的許可權

如果你想在名稱空間內定義一個角色,請使用 Role;如果你想在叢集範圍定義一個角色,請使用 ClusterRole。

角色示例

這裡是一個“default”名稱空間中的 Role 示例,可用於授予對 Pod 的讀訪問許可權

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

ClusterRole 示例

ClusterRole 可以用於授予與 Role 相同的許可權。由於 ClusterRole 是叢集範圍的,你還可以使用它們來授予對以下資源的訪問許可權

  • 叢集範圍的資源(如 節點

  • 非資源端點(如 `healthz`)

  • 所有名稱空間中的名稱空間資源(如 Pod)

    例如:你可以使用 ClusterRole 允許特定使用者執行 `kubectl get pods --all-namespaces`

以下是一個 ClusterRole 示例,可用於授予對任何特定名稱空間或所有名稱空間中 Secret 的讀訪問許可權(取決於其繫結方式)

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Secret
  # objects is "secrets"
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

Role 或 ClusterRole 物件的名稱必須是有效的路徑段名稱

RoleBinding 和 ClusterRoleBinding

角色繫結將角色中定義的許可權授予一個或一組使用者。它包含一個**主體**(使用者、組或服務賬號)列表,以及對所授予角色的引用。RoleBinding 授予特定名稱空間內的許可權,而 ClusterRoleBinding 授予叢集範圍的訪問許可權。

RoleBinding 可以引用同一名稱空間中的任何 Role。或者,RoleBinding 可以引用 ClusterRole 並將該 ClusterRole 繫結到 RoleBinding 所在的名稱空間。如果你想將 ClusterRole 繫結到叢集中的所有名稱空間,則使用 ClusterRoleBinding。

RoleBinding 或 ClusterRoleBinding 物件的名稱必須是有效的路徑段名稱

RoleBinding 示例

以下是一個 RoleBinding 示例,它在“default”名稱空間中授予使用者“jane” “pod-reader” Role。這允許“jane”在“default”名稱空間中讀取 Pod。

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.
# You need to already have a Role named "pod-reader" in that namespace.
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
# You can specify more than one "subject"
- kind: User
  name: jane # "name" is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  # "roleRef" specifies the binding to a Role / ClusterRole
  kind: Role #this must be Role or ClusterRole
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

RoleBinding 還可以引用 ClusterRole,以將該 ClusterRole 中定義的許可權授予 RoleBinding 名稱空間內的資源。這種引用方式允許你在叢集中定義一組通用角色,然後在多個名稱空間中重用它們。

例如,即使下面的 RoleBinding 引用了一個 ClusterRole,"dave"(主體,區分大小寫)也只能在 "development" 名稱空間中讀取 Secret,因為 RoleBinding 的名稱空間(在其元資料中)是 "development"。

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "development" namespace.
# You need to already have a ClusterRole named "secret-reader".
kind: RoleBinding
metadata:
  name: read-secrets
  #
  # The namespace of the RoleBinding determines where the permissions are granted.
  # This only grants permissions within the "development" namespace.
  namespace: development
subjects:
- kind: User
  name: dave # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding 示例

要授予整個叢集的許可權,你可以使用 ClusterRoleBinding。以下 ClusterRoleBinding 允許“manager”組中的任何使用者讀取任何名稱空間中的 Secret。

apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

建立繫結後,你無法更改其引用的 Role 或 ClusterRole。如果你嘗試更改繫結的 `roleRef`,你將收到驗證錯誤。如果你確實想更改繫結的 `roleRef`,你需要刪除繫結物件並重新建立。

此限制有兩個原因

  1. 使 `roleRef` 不可變允許授予某人對現有繫結物件的 `update` 許可權,以便他們可以管理主體列表,而無法更改授予這些主體的角色。
  2. 繫結到不同角色本質上是一個完全不同的繫結。要求刪除/重新建立繫結以更改 `roleRef` 確保繫結中所有主體都應獲得新角色的許可權(而不是在未驗證所有現有主體都應獲得新角色的許可權的情況下僅啟用或意外修改 `roleRef`)。

`kubectl auth reconcile` 命令列工具建立或更新包含 RBAC 物件的清單檔案,並在需要更改其引用的角色時處理繫結物件的刪除和重新建立。有關更多資訊,請參閱命令用法和示例

引用資源

在 Kubernetes API 中,大多數資源都是使用其物件名稱的字串表示來表示和訪問的,例如 Pod 的 `pods`。RBAC 使用與相關 API 端點 URL 中顯示的名稱完全相同的名稱來引用資源。某些 Kubernetes API 涉及**子資源**,例如 Pod 的日誌。請求 Pod 日誌的示例如下:

GET /api/v1/namespaces/{namespace}/pods/{name}/log

在這種情況下,`pods` 是 Pod 資源的名稱空間資源,而 `log` 是 `pods` 的子資源。要在 RBAC 角色中表示這一點,請使用斜槓(`/`)來分隔資源和子資源。要允許主體讀取 `pods` 並訪問每個 Pod 的 `log` 子資源,你可以這樣寫:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

你還可以透過 `resourceNames` 列表在某些請求中按名稱引用資源。指定後,請求可以限制為資源的單個例項。這裡有一個示例,它將主體限制為只能 `get` 或 `update` 名為 `my-configmap` 的 ConfigMap

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing ConfigMap
  # objects is "configmaps"
  resources: ["configmaps"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

除了引用單個 `resources`、`apiGroups` 和 `verbs` 之外,你還可以使用萬用字元 `*` 符號來引用所有此類物件。對於 `nonResourceURLs`,你可以使用萬用字元 `*` 作為字尾全域性匹配。對於 `resourceNames`,空集表示允許所有操作。下面是一個示例,它允許訪問 `example.com` API 組中所有當前和將來的資源,並執行任何當前和將來的操作。這類似於內建的 `cluster-admin` 角色。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: example.com-superuser # DO NOT USE THIS ROLE, IT IS JUST AN EXAMPLE
rules:
- apiGroups: ["example.com"]
  resources: ["*"]
  verbs: ["*"]

聚合 ClusterRole

你可以將多個 ClusterRole **聚合**為一個組合的 ClusterRole。作為叢集控制平面一部分執行的控制器會監視設定了 `aggregationRule` 的 ClusterRole 物件。`aggregationRule` 定義一個標籤選擇器,控制器使用該選擇器來匹配應組合到該 ClusterRole 的 `rules` 欄位中的其他 ClusterRole 物件。

這是一個聚合 ClusterRole 的示例

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # The control plane automatically fills in the rules

如果你建立一個與現有聚合 ClusterRole 的標籤選擇器匹配的新 ClusterRole,該更改會觸發將新規則新增到聚合 ClusterRole 中。下面是一個示例,透過建立一個標籤為 `rbac.example.com/aggregate-to-monitoring: true` 的另一個 ClusterRole,將規則新增到“monitoring”ClusterRole 中。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-endpoints
  labels:
    rbac.example.com/aggregate-to-monitoring: "true"
# When you create the "monitoring-endpoints" ClusterRole,
# the rules below will be added to the "monitoring" ClusterRole.
rules:
- apiGroups: [""]
  resources: ["services", "endpointslices", "pods"]
  verbs: ["get", "list", "watch"]

預設使用者可見角色使用 ClusterRole 聚合。這允許你作為叢集管理員,為自定義資源(例如由 CustomResourceDefinitions 或聚合 API 伺服器提供)包含規則,以擴充套件預設角色。

例如:以下 ClusterRole 允許“admin”和“edit”預設角色管理名為 CronTab 的自定義資源,而“view”角色只能對 CronTab 資源執行讀取操作。你可以假設 CronTab 物件在 API 伺服器可見的 URL 中名為 `"crontabs"`。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: aggregate-cron-tabs-edit
  labels:
    # Add these permissions to the "admin" and "edit" default roles.
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
rules:
- apiGroups: ["stable.example.com"]
  resources: ["crontabs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: aggregate-cron-tabs-view
  labels:
    # Add these permissions to the "view" default role.
    rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["stable.example.com"]
  resources: ["crontabs"]
  verbs: ["get", "list", "watch"]

角色示例

以下示例是 Role 或 ClusterRole 物件的節選,僅顯示 `rules` 部分。

允許在核心 API 組中讀取 `pods` 資源

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Pod
  # objects is "pods"
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

允許在“apps”API 組中讀/寫 Deployments(在 HTTP 級別:URL 資源部分包含 `deployments` 的物件)

rules:
- apiGroups: ["apps"]
  #
  # at the HTTP level, the name of the resource for accessing Deployment
  # objects is "deployments"
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允許讀取核心 API 組中的 Pod,以及讀取或寫入“batch”API 組中的 Job 資源

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Pod
  # objects is "pods"
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
  #
  # at the HTTP level, the name of the resource for accessing Job
  # objects is "jobs"
  resources: ["jobs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允許讀取名為 "my-config" 的 ConfigMap(必須與 RoleBinding 繫結,以限制為單個名稱空間中的單個 ConfigMap)

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing ConfigMap
  # objects is "configmaps"
  resources: ["configmaps"]
  resourceNames: ["my-config"]
  verbs: ["get"]

允許讀取核心組中的資源 `nodes`(因為節點是叢集範圍的,這必須在一個 ClusterRole 中,並透過 ClusterRoleBinding 繫結才能生效)

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Node
  # objects is "nodes"
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]

允許對非資源端點 `/healthz` 和所有子路徑進行 GET 和 POST 請求(必須在透過 ClusterRoleBinding 繫結的 ClusterRole 中才能生效)

rules:
- nonResourceURLs: ["/healthz", "/healthz/*"] # '*' in a nonResourceURL is a suffix glob match
  verbs: ["get", "post"]

引用主體

RoleBinding 或 ClusterRoleBinding 將角色繫結到主體。主體可以是組、使用者或 ServiceAccount

Kubernetes 將使用者名錶示為字串。這些可以是:普通名稱,如“alice”;電子郵件樣式名稱,如“bob@example.com”;或表示為字串的數字使用者 ID。作為叢集管理員,你需要配置身份驗證模組,以便身份驗證產生你想要的使用者名稱格式。

在 Kubernetes 中,身份驗證模組提供組資訊。與使用者一樣,組也表示為字串,並且該字串沒有格式要求,除了 `system:` 字首被保留。

ServiceAccounts 的名稱字首為 `system:serviceaccount:`,並且屬於名稱字首為 `system:serviceaccounts:` 的組。

RoleBinding 示例

以下示例是 `RoleBinding` 的摘錄,僅顯示 `subjects` 部分。

對於名為 `alice@example.com` 的使用者

subjects:
- kind: User
  name: "alice@example.com"
  apiGroup: rbac.authorization.k8s.io

對於名為 `frontend-admins` 的組

subjects:
- kind: Group
  name: "frontend-admins"
  apiGroup: rbac.authorization.k8s.io

對於“kube-system”名稱空間中的預設服務帳戶

subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system

對於“qa”名稱空間中的所有服務帳戶

subjects:
- kind: Group
  name: system:serviceaccounts:qa
  apiGroup: rbac.authorization.k8s.io

對於任何名稱空間中的所有服務賬號

subjects:
- kind: Group
  name: system:serviceaccounts
  apiGroup: rbac.authorization.k8s.io

對於所有已認證使用者

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io

對於所有未認證使用者

subjects:
- kind: Group
  name: system:unauthenticated
  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

預設角色和角色繫結

API 伺服器會建立一組預設的 ClusterRole 和 ClusterRoleBinding 物件。其中許多都帶有 `system:` 字首,這表明該資源由叢集控制平面直接管理。所有預設的 ClusterRole 和 ClusterRoleBinding 都帶有 `kubernetes.io/bootstrapping=rbac-defaults` 標籤。

自動協調

在每次啟動時,API 伺服器會更新預設叢集角色中任何缺失的許可權,並更新預設叢集角色繫結中任何缺失的主體。這允許叢集修復意外修改,並有助於在新的 Kubernetes 版本中許可權和主體發生變化時保持角色和角色繫結保持最新。

要選擇退出此協調,請在預設叢集角色或預設叢集 RoleBinding 上將 `rbac.authorization.kubernetes.io/autoupdate` 註解設定為 `false`。請注意,缺失預設許可權和主體可能導致叢集無法正常執行。

如果 RBAC 授權器處於活動狀態,則預設啟用自動協調。

API 發現角色

預設叢集角色繫結授權未經驗證和已驗證的使用者讀取被認為可以公開訪問的 API 資訊(包括 CustomResourceDefinitions)。要停用匿名未經驗證的訪問,請在 API 伺服器配置中新增 `--anonymous-auth=false` 標誌。

要透過 `kubectl` 檢視這些角色的配置,請執行

kubectl get clusterroles system:discovery -o yaml
Kubernetes RBAC API 發現角色
預設 ClusterRole預設 ClusterRoleBinding描述
system:basic-user**system:authenticated** 組允許使用者對其自身的基本資訊進行只讀訪問。在 v1.14 之前,此角色預設也繫結到system:unauthenticated預設情況下。
system:discovery**system:authenticated** 組允許對發現和協商 API 級別所需的 API 發現端點進行只讀訪問。在 v1.14 之前,此角色也繫結到system:unauthenticated預設情況下。
system:public-info-viewer**system:authenticated** 和 **system:unauthenticated** 組允許對叢集的非敏感資訊進行只讀訪問。在 Kubernetes v1.14 中引入。

面向使用者的角色

一些預設的 ClusterRole 沒有 `system:` 字首。這些是面向使用者的角色。它們包括超級使用者角色 (`cluster-admin`)、旨在透過 ClusterRoleBinding 在叢集範圍內授予的角色,以及旨在透過 RoleBinding 在特定名稱空間內授予的角色 (`admin`、`edit`、`view`)。

面向使用者的 ClusterRole 使用ClusterRole 聚合,允許管理員在這些 ClusterRole 上包含自定義資源的規則。要向 `admin`、`edit` 或 `view` 角色新增規則,請建立帶有以下一個或多個標籤的 ClusterRole:

metadata:
  labels:
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-view: "true"

預設 ClusterRole預設 ClusterRoleBinding描述
cluster-admin**system:masters** 組允許超級使用者訪問以對任何資源執行任何操作。當用於 **ClusterRoleBinding** 時,它賦予對叢集中所有資源和所有名稱空間的完全控制。當用於 **RoleBinding** 時,它賦予對角色繫結名稱空間中所有資源的完全控制,包括名稱空間本身。
admin允許管理員訪問許可權,旨在透過 **RoleBinding** 在名稱空間內授予。

如果用於 **RoleBinding**,允許對名稱空間中的大多數資源進行讀/寫訪問,包括在名稱空間內建立角色和角色繫結的能力。此角色不允許對資源配額或名稱空間本身進行寫訪問。此角色也不允許對使用 Kubernetes v1.22+ 建立的叢集中的 EndpointSlice 進行寫訪問。更多資訊請參見“EndpointSlice 的寫訪問”部分

edit允許對名稱空間中的大多數物件進行讀/寫訪問。

此角色不允許檢視或修改角色或角色繫結。但是,此角色允許訪問 Secret 並以名稱空間中任何 ServiceAccount 的身份執行 Pod,因此它可用於獲取名稱空間中任何 ServiceAccount 的 API 訪問級別。此角色也不允許對使用 Kubernetes v1.22+ 建立的叢集中的 EndpointSlice 進行寫訪問。更多資訊請參見“EndpointSlice 的寫訪問”部分

view允許只讀訪問以檢視名稱空間中的大多數物件。它不允許檢視角色或角色繫結。

此角色不允許檢視 Secret,因為讀取 Secret 的內容會允許訪問名稱空間中的 ServiceAccount 憑據,這將允許以名稱空間中任何 ServiceAccount 的身份進行 API 訪問(一種許可權提升形式)。

核心元件角色

預設 ClusterRole預設 ClusterRoleBinding描述
system:kube-scheduler**system:kube-scheduler** 使用者允許訪問 排程器元件所需的資源。
system:volume-scheduler**system:kube-scheduler** 使用者允許訪問 kube-scheduler 元件所需的卷資源。
system:kube-controller-manager**system:kube-controller-manager** 使用者允許訪問 控制器管理器 元件所需的資源。各個控制器所需的許可權在控制器角色中詳述。
system:node允許訪問 kubelet 所需的資源,**包括對所有 Secret 的讀訪問許可權和對所有 Pod 狀態物件的寫訪問許可權**。

你應該使用 節點授權器NodeRestriction 准入外掛 來代替system:node角色,並允許基於計劃在其上執行的 Pod 向 kubelet 授予 API 訪問許可權。

system:node角色僅為了與從 v1.8 之前版本升級的 Kubernetes 叢集相容而存在。

system:node-proxier**system:kube-proxy** 使用者允許訪問 kube-proxy 元件所需的資源。

其他元件角色

預設 ClusterRole預設 ClusterRoleBinding描述
system:auth-delegator允許委託身份驗證和授權檢查。這通常用於外掛 API 伺服器的統一身份驗證和授權。
system:heapsterHeapster 元件的角色(已棄用)。
system:kube-aggregatorkube-aggregator 元件的角色。
system:kube-dns**kube-system** 名稱空間中的 **kube-dns** 服務賬號kube-dns 元件的角色。
system:kubelet-api-admin允許完全訪問 kubelet API。
system:node-bootstrapper允許訪問執行 kubelet TLS 引導所需的資源。
system:node-problem-detectornode-problem-detector 元件的角色。
system:persistent-volume-provisioner允許訪問大多數動態卷供應器所需的資源。
system:monitoring**system:monitoring** 組允許對控制平面監控端點(即 kube-apiserver 的活躍度和就緒度端點(/healthz, /livez, /readyz)、各個健康檢查端點(/healthz/*, /livez/*, /readyz/*), /metrics)進行讀訪問,並使 kube-apiserver 遵循請求中提供的 traceparent 頭部以進行跟蹤。請注意,各個健康檢查端點和指標端點可能會暴露敏感資訊。

內建控制器角色

Kubernetes 控制器管理器 執行內置於 Kubernetes 控制平面中的控制器。當使用 `--use-service-account-credentials` 呼叫時,kube-controller-manager 使用單獨的服務帳戶啟動每個控制器。每個內建控制器都有相應的角色,字首為 `system:controller:`。如果控制器管理器未透過 `--use-service-account-credentials` 啟動,它將使用自己的憑據執行所有控制迴圈,該憑據必須被授予所有相關角色。這些角色包括:

  • system:controller:attachdetach-controller
  • system:controller:certificate-controller
  • system:controller:clusterrole-aggregation-controller
  • system:controller:cronjob-controller
  • system:controller:daemon-set-controller
  • system:controller:deployment-controller
  • system:controller:disruption-controller
  • system:controller:endpoint-controller
  • system:controller:expand-controller
  • system:controller:generic-garbage-collector
  • system:controller:horizontal-pod-autoscaler
  • system:controller:job-controller
  • system:controller:namespace-controller
  • system:controller:node-controller
  • system:controller:persistent-volume-binder
  • system:controller:pod-garbage-collector
  • system:controller:pv-protection-controller
  • system:controller:pvc-protection-controller
  • system:controller:replicaset-controller
  • system:controller:replication-controller
  • system:controller:resourcequota-controller
  • system:controller:root-ca-cert-publisher
  • system:controller:route-controller
  • system:controller:service-account-controller
  • system:controller:service-controller
  • system:controller:statefulset-controller
  • system:controller:ttl-controller

許可權提升預防和引導

RBAC API 透過阻止使用者編輯角色或角色繫結來防止許可權提升。由於這是在 API 級別強制執行的,因此即使不使用 RBAC 授權器也適用。

角色建立或更新的限制

只有在滿足以下至少一個條件時,你才能建立/更新角色:

  1. 你已擁有該角色中包含的所有許可權,並且作用域與正在修改的物件相同(ClusterRole 為叢集範圍,Role 為相同名稱空間或叢集範圍)。
  2. 你被明確授予對 `rbac.authorization.k8s.io` API 組中 `roles` 或 `clusterroles` 資源執行 `escalate` 動詞的許可權。

例如,如果 `user-1` 沒有列出叢集範圍內 Secret 的能力,他們就不能建立一個包含該許可權的 ClusterRole。要允許使用者建立/更新角色:

  1. 根據需要,授予他們一個允許他們建立/更新 Role 或 ClusterRole 物件的角色。
  2. 授予他們許可權,使其能夠在其建立/更新的角色中包含特定許可權。
    • 隱式地,透過賦予他們這些許可權(如果他們嘗試建立或修改一個包含他們自己未被授予許可權的 Role 或 ClusterRole,API 請求將被禁止)。
    • 或者透過授予他們對 `rbac.authorization.k8s.io` API 組中 `roles` 或 `clusterroles` 資源執行 `escalate` 動詞的許可權,明確允許在 `Role` 或 `ClusterRole` 中指定任何許可權。

角色繫結建立或更新的限制

只有在你已擁有引用角色中包含的所有許可權(與角色綁定範圍相同),或者你已獲授權對引用角色執行 `bind` 動詞時,你才能建立/更新角色繫結。例如,如果 `user-1` 沒有列出叢集範圍內 Secret 的能力,他們就不能建立 ClusterRoleBinding 到授予該許可權的角色。要允許使用者建立/更新角色繫結:

  1. 根據需要,授予他們一個允許他們建立/更新 RoleBinding 或 ClusterRoleBinding 物件的角色。
  2. 授予他們繫結特定角色所需的許可權
    • 隱式地,透過賦予他們角色中包含的許可權。
    • 明確地,透過授予他們對特定 Role(或 ClusterRole)執行 `bind` 動詞的許可權。

例如,這個 ClusterRole 和 RoleBinding 將允許 `user-1` 在名稱空間 `user-1-namespace` 中授予其他使用者 `admin`、`edit` 和 `view` 角色。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: role-grantor
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["rolebindings"]
  verbs: ["create"]
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["clusterroles"]
  verbs: ["bind"]
  # omit resourceNames to allow binding any ClusterRole
  resourceNames: ["admin","edit","view"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: role-grantor-binding
  namespace: user-1-namespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: role-grantor
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: user-1

在引導初始角色和角色繫結時,初始使用者需要授予他們尚未擁有的許可權。要引導初始角色和角色繫結:

  • 使用具有 "system:masters" 組的憑證,該組透過預設繫結繫結到 "cluster-admin" 超級使用者角色。

命令列工具

kubectl create role

建立一個 Role 物件,用於在單個名稱空間內定義許可權。示例:

  • 建立一個名為 "pod-reader" 的 Role,允許使用者對 Pod 執行 `get`、`watch` 和 `list` 操作。

    kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
    
  • 建立一個名為 "pod-reader" 的 Role,並指定 resourceNames。

    kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
    
  • 建立一個名為 "foo" 的 Role,並指定 apiGroups。

    kubectl create role foo --verb=get,list,watch --resource=replicasets.apps
    
  • 建立一個名為 "foo" 的 Role,並帶有子資源許可權。

    kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
    
  • 建立一個名為 "my-component-lease-holder" 的 Role,具有獲取/更新特定名稱資源的許可權。

    kubectl create role my-component-lease-holder --verb=get,list,watch,update --resource=lease --resource-name=my-component
    

kubectl create clusterrole

建立 ClusterRole。示例:

  • 建立一個名為 "pod-reader" 的 ClusterRole,允許使用者對 Pod 執行 `get`、`watch` 和 `list` 操作。

    kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods
    
  • 建立一個名為 "pod-reader" 的 ClusterRole,並指定 resourceNames。

    kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
    
  • 建立一個名為 "foo" 的 ClusterRole,並指定 apiGroups。

    kubectl create clusterrole foo --verb=get,list,watch --resource=replicasets.apps
    
  • 建立一個名為 "foo" 的 ClusterRole,並帶有子資源許可權。

    kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status
    
  • 建立一個名為 "foo" 的 ClusterRole,並指定 nonResourceURL。

    kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*
    
  • 建立一個名為 "monitoring" 的 ClusterRole,並指定 aggregationRule。

    kubectl create clusterrole monitoring --aggregation-rule="rbac.example.com/aggregate-to-monitoring=true"
    

kubectl create rolebinding

在特定名稱空間內授予 Role 或 ClusterRole。示例:

  • 在名稱空間 "acme" 中,將 "admin" ClusterRole 的許可權授予使用者 "bob"。

    kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
    
  • 在“acme”名稱空間中,將“view”ClusterRole 的許可權授予“acme”名稱空間中名為“myapp”的服務帳戶。

    kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme
    
  • 在名稱空間 "acme" 中,將 "view" ClusterRole 的許可權授予名稱空間 "myappnamespace" 中名為 "myapp" 的服務帳戶。

    kubectl create rolebinding myappnamespace-myapp-view-binding --clusterrole=view --serviceaccount=myappnamespace:myapp --namespace=acme
    

kubectl create clusterrolebinding

授予整個叢集(所有名稱空間)的 ClusterRole。示例:

  • 在整個叢集中,將 "cluster-admin" ClusterRole 的許可權授予名為 "root" 的使用者。

    kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
    
  • 在整個叢集中,將 "system:node-proxier" ClusterRole 的許可權授予名為 "system:kube-proxy" 的使用者。

    kubectl create clusterrolebinding kube-proxy-binding --clusterrole=system:node-proxier --user=system:kube-proxy
    
  • 在整個叢集中,將“view”ClusterRole 的許可權授予名稱空間“acme”中名為“myapp”的服務帳戶。

    kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
    

kubectl auth reconcile

從清單檔案建立或更新 `rbac.authorization.k8s.io/v1` API 物件。

如果需要,將建立缺失的物件,併為名稱空間物件建立包含名稱空間。

如果指定了 `--remove-extra-permissions`,則更新現有角色以包含輸入物件中的許可權,並刪除多餘的許可權。

如果指定了 `--remove-extra-subjects`,則更新現有繫結以包含輸入物件中的主體,並刪除多餘的主體。

示例

  • 測試應用 RBAC 物件的清單檔案,顯示將進行的更改。

    kubectl auth reconcile -f my-rbac-rules.yaml --dry-run=client
    
  • 應用 RBAC 物件的清單檔案,保留任何額外許可權(在角色中)和任何額外主體(在繫結中)。

    kubectl auth reconcile -f my-rbac-rules.yaml
    
  • 應用 RBAC 物件的清單檔案,移除任何額外的許可權(在角色中)和任何額外的主體(在繫結中)。

    kubectl auth reconcile -f my-rbac-rules.yaml --remove-extra-subjects --remove-extra-permissions
    

ServiceAccount 許可權

預設 RBAC 策略授予控制平面元件、節點和控制器作用域許可權,但除了API 發現角色授予的許可權外,**不授予** `kube-system` 名稱空間之外的服務賬號任何許可權。

這允許你根據需要向特定的 ServiceAccounts 授予特定的角色。細粒度的角色繫結提供了更高的安全性,但管理起來需要更多精力。更廣泛的授權可能會授予 ServiceAccounts 不必要(且可能升級)的 API 訪問許可權,但管理起來更容易。

從最安全到最不安全,方法如下:

  1. 向特定於應用程式的服務賬號授予角色(最佳實踐)

    這要求應用程式在其 Pod Spec 中指定 `serviceAccountName`,並且服務賬號已建立(透過 API、應用程式清單、`kubectl create serviceaccount` 等)。

    例如,授予“my-namespace”中“my-sa”服務賬號只讀許可權。

    kubectl create rolebinding my-sa-view \
      --clusterrole=view \
      --serviceaccount=my-namespace:my-sa \
      --namespace=my-namespace
    
  2. 向名稱空間中的“default”服務賬號授予角色

    如果應用程式未指定 `serviceAccountName`,則使用“default”服務賬號。

    例如,授予“my-namespace”中“default”服務賬號只讀許可權。

    kubectl create rolebinding default-view \
      --clusterrole=view \
      --serviceaccount=my-namespace:default \
      --namespace=my-namespace
    

    許多附加元件以 `kube-system` 名稱空間中的“default”服務賬號執行。為了允許這些附加元件以超級使用者許可權執行,請向 `kube-system` 名稱空間中的“default”服務賬號授予 cluster-admin 許可權。

    kubectl create clusterrolebinding add-on-cluster-admin \
      --clusterrole=cluster-admin \
      --serviceaccount=kube-system:default
    
  3. 向名稱空間中的所有服務賬號授予角色

    如果你希望名稱空間中的所有應用程式都擁有某個角色,無論它們使用哪個服務賬號,你可以向該名稱空間的服務賬號組授予該角色。

    例如,授予“my-namespace”中所有服務賬號只讀許可權。

    kubectl create rolebinding serviceaccounts-view \
      --clusterrole=view \
      --group=system:serviceaccounts:my-namespace \
      --namespace=my-namespace
    
  4. 向叢集範圍內的所有服務賬號授予受限角色(不建議)

    如果你不想按名稱空間管理許可權,可以向所有服務帳戶授予叢集範圍的角色。

    例如,授予對叢集中所有服務帳戶跨所有名稱空間的只讀許可權。

    kubectl create clusterrolebinding serviceaccounts-view \
      --clusterrole=view \
     --group=system:serviceaccounts
    
  5. 向叢集範圍內的所有服務賬號授予超級使用者訪問許可權(強烈不建議)

    如果你根本不關心許可權劃分,你可以授予所有服務賬號超級使用者訪問許可權。

    kubectl create clusterrolebinding serviceaccounts-cluster-admin \
      --clusterrole=cluster-admin \
      --group=system:serviceaccounts
    

EndpointSlice 的寫訪問

在 Kubernetes v1.22 之前建立的 Kubernetes 叢集,聚合的“edit”和“admin”角色中包含對 EndpointSlice(以及現在已棄用的 Endpoints API)的寫訪問許可權。作為對 CVE-2021-25740 的緩解措施,此訪問許可權不屬於使用 Kubernetes v1.22 或更高版本建立的叢集中的聚合角色。

已升級到 Kubernetes v1.22 的現有叢集不受此更改的影響。CVE 公告中包含了在現有叢集中限制此訪問的指導。

如果你希望新叢集在聚合角色中保留此級別的訪問許可權,你可以建立以下 ClusterRole:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    kubernetes.io/description: |-
      Add endpoints write permissions to the edit and admin roles. This was
      removed by default in 1.22 because of CVE-2021-25740. See
      https://issue.k8s.io/103675. This can allow writers to direct LoadBalancer
      or Ingress implementations to expose backend IPs that would not otherwise
      be accessible, and can circumvent network policies or security controls
      intended to prevent/isolate access to those backends.
      EndpointSlices were never included in the edit or admin roles, so there
      is nothing to restore for the EndpointSlice API.      
  labels:
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
  name: custom:aggregate-to-edit:endpoints # you can change this if you wish
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["create", "delete", "deletecollection", "patch", "update"]

從 ABAC 升級

最初執行較舊 Kubernetes 版本的叢集通常使用寬容的 ABAC 策略,包括授予所有服務賬號完整的 API 訪問許可權。

預設 RBAC 策略授予控制平面元件、節點和控制器作用域許可權,但除了API 發現角色授予的許可權外,**不授予** `kube-system` 名稱空間之外的服務賬號任何許可權。

雖然這種方法更加安全,但可能會對期望自動獲得 API 許可權的現有工作負載造成破壞。以下是管理此過渡的兩種方法:

並行授權器

同時執行 RBAC 和 ABAC 授權器,並指定包含遺留 ABAC 策略的策略檔案。

--authorization-mode=...,RBAC,ABAC --authorization-policy-file=mypolicy.json

詳細解釋第一個命令列選項:如果較早的授權器(例如 Node)拒絕請求,那麼 RBAC 授權器會嘗試授權 API 請求。如果 RBAC 也拒絕該 API 請求,則會執行 ABAC 授權器。這意味著 RBAC 或 ABAC 策略允許的**任何**請求都將被允許。

當 kube-apiserver 以 RBAC 元件日誌級別 5 或更高執行(`--vmodule=rbac*=5` 或 `--v=5`)時,你可以在 API 伺服器日誌中看到 RBAC 拒絕(字首為 `RBAC`)。你可以使用該資訊來確定需要向哪些使用者、組或服務賬號授予哪些角色。

一旦你向服務賬號授予了角色並且工作負載在伺服器日誌中沒有 RBAC 拒絕訊息的情況下執行,你就可以移除 ABAC 授權器。

寬鬆的 RBAC 許可權

你可以使用 RBAC 角色繫結來複制寬鬆的 ABAC 策略。

切換到使用 RBAC 後,你應該調整叢集的訪問控制,以確保其滿足你的資訊安全需求。

最後修改時間:2025 年 7 月 3 日太平洋標準時間下午 7:31:更新 apiserver 跟蹤至 GA (83f0fd8f72)