一文徹底搞懂 Kubernetes 中的認證

作者:陳亦帥,中國移動雲能力中心軟件研發工程師,專注於雲原生、微服務、算力網絡等領域。

前言

本文首先介紹了 K8s 的訪問控制過程,並對 K8s 認證的用戶模型進行講解。最後對認證過程中的用戶證書認證以及 Service Account Token 認證進行舉例剖析。

K8s API 請求訪問控制的過程

我們知道,不論是通過 kubectl 客戶端還是 REST 請求訪問 K8s 集羣,最終都需要經過 API Server 來進行資源的操作,生效結果會被持久化至 etcd 中,etcd 中的數據安全就變得十分重要。爲了保證 etcd 的安全性,K8s 只允許 API Server 去訪問操作 etcd,此時 API Server 就擔負起了整個 etcd 的安全。那麼 K8s 是如何管控和保障 API Server 訪問過程的安全的呢?

如下圖 1 所示,整個過程可以分爲 4 個階段

圖 1 K8s API 請求訪問過程

整體過程簡述:請求發起方進行 K8s API 請求,經過 Authentication(認證)、Authorization(鑑權)、AdmissionControl(准入控制)三個階段的校驗,最後把請求轉化爲對 K8s 對象的變更操作持久化至 etcd 中。

認證階段。當請求發起方建立與 API Server 的安全連接後,進入請求的認證階段(圖中步驟 1)。認證的方式主要有:客戶端證書、密碼、普通 token、bootstrap token 和 JWT 認證 (主要用於 Service Account)。認證模塊會檢查請求頭或者客戶端證書的內容,我們可以同時配置一種或幾種方式對請求進行認證。多種認證方式會被依次執行,只要一種方式通過,請求便得到合法認證。當所有方式都未通過時,會返回 401 狀態碼並中斷請求。認證解決的問題是校驗訪問方是否合法並識別其身份。

鑑權階段。K8s API 訪問請求必須包括請求者的用戶名、請求的操作以及操作對象,該階段就是對用戶的操作合法性進行校驗。如果現有策略聲明用戶具有完成請求操作的權限,則對請求進行授權。K8s 支持 ABAC 模式、RBAC 模式、Webhook 模式等多種授權模塊。同樣的,當多個授權模塊被配置時,請求只要滿足其中任意一種授權規則便會被放行,反之,API Server 會返回 403 狀態碼並終止該請求。鑑權是爲了判別用戶的操作權限範圍。

准入控制階段。准入控制是請求操作被持久化到 etcd 之前的 “攔截器”。准入控制模塊由多個 “准入控制器” 構成,“准入控制器” 就是一段自定義代碼,它們能夠在請求對 K8s 創建、修改、刪除或者連接一個 K8s 對象時生效。官方自帶了 30 多個准入控制器可供使用,同時支持用戶擴展。准入控制器的作用往往是檢查請求的規範性或者賦予一些默認信息。例如,我們在創建一個 pod 時,准入控制器會檢查提交的信息是否符合 pod 資源的規範,並對請求中沒有明確規定的字段,設置對應的默認值填充到請求中。與前兩個階段不同的是,只要有一個 “准入校驗” 邏輯未通過,那麼請求就會被拒絕。若請求僅僅是讀取一個對象,“准入控制器” 將不會生效。准入控制作用於 K8s 中的對象,通過校驗規範和默認值的設置,能夠保證系統的安全可靠。

持久化階段。當我們的請求通過了前面三個階段的校驗,它會被轉換爲一個 K8s 對象相應的變更請求,最終持久化到 etcd 中。

需要注意的是,認證授權過程只存在 HTTPS 形式的 API 中。即是說,客戶端使用 HTTP 連接到 API Server,是不會進行認證授權的。但 API Server 的非安全認證端口 8080 已經在 v1.12 中廢棄了,全面使用了 HTTPS。接下來讓我們來詳細瞭解下 K8s 的認證。

K8s 的用戶模型

從圖 1 中我們可以看出,K8s 的用戶主要分爲兩類:通過客戶端進行連接的人類操作者和 K8s 內諸如進程、控制器等非人類操作的客戶端。我們稱前者爲 Normal Users(常規用戶),後者爲 Service Account(服務賬戶)。因爲 K8s 內沒有爲 Normal Users 定義存儲對象,我們無法像操作 pod 一樣在 K8s 內部管理這類用戶,它們通常是由外部服務進行管理,藉由證書憑證或者靜態配置文件進行認證。而 Service Account 可由 K8s API 直接進行管理。

