天天看點

[Kubernetes]如何通過服務名發現服務? kube-proxy 和 kube-dns 原了解密

前言

在這裡,你将了解 Kubernetes 叢集如何實作通過服務名,進行服務發現,負載均衡,調用後端服務。

這裡,我們以服務名為ticknet為例,假設我們要通路内部服務ticknet的某個http接口,則,我們的請求連結格式可以是:http://ticknet/get/user/10000

1. kube-dns服務發現原理

    DNS:我們非常熟悉且最簡單的一種方式,跟域名和IP映射的原理類似,我們可以将服務域名名稱和一到多個機器IP進行關聯或者是一個負載均衡器(指向服負載均衡好處是可以避免失效DNS條目問題)。DNS的服務發現方式最大的優點就是它是一種大家熟知的标準形式,技術支援性好。缺點就是當服務節點的啟動和銷毀變得更加動态時DNS更新條目很難做到高可用和實時性。

K8S選擇的是DNS作服務發現,除此之外,感興趣還可以了解Zookeeper、Consoul、Doozerd、Eureka、Etcd

注意:Etcd在k8s叢集中的作用是用于儲存叢集所有的網絡配置和對象的狀态資訊。如果etcd需要實作負載均衡,需要與第三方工具結合,常與Registrator(通過檢查容器線上或停止來完成相關服務資料的注冊和更新)和Confd(為輕量級的配置管理工具通過儲存在Etcd中的資料來保持配置檔案的最新狀态)結合。

a. kube-dns原理

    kube-dns組成

[Kubernetes]如何通過服務名發現服務? kube-proxy 和 kube-dns 原了解密

    etcd存儲SkyDNS需要的各種資料;kube2sky是資料寫入方;skydns是資料讀入方;execheathz是輔助容器,有健康檢查作用。

    域名格式

    kube-dns支援的域名格式,具體為:<service_name>.<namespace>.svc.<cluster_domain>。

b. K8S自動為容器配置域名解析

進入K8S叢集某個Pod容器,我們通過指令行cat /etc/resolv.conf,得到:

nameserver 172.22.0.10

search default.svc.cluster.local svc.cluster.local cluster.local

options ndots:5

感興趣的可以在網上查找一些resolv.conf的資料來了解具體的含義。之是以能夠通過Service名稱和Namespace就能通路Service,就是因為search配置的規則。

舉個栗子:我們有服務名ticknet,則其服務名(Service)對應的完整域名就是ticknet.default.svc.cluster.local。看到這裡,相信很多人會有疑問,既然完整域名是這樣的,那為什麼在Pod中隻通過Service名稱和Namespace就能通路Service呢?下面kube-proxy會告訴你。

c. 通過域名配置解析到該服務的IP位址

在解析域名(此時域名我叫“短域名”)時會自動拼接成完整域名去查詢DNS。查詢到DNS後,我們查找到該DNS的A記錄IP位址,然後轉發請求該IP位址。

該IP位址是我們服務名的IP位址,也可以說是該服務的叢集IP位址,也可以說是該服務的網關IP。

但是我們是如何從服務IP請求轉發到其“内部”的Pod呢?這就是接下來要講的負載均衡了。

2. kube-proxy實作負載均衡

    service是一組pod的服務抽象,相當于一組pod的LB,負責将請求分發給對應的pod。service會為這個LB提供一個IP,一般稱為cluster IP。

kube-proxy的作用主要是負責service的實作,具體來說,就是實作了内部從pod到service和外部的從node port向service的通路。

舉個栗子:我們有服務名ticknet,其下,我們運作了兩個執行個體(pod)。那麼kube-proxy的作用,就是可以将對服務 ticknet的請求轉發到其下任一個執行個體容器上。

當然,我們可以通過kubectl logs <Pod Name>來檢視這兩個Pod的通路日志來确認是否真的負載均衡了。

a.kube-proxy負載均衡的方式

    Iptables模式(目前的預設模式),它支援相當複雜的基于規則的IP管理。在核心中通過iptables的NAT實作本地轉發和負載均衡。預設負載均衡方案是随機轉發。在大規模試用下存在性能問題。。

