配置聚合層
配置聚合層允許透過額外的 API 擴充套件 Kubernetes apiserver,這些 API 不屬於核心 Kubernetes API。
準備工作
你需要有一個 Kubernetes 叢集,並且 kubectl 命令列工具已配置為與你的叢集通訊。建議在至少有兩個不是控制平面主機的節點的叢集上執行本教程。如果你還沒有叢集,可以使用 minikube 建立一個,或者你可以使用這些 Kubernetes 操場之一。
要檢查版本,請輸入 kubectl version
。
注意
為了讓聚合層在你的環境中工作以支援代理和擴充套件 apiserver 之間的相互 TLS 認證,有一些設定要求。Kubernetes 和 kube-apiserver 有多個 CA,所以請確保代理由聚合層 CA 簽名,而不是由其他東西(如 Kubernetes 通用 CA)簽名。注意
為不同型別的客戶端重用相同的 CA 可能會對叢集的功能產生負面影響。有關更多資訊,請參閱CA 重用和衝突。認證流程
與自定義資源定義 (CRD) 不同,聚合 API 除了標準的 Kubernetes apiserver 之外,還涉及另一個伺服器——你的擴充套件 apiserver。Kubernetes apiserver 需要與你的擴充套件 apiserver 通訊,你的擴充套件 apiserver 也需要與 Kubernetes apiserver 通訊。為了確保這種通訊安全,Kubernetes apiserver 使用 x509 證書進行自我認證以訪問擴充套件 apiserver。
本節描述了認證和授權流程的工作原理,以及如何配置它們。
高階流程如下:
- Kubernetes apiserver:認證請求使用者並授權他們訪問請求的 API 路徑的權利。
- Kubernetes apiserver:將請求代理到擴充套件 apiserver。
- 擴充套件 apiserver:認證來自 Kubernetes apiserver 的請求。
- 擴充套件 apiserver:授權來自原始使用者的請求。
- 擴充套件 apiserver:執行。
本節的其餘部分將詳細描述這些步驟。
流程如下圖所示。
上述泳道的來源可以在本文件的來源中找到。
Kubernetes Apiserver 認證和授權
對由擴充套件 apiserver 提供服務的 API 路徑的請求以與所有 API 請求相同的方式開始:與 Kubernetes apiserver 的通訊。該路徑已由擴充套件 apiserver 在 Kubernetes apiserver 中註冊。
使用者與 Kubernetes apiserver 通訊,請求訪問該路徑。Kubernetes apiserver 使用與 Kubernetes apiserver 配置的標準認證和授權來認證使用者並授權訪問特定路徑。
有關 Kubernetes 叢集認證的概述,請參閱“叢集認證”。有關 Kubernetes 叢集資源訪問授權的概述,請參閱“授權概述”。
到目前為止,一切都是標準的 Kubernetes API 請求、認證和授權。
Kubernetes apiserver 現在準備將請求傳送到擴充套件 apiserver。
Kubernetes Apiserver 代理請求
Kubernetes apiserver 現在將把請求傳送或代理到已註冊處理該請求的擴充套件 apiserver。為此,它需要知道幾件事:
- Kubernetes apiserver 應如何向擴充套件 apiserver 進行身份驗證,告知擴充套件 apiserver 透過網路傳入的請求來自有效的 Kubernetes apiserver?
- Kubernetes apiserver 應如何將原始請求已透過身份驗證的使用者名稱和組通知擴充套件 apiserver?
為了提供這兩個功能,您必須使用幾個標誌配置 Kubernetes apiserver。
Kubernetes Apiserver 客戶端認證
Kubernetes apiserver 透過 TLS 連線到擴充套件 apiserver,並使用客戶端證書進行自我認證。您必須在啟動時透過提供的標誌向 Kubernetes apiserver 提供以下資訊:
- 私鑰檔案透過 `—proxy-client-key-file`
- 簽名客戶端證書檔案透過 `—proxy-client-cert-file`
- 簽署客戶端證書檔案的 CA 證書透過 `—requestheader-client-ca-file`
- 簽名客戶端證書中有效的通用名稱 (CN) 值透過 `—requestheader-allowed-names`
Kubernetes apiserver 將使用 `—proxy-client-*-file` 指示的檔案向擴充套件 apiserver 進行認證。為了使請求被合規的擴充套件 apiserver 視為有效,必須滿足以下條件:
- 連線必須使用由其證書位於 `—requestheader-client-ca-file` 中的 CA 簽名的客戶端證書進行。
- 連線必須使用其 CN 屬於 `—requestheader-allowed-names` 中列出的名稱之一的客戶端證書進行。
注意
您可以將此選項設定為空,即 `—requestheader-allowed-names=""`。這將向擴充套件 apiserver 指示**任何** CN 都是可接受的。當使用這些選項啟動時,Kubernetes apiserver 將:
- 使用它們向擴充套件 apiserver 進行身份驗證。
- 在 `kube-system` 名稱空間中建立一個名為 `extension-apiserver-authentication` 的配置對映 (ConfigMap),其中包含 CA 證書和允許的 CN。擴充套件 apiserver 可以檢索這些資訊來驗證請求。
請注意,Kubernetes apiserver 使用相同的客戶端證書來針對**所有**擴充套件 apiserver 進行身份驗證。它不會為每個擴充套件 apiserver 建立一個客戶端證書,而是建立一個單獨的證書來作為 Kubernetes apiserver 進行身份驗證。此證書用於所有擴充套件 apiserver 請求。
原始請求的使用者名稱和組
當 Kubernetes apiserver 將請求代理到擴充套件 apiserver 時,它會告知擴充套件 apiserver 原始請求成功認證的使用者名稱和組。它透過代理請求的 HTTP 頭提供這些資訊。您必須告知 Kubernetes apiserver 要使用的頭名稱。
- 用於儲存使用者名稱的頭透過 `—requestheader-username-headers`
- 用於儲存組的頭透過 `—requestheader-group-headers`
- 新增到所有額外頭的請求頭字首透過 `—requestheader-extra-headers-prefix`
這些頭名稱也放在 `extension-apiserver-authentication` ConfigMap 中,因此擴充套件 apiserver 可以檢索並使用它們。
擴充套件 Apiserver 認證請求
擴充套件 apiserver 在收到來自 Kubernetes apiserver 的代理請求後,必須驗證該請求是否確實來自有效的認證代理(Kubernetes apiserver 正在履行此角色)。擴充套件 apiserver 透過以下方式進行驗證:
- 從 `kube-system` 中的 ConfigMap 中檢索以下資訊,如上所述:
- 客戶端 CA 證書
- 允許的名稱列表 (CNs)
- 使用者名稱、組和額外資訊的頭名稱
- 檢查 TLS 連線是否使用客戶端證書進行身份驗證,該證書:
- 由其證書與檢索到的 CA 證書匹配的 CA 簽名。
- 在允許的 CN 列表中有一個 CN,除非列表為空,在這種情況下所有 CN 都允許。
- 從相應的頭中提取使用者名稱和組
如果上述檢查透過,則該請求是來自合法認證代理(本例中為 Kubernetes apiserver)的有效代理請求。
請注意,提供上述功能是擴充套件 apiserver 實現的責任。許多實現預設透過利用 `k8s.io/apiserver/` 包來完成此操作。其他實現可能會提供選項,使用命令列選項來覆蓋它。
為了有許可權檢索 ConfigMap,擴充套件 apiserver 需要適當的角色。在 `kube-system` 名稱空間中有一個名為 `extension-apiserver-authentication-reader` 的預設角色,可以分配給擴充套件 apiserver。
擴充套件 Apiserver 授權請求
擴充套件 apiserver 現在可以驗證從頭部檢索到的使用者/組是否有權執行給定的請求。它透過向 Kubernetes apiserver 傳送標準的 SubjectAccessReview 請求來完成此操作。
為了使擴充套件 apiserver 本身有權向 Kubernetes apiserver 提交 `SubjectAccessReview` 請求,它需要正確的許可權。Kubernetes 包含一個名為 `system:auth-delegator` 的預設 `ClusterRole`,它具有適當的許可權。可以將其授予擴充套件 apiserver 的服務賬戶。
擴充套件 Apiserver 執行
如果 `SubjectAccessReview` 透過,擴充套件 apiserver 將執行請求。
啟用 Kubernetes Apiserver 標誌
透過以下 `kube-apiserver` 標誌啟用聚合層。您的提供商可能已經處理了它們。
--requestheader-client-ca-file=<path to aggregator CA cert>
--requestheader-allowed-names=front-proxy-client
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--proxy-client-cert-file=<path to aggregator proxy cert>
--proxy-client-key-file=<path to aggregator proxy key>
CA 重用和衝突
Kubernetes apiserver 有兩個客戶端 CA 選項
—client-ca-file
—requestheader-client-ca-file
這些功能獨立執行,如果使用不當,可能會相互衝突。
- `--client-ca-file`:當請求到達 Kubernetes apiserver 時,如果此選項已啟用,Kubernetes apiserver 會檢查請求的證書。如果該證書由 `--client-ca-file` 引用檔案中的某個 CA 證書籤名,則該請求被視為合法請求,使用者是通用名稱 `CN=` 的值,而組是組織 `O=`。請參閱 TLS 認證文件。
- `--requestheader-client-ca-file`:當請求到達 Kubernetes apiserver 時,如果此選項已啟用,Kubernetes apiserver 會檢查請求的證書。如果該證書由 `--requestheader-client-ca-file` 引用檔案中的某個 CA 證書籤名,則該請求被視為潛在的合法請求。然後 Kubernetes apiserver 檢查通用名稱 `CN=` 是否是 `--requestheader-allowed-names` 提供的列表中允許的名稱之一。如果該名稱被允許,則請求被批准;如果不是,則請求不被批准。
如果同時提供了 `--client-ca-file` 和 `--requestheader-client-ca-file`,則請求首先檢查 `--requestheader-client-ca-file` CA,然後檢查 `--client-ca-file`。通常,這兩種選項使用不同的 CA(無論是根 CA 還是中間 CA);常規客戶端請求與 `--client-ca-file` 匹配,而聚合請求與 `--requestheader-client-ca-file` 匹配。但是,如果兩者使用**相同**的 CA,那麼通常會透過 `--client-ca-file` 的客戶端請求將失敗,因為 CA 將與 `--requestheader-client-ca-file` 中的 CA 匹配,但通用名稱 `CN=` 將**不**匹配 `--requestheader-allowed-names` 中允許的通用名稱之一。這可能導致您的 kubelet 和其他控制平面元件,以及終端使用者,無法向 Kubernetes apiserver 進行身份驗證。
因此,對於 `—client-ca-file` 選項(用於授權控制平面元件和終端使用者)和 `—requestheader-client-ca-file` 選項(用於授權聚合 apiserver 請求),請使用不同的 CA 證書。
警告
除非您瞭解風險以及保護 CA 使用的機制,否則**不要**重用在不同上下文中使用的 CA。如果您沒有在執行 API 伺服器的主機上執行 kube-proxy,那麼您必須確保系統已啟用以下 `kube-apiserver` 標誌:
--enable-aggregator-routing=true
註冊 APIService 物件
您可以動態配置哪些客戶端請求被代理到擴充套件 apiserver。以下是一個註冊示例:
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: <name of the registration object>
spec:
group: <API group name this extension apiserver hosts>
version: <API version this extension apiserver hosts>
groupPriorityMinimum: <priority this APIService for this group, see API documentation>
versionPriority: <prioritizes ordering of this version within a group, see API documentation>
service:
namespace: <namespace of the extension apiserver service>
name: <name of the extension apiserver service>
caBundle: <pem encoded ca cert that signs the server cert used by the webhook>
APIService 物件的名稱必須是有效的路徑段名稱。
聯絡擴充套件 apiserver
一旦 Kubernetes apiserver 確定一個請求應該傳送到擴充套件 apiserver,它就需要知道如何聯絡它。
`service` 語句是對擴充套件 apiserver 服務的引用。服務名稱空間和名稱是必需的。埠是可選的,預設為 443。
以下是一個擴充套件 apiserver 的示例,該 apiserver 配置為在埠“1234”上呼叫,並使用自定義 CA 捆綁包針對 ServerName `my-service-name.my-service-namespace.svc` 驗證 TLS 連線。
apiVersion: apiregistration.k8s.io/v1
kind: APIService
...
spec:
...
service:
namespace: my-service-namespace
name: my-service-name
port: 1234
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
...
下一步
- 設定擴充套件 API 伺服器以與聚合層協同工作。
- 如需高階概述,請參閱使用聚合層擴充套件 Kubernetes API。
- 瞭解如何使用自定義資源定義擴充套件 Kubernetes API。