天天看點

位元組跳動 kube-apiserver 高可用方案 KubeGateway

作者:位元組跳動技術團隊
本文整理自 2022 年稀土開發者大會,位元組跳動雲原生工程師章駿分享了 Kubernetes 叢集 kube-apiserver 請求的負載均衡和治理方案 KubeGateway。

KubeGateway 是位元組跳動針對 kube-apiserver 流量特征專門定制的七層網關,它徹底解決了 kube-apiserver 負載不均衡的問題,同時在社群範圍内首次實作了對 kube-apiserver 請求的完整治理,包括請求路由、分流、限流、降級等,顯著提高了 Kubernetes 叢集的可用性。

項目位址:https://github.com/kubewharf/kubegateway

1. 背景

在 Kubernetes 叢集中,kube-apiserver 是整個叢集的入口,任何使用者或者程式對叢集資源的增删改查操作都需要經過 kube-apiserver,是以它的高可用性決定了整個叢集的高可用能力。kube-apiserver 本質上是一個無狀态的伺服器,為了實作其高可用,通常會部署多個 kube-apiserver 執行個體,同時引入外部負載均衡器(以下簡稱 LB)進行流量代理。

位元組跳動 kube-apiserver 高可用方案 KubeGateway

為了保證叢集的安全,kube-apiserver 對請求進行認證和授權的準入控制,其中認證是為了識别出使用者的身份。Kubernetes 支援多種認證政策,比如 Bootstrap Token、Service Account Token、OpenID Connect Token、TLS 雙向認證等。

目前 kube-apiserver 的用戶端使用得較多的政策是 TLS 雙向認證。TLS 雙向認證需要 LB 将請求中的 Client X509 Cert 正确傳遞給 kube-apiserver,但是傳統的七層 LB 無法做到這一點,在轉發過程中會丢失 Client X509 Cert,導緻 kube-apiserver 無法認證使用者。

是以目前 LB 的選型一般為 LVS、雲廠商的 SLB 或 nginx、HAProxy 的四層負載均衡方案。

四層負載均衡工作在 OSI 的第四層即傳輸層,使用 NAT 技術進行代理轉發

七層負載均衡工作在 OSI 的第七層即應用層,一般是基于請求 URL 位址的方式進行代理轉發。

但是使用四層 LB 會引起另外的問題,具體如下:

1.請求負載不均衡:由于 kube-apiserver 和 client 是使用 HTTP2 協定連接配接,HTTP2 的多個請求都會複用底層的同一個 TCP 連接配接并且長時間不斷開。在 kube-apiserver 滾動更新或者某個執行個體重新開機時,很容易引起遲些啟動的 kube-apiserver 在長時間内隻有很少的請求數。極端情況下,負載較高的執行個體會出現 OOM,甚至引起雪崩。

位元組跳動 kube-apiserver 高可用方案 KubeGateway

2.缺乏請求治理的靈活性:4 層負載均衡在傳輸層工作,它隻負責消息的傳遞,但是無法處理應用層的 HTTP 協定的資訊,是以相較于 7 層負載缺乏對請求治理的“靈活性”和 “智能性”。比如無法根據請求的内容(比如 verb、url 等字段)制定靈活的負載均衡和路由政策,也無法在網關層對請求級别進行限流降級等處理。

社群中有一些相關工作試圖解決上述問題,但均沒有根治問題:

位元組跳動 kube-apiserver 高可用方案 KubeGateway

随着雲原生技術的發展,目前位元組跳動 95% 以上的業務跑在 Kubernetes 上,對叢集高可用提出了更高的要求。事實上,在生産環境中,我們也曾遇到過多次由于 kube-apiserver 負載不均衡或者缺乏請求治理能力帶來的事故,面對以上問題,我們針對 kube-apiserver 的流量特征自研了七層網關 KubeGateway。

2. 架構設計

