Kubernetes裏的Service到底是如何工做的呢?

"本文將爲你介紹Service在Kubernetes集羣中的價值和做用"

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

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

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

二、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的傳輸層,高效穩定。
可是這種方式有以下缺點:
一、iptables代理模型挑中的pod無響應時,不能自動重定向到集羣內部其它pod資源對象之上。
二、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的做用和關係了。

三、Kubernetes的服務發現是經過dns實現,那麼爲何會出現四種類型的服務暴露方式呢?
說到Service不得不介紹kubernetes網絡模型和通訊方式

一個完整的Kubernetes集羣應該包含三層網絡,首先第一層是mater和node節點之間的網絡,這個網絡須要在部署kubernetes集羣以前配置完成;
第二層網絡是pod的網絡經過kubelet或者cni插件實現,用於pod之間或者內部的通訊,集羣中的全部pod均處在同一個網絡平面空間內,能夠直接通訊;
第三層網絡是Service資源的網絡,是一個虛擬網絡,用於爲Kubernetes集羣配置IP地址,但此地址並不配置於任何主機或者容器的網絡接口之上,而是經過kubeproxy配置爲iptables規則,將發往該地址的全部流量調度至後端的pod之上。

通訊方式分爲如下四種:
  • 同一個pod的內部通訊;
    java

  • 各個pod彼此通訊;
    node

  • pod和service的通訊;
    web

  • 集羣外部流向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: ServiceapiVersion: v1metadata: name: mongospec: type: ExternalName externalName: mango123456.com
你只須要訪問:mongodb://<dbuser>:<dbpassword>@mongo:<port>就能夠自動訪問外部服務。

四、Service自己有端口、Pod也有端口、容器也有端口,之間有什麼關係呢?

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

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

targetPort:pod目標端口,若是不設置使用默認port端口,port和nodePort的數據經過這個端口進入到Pod內部,Pod裏面的containers的端口映射到這個端口,提供服務;
nodePort:Kubernetes集羣外部用戶訪問端口;

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

Kubernetes排障指南mongodb

從零搭建Kubernetes下的nignx和tomcat
docker

Kubernetes中如何使用ClusterDNS進行服務發現?數據庫

Kubernetes入門培訓(內含PPT)
後端

從Ice到Kubernetes容器技術,微服務架構經歷了什麼?
api



原創不易,隨手關注或者」在看「,誠摯感謝!
tomcat

本文分享自微信公衆號 - 雲原生技術愛好者社區(programmer_java)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索