1. 程式人生 > 其它 >kubernetes service 原理解析

kubernetes service 原理解析

為什麼需要 service

在 kubernetes 中,當建立帶有多個副本的 deployment 時,kubernetes 會創建出多個 pod,此時即一個服務後端有多個容器,那麼在 kubernetes 中負載均衡怎麼做,容器漂移後 ip 也會發生變化,如何做服務發現以及會話保持?這就是 service 的作用,service 是一組具有相同 label pod 集合的抽象,叢集內外的各個服務可以通過 service 進行互相通訊,當建立一個 service 物件時也會對應建立一個 endpoint 物件,endpoint 是用來做容器發現的,service 只是將多個 pod 進行關聯,實際的路由轉發都是由 kubernetes 中的 kube-proxy 元件來實現,因此,service 必須結合 kube-proxy 使用,kube-proxy 元件可以執行在 kubernetes 叢集中的每一個節點上也可以只執行在單獨的幾個節點上,其會根據 service 和 endpoints 的變動來改變節點上 iptables 或者 ipvs 中儲存的路由規則。

service 的工作原理

endpoints controller 是負責生成和維護所有 endpoints 物件的控制器,監聽 service 和對應 pod 的變化,更新對應 service 的 endpoints 物件。當用戶建立 service 後 endpoints controller 會監聽 pod 的狀態,當 pod 處於 running 且準備就緒時,endpoints controller 會將 pod ip 記錄到 endpoints 物件中,因此,service 的容器發現是通過 endpoints 來實現的。而 kube-proxy 會監聽 service 和 endpoints 的更新並呼叫其代理模組在主機上重新整理路由轉發規則。

service 的負載均衡

上文已經提到 service 實際的路由轉發都是由 kube-proxy 元件來實現的,service 僅以一種 VIP(ClusterIP) 的形式存在,kube-proxy 主要實現了叢集內部從 pod 到 service 和叢集外部從 nodePort 到 service 的訪問,kube-proxy 的路由轉發規則是通過其後端的代理模組實現的,kube-proxy 的代理模組目前有四種實現方案,userspace、iptables、ipvs、kernelspace,其發展歷程如下所示:

  • kubernetes v1.0:services 僅是一個“4層”代理,代理模組只有 userspace
  • kubernetes v1.1:Ingress API 出現,其代理“7層”服務,並且增加了 iptables 代理模組
  • kubernetes v1.2:iptables 成為預設代理模式
  • kubernetes v1.8:引入 ipvs 代理模組
  • kubernetes v1.9:ipvs 代理模組成為 beta 版本
  • kubernetes v1.11:ipvs 代理模式 GA

在每種模式下都有自己的負載均衡策略,下文會詳解介紹。

userspace 模式

在 userspace 模式下,訪問服務的請求到達節點後首先進入核心 iptables,然後回到使用者空間,由 kube-proxy 轉發到後端的 pod,這樣流量從使用者空間進出核心帶來的效能損耗是不可接受的,所以也就有了 iptables 模式。

為什麼 userspace 模式要建立 iptables 規則,因為 kube-proxy 監聽的埠在使用者空間,這個埠不是服務的訪問埠也不是服務的 nodePort,因此需要一層 iptables 把訪問服務的連線重定向給 kube-proxy 服務。

iptables 模式

iptables 模式是目前預設的代理方式,基於 netfilter 實現。當客戶端請求 service 的 ClusterIP 時,根據 iptables 規則路由到各 pod 上,iptables 使用 DNAT 來完成轉發,其採用了隨機數實現負載均衡。

iptables 模式與 userspace 模式最大的區別在於,iptables 模組使用 DNAT 模組實現了 service 入口地址到 pod 實際地址的轉換,免去了一次核心態到使用者態的切換,另一個與 userspace 代理模式不同的是,如果 iptables 代理最初選擇的那個 pod 沒有響應,它不會自動重試其他 pod。

iptables 模式最主要的問題是在 service 數量大的時候會產生太多的 iptables 規則,使用非增量式更新會引入一定的時延,大規模情況下有明顯的效能問題。

ipvs 模式

當叢集規模比較大時,iptables 規則重新整理會非常慢,難以支援大規模叢集,因其底層路由表的實現是連結串列,對路由規則的增刪改查都要涉及遍歷一次連結串列,ipvs 的問世正是解決此問題的,ipvs 是 LVS 的負載均衡模組,與 iptables 比較像的是,ipvs 的實現雖然也基於 netfilter 的鉤子函式,但是它卻使用雜湊表作為底層的資料結構並且工作在核心態,也就是說 ipvs 在重定向流量和同步代理規則有著更好的效能,幾乎允許無限的規模擴張。

ipvs 支援三種負載均衡模式:DR模式(Direct Routing)、NAT 模式(Network Address Translation)、Tunneling(也稱 ipip 模式)。三種模式中只有 NAT 支援埠對映,所以 ipvs 使用 NAT 模式。linux 核心原生的 ipvs 只支援 DNAT,當在資料包過濾,SNAT 和支援 NodePort 型別的服務這幾個場景中ipvs 還是會使用 iptables。

此外,ipvs 也支援更多的負載均衡演算法,例如:

  • rr:round-robin/輪詢
  • lc:least connection/最少連線
  • dh:destination hashing/目標雜湊
  • sh:source hashing/源雜湊
  • sed:shortest expected delay/預計延遲時間最短
  • nq:never queue/從不排隊

userspace、iptables、ipvs 三種模式中預設的負載均衡策略都是通過 round-robin 演算法來選擇後端 pod 的,在 service 中可以通過設定 service.spec.sessionAffinity 的值實現基於客戶端 ip 的會話親和性,service.spec.sessionAffinity 的值預設為"None",可以設定為 "ClientIP",此外也可以使用 service.spec.sessionAffinityConfig.clientIP.timeoutSeconds 設定會話保持時間。kernelspace 主要是在 windows 下使用的,本文暫且不談。

轉載自:https://blog.csdn.net/liukuan73/article/details/82585732

https://zhuanlan.zhihu.com/p/111244353