KubeGateway 作為七層網關接入和轉發 kube-apiserver 的請求,它具有以下特點:

  1. 對于用戶端完全透明,用戶端無需任何改造即可以接入 KubeGateway;
  2. 支援同時代理多個 K8s 叢集的請求,不同 K8s 叢集通過不同的域名或者虛拟位址(vip)進行區分。
  3. 負載均衡從 TCP 連接配接級别變為 HTTP 請求級别,進而實作快速、有效的進行負載均衡,徹底解決 kube-apiserver 負載不均衡的問題。
  4. 高擴充性的負載均衡政策,目前支援 Round Robin、Random 政策,負載均衡政策插件化,易于擴充。
  5. 支援靈活的路由政策,KubeGateway 根據請求資訊,包括但不限于 resource/ verb/ user/ namespace/ apigroup 等進行路由。為 kube-apiserver 分組提供基礎能力,以低運維成本實作 kube-apiserver 組之間的隔離性,提高叢集穩定性。
  6. 配置管理雲原生化,以 K8s 的标準 API 形式管理網關配置,支援配置熱更新。
  7. 支援限流、降級、動态服務發現、優雅退出、upstream 異常檢測等網關的通用能力。

KubeGateway 對外以 K8s 标準 API 的形式提供代理配置管理的服務,主要提供路由轉發規則、上遊叢集 kube-apiserver 位址、叢集證書資訊、限流等請求治理政策等配置資訊的維護變更。它代理 kube-apiserver 的請求的流程如下圖所示,主要分為五個步驟:請求解析、路由比對、使用者認證、流量治理和反向代理。下面依次對這些步驟進行詳細介紹:

位元組跳動 kube-apiserver 高可用方案 KubeGateway

2.1 請求解析

KubeGateway 可以深入了解 kube-apiserver 請求模型,從中解析出更多的資訊,它将 kube-apiserver 的請求分為兩種類型:

  • 資源請求,如對 Pod 的 CRUD(增删改查)。
  • 非資源請求,如通路 /healthz 檢視 kube-apiserver 的健康情況,通路 /metrics 檢視暴露的名額等。

對于資源請求,可以從請求的 URL 和 Header 中解析出以下的内容:

位元組跳動 kube-apiserver 高可用方案 KubeGateway

最終一個請求可以解析出多元度的路由字段,如下圖所示,這些字段将作為路由選擇的依據。

位元組跳動 kube-apiserver 高可用方案 KubeGateway

2.2 路由比對

從請求中解析出多元度的路由字段後,可以很友善地組合出非常強大的路由規則來區分不同的 API 請求,比如

  • 通過 Verb 和 Resource 的結合,我們可以直接比對到所有的 list pod 的請求。
  • 通過 User,UserGroup,ServiceAccount 等,我們可以比對出 kube-controller-manager,kube-scheduler 等核心控制元件的請求。

将不同的請求經過路由規則比對後,我們能對它們做更精細化的分流,限流,熔斷等流量控制。

比對規則可以直接通過修改 KubeGateway 的配置管理服務對外暴露的 API -- UpstreamCluster 實時生效。

2.3 使用者認證

為了能夠正确地代理 kube-apiserver 的七層流量,讓請求經過代理後的在 upstream kube-apiserver 能被正确地進行認證授權,KubeGateway 需要将請求中的使用者資訊透傳給 kube-apiserver,這要求 KubeGateway 也能認證出請求中的使用者資訊。

KubeGateway 将 kube-apiserver 支援的認證方式可以分為以下幾類

  • 基于 x509 用戶端證書的認證方式:KubeGateway 通過規則 upstream kube-apiserver 中的 CA 證書,解析出用戶端證書中使用者和使用者組資訊
  • 基于 Bearer Token 的認證方式:KubeGateway 通過給 upstream kube-apiserver 發送 TokenReview 請求,要求 upstream kube-apiserver 對 Bearer Token 進行認證,進而得到對應的使用者資訊。

