Kubernetes RBAC 提供了精細的許可權控制,允許管理員根據不同角色的需求分配不同的許可權。透過 Roles 和 ClusterRoles 定義許可權範圍,再透過 RoleBindings 和 ClusterRoleBindings 將許可權賦予特定使用者、群組或服務帳戶,可以有效地管理叢集資源的存取。聚合式 ClusterRoles 則進一步簡化了許可權管理的複雜性,允許將多個 ClusterRoles 組合起來,方便維護和擴充套件。在多租戶環境中,名稱空間的應用可以有效隔離不同租戶的資源,搭配 RBAC 策略,可以實作更細粒度的資源存取控制。最後,Kubernetes 的稽核功能可以記錄叢集中的所有 API 請求,幫助管理員追蹤和除錯安全相關的問題,確保叢集的安全性。

Kubernetes 中的角色與許可權管理:深入 RBAC 政策與稽核

Kubernetes 的 Role-Based Access Control(RBAC)是一種強大的許可權管理系統,允許管理員精確控制對叢集資源的存取。在本章中,我們將探討 RBAC 的核心概念,包括 Roles、ClusterRoles、RoleBindings 和 ClusterRoleBindings,並瞭解如何有效地使用它們來管理叢集的許可權。

聚合式 ClusterRoles:簡化許可權管理

在 Kubernetes 中,ClusterRoles 可以變得複雜且難以維護。為瞭解決這個問題,Kubernetes 引入了聚合式 ClusterRoles(Aggregated ClusterRoles)的概念。這種設計允許將多個較小的 ClusterRoles 組合起來,形成一個更全面的許可權集合。