下表給出了其主要區別:

KHA08e

我們可以一次性啓用多種認證方式,但通常應該至少包含以下兩方面:

    1. 針對於 Service Account 的 token 方式;
    1. 至少一種用於 Normal Users 身份驗證的其他方式。通過認證的用戶會被包含在名爲 system:authenticated 的 group 中。

Basic 認證

認證方法是管理員將 password、user、uid、group 信息加入到 csv 格式的靜態文件中,並在 API Server 啓動時使用參數–Basic-authfile={文件路徑},指定使用的憑證文件。之後,認證憑證就將一直有效,只有在重啓 API Server 時才能修改密碼。憑證文件中的數據示例如下:

password,user,uid,"group1,group2,group3"

其中,當一個 user 對應多個組,多個 group 之間需要用逗號分隔並且使用雙引號。

客戶端請求時,需要在頭部加入 Basic BASE64ENCODED (USER:PASSWORD),服務端會校驗用戶名和密碼。該方式使用簡單,但是因爲用戶名和密碼使用明文,用戶名和密碼修改必須重啓服務,十分不靈活,一般只用於測試場景。

X509 證書認證

本文我們假設讀者已經瞭解數字證書和 CA 的基本原理,若不瞭解可以先閱讀下這篇文章《數字證書原理》[1]。

K8s 中組件之間通信,證書的驗證是在協議層通過 TLS 完成的,TLS 驗證分爲 2 種:

雙向認證的簡化過程如下圖 2 所示

圖 2 雙向 TLS 過程

當兩個組件進行雙向 TLS 認證時,會涉及到下表中的相關文件:

5qeVzH

下面我們用一個例子來演示證書籤發並進行客戶端配置的過程,演示的 K8s 環境已經存在 CA 根證書文件以及 API Server 文件,文件和目錄情況如圖 3 所示:

圖 3 文件和目錄情況圖

其中 ca.crt 是我們使用的 CA 根證書,apiserver.crt 是我們 K8s API Server 的服務端證書文件,它由 ca.crt 根證書進行簽發和配置,例子中 API Server 的啓動參數如圖 4 所示:

圖 4 API Server 的啓動配置

紅框部分信息分別指明瞭 API Server 所使用的 CA 根證書、服務端證書和服務端私鑰的路徑。簽發用戶證書步驟如下 (以 openssl 工具爲例):

  1. 1. 生成私鑰

圖 5 生成用戶私鑰

  1. 1. 使用私鑰爲用戶生成簽署請求文件

圖 6 生成簽署請求文件

命令中指定的 CN 是 Common Name 的縮寫,代表最終生成客戶端證書認證通過後在 K8s 內被識別的用戶名,O 是 Organization 的縮寫,代表被識別用戶所屬的組。

  1. 1. 使用服務端信任的 CA 其簽署證書

圖 7 簽署證書

至此,一個客戶端證書便籤發完畢了。我們可以查看其中的內容:

圖 8 my-user.crt

其中 CN 和 O 的信息即來自步驟 2 所輸入,K8s 通過這兩個信息確定訪問用戶的信息,示意圖如 9 所示:

圖 9 用戶信息認證示意圖

那麼如何配置客戶端才能使用這個證書呢?K8s 的每個客戶端(例如:kubectl)都有一個配置文件用來記錄客戶端證書驗證相關信息,我們稱爲 kubeconfig。K8s 中的每個組件都有一個這樣的配置文件來關聯集羣、用戶以及證書的情況,我們以 kubectl 爲例,來說明如何使用 kubeconfig:

    1. 查看當前 kubectl 的配置文件內容。

默認情況下,kubectl 命令從 $HOME/.kube 目錄下查找一個名字叫做 config 的文件作爲 kubeconfig,我們也可以用命令 kubectl config view 來列出相關配置內容,結果如圖 10 所示:

圖 10 kubectl config view 結果圖

Kubectl 配置 kubeconfig 後與集羣進行交互時的整體結構如圖 11 所示

圖 11 kubectl 交互整體結構圖

  1. 1. 建立用戶和證書的關係

圖 12 建立用戶證書關係

再次使用 kubectl config view 查看配置可以發現多了一個 user 的配置項

圖 13 新增的用戶配置

  1. 1. 把集羣信息和用戶信息進行關聯

圖 14 關聯集羣和用戶信息