識别出使用者後,KubeGateway 通過 kube-apiserver 提供的 Impersonate(使用者扮演)機制進行轉發,詳細内容會在 2.5.1 部分進行介紹。此外,KubeGateway 隻會對請求進行認證,并不會對請求進行授權判斷,授權操作由 upstream kube-apiserver 進行。

2.4 請求治理

KubeGateway 作為七層網關,有着豐富的流量治理能力,具體包括:

2.4.1 負載均衡

UpstreamCluster 确定後,Upstream Servers 也随之确定。KubeGateway 按照負載均衡政策從 Upstream Servers 中選擇出一個進行請求轉發。良好的負載均衡政策可以優化資源效率,最大化吞吐量,減少延遲和容錯。

目前 KubeGateway 支援 Round Robin 和 Random 負載均衡政策,這兩種政策簡單有效,能夠滿足大部分場景的需求。此外,KubeGateway 支援靈活的負載均衡政策擴充,可以快速實作 Least Request 等算法,以滿足更多場景的需求。

2.4.2 健康監測

KubeGateway 會定期主動地通路 kube-apiserver 的 /healthz 接口進行健康監測。代理流量隻會轉發給健康的 kube-apiserver;而不健康的 kube-apiserver 會被臨時屏蔽,當它被恢複健康後才會重新有新的流量

2.4.3 限流

KubeGateway 預設提供限流的能力,可以有效地防止 upstream kube-apiserver 在某些情況下過載。它的限流方案相比于 Kubernetes 本身的 APF(API Priority and Fairness)更容易了解和配置。請求經過請求解析和路由比對之後,KubeGateway 會确定這個請求的限流規則。

比如我們想要限制普通使用者 list pod 的 QPS 但是又要對管控元件(如 controller-manager,scheduler)進行豁免,可以在路由比對中區分出兩種類型的使用者然後為他們單獨配置 FlowControl 限流規則。

位元組跳動 kube-apiserver 高可用方案 KubeGateway

KubeGateway 提供了兩種限流政策:

  • token bucket:令牌桶是常用的限流方式,它能有效地限制請求的 QPS 并在一定程度上允許突發的請求。
  • max requests inflight:最大請求數是比令牌桶更嚴格的限制方式,它限制在某個時刻能夠執行的最大請求數量,通常用來限制一些更加耗時的請求,比如在大叢集 list 全量 pods,這種請求會可能會持續好幾分鐘,而且會占用 kube-apiserver 大量的資源,隻通過令牌桶的限流會放入過多的請求而造成 kube-apiserver OOM 等問題。

2.4.4 降級

KubeGateway 支援降級以應對叢集管控面異常的情況。

在 kube-apiserver 或者 ETCD 發生故障的時候,可能引起叢集的雪崩。在雪崩情況下,部分請求會傳回成功,部分請求傳回失敗,加上用戶端不斷重試,容易導緻叢集出現非預期行為,比如 Node NotReady、 Pod 大量驅逐和删除等。

在這種情況下,開發人員可以通過 KubeGateway 進行降級操作拒掉所有流量。在降級狀态下叢集相當于被當機了,所有寫入都無法成功,可以保證存量的 Pod 程序保持存活狀态,避免對業務造成影響。在叢集恢複正常後,首先放開限制允許 Node 上報心跳,然後再恢複叢集的其他流量。

2.5 反向代理

KubeGateway 在反向代理部分,有以下關鍵的技術點:

2.5.1 Impersonate(使用者扮演)

在通過流量治理後,KubeGateway 會根據選擇出的 kube-apiserver 進行轉發。在轉發的時候 KubeGateway 通過 impersonate 的機制将使用者資訊通過 Request Header 傳遞給 upstream kube-apiserver。在 Request Header 中添加以下資訊:

Impersonate-User: Client 使用者名
Impersonate-Group: Client 使用者組           