[Kubernetes]如何通過服務名發現服務? kube-proxy 和 kube-dns 原了解密
[Kubernetes]如何通過服務名發現服務? kube-proxy 和 kube-dns 原了解密

    Userspace模式。這種模式時最早的,不過已經不推薦使用了,它使用循環的負載配置設定,在IP清單上來配置設定下一個可以使用的pod,然後更換(或置換)該清單。效率低,因為需要在核心空間和使用者空間轉換。

    Ipvs模式。可選方案,如果核心支援且使用者指定那麼kube-proxy将使用這種模式。在早期版本的K8S中不支援。

b. iptables實作負載均衡

    Kubernetes通過在目标node的iptables中的nat表的PREROUTING和POSTROUTING鍊中建立一系列的自定義鍊 (這些自定義鍊主要是“KUBE-SERVICES”鍊、“KUBE-POSTROUTING”鍊、每個服務所對應的“KUBE-SVC-XXXXXXXXXXXXXXXX”鍊和“KUBE-SEP-XXXXXXXXXXXXXXXX”鍊),然後通過這些自定義鍊對流經到該node的資料包做DNAT和SNAT操作以實作路由、負載均衡和位址轉換。

先來看一下iptables。通過指令過濾iptables逐條分析請求如何通過iptables實作負載均衡

首先通過通過ticknet端口1081通路,則會進入到以下鍊: (指令iptables -S -t nat | grep ticknet)

-A KUBE-SERVICES ! -s 172.21.0.0/16 -d 172.22.205.23/32 -p tcp -m comment --comment "default/ticknet:1081tcp10812 cluster IP" -m tcp --dport 1081 -j KUBE-MARK-MASQ

-A KUBE-SERVICES -d 172.22.205.23/32 -p tcp -m comment --comment "default/ticknet:1081tcp10812 cluster IP" -m tcp --dport 1081 -j KUBE-SVC-YEIPYIOWWP7C4WPS

然後進一步跳轉到KUBE-SEP-MTUPTVFIZED52LUP的鍊:(指令iptables -S -t nat | grep KUBE-SEP-MTUPTVFIZED52LUP)

-A KUBE-SVC-YEIPYIOWWP7C4WPS -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-MTUPTVFIZED52LUP

-A KUBE-SVC-YEIPYIOWWP7C4WPS -j KUBE-SEP-UEPUCSEE5ENLOTNT

這裡利用了iptables的–probability的特性,使連接配接有50%的機率分别進入兩個鍊 KUBE-SEP-MTUPTVFIZED52LUP 和 KUBE-SEP-UEPUCSEE5ENLOTNT 。

以 KUBE-SEP-MTUPTVFIZED52LUP 為例,發現就是将請求通過DNAT發送到172.21.192.6的1081端口:(指令iptables -S -t nat | grep KUBE-SEP-MTUPTVFIZED52LUP)

-A KUBE-SEP-MTUPTVFIZED52LUP -s 172.21.192.6/32 -j KUBE-MARK-MASQ

-A KUBE-SEP-MTUPTVFIZED52LUP -p tcp -m tcp -j DNAT --to-destination 172.21.192.6:1081

分析完nodePort的工作方式,接下裡說一下clusterIP的通路方式。

對于直接通路cluster IP(10.254.162.44)的3306端口會直接跳轉到KUBE-SVC-YEIPYIOWWP7C4WPS。

-A KUBE-SERVICES -d 172.22.205.23/32 -p tcp -m comment --comment "tce-sandbox/tdea-test:1081tcp10812 cluster IP" -m tcp --dport 1081 -j KUBE-SVC-YEIPYIOWWP7C4WPS

接下來的跳轉方式同上文,這裡就不再贅述了。

是以我們通過iptables的負載均衡轉發,預設是随機的方式

3. 總結

小夥伴們再看到這個圖,應該很好了解了。

[Kubernetes]如何通過服務名發現服務? kube-proxy 和 kube-dns 原了解密
[Kubernetes]如何通過服務名發現服務? kube-proxy 和 kube-dns 原了解密
[Kubernetes]如何通過服務名發現服務? kube-proxy 和 kube-dns 原了解密

繼續閱讀