淺析 kubernetes 的認證與鑒權機制
- 2019 年 12 月 20 日
- 筆記
筆者最初接觸 kubernetes 時使用的是 v1.4 版本,集群間的通訊僅使用 8080 埠,認證與鑒權機制還未得到完善,到後來開始使用 static token 作為認證機制,直到 v1.6 時才開始使用 TLS 認證。隨著社區的發展,kubernetes 的認證與鑒權機制已經越來越完善,新版本已經全面趨於 TLS + RBAC 配置,但其認證與鑒權機制也極其複雜,本文將會帶你一步步了解。
kubernetes 集群的所有操作基本上都是通過 apiserver 這個組件進行的,它提供 HTTP RESTful 形式的 API 供集群內外客戶端調用。kubernetes 對於訪問 API 來說提供了三個步驟的安全措施:認證、授權、准入控制,當用戶使用 kubectl,client-go 或者 REST API 請求 apiserver 時,都要經過以上三個步驟的校驗。認證解決的問題是識別用戶的身份,鑒權是為了解決用戶有哪些許可權,准入控制是作用於 kubernetes 中的對象,通過合理的許可權管理,能夠保證系統的安全可靠。認證授權過程只存在 HTTPS 形式的 API 中,也就是說,如果客戶端使用 HTTP 連接到 apiserver,是不會進行認證授權的,然而 apiserver 的非安全認證埠 8080 已經在 v1.12 中廢棄了,未來將全面使用 HTTPS。

首先來看一下 kubernetes 中的認證、授權以及訪問控制機制。
kubernetes 的認證機制(Authentication)
kubernetes 目前所有的認證策略如下所示:
- X509 client certs
- Static Token File
- Bootstrap Tokens
- Static Password File
- Service Account Tokens
- OpenId Connect Tokens
- Webhook Token Authentication
- Authticating Proxy
- Anonymous requests
- User impersonation
- Client-go credential plugins
可以看到,kubernetes 的認證機制非常多,要想一個個搞清楚也絕非易事,本文僅分析幾個比較重要且使用廣泛的認證機制。
X509 client certs
X509是一種數字證書的格式標準,現在 HTTPS 依賴的 SSL 證書使用的就是使用的 X509 格式。X509 客戶端證書認證方式是 kubernetes 所有認證中使用最多的一種,相對來說也是最安全的一種,kubernetes 的一些部署工具 kubeadm、minkube 等都是基於證書的認證方式。客戶端證書認證叫作 TLS 雙向認證,也就是伺服器客戶端互相驗證證書的正確性,在都正確的情況下協調通訊加密方案。目前最常用的 X509 證書製作工具有 openssl、cfssl 等。
Service Account Tokens
有些情況下,我們希望在 pod 內部訪問 apiserver,獲取集群的資訊,甚至對集群進行改動。針對這種情況,kubernetes 提供了一種特殊的認證方式:serviceaccounts。 serviceaccounts 是面向 namespace 的,每個 namespace 創建的時候,kubernetes 會自動在這個 namespace 下面創建一個默認的 serviceaccounts;並且這個 serviceaccounts 只能訪問該 namespace 的資源。serviceaccounts 和 pod、service、deployment 一樣是 kubernetes 集群中的一種資源,用戶也可以創建自己的 serviceaccounts。
serviceaccounts 主要包含了三個內容:namespace、token 和 ca,每個 serviceaccounts 中都對應一個 secrets,namespace、token 和 ca 資訊都是保存在 secrets 中且都通過 base64 編碼的。namespace 指定了 pod 所在的 namespace,ca 用於驗證 apiserver 的證書,token 用作身份驗證,它們都通過 mount 的方式保存在 pod 的文件系統中,其三者都是保存在 /var/run/secrets/kubernetes.io/serviceaccount/
目錄下。
關於 serviceaccounts 的配置可以參考官方的 Configure Service Accounts for Pods 文檔。
認證機制的官方文檔,請參考:https://kubernetes.io/docs/reference/access-authn-authz/authentication/
小結:
kubernetes 中有多種認證方式,上面講了最常使用的兩種認證方式,X509 client certs 認證方式是用在一些客戶端訪問 apiserver 以及集群組件之間訪問時使用,比如 kubectl 請求 apiserver 時。serviceaccounts 是用在 pod 中訪問 apiserver 時進行認證的,比如使用自定義 controller 時。
認證解決的問題是識別用戶的身份,那 kubernetes 中都有哪幾種用戶?目前 kubernetes 中的用戶分為內部用戶和外部用戶,內部用戶指在 kubernetes 集群中的 pod 要訪問 apiserver 時所使用的,也就是 serviceaccounts,內部用戶需要在 kubernetes 中創建。外部用戶指 kubectl 以及一些客戶端工具訪問 apiserver 時所需要認證的用戶,此類用戶嵌入在客戶端的證書中。
kubernetes 的鑒權機制(Authorization)
kubernetes 目前支援如下四種鑒權機制:
- Node
- ABAC
- RBAC
- Webhook
下面僅介紹兩種最常使用的鑒權機制:
Node
僅 v1.7 版本以上支援 Node 授權,配合 NodeRestriction 准入控制來限制 kubelet,使其僅可訪問 node、endpoint、pod、service 以及 secret、configmap、pv、pvc 等相關的資源,在 apiserver 中使用以下配置來開啟 node 的鑒權機制:
KUBE_ADMISSION_CONTROL="...,NodeRestriction,..." KUBE_API_ARGS="...,--authorization-mode=Node,..."
RBAC
RBAC(Role-Based Access Control)是 kubernetes 中負責完成授權,是基於角色的訪問控制,通過自定義角色並將角色和特定的 user,group,serviceaccounts 關聯起來已達到許可權控制的目的。
RBAC 中有三個比較重要的概念:
- Role:角色,它其實是一組規則,定義了一組對 Kubernetes API 對象的操作許可權;
- Subject:被作用者,包括 user,group,serviceaccounts,通俗來講就是認證機制中所識別的用戶;
- RoleBinding:定義了「被作用者」和「角色」的綁定關係,也就是將用戶以及操作許可權進行綁定;
RBAC 其實就是通過創建角色(Role),通過 RoleBinding 將被作用者(subject)和角色(Role)進行綁定。下圖是 RBAC 中的幾種綁定關係:

