如前面的文章我們說了,kubernetes的服務發現是服務端發現模式。它有一個服務注冊中心,使用DNS作為服務的注冊表。每個集群都會運行一個DNS服務,默認是CoreDNS服務。每個服務都會在這個DNS中注冊。注冊的大致過程:
1、向kube-apiserver提交一個新服務對象的定義
2、創建服務對象,并分配它一個ClusterIP,保存服務對象數據到etcd中
3、DNS服務監聽kube-apiserver,一旦有新服務對象創建就創建一個從服務對象名稱映射到ClusterIP的域名記錄。服務就是不需要主動去DNS中注冊,靠DNS的控制器就能完成服務的自動注冊。
一旦注冊完成后,服務對象后面的Pod列表就會被更新。服務對象中的label selector字段與選擇器中定義的標簽相匹配的Pod就會納入當前服務對象的Pod列表中。服務對象的選擇控制器會持續掃描和服務對象的標簽相匹配的Pod,然后更新到EndPoint對象中。
在kubernetes中,Pod列表對應一個EndPoint對象,這個對象負責保存一個和服務標簽選擇器相配匹的Pod列表。
每個Pod都要知道集群DNS服務地址,Pod容器的/etc/resolv.conf文件都被配置為使用集群的DNS進行解析。
在kubernetes中的DNS服務查詢過程如下:
1、調用者向DNS服務發起域名(服務名稱)查詢,如果本地沒有緩存就會被提交到DNS服務,DNS服務返回對應的ClusterIP。ClusterIP是服務對象的IP地址,并不是具體提供服務的Pod的IP地址。
2、通過返回的ClusterIP訪問對應的Pod。kubernetes的每個節點(Node)上都有一個kube-proxy代理服務,這個代理會通過服務對象和Pod的對應關系創建iptables或IPVS路由規則,節點Node會基于這些規則將請求轉發到具體的Pod上。
順便提一下服務網格中邊車代理(sidecar proxy),流量會首先被這個代理劫持,這是通過修改iptables路由規則來做到這一點的。其次服務網格也會監聽集群內服務對象的變化情況,從而獲得最的服務地址。最后一點是關于負載均衡,服務網絡是基于服務對象而不是基于Pod的。它給服務對象前加上一層負載均衡,這樣才能實現基于服務層面的流量管理。