設定聚合層

設定聚合層允許使用非核心 Kubernetes API 的額外 API 來擴充 Kubernetes apiserver。

事前準備

您需要有一個 Kubernetes 叢集,且 kubectl 命令列工具必須設定為與您的叢集通訊。建議在至少有兩個節點且未作為控制平面主機的叢集上執行本教學課程。如果您還沒有叢集,可以使用 minikube 建立一個,或者您可以使用以下 Kubernetes 體驗環境之一

若要檢查版本,請輸入 kubectl version

驗證流程

與自訂資源定義 (CRD) 不同,聚合 API 除了標準 Kubernetes apiserver 之外,還涉及另一個伺服器 - 您的擴充 apiserver。Kubernetes apiserver 需要與您的擴充 apiserver 通訊,而您的擴充 apiserver 需要與 Kubernetes apiserver 通訊。為了確保此通訊安全,Kubernetes apiserver 使用 x509 憑證向擴充 apiserver 驗證自身。

本節說明驗證與授權流程如何運作,以及如何設定它們。

高階流程如下

  1. Kubernetes apiserver:驗證請求使用者並授權他們對請求的 API 路徑的權限。
  2. Kubernetes apiserver:將請求代理到擴充 apiserver
  3. 擴充 apiserver:驗證來自 Kubernetes apiserver 的請求
  4. 擴充 apiserver:授權來自原始使用者的請求
  5. 擴充 apiserver:執行

本節的其餘部分詳細說明這些步驟。

流程可以在下圖中看到。

aggregation auth flows

上方泳道圖的來源可以在本文件的來源中找到。

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 現在將會發送請求,或將請求代理至已註冊處理該請求的擴充 API 伺服器。為了做到這一點,它需要知道幾件事

  1. Kubernetes apiserver 應該如何向擴充 API 伺服器進行身份驗證,以告知擴充 API 伺服器,透過網路傳輸的請求是來自有效的 Kubernetes apiserver?
  2. Kubernetes apiserver 應該如何將原始請求已驗證的使用者名稱和群組告知擴充 API 伺服器?

為了提供這兩項功能,您必須使用幾個標記來設定 Kubernetes apiserver。

Kubernetes API 伺服器用戶端身份驗證

Kubernetes apiserver 透過 TLS 連線至擴充 API 伺服器,並使用用戶端憑證進行自身身份驗證。您必須在啟動時,使用提供的標記,向 Kubernetes apiserver 提供以下資訊

  • 透過 --proxy-client-key-file 提供的私密金鑰檔案
  • 透過 --proxy-client-cert-file 提供的已簽署用戶端憑證檔案
  • 透過 --requestheader-client-ca-file 提供的簽署用戶端憑證檔案的 CA 憑證
  • 透過 --requestheader-allowed-names 提供的已簽署用戶端憑證中的有效通用名稱值 (CN)

Kubernetes apiserver 將使用 --proxy-client-*-file 指示的檔案向擴充 API 伺服器進行身份驗證。為了使請求被符合規範的擴充 API 伺服器視為有效,必須滿足以下條件

  1. 連線必須使用用戶端憑證建立,該憑證由 --requestheader-client-ca-file 中的憑證授權單位 (CA) 簽署。
  2. 連線必須使用用戶端憑證建立,該憑證的 CN 是 --requestheader-allowed-names 中列出的名稱之一。

當使用這些選項啟動時,Kubernetes apiserver 將會

  1. 使用它們向擴充 API 伺服器進行身份驗證。
  2. 在名為 extension-apiserver-authenticationkube-system 命名空間中建立一個 configmap,它將在其中放置 CA 憑證和允許的 CN。這些憑證和 CN 接著可以由擴充 API 伺服器檢索,以驗證請求。

請注意,Kubernetes apiserver 使用相同的用戶端憑證來驗證所有擴充 API 伺服器。它不會為每個擴充 API 伺服器建立一個用戶端憑證,而是建立一個單一憑證來作為 Kubernetes apiserver 進行身份驗證。同一個憑證會重複用於所有擴充 API 伺服器請求。