圖 15 演示首先由默認的 context 中管理員權限的證書查看 pods 的情況,接着切換到我們新添加的 chris 用戶再查看 default 空間下 pods 的情況對比:

圖 15 上下文切換使用對比

我們發現,開始我們使用 Kubernetes-admin99 用戶能夠正常查詢 defaut 下的 pod 信息,但切換到上下文 chris@cluster99 後,訪問被阻止了,但是用戶沒有認證失敗,chris 用戶被正確識別了。這是因爲我們雖然通過了認證階段,但是在第二階段(鑑權階段),我們並沒有爲 chris 用戶添加相應的操作權限導致(權限控制部分我們講解),至此對於用戶的認證已經生效。

使用 x509 證書認證相對 Basic 認證來說顯然會更安全,只要證書不泄露,便可認爲是安全的。但目前卻沒有便捷的方案註銷證書,若使用證書輪轉,則需要重新辦法所有證書。所以使用 x509 證書認證適用於 Kubernetes 內部組件之間認證,普通用戶認證並不推薦通過證書的形式進行認證。

圖 16 列出了 K8s 中各個主要組件證書的使用情況

圖 16 K8s 主要組件證書使用情況

其中 kubelet 即作爲服務端爲 API Server 提供主機運行情況,同時又作爲客戶端從 API Server 中獲取信息所以既存在客戶端證書又存在服務端證書,API Server 同理,其他組件只作爲客戶端從 API Server 中獲取信息,所以擁有客戶端證書即可。

Service Account token 認證

Service Account 是 K8s 中唯一能夠通過 API 自己管理的實體賬號。它主要用於 Pod 訪問 API Server。每個 namespace 創建的時候,K8s 會自動在這個 namespace 下面創建一個默認的 Service Account 和對應的 secret 實例,該 Service Account 只能訪問這個 namespace 的資源。

圖 17 default 空間下的 Service Account 和其對應的 secret

Service Account 包含了 namespace、token 和 ca 三部分內容,通過 base64 編碼保存於對應的 secret 中。namespace 指定了 Pod 所屬的 namespace,ca 用於生成和驗證 token,token 用作身份驗證。三者都通過 mount 的方式掛載在 pod 文件系統的目錄 /var/run/secrets/kubernetes.io/serviceaccount/ 下。若創建的 pod 未自己指定 Service Account,K8s 會爲其綁定默認的 Service Account。圖 18、圖 19 和圖 20 展示了上述內容。

圖 18 Service Account 對應 secret 內容

圖 19 default 空間下的 pod 綁定默認 Service Account

圖 20 掛載目錄下的內容

當爲一個 Pod 指定了 Service Account 後,K8s 會爲這個 Service Account 生成一個 JWT(JSON Web Token),並使用 secret 將該 token 加載到 pod 上。JWT 認證機制的原理也是通過 CA 根證書進行簽名和公私鑰校驗 token。其中公鑰和私鑰分別被配置到了 API Server 和 Controller-Manager 的命令行參數中。如圖 21 和圖 22 所示。

圖 21 部分 API Server 啓動參數)

圖 22 部分 Controller-Manager 啓動參數

之後 Pod 便可使用 token 來訪問 API Server 了。API Server 再驗證對應 token 信息,就能知道這個 token 是對應 Service Account,最後識別到對應 Service Account 的權限。圖 23 展示了 K8s 使用和驗證 Service Account Token 的過程。

圖 23 Service AccountToken 的使用和驗證過程

與創建 namespace 創建 defalut 類似,若我們通過 K8s API 的方式創建 Service Account,它一樣會創建對應的 secret。當 Pod 使用該 Service Account 的 token 去 API Server 認證,API Server 一樣可以識別 Token 對應的 Service Account 從而通過認證(與證書認證相同的是若沒有進行授權,一樣無法通過鑑權階段)。如圖 24 和圖 25 所示。

圖 24 手動創建 Service Account

圖 25 查看驗證創建 Service Account 對應 secret

總結

參考資料

引用鏈接

[1] 《數字證書原理》: https://www.zhaohuabing.com/post/2020-03-19-pki/
[2] https://cloudnative.to/blog/k8s-certificate/#kube-apiserver-%E8%AF%81%E4%B9%A6%E9%85%8D%E7%BD%AE: https://cloudnative.to/blog/k8s-certificate/#kube-apiserver - 證書配置

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/bf4q8LcKvvoJsgRAL9sANg