本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

可擴充套件准入進入 Beta 階段

在這篇文章中,我們將回顧 Kubernetes API 伺服器中可用的一個特性,它允許您實現任意控制決策,並且在 Kubernetes 1.9 中已經相當成熟。

API 伺服器處理的准入階段是保護 Kubernetes 叢集最強大的工具之一,透過限制可以建立的物件,但它一直侷限於編譯程式碼。在 1.9 中,我們將准入 webhook 提升到 Beta 階段,允許您從 API 伺服器程序外部利用准入。

什麼是准入?

准入處理 API 伺服器請求的一個階段,發生在資源持久化之前,但在授權之後。准入可以訪問與授權相同的資訊(使用者、URL 等)以及 API 請求的完整正文(對於大多數請求)。

准入階段由獨立的外掛組成,每個外掛都專注於特定的領域,並對其所檢查的內容具有語義知識。示例包括:PodNodeSelector(影響排程決策)、PodSecurityPolicy(防止特權升級容器)和 ResourceQuota(按名稱空間強制執行資源分配)。

准入分為兩個階段

  1. 變更:允許修改正文內容本身以及拒絕 API 請求。
  2. 驗證:允許內省查詢和拒絕 API 請求。准入外掛可以同時存在於兩個階段,但所有變更都發生在驗證之前。

變更

准入的變更階段允許在資源持久化之前修改資源內容。由於在准入鏈中,同一個欄位可以被多次變更,因此准入外掛在變更中的順序很重要。

一個變更准入外掛的例子是 PodNodeSelector 外掛,它使用名稱空間上的註釋 namespace.annotations[“scheduler.alpha.kubernetes.io/node-selector”] 來查詢標籤選擇器並將其新增到 pod.spec.nodeselector 欄位。這積極地限制了特定名稱空間中的 pod 可以落在哪些節點上,而不是像汙點那樣提供消極限制(也透過准入外掛)。

驗證

准入的驗證階段允許對特定 API 資源強制執行不變性。驗證階段在所有變更器完成之後執行,以確保資源不會再次更改。

一個驗證准入外掛的例子也是 PodNodeSelector 外掛,它確保所有 pod 的 spec.nodeSelector 欄位都受到名稱空間上的節點選擇器限制。即使一個變更准入外掛試圖在 PodNodeSelector 在變更鏈中執行之後更改 spec.nodeSelector 欄位,驗證鏈中的 PodNodeSelector 也會阻止建立 API 資源,因為它未能透過驗證。

什麼是准入 webhook?

准入 webhook 允許 Kubernetes 安裝程式或叢集管理員向 kube-apiserver 的准入鏈以及基於 k8s.io/apiserver 1.9 的任何擴充套件 apiserver(例如 metricsservice-catalogkube-projects)新增變更和驗證准入外掛,而無需重新編譯它們。兩種型別的准入 webhook 都執行在各自鏈的末尾,並具有與編譯准入外掛相同的能力和限制。

它們有什麼用?

Webhook 准入外掛允許對任何 API 伺服器上的任何資源進行變更和驗證,因此可能的應用非常廣泛。一些常見的用例包括:

  1. Pod 等資源的變更。Istio 曾討論過透過這種方式將 Sidecar 容器注入到 Pod 中。您還可以編寫一個外掛,強制將映象標籤解析為映象 SHA。
  2. 名稱限制。在多租戶系統中,預留名稱空間已成為一個用例。
  3. 複雜的 CustomResource 驗證。由於整個物件可見,一個巧妙的准入外掛可以對依賴欄位(A 需要 B)甚至外部資源(與 LimitRanges 比較)執行復雜的驗證。
  4. 安全響應。如果您將映象標籤強制解析為映象 SHA,您可以編寫一個准入外掛來阻止某些 SHA 的執行。

註冊

兩種型別的 Webhook 准入外掛都在 API 中註冊,並且所有 API 伺服器(kube-apiserver 和所有擴充套件 API 伺服器)共享它們的通用配置。在註冊過程中,Webhook 准入外掛描述了:

  1. 如何連線到 webhook 准入伺服器
  2. 如何驗證 webhook 准入伺服器(它真的是我期望的伺服器嗎?)
  3. 將資料傳送到該伺服器的哪個 URL 路徑
  4. 它將處理哪些資源和哪些 HTTP 動詞
  5. API 伺服器在連線失敗時應採取的措施(例如,如果准入 webhook 伺服器宕機)
