淺談 k8s ingress controller 選型
大家好,先簡單自我介紹下,我叫厲輝,來自騰訊雲。業餘時間比較喜歡開源,現在是Apache APISIX PPMC。今天我來簡單給大家介紹下 K8S Ingress 控制器的選型經驗,今天我講的這些內容需要大家對 K8S 有一定的瞭解,下面是我的分享。
名詞解釋
閱讀本文需要熟悉以下基本概念:
叢集:是指容器執行所需雲資源的集合,包含了若干臺雲伺服器、負載均衡器等雲資源。
例項(Pod):由相關的一個或多個容器構成一個例項,這些容器共享相同的儲存和網路空間。
工作負載(Node):Kubernetes 資源物件,用於管理 Pod 副本的建立、排程以及整個生命週期的自動控制。
服務(Service):由多個相同配置的例項(Pod)和訪問這些例項(Pod)的規則組成的微服務。
Ingress:Ingress 是用於將外部 HTTP(S)流量路由到服務(Service)的規則集合。
K8S 訪問現狀
在 K8S 中,服務跟 Pod IP 主要供服務在叢集內訪問使用,對於叢集外的應用是不可見的。怎麼解決這個問題呢?為了讓外部的應用能夠訪問 K8S 叢集中的服務,通常解決辦法是 NodePort 和 LoadBalancer。
這兩種方案其實有各自的缺點,NodePort 的缺點是一個埠只能掛載一個 Service,而且為了更高的可用性,需要額外搭建一個負載均衡。LoadBalancer 的缺點則是每個服務都必須要有一個自己的 IP,不論是內網 IP 或者外網 IP。更多情況下,為了保證 LoadBalancer 的能力,一般需要依賴於雲服務商。
在K8S的實踐、部署中,為了解決像 Pod 遷移、Node Pod 埠、域名動態分配,或者是 Pod 後臺地址動態更新這種問題,就產生了 ingress 解決方案。
Ingress 選型
Nginx ingress 的缺點
Ingress 是 K8S 中非常重要的外網流量入口,前面又拍雲的總監也講到了 K8S 預設的 Nginx ingress。這個 ingress 是 K8S 所推薦的預設的 ingress。為了跟後面的 Nginx 提供的商業版 ingress 作為區分,我就叫它叫 K8S ingress。K8S ingress,顧名思義基於 Nginx 的平臺,Nginx 現在是世界上最流行的 Nginx HTTP Sever,相信在座各位都對 Nginx 比較熟悉,這是一個優點。第二個優點則是 Nginx ingress 接入 K8S 叢集所需配置非常少,而且有很多文件來指引你如何使用這個 ingress。這對於大部分剛接觸 K8S 的人或者創業公司來說,Nginx ingress 確實是一個非常好的選擇。
但是當 Nginx ingress 在一些大環境上使用時,就會有非常多的問題。第一個,Nginx ingress它用了一些 OpenResty 的特性,但最終配置載入還是依賴於原有的 Nginx config reload。當路由配置非常大的時候,Nginx reload 會耗時非常久,可以達到幾秒甚至十幾秒,這種 reload 會很嚴重的影響業務,甚至造成業務中斷,這是第一個問題。
第二個問題是 Nginx ingress 的外掛開發非常困難,如果你覺得 Nginx ingress 本身外掛夠用,那還是可以用的。但如果想用一些定製化的外掛,比如像阿里雲的IM鑑權,或者是騰訊雲的 KM 鑑權都需要進行額外的開發。Nginx ingress 開發外掛非常痛苦,額外開發就非常麻煩,所以 Nginx ingress 的外掛能力和可擴充套件性是比較差的。
Ingress 選型原則
既然發現了 Nginx ingress 有很多問題,那是不是考慮選擇開源的更好用的 ingress,市場上說比 K8S ingress 好用的起碼有十幾家。如何從這麼多 ingress 中選擇適合自己的,這讓人感到困擾。
Ingress 最終是基於 HTTP 閘道器的,市面上 HTTP 閘道器主要有這麼幾種。比如 Nginx、Golang 原生的以及新崛起的 Envoy 這些閘道器。但是每個開發人員所擅長的技術棧不同,例如我對 Nginx 比較熟悉,但有些人對 HAproxy 更加熟悉,或者有些人對新興的 Envoy 這個閘道器更加熟悉。因為每個人熟悉的底層閘道器不一樣,所以適合的 ingress 也會不一樣。
那麼問題來了,我們如何選擇一個更加好用的 ingress 呢?或者縮小點範圍,熟悉 Nginx 或 OpenResty 的開發人員,應該選擇哪一個 ingress 呢?
下面來介紹一下我對 ingress 控制器選型的一些經驗。
基本特點
圖中的這些我覺得是基本功能,這些功能必須要有。如果連這些功能都沒有,那完全可以直接pass。
必須開源的,不開源的無法使用
K8S 中 Pod 變化非常頻繁,服務發現非常重要
現在 HTTPS 已經很普及了,TLS 或者 SSL 的能力也非常重要,比如證書管理的功能
支援 WebSocket 等常見協議,在某些情況下,可能還需要支援 HTTP2 、QUIC 等
基礎軟體
前面有提到,每個人擅長的技術平臺不一樣,所以選擇自己更加熟悉的 HTTP 閘道器也顯得至關重要。比如 Nginx、HAProxy、Envoy 或者是 Golang 原生閘道器。因為你熟悉它的原理,在使用中可以更快落地。
在生產環境上,高效能是一個很重要的點,但比之更重要的是高可用。這意味著你選擇的閘道器,它的可用性、穩定性一定要非常強,只有這樣,服務才能穩定。
功能需求
拋開上述兩點,就是公司業務對閘道器的特殊需求。你選擇一個開源產品,最好肯定是開箱能用的。比如你需要 GRPC 協議轉換的能力,那當然希望選的閘道器直接支援這個功能。而肯定不希望去選擇還需要開發的閘道器。這裡簡單列一下影響選擇的點:
協議上是否支援 HTTP2、HTTP3;
負載均衡演算法上,最基本的WRR,或者是一致性雜湊這種負載均衡演算法是否足夠,還是需要更加複雜的類似EWMA負載均衡演算法。
鑑許可權流上,簡單的鑑權是否足夠,還是說需要更進階的鑑權方式,或者要整合,或者很方便的能開發像阿里雲、騰訊雲的 IM 鑑權。前面我們有提到K8S ingress主要有這麼些缺點,比如說 Nginx reload 的問題,外掛擴充套件能力比較弱。其實它的後端節點調整權重的能力也不太好。
選擇 APISIX 作為 Ingress controller
這裡就要推薦一下 APISIX,它有非常強大的路由能力,外掛能力也非常靈活。雖然它在功能上比 Kong 會少很多,但是 APISIX 很好的路由能力、靈活的外掛能力,以及本身的高效能,能夠彌補在 ingress 選型上的一些缺點。如果你們是基於 Nginx 或 Openresty 的開發人員,又對現在的 ingress 不滿意,我推薦你們去使用 APISIX 作為 ingress。
如何將 APISIX 作為 ingress 呢?我們先要做出一個區分,ingress 是 K8S 名稱的定義或者規則定義,ingress controller 是將 K8S 叢集狀態同步到閘道器的一個元件。但 APISIX 本身只是 API 閘道器,怎麼把 APISIX 實現成 ingress controller 呢?我們先來簡要了解一下如何實現 ingress。
實現 ingress,本質上就是兩點。第一點,需要將 K8S 叢集中的配置,或者 K8S 叢集中的狀態同步到 APISIX 叢集。第二點,需要將 APISIX中 的一些概念,比如像服務、upstream 等概念定義為 K8S 中的 CRD。實現了第二部分的話,通過 K8S ingress 的配置,很快的去產生 APISIX,通過 APISIX ingress controller 就會產生 APISIX 相關的配置。我們當前為了快速的將 APISIX 落地為能夠支援 K8S 的 ingress 。我們建立了一個開源專案,叫 ingress controller。
專案的架構大概是這樣。左邊是 K8S 的叢集,這裡可以匯入一些 yaml 檔案,對 K8S 進行配置上的變更。右邊則是 APISIX 叢集,以及它的控制面和資料面。在這裡,APISIX Ingress 充當這兩個 K8S 叢集以及 APISIX 叢集之間的連線者。它主要是監聽 K8S 叢集中節點的變化,去將叢集中的狀態同步到 APISIX 叢集。另外,K8S 倡導所有元件都要高可用,所以 APISIX Ingress 設計之初,也考慮到它的高可用。我們通過雙節點或多節點的模式,來實現 APISIX ingress controller 的高可用。
各種 Ingress 橫向對比
相對於市面上流行的 ingress 控制器,我們簡單對比來看看 APISIX ingress 有什麼優缺點。上圖是外國開發人員針對 K8S ingress 選型做的一張表格。我在原來表格的基礎上,結合自己的理解,將 APISIX ingress 的功能加入了進來。我們可以看到,最左邊的是APISIX,後邊就是 K8S ingress 和 Kong Ingress,後面的 Traefik,就是基於 Golang 的 ingress。HAproxy 是比較常見的,過去是比較流行的負載均衡器。Istio 和 Ambassador 是國外非常流行的兩個ingress。
我們可以簡單聊一下這些 ingress。首先說下 APISIX ingress,APISIX ingress 的優點前面也說到了,它有非常強大的路由能力,效能非常強,也有非常靈活的外掛拓展能力。APISIX 剛開源沒幾個月,就已經有非常多的功能。但是它的缺點也非常明顯,APISIX 有非常多的功能,但是缺少落地案例,沒有文章去教大家如何將這些功能都給用起來。
第二個就是我前面吐槽了很多的 K8S ingress,也是那個 K8S 推薦的 Nginx Ingress。它的主要優點前面也說了,簡單、易接入。但缺點就非常明顯,Nginx reload根本就沒有解決,外掛是很多的,但外掛擴充套件能力是非常弱的。
我們再說第三個,Nginx ingress主要優點是在於它對 TCP 和 UDP 協議的完全支援,但是其他的,比如像鑑權方式,或者流量排程,這個功能都是非常缺失的。
Kong 本身是一個 API 閘道器,他也算是開創了先河,將 API 閘道器引入到 K8S 中當 ingress。另外對於邊緣閘道器,大家還是有很多需求的,比如說像鑑權、限流、灰度部署等能力。Kong 在這些方面做的非常好。另外 Kong ingress 還有一個非常大的優點,他提供了一些 API、服務的定義,去抽象成 K8S 的 CRD,所以可以很方便地通過 K8S ingress 配置,去同步到 Kong 的叢集。雖然 Kong 有很多優點,但 Kong 也有一個非常大的缺點,那就是部署特別困難,另外他的高可用,與 APISIX 相比也是相形見絀。
Traefik 是基於 Golang 的 ingress,它本身是一個微服務閘道器,但是在 ingress 的場景應用比較多。他的主要平臺是基於 Golang,自身支援的協議也非常多,總體來說是沒有什麼缺點。如果大家熟悉 Golang 的話,也推薦一用。
HAproxy,是一個久負盛名的負載均衡器。它主要優點是有非常強大的負載均衡能力,其他方面並不佔優勢。
Istio ingress 和 Ambassador ingress 都是基於最近非常流行的 envoy。說實話,我覺得這兩個 ingress 沒有什麼缺點,可能唯一的缺點是他們基於 envoy 平臺,大家對這個平臺都不是很熟悉,上手門檻會比較高。
騰訊雲 CLB ingress
前面主要說了開源中的一些 ingress,現在再來說一下 ingress 在騰訊雲的落地情況。前面提到的,像 K8S APISIX,或者是 ingress,他們都是開源的。K8S 跟 ingress,它們都是相互對應的。要聊騰訊雲中的 ingress,自然要先去了解騰訊雲中的 K8S 是什麼。所以我先簡要介紹一下騰訊雲的 TKE,也就是騰訊雲的 K8S 平臺,然後再是騰訊雲 ingress 的落地情況,它是集成了 CLB 來完成了 ingress 的功能。
上圖是當前騰訊雲的 TKE 平臺的整體縱覽,主要由使用者接入層、核心功能,和整合產品三方面組成,整合產品將 Iaas 層和 PaaS 層進行了一些整合。
TKE 的全稱是 Tencent Kubernetes Engine,是⼀個⾼度可擴充套件的⾼效能容器管理服務。最核心的是 TKE 解決了多租戶的問題,K8S 本身是單租戶的,怎麼在騰訊雲上變成多租戶的場景呢?我們花了很長的時間去改造它。其次,在 K8S 節點內,解決了其他一些問題。我們採用了騰訊雲的 VPC 的方案,解決了 Service 和 Pod 之間的通訊問題。另外,內部網路集成了 vpc 的能力,對外網路整合 CLB 的負載均衡能力,硬碟儲存上整合 CBS 的儲存能力等等,最終實現了騰訊雲 K8S 的公有云版。當前 TKE 在騰訊雲上差不多有 200 萬的狀態吧。
CLB 是怎麼樣的?上圖是騰訊雲 CLB ingress 的整體架構圖。因為我想從高效能、高可用的角度來講我們的 ingress 叢集,所以把 K8S 這塊做了簡化,只留了使用者操作,API Server 以及控制器這些。
TKE 需要將 ingress 整合,只需將原有負載均衡的概念,去抽象成 K8S 中一些 CRD 的源語,然後就可以進行對映。比如建立 ingress 或者節點進行排程的時候,我們都可以通過呼叫 CLB 的介面去更新狀態,完成整個 ingress 鏈路。
接下來就聊一下騰訊雲 CLB 的高效能與高可用。因為後臺服務最關注的也是這兩點。
高效能
高效能閘道器主要說兩部分,一是資料面,二是控制面。我們先說資料面,資料面這邊的話,我們做的七層 CLB 主要是基於 Nginx。為了保證高效能,第一步就是要對 Nginx 進行優化。第二步優化是負載均衡,負載均衡最重要的就是 HTTPS 的能力,HTTPS 其實是非常消耗 CPU的。開源界裡,HTTPS 的的優化空間非常大。舉個例子,就比如開源 Nginx,我記不大清是八核還是四核,可以很輕鬆的達到10萬 KBS。但是一旦用了 HTTPS 後,可能連 1 萬 KBS 都達不到。所以 HTTPS 是有很大優化空間的。我們在做七層高效能時,花了很多時間去優化這塊。怎麼優化呢?百度搜一下 Nginx 常見的優化,結果裡出現的,基本上都能優化,當然我們還做了另外一些細節上的優化。
第二部分是協議層上的優化,主要是對 HTTPS 協議本身的優化,這包含很多,包括加密協議、open ssl 庫等,我們都做了一些優化。另外還有 HTTP2 協議的優化,HTTP2 是預設開啟 TLS 加密的,所以也繞不過 HTTPS 協議的優化。
第二方面,我們做了很多控制面的的優化。前面已經提了很多次,只要用 Nginx,肯定避免不了 Nginx reload 的問題。只有幾條路由時,可能沒有問題。但是當有幾千條、幾十萬條路由配置時,如果用 Nginx reload 至少要花十幾秒,這對業務中斷影響非常嚴重,完全不能接受。那該怎麼辦呢?我們作為一個雲廠商,客戶不僅僅在 upsteam這 塊,在後臺節點的變化也非常快,而且客戶是共享叢集,非常多的客戶可能都在操作規則,例如操作 Nginx Server。所以我們又做了動態 Server 的優化。在完成 upstream 和動態 Server 這兩個優化後,對於 99.9% 的規則,基本上都可以通過 Nginx 動態 Server 以及 Nginx 動態 upstream 來解決配置載入、變更,而不需要再去經歷 Nginx reload,這是我們控制面的優化。
高可用
高可用也分兩方面,一是控制叢集,也就是控制面的高可用,二是資料面的高可用。我們先來說資料面的高可用。
資料面的高可用,主要是如上圖的鏈路。四層閘道器與七層閘道器,七層閘道器與後端節點之間,其實他們都有專門的心跳探測,有熔斷機制、超時能力等來保證高可用。比如發現某些節點有問題時,我會去剔除該節點。但也會去定時的撥測,一旦該節點恢復狀態之後,會再將節點去加回來,這是第一方面,資料面的高可能主要通過心跳探測。
第二方面的話,也就是閘道器的跨可用區容災。我們也做了一個 7 層閘道器與 4 層閘道器的跨可用區容災比如當某一個機房的閘道器完全掛掉之後,我們依然可以提供一個高可用、高效能的服務。控制面的話這個主要是通過 master agent 叢集化的模式來保證高可用。
騰訊雲未來的 Ingress——APISIX
說了 CLB ingress 的架構,看起來確實挺美好的,高可用,效能也非常好,那麼它的缺點呢?其實它也是有一些缺點的。
第一,雖然前面說通過動態 upstream 和動態 Server 可以解決掉 99.9% 的配置變更問題,而不需要走 Nginx reload。但是本質上沒有解決配置變更的一些問題,尤其是在一些突發或者後端節點比較多的情況下出現問題。因為過去的後端節點最多也就幾十個,但是當 Docker 化時,後端節點很容易達到上千個甚至上萬個。這時很容易觸發動態 upstream 的域值,讓本來應該走動態 upsteam 的,最終去走了 Nginx reload,這會產生非常嚴重的效能問題。
第二,CLB ingress 所有的邏輯、附加功能都是基於 Nginx,比如像 ACL 限流等都是通過 Nginx 模組來開發的。這樣的話,首先開發門檻會非常高,其次開發效率也比較低。
我們對負載均衡的要求並不高。比如對負載均衡的主要要求,一是七層閘道器效能一定要好,二是 HTTPS 協議的支援能力一定要好,三是支援更多協議。但是對於 K8S ingress 的要求就不滿足了,因為 K8S 有很多節點,我更希望有一個很好用的灰度能力。現在的 CLB,是滿足不了定製化的灰度釋出需求。所以,通過 TKE 集成了 CLB 負載均衡的能力,當作一個 ingress,只是到了能用的級別,但並沒有完全的去貼合 K8S 平臺的需要。
當前 CLB ingress 主要存在的問題就是這些。灰度能力比較弱,也很容易觸發 Nginx reload,從而影響業務,除了這兩點,還有就是隔離性非常差。CLB 的這種部署方式,依然還是很多客戶共用一組 ingress。客戶與客戶之間,其實是會互相影響的。而 K8S 的設計理念是希望客戶能夠獨佔 ingress,不希望客戶與客戶之間的 ingress 會互相影響。我們想要解決上述的問題,恰巧遇見了 APISIX 這個專案。
APISIX 的優勢是效能好,這裡就不贅述了。另外 APISIX 外掛能力靈活,可以支援在更多位置去插入外掛。並且,APISIX 是從雲原生角度去設計的,這意味著 APISIX 非常適合在容器中部署,不像過去的 CLB 在物理機上部署還好,但是在容器上部署,控制面架構就非常不適合。而 APISIX 的控制架構,我們可以非常輕鬆地選擇是讓客戶去共用一組 ingress,還是每個客戶有自己獨佔的 ingress。APISIX 在這三個方面都做的非常好,最終我們打算去落地 APISIX ingress 去替代 TKE 平臺中的 ingress。
最後總結一下,雖然主要是聊 ingress 選型。前面其實就講到了 ingress 的定位,如何去選擇 ingress,選型要考慮哪些問題。後面將 APISIX ingress 與當前開源的一些 ingress 做了橫向對比,讓大家瞭解各個 ingress 的優劣勢,方便後續選型時能夠快速選擇適合自己的 ingress。最後簡要介紹了我們騰訊雲的 CLB ingress,以及它當前存在的問題和下一步計劃。
推薦閱讀
3 分鐘帶你深入瞭解 Cookie、Session、Token
又拍雲邵海楊:基於 OpenResty 的動態服務路由方