Impersonate 是 kube-apiserver 對外提供的一種機制,它允許一個使用者扮演成另外一個使用者執行 API 請求。在使用這個機制之前,我們需要在 upstream kube-apiserver 為 KubeGateway 的用戶端配置好 Impersonate 的權限,Impersonate 的請求具體的流程如下:

位元組跳動 kube-apiserver 高可用方案 KubeGateway
  • kube-apiserver 認證 KubeGateway 使用者,識别出使用者扮演的行為。
  • kube-apiserver 確定 KubeGateway 具有 Impersonate 權限。
  • kube-apiserver 根據 HTTP Header 識别出 KubeGateway 扮演的使用者名和使用者組,然後将請求執行者替換成被扮演的使用者。
  • 對被扮演的使用者進行授權驗證,檢查他是否有權限通路對應的資源。

kube-apiserver 對于 Impersonate 機制支援的很完善,審計日志中也相容了 Impersonate。

最終 KubeGateway 依靠使用者認證和 Impersonate 機制,完成原始使用者資訊的透傳,解決了傳統七層 LB 無法代理 kube-apiserver 請求的問題。而且在代理過程中,對于用戶端是完全透明的,用戶端無需進行任何修改即可接入 KubeGateway。

2.5.2 HTTP2 多路複用

KubeGateway 預設使用 HTTP2 協定,基于 HTTP2 協定的多路複用能力,單條連接配接上預設支援 250 個 Stream,即單個連接配接上支援 250 個并發的請求,使得 upstream 單個 kube-apiserver 的 TCP 連接配接數可以降低兩個數量級。

位元組跳動 kube-apiserver 高可用方案 KubeGateway

2.5.3 Forward & Exec 類請求處理

KubeGateway 支援所有原生 kube-apiserver 請求的透明代理。由于 Forward 、Exec 等部分請求需要通過 HTTP 1.1 建立的連結之上使用其他的協定(比如 SPDY、WebSocket 等)來進行通信,KubeGateway 在轉發這類請求時會禁止 http2,且支援 Hijacker 處理。

3. 落地效果

經過壓測,KubeGateway 性能優異,經過代理後,請求延遲增加在 1ms 左右。目前 KubeGateway 已經平滑的接管了位元組所有的 Kubernetes 叢集,總 QPS 20w+。在 KubeGateway 的幫助下,研發團隊徹底解決了 kube-apiserver 流量不均衡的問題,而且極大增強了 kube-apiserver 請求的治理能力,包括請求分組、路由、限流、降級等,有效提高了叢集的穩定性和可用性。

同時,我們在 KubeGateway 優雅更新、多叢集動态證書管理、可觀測性上也做了很多優化,具體技術細節以後會進行更多的介紹,敬請期待。

4. 未來演進

目前,KubeGateway 已在 GitHub 開源,未來它會在以下幾個方面持續演進:

  1. 提供更完整的 7 層網關能力,比如黑白名單,緩存等;
  2. 持續提高可觀測性,可以在異常情況下能夠快速定位到問題,輔助排障;
  3. 探索基于 KubeGateway 網關實作新型的聯邦方案,通過 KubeGateway 可以将多個 K8s 叢集透明地聚合成一個叢集;

期待有更多朋友關注和加入 KubeGateway 社群,也歡迎大家在 GitHub 給我們提出各種建議!

位元組基礎架構編排排程團隊,負責建構位元組跳動内部的容器雲平台,為産品線提供運作基石;以超大容器叢集規模整體支撐了位元組内産品線,涵蓋今日頭條、抖音、西瓜視訊等。

團隊支援業務同時覆寫線上、離線機器學習,推薦/廣告/搜尋等多種應用場景;在持續多年的超高速增長中,積累了豐富的 Kubernetes/容器超大規模應用經驗,旨在打造覆寫多場景,多地域的千萬級容器的大平台。歡迎志同道合的同學們加入我們。

履歷投遞:[email protected]

繼續閱讀