鑒權機制的官方文檔,請參考:https://kubernetes.io/docs/reference/access-authn-authz/authorization/#authorization-modules
准入控制(Admission Control)
准入控制是請求的最後一個步驟,准入控制有許多內置的模組,可以作用於對象的 「CREATE」、」UPDATE」、」DELETE」、」CONNECT」 四個階段。在這一過程中,如果任一準入控制模組拒絕,那麼請求立刻被拒絕。一旦請求通過所有的准入控制器後就會寫入對象存儲中。
准入控制是在 apiserver 中進行配置的:
KUBE_ADMISSION_CONTROL="--enable-admission-plugins=NamespaceLifecycle,LimitRanger,...MutatingAdmissionWebhook,ValidatingAdmissionWebhook,NodeRestriction..."
准入控制的配置是有序的,不同的順序會影響 kubernetes 的性能,建議使用官方的配置。
若需要對 kubernetes 中的對象做一些擴展,可以使用准入控制,比如:創建 pod 時添加 initContainer 或者校驗欄位等。准入控制最常使用的擴展方式就是 admission webhooks,以前寫過一篇類似的文章,可以參考:http://blog.tianfeiyu.com/2019/07/02/k8s_crd_verify/。
准入控制更詳細的文檔,請參考:https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
小結:
上文已經說了 kubernetes 中有兩種用戶,一種是內置用戶被稱為 serviceaccounts,一種外部用戶,嵌入在客戶端的證書中,那麼 kubernetes 中有哪些證書鏈以及內嵌的用戶如何與 RBAC 結合呢?
kubernetes 中的證書鏈
筆者通過自己的研究及實踐經驗發現,在目前主流版本的 kubernetes 集群中,有四條重要的 CA 證書鏈,而在大多數生產環境中,則至少需要兩條 CA 證書鏈。
- apiserver CA 證書鏈:主要用於 kubernetes 內部組件互相訪問以及外部客戶端訪問 apiserver 使用
- etcd CA 證書鏈:主要用於 etcd 節點之間的訪問以及 apiserver 訪問 etcd 使用
- extension apiserver CA 證書鏈:用於訪問 extension apiserver 使用,比如 metrics-server
- kubelet CA 信任鏈:用於 apiserver 訪問 kubelet 時使用
- 其他證書鏈:admission webhook 證書鏈、audit webhook 證書鏈,用於 apiserver 訪問 webhook 時使用
以上這幾套 CA 證書鏈中,apiserver CA 證書鏈和 etcd CA 證書鏈是必要的。extension apiserver 的 CA 證書鏈只有在使用時才會用到,且不可與 apiserver CA 證書鏈相同。kubelet 的 CA 證書鏈不是必要的,根據部署的實際情況可以和 apiserver CA 證書鏈公用。
證書中的內嵌用戶如何與 RBAC 配置進行結合
證書中的內嵌用戶
以下是 kubelet 的證書請求文件(CSR):
{ "CN": "system:node:<nodeName>", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "China", "L": "Shanghai", "O": "system:nodes", "OU": "Kubernetes", "ST": "Shanghai" } ] }
- 「CN」:Common Name,從證書中提取該欄位作為請求的用戶名 (User Name);
- 「O」:Organization,從證書中提取該欄位作為請求用戶所屬的組 (Group);
kubernetes 使用 X509 證書中 CN(Common Name) 以及 O(Organization) 欄位對應 kubernetes 中的 user 和 group,即 RBAC 中的 subject,而 kubernetes 也為多個組件內置了 Role 以及 RoleBinding,巧妙的將 Authentication 和 RBAC Authorization 結合到了一起。
查看 kubernetes 中內置的 RBAC:
$ kubectl get clusterrole $ kubectl get clusterrolebinding
下面是 kubernetes 中核心組件內置的 user 和 group,在為每個組件生成證書時需要在其 CSR 中使用對應的 CN 和 O 欄位。

