您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關TKE基于彈性網卡直連Pod的網絡負載均衡是怎樣的,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
Kubernetes
在集群接入層設計并提供了兩種原生資源Service
和Ingress
,分別負責四層和七層的網絡接入層配置。
傳統的做法是創建Ingress或LoadBalancer類型的Service來綁定騰訊云的負載均衡將服務對外暴露。這種做法將用戶流量負載到用戶節點的NodePort上,通過KubeProxy組件轉發到容器網絡中,但這種方案在業務的性能和能力支持會有所局限。
為了解決這個問題,TKE容器團隊為在騰訊云上使用獨立或托管集群的用戶提供了一種新的網絡模式,利用彈性網卡直連Pod的方案很大的增強了性能和業務能力的支持。
本文將會從傳統的模式的問題入手,比較新舊模式的區別,并在最后提供新直連模式的使用指引。
KubeProxy
在集群中會將用戶NodePort
的流量通過NAT的方式轉發到集群網絡中。這個NAT轉發帶來了以下一些問題。
NAT轉發導致請求在性能上有一定的損失。
進行NAT操作本身會帶來性能上的損失。
NAT轉發的目的地址可能會使得流量在容器網絡內跨節點轉發。
NAT轉發導致請求的來源IP被修改了,客戶端無法獲取來源IP。
當負載均衡的流量集中到幾個NodePort時。過于集中的流量會導致NodePort的SNAT轉發過多,使得源端口耗盡流量異常。還可能導致 conntrack 插入沖突導致丟包,影響性能。
KubeProxy
的轉發具有隨機性,無法支持會話保持。
KubeProxy
的每個NodePort其實也起到獨立的負載均衡作用,由于負載均衡無法收斂到一個地方,所以難以達到全局的負載均衡。
為了解決以上問題,我們以前給用戶提供的技術建議主要是通過Local轉發的方式,避免KubeProxy
NAT轉發帶來的問題。但是因為轉發的隨機性,一個節點上部署多個副本時會話保持依舊無法支持。而且Local轉發在滾動更新時,容易出現服務的閃斷,對業務的滾動更新策略以及優雅停機提出了更高的要求。我們有理由去尋找更好的方案解決這個問題。
通過NodePort接入服務時,NodePort的設計存在極大的容錯性。負載均衡會綁定集群所有節點的NodePort作為后端。集群任意一個節點的訪問服務時,流量將隨機分配到集群的工作負載中。這就意味著部分NodePort的不可用,或者是Pod的不可用都不會影響服務的流量接入。
和Local訪問一樣,直接將負載均衡后端連接到用戶Pod的情況下,當業務在滾動更新時,如果負載均衡不能夠及時綁定上新的Pod,業務的快速滾動可能導致業務入口的負載均衡后端數量嚴重不足甚至被清空。因此,業務滾動更新的時候,接入層的負載均衡的狀態良好,方能保證滾動更新的安全平穩。
負載均衡的控制面接口。包括創建刪除修改四層、七層監聽器,創建刪除七層規則,綁定各個監聽器或者規則的后端。這些接口大部分是異步接口,需要輪詢請求結果,接口的調用時間相對較長。當用戶集群規模較大時,大量的接入層資源同步會導致組件存在很大的時延上的壓力。
Pod直連模式已經在騰訊TKE上線,是對負載均衡的控制面優化。針對整個同步流程,重點優化了批量調用和后端實例查詢兩個遠程調用比較頻繁的地方。**優化完成后,Ingress典型場景下的控制面性能較優化前版本有了95%-97%左右的性能提升。**目前同步的耗時主要集中在異步接口的等待上。
除去控制面性能優化這樣的硬核優化,負載均衡能夠直接訪問容器網絡的Pod就是組件業務能力最重要的組成部分了,其不僅避免了NAT轉發性能上的損失,同時避免了NAT轉發帶來的各種對集群內業務功能影響。但是在啟動該項目時這一塊還沒有特別好的訪問容器網絡的支持。所以一期考慮集群CNI網絡模式下Pod有彈性網卡入口,這個入口可以直接接入到負載均衡以達到直接訪問的目的。負載均衡直接后端訪問到容器網絡,目前已經有通過云聯網解決的方案,后續也會繼續跟進這種更貼近集群網絡的直連方案。
接下來能夠直接訪問了,如何保證滾動更新時的可用性保證呢?我們找到了官方提供的一個特性ReadinessGate
。這個特性在1.12正式提供出來,主要是用來控制Pod的狀態。默認情況下,Pod有以下Condition:PodScheduled、Initialized、ContainersReady,當這幾個狀態都Ready的時候,Pod Ready的Condition就通過了。但是在云原生的場景下面,Pod的狀態是非常有可能需要參考其他狀態的。ReadinessGate
提供了這樣一個機制,允許為Pod的狀態判斷添加一個柵欄,由第三方來進行判斷與控制。這樣Pod的狀態就和第三方關聯起來了。
請求流量進入負載均衡
請求被負載均衡轉發到某一個節點的NodePort
KubeProxy將來自NodePort的流量進行NAT轉發,目的地址是隨機的一個Pod。
請求進入容器網絡,并根據Pod地址轉發到對應節點。
請求來到Pod所屬節點,轉發到Pod。
請求流量進入負載均衡
請求被負載均衡轉發到某一個Pod的ENI彈性網卡
看起來這兩種訪問方式的效果是一樣的,但是在細節上還是存在一些差別。
從性能上區別不大,開啟Local訪問時,流量不會進行NAT操作也不會進行跨節點轉發,所以僅僅多了一個到容器網絡的路由。
沒有進行NAT操作,來源IP就能夠正確獲取了。會話保持功能可能會有以下問題,當一個節點上存在多個Pod時,流量到哪一個Pod是隨機的,這個機制可能會使話保持出現問題。
前面有兩個細節,可以在這里得到解答。
為什么要求集群版本高于 1.12
為什么kubectl get pod -o wide
的結果中READINESS GATES
列有內容。
這里涉及到一個滾動更新相關的問題 當用戶開始為應用做滾動更新的時候,Kubernetes
會根據更新策略進行滾動更新。但是其判斷一批Pod啟動的標識僅包括Pod自身的狀態,并不會考慮這個Pod在負載均衡上是否已經進行配置健康檢查是否通過。有的時候當接入層組件高負載,不能及時對這些Pod進行及時調度的話,這些滾動更新成功的Pod可能并沒有正在對外提供服務,從而導致服務的中斷。為了將滾動更新和負載均衡的后端狀態關聯起來,TKE接入層組件引入了Kubernetes 1.12中引入的新特性ReadinessGate
。TKE接入層組件只有在確認后端綁定成功并且健康檢查通過時,通過配置ReadinessGate
的狀態來使Pod達到Ready的狀態,從而推動整個工作負載的滾動更新。
在集群中使用ReadinessGate
的細節 Kubernetes集群提供的是一個服務注冊的機制,你只需要將你的服務以MutatingWebhookConfigurations
資源的形式注冊到集群中就可以了。集群會在Pod創建的時候按照你的配置的回調路徑通知你,這個時候就可以對Pod做一些創建前的操作,在這個Case里面就是給Pod加上ReadinessGate
。唯一需要注意的就是這個回調過程必須是Https的,所以標配需要在MutatingWebhookConfigurations
中配置簽發請求的CA,并在服務端配置該CA簽發的證書。
ReadinessGate
機制的災難恢復 用戶集群中的服務注冊或是證書有可能被用戶刪除,雖然這些系統組件資源不應該被用戶修改或破壞。但在用戶對集群的探索或是誤操作下,這類問題會不可避免的出現。所以接入層組件在啟動時會檢查以上資源的完整性,在完整性受到破壞時會重建以上資源,加強系統的魯棒性。
直連與NodePort是服務應用的接入層方案,其實最終參與工作的還是用戶部署的工作負載,用戶工作負載的能力直接決定了業務的QPS等指標。所以我們針對這兩種接入層方案,在工作負載壓力較低的情況下,重點針對網絡鏈路的時延進行了一些對比測試。直連在接入層的網絡鏈路上能夠優化10%左右的時間。同時測試中的監控也發現,直連模式減少了大量VPC網絡內的流量。測試場景,從20節點到80節點,逐步增大集群規模,通過wrk工具對集群進行網絡延時的測試。針對QPS和網絡時延,下圖給出了直連場景與NodePort的對比測試。
KubeProxy
的缺點也在前文中提到的一樣明顯。但是基于云上負載均衡、VPC網絡的各種特性,我們能給出各種其他更加本地化的接入層方案。但這并不意味著KubeProxy
的設計不好或是作用不大。其對集群接入層的設計極具普適性、容錯性,基本適用于所有業務場景下的集群,作為一個官方提供的組件這個設計是非常合適的。
Kubernetes
集群版本需要高于 1.12。
集群網絡模式必須開啟VPC-CNI
彈性網卡模式。
直連模式Service
使用的工作負載需使用VPC-CNI
彈性網卡模式。
登錄 容器服務控制臺。
參考控制臺 創建 Service 步驟,進入 “新建Service” 頁面,根據實際需求設置 Service 參數。
其中,部分關鍵參數信息需進行如下設置,如下圖所示:
服務訪問方式:選擇為【提供公網訪問】或【VPC內網訪問】。
網絡模式:勾選【采用負載均衡直連Pod模式】。
Workload綁定:選擇【引用Worklocad】,并在彈出窗口中選擇 VPC-CNI 模式的后端工作負載。
單擊【創建服務】,完成創建。
Workload示例:nginx-deployment-eni.yaml
注意
spec.template.metadata.annotations
中聲明了tke.cloud.tencent.com/networks: tke-route-eni
,在工作負載使用VPC-CNI彈性網卡模式。
apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment-eni spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: annotations: tke.cloud.tencent.com/networks: tke-route-eni labels: app: nginx spec: containers: - image: nginx:1.7.9 name: nginx ports: - containerPort: 80 protocol: TCP
- Service示例:nginx-service-eni.yaml > 注意:`metadata.annotations`中聲明了`service.cloud.tencent.com/direct-access: "true"`,Service在同步負載均衡時將采用直連的方式配置訪問后端。 ```yaml apiVersion: v1 kind: Service metadata: annotations: service.cloud.tencent.com/direct-access: "true" labels: app: nginx name: nginx-service-eni spec: externalTrafficPolicy: Cluster ports: - name: 80-80-no port: 80 protocol: TCP targetPort: 80 selector: app: nginx sessionAffinity: None type: LoadBalancer ``` - 部署以上內容到集群 > 注意:在你的環境你首先需要連接到集群(沒有集群的需要先創建集群),可以參考文章尾部的幫助文檔配置kubectl連接集群。 ```shell ? ~ kubectl apply -f nginx-deployment-eni.yaml deployment.apps/nginx-deployment-eni created ? ~ kubectl apply -f nginx-service-eni.yaml service/nginx-service-eni configured ? ~ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deployment-eni-bb7544db8-6ljkm 1/1 Running 0 24s 172.17.160.191 172.17.0.3 <none> 1/1 nginx-deployment-eni-bb7544db8-xqqtv 1/1 Running 0 24s 172.17.160.190 172.17.0.46 <none> 1/1 nginx-deployment-eni-bb7544db8-zk2cx 1/1 Running 0 24s 172.17.160.189 172.17.0.9 <none> 1/1 ? ~ kubectl get service -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.187.252.1 <none> 443/TCP 6d4h <none> nginx-service-eni LoadBalancer 10.187.254.62 150.158.221.31 80:32693/TCP 6d1h app=nginx ```
看完上述內容,你們對TKE基于彈性網卡直連Pod的網絡負載均衡是怎樣的有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。