原始請求使用者名稱和群組

當 Kubernetes apiserver 將請求代理至擴充 API 伺服器時,它會將原始請求成功驗證的使用者名稱和群組告知擴充 API 伺服器。它在代理請求的 http 標頭中提供這些資訊。您必須告知 Kubernetes apiserver 要使用的標頭名稱。

  • 用於儲存使用者名稱的標頭,透過 --requestheader-username-headers
  • 用於儲存群組的標頭,透過 --requestheader-group-headers
  • 要附加到所有額外標頭的前綴,透過 --requestheader-extra-headers-prefix

這些標頭名稱也放置在 extension-apiserver-authentication configmap 中,以便它們可以被擴充 API 伺服器檢索和使用。

擴充 API 伺服器驗證請求

擴充 API 伺服器在收到來自 Kubernetes apiserver 的代理請求後,必須驗證該請求實際上是否來自有效的身份驗證代理,Kubernetes apiserver 正在履行此角色。擴充 API 伺服器透過以下方式驗證它

  1. 從上述 kube-system 中的 configmap 檢索以下內容
    • 用戶端 CA 憑證
    • 允許名稱 (CN) 清單
    • 使用者名稱、群組和額外資訊的標頭名稱
  2. 檢查 TLS 連線是否使用用戶端憑證進行了身份驗證,該憑證
    • 是否由 CA 簽署,其憑證與檢索到的 CA 憑證相符。
    • 是否具有允許 CN 清單中的 CN,除非該清單為空白,在這種情況下,所有 CN 都是允許的。
    • 從適當的標頭中提取使用者名稱和群組

如果以上檢查都通過,則該請求是來自合法身份驗證代理 (在本例中為 Kubernetes apiserver) 的有效代理請求。

請注意,提供上述功能是擴充 API 伺服器實作的責任。許多實作預設會執行此操作,利用 k8s.io/apiserver/ 套件。其他實作可能會提供選項,以使用命令列選項覆寫它。

為了有權限檢索 configmap,擴充 API 伺服器需要適當的角色。在 kube-system 命名空間中,有一個名為 extension-apiserver-authentication-reader 的預設角色可以被指派。

擴充 API 伺服器授權請求

擴充 API 伺服器現在可以驗證從標頭檢索到的使用者/群組是否有權執行給定的請求。它透過向 Kubernetes apiserver 發送標準的 SubjectAccessReview 請求來做到這一點。

為了使擴充 API 伺服器本身被授權向 Kubernetes apiserver 提交 SubjectAccessReview 請求,它需要正確的權限。Kubernetes 包含一個名為 system:auth-delegator 的預設 ClusterRole,它具有適當的權限。它可以被授予擴充 API 伺服器的服務帳戶。

擴充 API 伺服器執行

如果 SubjectAccessReview 通過,則擴充 API 伺服器執行該請求。

啟用 Kubernetes API 伺服器標記

透過以下 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 憑證。

如果您未在執行 API 伺服器的主機上執行 kube-proxy,則必須確保系統已啟用以下 kube-apiserver 標記

--enable-aggregator-routing=true

註冊 APIService 物件

您可以動態配置哪些用戶端請求被代理至擴充 API 伺服器。以下是一個範例註冊


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 物件的名稱必須是有效的 路徑段名稱

聯絡擴充 API 伺服器

一旦 Kubernetes apiserver 確定應將請求發送到擴充 API 伺服器,它就需要知道如何聯絡它。

service stanza 是對擴充 API 伺服器的服務的參考。服務命名空間和名稱是必需的。port 是可選的,預設為 443。

以下是一個擴充 API 伺服器的範例,該伺服器被配置為在埠 "1234" 上呼叫,並使用自訂 CA bundle 驗證針對 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"
...

下一步

上次修改時間:2023 年 12 月 29 日下午 9:47 PST:修復過時的連結/錨點 (bcc55ae7c9)