訪問 apiserver 的幾種方式
通過上文可以知道訪問 apiserver 時需要通過認證、鑒權以及訪問控制三個步驟,認證的方式可以使用 serviceaccounts 和 X509 證書,鑒權的方式使用 RBAC,訪問控制若沒有特殊需求可以不使用。
serviceaccounts 是 kubernetes 針對 pod 內訪問 apiserver 提供的認證方式,那可以用在外部 client 端嗎?答案是可以的,serviceaccounts 最終是通過 ca + token 的方式訪問的,你只要創建一個 serviceaccounts 並從對應的 secrets 中獲取 ca + token 即可訪問 apiserver。那使用證書認證的方式可以在 pod 內訪問 apiserver 嗎?當然也可以,不過創建證書比 serviceaccounts 麻煩,證書默認是用於內置組件訪問 apiserver 使用的。不論哪種方式,你都需要為其創建 RBAC 配置。
所以在 TLS +RBAC 模式下,訪問 apiserver 目前有兩種方式:
- 使用 serviceaccounts + RBAC :需要創建 serviceaccounts 以及關聯對應的 RBAC(ca + token + RBAC)
- 使用證書 + RBAC:需要用到 ca、client、client-key 以及關聯對應的 RBAC(ca + client-key + client-cert + RBAC)
總結
本文主要講述了 kubernetes 中的認證(Authentication)以及鑒權(Authorization)機制,其複雜性主要體現在部署 kubernetes 集群時組件之間的認證以及在集群中為附加組件配置正確的許可權,希望通過本節你可以了解到 kubernetes 中的組件需要哪些許可權認證以及如何為相關組件配置正確的許可權。
參考:
Controlling Access to the Kubernetes API:https://kubernetes.io/docs/reference/access-authn-authz/controlling-access/
admission controllers:https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
kubelet 配置許可權認證:https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-authentication-authorization/
master-node communication:https://kubernetes.io/docs/concepts/architecture/master-node-communication/
kubernetes 數字證書體系淺析:https://mp.weixin.qq.com/s/iXuDbPKjSc65t_9Y1–bog