例如,admin ClusterRole 是一個典型的聚合式 ClusterRole。它透過 aggregationRule 部分定義了一組標籤選擇器,用於自動包含具有特定標籤的其他 ClusterRoles。當建立新的自定義資源定義(CRD)時,可以建立一個新的 ClusterRole 並為其新增特定的標籤,使其自動包含在 admin 角色中。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: aggregate-superwidget-admin
  labels:
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups: ["myapi"]
  resources: ["superwidgets"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

內容解密:

此 YAML 組態定義了一個名為 aggregate-superwidget-admin 的 ClusterRole,並將其標記為 rbac.authorization.k8s.io/aggregate-to-admin: "true",使其能夠被聚合到 admin ClusterRole 中。該角色允許對 myapi API 群組中的 superwidgets 資源執行多種操作,包括讀取、建立、更新和刪除。

RoleBindings 和 ClusterRoleBindings:賦予許可權

定義好許可權後,需要將其賦予給特定的主體(subjects),如使用者、群組或服務帳戶。這是透過 RoleBindings 和 ClusterRoleBindings 實作的。

  • RoleBinding 將 Role 或 ClusterRole 繫結到特定的名稱空間。
  • ClusterRoleBinding 將 ClusterRole 繫結到整個叢集。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-and-pod-logs-reader
  namespace: default
subjects:
- kind: ServiceAccount
  name: mysa
  namespace: default
  apiGroup: rbac.authorization.k8s.io
- kind: User
  name: podreader
- kind: Group
  name: podreaders
roleRef:
  kind: Role
  name: pod-and-pod-logs-reader
  apiGroup: rbac.authorization.k8s.io

內容解密:

此 RoleBinding 將 pod-and-pod-logs-reader Role 繫結到 default 名稱空間中的三個主體:一個服務帳戶 mysa、一個使用者 podreader 和一個群組 podreaders。這使得這些主體能夠讀取 default 名稱空間中的 Pod 和其日誌。

結合 ClusterRoles 和 RoleBindings:靈活的許可權管理

在某些情況下,我們希望在多個名稱空間中授予相同的許可權,但不希望使用 ClusterRoleBinding,因為它會授予叢集範圍內的許可權。此時,可以定義一個 ClusterRole,然後在需要的名稱空間中使用 RoleBinding 參照它。

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-and-pod-logs-reader
  namespace: default
subjects:
- kind: ServiceAccount
  name: mysa
  namespace: default
  apiGroup: rbac.authorization.k8s.io
- kind: User
  name: podreader
- kind: Group
  name: podreaders
roleRef:
  kind: ClusterRole
  name: cluster-pod-and-pod-logs-reader
  apiGroup: rbac.authorization.k8s.io

內容解密:

此組態展示瞭如何使用 RoleBinding 參照一個 ClusterRole。這種方法允許在特定的名稱空間中重用 ClusterRole 定義,從而簡化了許可權的管理和維護。

將企業身份對映到 Kubernetes 以授權資源存取

集中身份驗證的優點之一是利用企業現有的身份,而不是為與叢集互動的使用者建立新的需要記憶的憑據。瞭解如何將策略對映到這些集中式使用者非常重要。在第 7 章「將身份驗證整合到叢集中」中,您建立了一個叢集,並將其與 Active Directory Federation Services(ADFS)或 Tremolo Security 的測試身份提供者整合。為了完成整合,建立了以下 ClusterRoleBinding:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ou-cluster-admins
subjects:
- kind: Group
  name: k8s-cluster-admins
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

內容解密:

此 ClusterRoleBinding 允許 k8s-cluster-admins 群組的所有成員擁有完整的叢集存取許可權。當時重點關注身份驗證,因此沒有提供太多關於為何建立此繫結的詳細資訊。

如果我們想直接授權使用者,以便控制誰有權存取我們的叢集,那麼我們的 RBAC ClusterRoleBinding 將會有所不同:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ou-cluster-admins
subjects:
- kind: User
  name: https://k8sou.apps.192-168-2-131.nip.io/auth/idp/k8sIdp#mlbiamext
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

內容解密:

使用與之前相同的 ClusterRole,此 ClusterRoleBinding 將僅將 cluster-admin 許可權分配給我的測試使用者。

第一個需要注意的問題是,使用者的 OpenID Connect 發行者 URL 位於使用者名稱之前。當 OpenID Connect 最初被引入時,人們認為 Kubernetes 將與多個身份提供者和不同型別的身份提供者整合,因此開發人員希望您能夠輕鬆區分不同身份來源的使用者。

這種方法可能會導致一些問題:

  • 變更身份提供者 URL:今天,您正在使用一個 URL 的身份提供者,但明天您決定更改它。現在,您需要遍歷每個 ClusterRoleBinding 並更新它們。
  • 稽核:您無法查詢與使用者相關聯的所有 RoleBinding。您需要列舉每個繫結。
  • 大型繫結:根據您的使用者數量,您的繫結可能會變得非常龐大且難以追蹤。

雖然有一些工具可以幫助管理這些問題,但將繫結與群組而非個別使用者相關聯要容易得多。

實施名稱空間多租戶

為多個利益相關者或租戶佈署的叢集應按名稱空間劃分。這是從一開始就設計到 Kubernetes 中的邊界。在佈署名稱空間時,通常會將兩個 ClusterRole 分配給名稱空間中的使用者:

  • admin:此聚合的 ClusterRole 提供對 Kubernetes 中幾乎所有資源和動詞的存取許可權,使 admin 使用者成為其名稱空間的管理者。但無法更改 namespace 物件本身,因為 namespace 是叢集級別的資源。
  • edit:與 admin 類別似,但無法建立 RBAC Role 或 RoleBinding。

根據您的多租戶策略,admin ClusterRole 可能並不合適。建立 RBAC Role 和 RoleBinding 物件的能力意味著名稱空間管理員可以授予自己更改資源配額或執行升高的 PodSecurityPolicy 許可權。

存取控制的替代方案

  • 不授予對 Kubernetes 的存取許可權:許多叢集擁有者希望將 Kubernetes 控制在自己的手中,並限制使用者與外部 CI/CD 工具的互動。
  • 將存取視為特權:大多數企業要求特權使用者存取基礎架構。這通常是透過特權存取模型實作的,其中管理員擁有一個單獨的帳戶,需要「簽出」才能使用,並且僅在獲得「變更委員會」或流程批准的特定時間授權。

在 Plantuml 圖表中呈現多租戶架構如下: 圖表翻譯: 此圖示呈現了一個多租戶叢集架構,其中叢集被劃分為多個名稱空間,每個名稱空間都有自己的 admin 和 edit 使用者。admin 使用者擁有對其名稱空間的完全控制權,而 edit 使用者則具有有限的許可權。

Kubernetes 稽核與 RBAC 政策實作

在多租戶的 Kubernetes 環境中,除了實施嚴格的授權政策外,還需要一套完整的稽核機制來監控叢集中的所有活動。Kubernetes 提供了稽核日誌功能,可以記錄所有對叢集的 API 請求,幫助管理員追蹤和除錯安全相關的問題。

為什麼需要 Kubernetes 稽核?

在多租戶環境中,瞭解誰在何時對叢集進行了什麼操作至關重要。Kubernetes 稽核日誌可以提供詳細的 API 請求記錄,幫助管理員進行以下工作:

  • 追蹤叢集中的異常行為
  • 除錯 RBAC 政策
  • 符合法規和合規性要求

建立稽核政策

Kubernetes 稽核政策定義了哪些事件需要被記錄,以及如何儲存這些記錄。一個典型的稽核政策檔案如下所示:

apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
  - level: Request
    userGroups: ["system:nodes"]
    verbs: ["update", "patch"]
    resources:
      - group: "" # core
        resources: ["nodes/status", "pods/status"]
    omitStages:
      - "RequestReceived"

稽核政策解密:

  • level:定義了要記錄的事件級別,可以是 NoneMetadataRequestRequestResponse
  • userGroupsverbsresources:用於匹配特定的 API 請求。
  • omitStages:定義了要忽略的事件階段,例如 RequestReceived

啟用 Kubernetes 稽核

要在 Kubernetes 叢集中啟用稽核,需要以下步驟:

  1. 建立稽核政策檔案。
  2. 將稽核政策檔案複製到 API 伺服器容器中。
  3. 建立用於儲存稽核日誌的目錄。
  4. 修改 kube-apiserver.yaml 檔案,新增啟用稽核所需的命令列引數。

程式碼範例:啟用稽核

# 將稽核政策檔案複製到 API 伺服器容器中
docker cp k8s-audit-policy.yaml cluster01-control-plane:/etc/kubernetes/audit/

# 建立用於儲存稽核日誌的目錄
docker exec -ti cluster01-control-plane bash
mkdir /var/log/k8s
mkdir /etc/kubernetes/audit

# 修改 kube-apiserver.yaml 檔案
- --audit-log-path=/var/log/k8s/audit.log
- --audit-log-maxage=1
- --audit-log-maxbackup=10
- --audit-log-maxsize=10
- --audit-policy-file=/etc/kubernetes/audit/k8s-audit-policy.yaml

程式碼解密:

  • 首先,將稽核政策檔案複製到 API 伺服器容器中的 /etc/kubernetes/audit/ 目錄下。
  • 然後,建立用於儲存稽核日誌的 /var/log/k8s 目錄和 /etc/kubernetes/audit 目錄。
  • 最後,修改 kube-apiserver.yaml 檔案,新增啟用稽核所需的命令列引數,例如 --audit-log-path--audit-policy-file

稽核日誌分析

啟用稽核後,Kubernetes 將根據稽核政策記錄相關的 API 請求。這些記錄可以被儲存到檔案中,也可以被傳送到遠端的日誌收集系統中。

要分析稽核日誌,可以使用 Elasticsearch、Fluentd 和 Kibana(EFK)等工具建立一個完整的記錄系統。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Kubernetes RBAC 許可權管理與稽核實踐

package "Kubernetes Cluster" {
    package "Control Plane" {
        component [API Server] as api
        component [Controller Manager] as cm
        component [Scheduler] as sched
        database [etcd] as etcd
    }

    package "Worker Nodes" {
        component [Kubelet] as kubelet
        component [Kube-proxy] as proxy
        package "Pods" {
            component [Container 1] as c1
            component [Container 2] as c2
        }
    }
}

api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2

note right of api
  核心 API 入口
  所有操作經由此處
end note

@enduml

圖表翻譯: 此圖示描述了一個典型的 Kubernetes 稽核日誌收集和分析流程。首先,Kubernetes API 生成稽核日誌,然後透過 Fluentd 收集並傳送到 Elasticsearch 中儲存。最後,使用 Kibana 對儲存的日誌進行查詢和分析。