本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
可擴充套件准入進入 Beta 階段
在這篇文章中,我們將回顧 Kubernetes API 伺服器中可用的一個特性,它允許您實現任意控制決策,並且在 Kubernetes 1.9 中已經相當成熟。
API 伺服器處理的准入階段是保護 Kubernetes 叢集最強大的工具之一,透過限制可以建立的物件,但它一直侷限於編譯程式碼。在 1.9 中,我們將准入 webhook 提升到 Beta 階段,允許您從 API 伺服器程序外部利用准入。
什麼是准入?
准入是處理 API 伺服器請求的一個階段,發生在資源持久化之前,但在授權之後。准入可以訪問與授權相同的資訊(使用者、URL 等)以及 API 請求的完整正文(對於大多數請求)。
准入階段由獨立的外掛組成,每個外掛都專注於特定的領域,並對其所檢查的內容具有語義知識。示例包括:PodNodeSelector(影響排程決策)、PodSecurityPolicy(防止特權升級容器)和 ResourceQuota(按名稱空間強制執行資源分配)。
准入分為兩個階段
- 變更:允許修改正文內容本身以及拒絕 API 請求。
- 驗證:允許內省查詢和拒絕 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(例如 metrics、service-catalog 或 kube-projects)新增變更和驗證准入外掛,而無需重新編譯它們。兩種型別的准入 webhook 都執行在各自鏈的末尾,並具有與編譯准入外掛相同的能力和限制。
它們有什麼用?
Webhook 准入外掛允許對任何 API 伺服器上的任何資源進行變更和驗證,因此可能的應用非常廣泛。一些常見的用例包括:
- Pod 等資源的變更。Istio 曾討論過透過這種方式將 Sidecar 容器注入到 Pod 中。您還可以編寫一個外掛,強制將映象標籤解析為映象 SHA。
- 名稱限制。在多租戶系統中,預留名稱空間已成為一個用例。
- 複雜的 CustomResource 驗證。由於整個物件可見,一個巧妙的准入外掛可以對依賴欄位(A 需要 B)甚至外部資源(與 LimitRanges 比較)執行復雜的驗證。
- 安全響應。如果您將映象標籤強制解析為映象 SHA,您可以編寫一個准入外掛來阻止某些 SHA 的執行。
註冊
兩種型別的 Webhook 准入外掛都在 API 中註冊,並且所有 API 伺服器(kube-apiserver 和所有擴充套件 API 伺服器)共享它們的通用配置。在註冊過程中,Webhook 准入外掛描述了:
- 如何連線到 webhook 准入伺服器
- 如何驗證 webhook 准入伺服器(它真的是我期望的伺服器嗎?)
- 將資料傳送到該伺服器的哪個 URL 路徑
- 它將處理哪些資源和哪些 HTTP 動詞
- 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 伺服器是否具有發出請求的授權 有三種主要的連線類別
- 從 kube-apiserver 或 extension-apiservers 到外部託管的准入 webhook(未在叢集中託管的 webhook)
- 從 kube-apiserver 到自託管的准入 webhook
- 從 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-apiserver 和 kubernetes-namespace-reservation 專案,以獲取該庫以及如何構建自己的安全且可移植的 webhook 准入伺服器的示例。
透過 1.9 中引入的准入 webhook,我們使 Kubernetes 更能適應您的需求。我們希望這項由 Red Hat 和 Google 共同推動的工作能夠支援更多的負載和生態系統元件。(Istio 就是一個例子。)現在是嘗試的好時機!
如果您有興趣提供反饋或為此領域做出貢獻,請加入我們 SIG API machinery。