1 apiVersion: admissionregistration.k8s.io/v1beta1  
2 kind: ValidatingWebhookConfiguration  
3 metadata:  
4   name: namespacereservations.admission.online.openshift.io  
5 webhooks:  
6 - name: namespacereservations.admission.online.openshift.io  
7   clientConfig:  
8     service:  
9       namespace: default  
10      name: kubernetes  
11     path: /apis/admission.online.openshift.io/v1alpha1/namespacereservations  
12    caBundle: KUBE\_CA\_HERE  
13  rules:  
14  - operations:  
15    - CREATE  
16    apiGroups:  
17    - ""  
18    apiVersions:  
19    - "\*"  
20    resources:  
21    - namespaces  
22  failurePolicy: Fail

第 6 行:name - webhook 本身的名稱。對於變更 webhook,它們按順序排列以提供排序。
第 7 行:clientConfig - 提供有關如何連線、信任和向 webhook 准入伺服器傳送資訊的資訊。
第 13 行:rules - 描述 API 伺服器何時應該呼叫此准入外掛。在此示例中,僅用於名稱空間的建立。您可以在此處指定任何資源,因此指定 serviceinstances.servicecatalog.k8s.io 的建立也是合法的。
第 22 行:failurePolicy - 說明如果 webhook 准入伺服器不可用時該怎麼做。選項是 “Ignore”(失敗開放)或 “Fail”(失敗關閉)。失敗開放會導致所有客戶端的行為不可預測。

身份驗證和信任

由於 webhook 准入外掛具有很大的許可權(請記住,它們可以檢視傳送給它們的任何請求的 API 資源內容,並且對於變更外掛可能會修改它們),因此考慮以下幾點非常重要:

  • 各個 API 伺服器如何驗證其與 webhook 准入伺服器的連線
  • webhook 准入伺服器如何精確地驗證哪個 API 伺服器正在與其聯絡
  • 該特定 API 伺服器是否具有發出請求的授權 有三種主要的連線類別
  1. 從 kube-apiserver 或 extension-apiservers 到外部託管的准入 webhook(未在叢集中託管的 webhook)
  2. 從 kube-apiserver 到自託管的准入 webhook
  3. 從 extension-apiservers 到自託管的准入 webhook 為了支援這些類別,webhook 准入外掛接受一個 kubeconfig 檔案,該檔案描述瞭如何連線到各個伺服器。對於與外部託管的准入 webhook 互動,實際上沒有其他方法可以手動配置該檔案,因為身份驗證/授權和訪問路徑由您要連線的伺服器擁有。

對於自託管類別,一個巧妙構建的 webhook 准入伺服器和拓撲可以利用准入外掛中內建的安全預設值,並擁有一個安全、可移植、零配置的拓撲,適用於任何 API 伺服器。

簡單、安全、可移植、零配置拓撲

如果您將您的 webhook 准入伺服器也構建為擴充套件 API 伺服器,那麼就可以像普通的 API 伺服器一樣聚合它。這有許多優點:

  • 您的 webhook 將像預設 kube-apiserver 服務 kubernetes.default.svc 下的任何其他 API 一樣可用(例如 https://kubernetes.default.svc/apis/admission.example.com/v1/mymutatingadmissionreviews)。除此之外,您可以使用 kubectl 進行測試。
  • 您的 webhook 自動(無需任何配置)利用 kube-apiserver 提供的叢集內身份驗證和授權。您可以使用正常的 RBAC 規則限制對 webhook 的訪問。
  • 您的擴充套件 API 伺服器和 kube-apiserver 自動(無需任何配置)使用其叢集內憑據與 webhook 進行通訊。
  • 擴充套件 API 伺服器不會將其服務帳戶令牌洩露給您的 webhook,因為它們透過 kube-apiserver,這是一個安全的代理。


來源:https://drive.google.com/a/redhat.com/file/d/12nC9S2fWCbeX_P8nrmL6NgOSIha4HDNp

簡而言之:安全的拓撲利用了 API 伺服器聚合的所有安全機制,並且不需要任何額外的配置。

其他拓撲也是可能的,但需要額外的手動配置以及大量的努力來建立安全的設定,尤其是在涉及到服務目錄等擴充套件 API 伺服器時。上述拓撲是零配置且可移植到每個 Kubernetes 叢集的。

我如何編寫 webhook 准入伺服器?

編寫一個完整的包含身份驗證和授權的伺服器可能令人望而生畏。為了簡化,有基於 Kubernetes 1.9 的專案提供了一個庫,用於在 200 行或更少的程式碼中構建您的 webhook 准入伺服器。請檢視 generic-admission-apiserverkubernetes-namespace-reservation 專案,以獲取該庫以及如何構建自己的安全且可移植的 webhook 准入伺服器的示例。

透過 1.9 中引入的准入 webhook,我們使 Kubernetes 更能適應您的需求。我們希望這項由 Red Hat 和 Google 共同推動的工作能夠支援更多的負載和生態系統元件。(Istio 就是一個例子。)現在是嘗試的好時機!

如果您有興趣提供反饋或為此領域做出貢獻,請加入我們 SIG API machinery