Kubernetes裏的Service究竟是如何工作的呢?

原創 半夏透心涼 [雲原生技術愛好者社區](javascript:void(0)😉 今天

“本文將爲你介紹Service在Kubernetes集羣中的價值和作用”

Service是Kubernetes接入層的一種抽象資源,它爲我們提供了一種固定的、統一的訪問接口地址和負載均衡能力,這時可能會想到,當時使用docker-compose的時候,不存在Service概念,不也運行起來了嗎?是的,在Kubernetes集羣內部Pod ip也是互通的,但是Pod的ip會經常因爲擴容、重建而導致客戶端訪問錯誤,pod訪問無法提供負載均衡的能力,而Service通過選擇一組Pod的label就直接可以訪問到Pod,而且可以使用萬年不變的域名,所以就選擇Service了。

1、Service是怎麼產生的,在集羣內部是如何存在的呢?

在kubernetes當中所謂的Service是kube-proxy生成iptables或ipvs規則,它會產生一組虛擬地址,在集羣環境下有效。Service不能直接到達Pod內部,中間會間隔EndPoints,這是一組ip和port的組合。默認類型是ClusterIP它僅能接收集羣中pod客戶端程序的訪問請求。這也是最常用的一種類型,另外還有NodePort、LoadBalancer、ExternalName。

2、iptables或ipvs,到底是iptables還是ipvs呢?

一個Service對象就是工作節點上的一些iptables或ipvs規則,用於將到達Service對象IP地址的流量調度轉發至相應的Endpoints對象指向的IP地址和端口之上。

這句話我們經常看到,如何理解呢?

Kubernetes1.1之前是基於userspace實現,這種模型之下,每次請求流量要先到達內核空間,經有套接字轉發到kube-proxy,然後再由它送回到內核空間,之後調度到後端pod之上,可以看出請求在用戶空間和內核空間來回轉發,效率必然不高。但是當pod無響應時,能夠自動重定向到其它pod。

在Kubernetes1.1版本開始引入iptables規則,Kubernetes1.2開始成爲默認類型。即在創建Service資源時,集羣上每個節點的kube-proxy都會收到通知,並且創建iptables規則,用於轉發到此Service ClusterIP的流量。工作TCP/IP的傳輸層,高效穩定。
但是這種方式有如下缺點:

1、iptables代理模型挑中的pod無響應時,不能自動重定向到集羣內部其它pod資源對象之上。

2、kube-proxy通過iptables處理Service和pod的交互,每產生一個計算節點或者產生大量的pod就需要產生相應大量的iptables規則,不難想象,這些iptables規則每次需要刷新匹配保證正確性,就需要佔用大量的CPU資源,所以基於iptables的Service實現就成了制約Kubernetes承載更多pod的瓶頸。

在Kubernetes1.11開始默認使用ipvs模型,在這種模型下kube-proxy會跟蹤APIServer上Service和endpoints對象變化,調用netlink創建ipvs規則,請求調度流量功能由ipvs實現,運行於netfilter之上的鉤子函數,具有流量轉發速度快,規則性能同步好的特點,支持衆多調度算法,剩下仍然由iptables完成。說到這裏我們就大概明白了iptables和ipvs的作用和關係了。

3、Kubernetes的服務發現是通過dns實現,那麼爲什麼會出現四種類型的服務暴露方式呢?

說到Service不得不介紹kubernetes網絡模型和通信方式

一個完整的Kubernetes集羣應該包含三層網絡,首先第一層是mater和node節點之間的網絡,這個網絡需要在部署kubernetes集羣之前配置完成;

第二層網絡是pod的網絡通過kubelet或者cni插件實現,用於pod之間或者內部的通信,集羣中的所有pod均處在同一個網絡平面空間內,可以直接通信;

第三層網絡是Service資源的網絡,是一個虛擬網絡,用於爲Kubernetes集羣配置IP地址,但此地址並不配置於任何主機或者容器的網絡接口之上,而是通過kubeproxy配置爲iptables規則,將發往該地址的所有流量調度至後端的pod之上。

通信方式分爲以下四種:

  • 同一個pod的內部通信;

  • 各個pod彼此通信;

  • pod和service的通信;

  • 集羣外部流向service的通信。

所以Service爲了滿足這些通信方式就出現瞭如下類型:

ClusterIP:爲集羣內部ip地址暴露服務,僅在集羣內可達,外部ip無法訪問,默認Service類型;

NodePort:這種類型建立在clusterIp之上,爲節點的IP地址暴NodePort服務,外部節點可以通過NodeIP:NodePort直接訪問;

LoadBalancer:這種類型構建在NodePort之上,它可以關聯到集羣外部的某個負載均衡設備。Kubernetes沒有爲私有化集羣提供LoadBalancer的支持。如果在私有化集羣使用需要自建負載均衡器;

ExternalName:其通過將Service映射至由externalName字段的內容指定的主機名來暴露服務,此主機名需要被DNS服務解析至CNAME類型的記錄。這句話怎麼理解呢?

舉個例子,你所有的服務都在集羣內部,但是你有個數據庫是mongodb,沒有實現容器化,更沒有部署在Kubernetes內部,當然你可以通過在ConfigMap中添加配置訪問這個外部服務,但是當你的環境發生變化,比如從開發環境和生產環境的數據地址不同,這個時候你需要修改和重建ConfigMap。

這個時候可以使用Kubernetes ExternalName內置服務發現機制運用於集羣外部運行的服務,像使用集羣內的服務一樣使用外部服務!通過這種方式,您可以在開發環境和生產環境中實現相同的功能,如果您最終將服務移入集羣內,則不需要更改任何代碼和配置。

kind: Service
apiVersion: v1
metadata:
 name: mongo
spec:
 type: ExternalName
 externalName: mango123456.com

你只需要訪問:mongodb://:@mongo:就可以自動訪問外部服務。

4、Service本身有端口、Pod也有端口、容器也有端口,之間有什麼關係呢?

containerPort:一個信息性數據,爲集羣提供一個可以快速瞭解相關pod可以訪問端口的途徑,而且顯式指定容器端口,無論你是否指定都不影響其他節點上的客戶端pod對其進行訪問;

port:服務提供端口,用於kubernetes集羣內部服務訪問;

targetPort:pod目標端口,如果不設置使用默認port端口,port和nodePort的數據通過這個端口進入到Pod內部,Pod裏面的containers的端口映射到這個端口,提供服務;

nodePort:Kubernetes集羣外部用戶訪問端口;

5、總結
本文主要總結了Service的工作原理和機制。只有明白Service這些概念,才能靈活使用Service,當我們服務出現故障的時候,根據它的原理去分析問題到底出在什麼地方,進而快速解決問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章