k8s 中的 service 如何找到綁定的 Pod 以及如何實現 Pod 負載均衡( 三 )


文章插圖
ipvs 支持三種負載均衡模式:
1、DR模式(Direct Routing);
2、NAT 模式(Network Address Translation);
3、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/從不排隊
kernelspacekernelspace 模式是 windows 上的代理模式,這里不展開討論了
服務發現service 的 endpoints 解決了容器發現問題,但是不提前知道 service 的 Cluster IP , 就無法知道 service 服務了 。Kubernetes 支持兩種基本的服務發現模式 —— 環境變量和 DNS 。
環境變量當一個 pod 創建完成之后,kubelet 會在該 pod 中注冊該集群已經創建的所有 service 相關的環境變量,但是需要注意的是,在 service 創建之前的所有 pod 是不會注冊該環境變量的 , 所以在平時使用時,建議通過 DNS 的方式進行 service 之間的服務發現 。
舉個例子,一個名稱為 redis-primary 的 Service 暴露了 TCP 端口 6379,同時給它分配了 Cluster IP 地址 10.0.0.11 , 這個 Service 生成了如下環境變量:
REDIS_PRIMARY_SERVICE_HOST=10.0.0.11REDIS_PRIMARY_SERVICE_PORT=6379REDIS_PRIMARY_PORT=tcp://10.0.0.11:6379REDIS_PRIMARY_PORT_6379_TCP=tcp://10.0.0.11:6379REDIS_PRIMARY_PORT_6379_TCP_PROTO=tcpREDIS_PRIMARY_PORT_6379_TCP_PORT=6379REDIS_PRIMARY_PORT_6379_TCP_ADDR=10.0.0.11DNS可以在集群中部署 CoreDNS 服務(舊版本的 kubernetes 群使用的是 kubeDNS) ,  來達到集群內部的 pod 通過DNS 的方式進行集群內部各個服務之間的通訊 。
當前 kubernetes 集群默認使用 CoreDNS 作為默認的 DNS 服務,主要原因是 CoreDNS 是基于 Plugin 的方式進行擴展的 , 簡單 , 靈活,并且不完全被Kubernetes所捆綁 。
同時 k8s 中也建議使用 DNS 來做服務發現 。
Kubernetes DNS 服務器是唯一的一種能夠訪問 ExternalName 類型的 Service 的方式 。
總結k8s 中一般使用 Service 為 Pod 對象提供一個固定、統一的訪問接口及負載均衡的能力;
k8s 中的負載均衡主要借助于 endpoint 和 kube-proxy 來實現;
endpoint 是 k8s 集群中的一個資源對象 , 存儲在 etcd 中,用來記錄一個 service 對應的所有 pod 的訪問地址 , 當一個 service 關聯的 pod 被刪除,更新,新增 , 對應的 endpoint 資源都會更新;
kube-proxy 是 Kubernetes 的核心組件,部署在每個 Node 節點上,它是實現 Kubernetes Service 的通信與負載均衡機制的重要組件; kube-proxy 負責為 Pod 創建代理服務,從 apiserver 獲取所有 server 信息 , 并根據 server 信息創建代理服務,實現server到Pod的請求路由和轉發,從而實現K8s層級的虛擬轉發網絡;
kube-proxy 的路由轉發規則是通過其后端的代理模塊實現的,其中 kube-proxy 的代理模塊目前有四種實現方案,userspace、iptables、ipvs、kernelspace ;
service 的 endpoints 和 kube-proxy 解決了容器的發現和負載均衡的問題 , 但是 service 服務如何被內部的服務找到呢,Kubernetes 支持兩種基本的服務發現模式 —— 環境變量和 DNS;
其中 k8s 中推薦使用 DNS 來做 service 的服務發現 , 當前 kubernetes 集群默認使用 CoreDNS 作為默認的 DNS 服務,主要原因是 CoreDNS 是基于 Plugin 的方式進行擴展的,簡單,靈活,并且不完全被Kubernetes所捆綁 。
參考【kubernetes service 原理解析】https://zhuanlan.zhihu.com/p/111244353【service selector】https://blog.csdn.net/luanpeng825485697/article/details/84296765【一文看懂 Kube-proxy】https://zhuanlan.zhihu.com/p/337806843【Kubernetes 【網絡組件】kube-proxy使用詳解】https://blog.csdn.net/xixihahalelehehe/article/details/115370095【Service】https://jimmysong.io/kubernetes-handbook/concepts/service.html【Service】https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/【k8s 中的 service 如何找到綁定的 Pod 以及如何實現 Pod 負載均衡】https://boilingfrog.github.io/2022/10/16/k8s中的service如何找到綁定的Pod以及如何實現Pod負載均衡/

推薦閱讀