k8s 服務代理和發現
今天主要學習一下 k8s 的Service
,之前的文章中有介紹過 k8s 內服務訪問的方式,但是自己也沒有特別的去了解具體的實現方式,今天就專門再來學習下Service
這個非常重要的資源。今天主要是學習官方的文檔,文檔地址:Service。另外我還是覺得中文文檔翻譯之後不太好理解,所以最好我覺得還是看英文文檔。
k8s 中的Service
是一個抽象的概念,它定義了一組邏輯的Pod
以及訪問這些Pod
的策略(有時這種模式被稱作微服務)。直白點講Service
本身並不提供所謂的服務
,它只是告訴你怎麼訪問你想要訪問的服務
。通常情況下Service
是通過Selector
來定位到目標Pod
的,當然你也可以通過創建相應的Endpoints
定位到具體的服務。
1、虛擬 IP 和服務代理
在 k8s 集羣中的每個節點上都會運行着一個kube-proxy
,由kube-proxy
負責爲非ExternalName
類型的Service
實現一種虛擬 IP。
之所以 k8s 選擇代理模式將入站流量轉發到後端,而不是通過配置多個 A 值(ipv6 爲 AAAA)0 的DNS
記錄,然後依賴輪詢名稱解析。主要有幾點原因:
1、一直以來DNS
都不遵守數據的 TTL(Time to live),即使在數據過期後依然會進行緩存;
2、對於某些應用只進行一次DNS
查找,但是結果卻會永久緩存;
3、即使應用和庫進行了適當的重新解析,DNS 記錄上的較低的 TTL 值低或零值可能會給DNS
帶來高負載,從而使管理變得困難。
1、用戶空間代理模式
這種模式下kube-proxy
會觀察 k8s 控制節點對Service
對象和 Endpoints
對象的添加和刪除操作。對於每一個Service
,kube-proxy
都會在本地的節點上打開一個隨機端口,任何連接到這個 “代理端口” 的請求,都會被轉發到該Service
對應的後端Pods
中的某一個上面。具體使用哪一個Pod
,是kube-proxy
基於該Service
的設置項SessionAffinity
來確定的。
最後,kube-proxy
會配置iptables
規則,捕獲到達該Service
的clusterIP
(是虛擬 IP)和 port
的請求,並重定向到代理端口,然後由代理端口再代理請求到後端Pod
。
用戶空間模式下的kube-proxy
默認通過輪轉算法選擇後端。
用戶空間模式見下圖:
圖 - 1.png
2、iptables 代理模式
和用戶空間代理模式,這種模式下kube-proxy
也會觀察 k8s 控制節點對Service
對象和Endpoints
對象的添加和刪除操作。不同的是對每個Service
,kube-proxy
會通過配置iptables
規則,從而捕獲到達該Service
的clusterIP
和port
的請求,然後將請求重定向到該Service
後端集合中的某個上面。對於每個Endpoints
對象,kube-proxy
也會配置 iptables
規則,這個規則會選擇一個後端Pod
。
在iptables
模式下kube-proxy
默認會隨機選擇一個後端。
使用iptables
處理流量具有較低的系統開銷,因爲流量由 Linux netfilter 處理,而無需在用戶空間和內核空間之間切換,而且這種方法也可能更可靠。
如果kube-proxy
在iptables
模式下運行,kube-proxy
隨機選擇的Pod
沒有響應,那麼此次連接失敗。這點與用戶空間模式不同。在用戶空間模式情況下,kube-proxy
如果檢測到與第一個Pod
的連接失敗,那麼它會自動使用其他後端Pod
進行重試。
我們可以使用Pod
readiness probes 驗證後端Pod
是否就緒以便iptables
模式下的kube-proxy
僅看到狀態正常且就緒的後端。readiness probes
在滾動發佈的時候也會用到。
iptables
代理模式如下圖:
圖 - 2.png
3、IPVS 代理模式
在ipvs
模式下kube-proxy
觀察 k8s 的Services
和Endpoints
,調用netlink
接口相應地創建IPVS
規則,並定期將IPVS
規則與 k8s 的Services
和Endpoints
同步。該控制循環可確保IPVS
狀態與所需狀態匹配。訪問Service
時,IPVS
將流量定向到後端Pod
之一。
IPVS
代理模式基於類似於iptables
模式的netfilter
鉤子函數, 但是使用哈希表作爲基礎數據結構,並且在內核空間中工作。這意味着與iptables
模式下的kube-proxy
相比,IPVS
模式下的kube-proxy
重定向通信的延遲要短,並且在同步代理規則時具有更好的性能。與其他代理模式相比IPVS
模式還支持更高的網絡流量吞吐量。
IPVS
提供了更多選項來平衡到達後端Pod
的流量。這些是:
rr:輪替(Round-Robin)
lc:最少鏈接(Least Connection),即打開鏈接數量最少者優先
dh:目標地址哈希(Destination Hashing)
sh:源地址哈希(Source Hashing)
sed:最短預期延遲(Shortest Expected Delay)
nq:從不排隊(Never Queue)
說明:
要想kube-proxy
使用IPVS
模式,必須在啓動kube-proxy
之前保證IPVS
在節點上可用。因爲當kube-proxy
以IPVS
代理模式啓動時,它將驗證IPVS
內核模塊是否可用, 如果未檢測到IPVS
內核模塊,則kube-proxy
將會使用iptables
代理模式運行。
IPVS
代理模式如下圖:
圖 - 3.png
在這些代理模式中,在客戶端不瞭解 k8s 或Service
或Pod
的任何信息的情況下,請求到Service
的ip:port
的流量最終被代理到具體的後端。
如果要確保每次都將來自特定客戶端的連接傳遞到同一Pod
, 則可以通過將service.spec.sessionAffinity
設置爲ClientIP
(默認值是None
),來基於客戶端的 IP 地址選擇會話關聯。你還可以通過適當設置 service.spec.sessionAffinityConfig.clientIP.timeoutSeconds
來設置最大會話停留時間(默認值爲 10800 秒,即 3 小時)。
2、服務發現
k8s 支持兩種基本的服務發現模式——環境變量和DNS
。
1、環境變量
當Pod
運行在Node
上,kubelet
會爲每個存活的Service
添加一組環境變量。它同時支持 Docker links compatible 變量 (見 makeLinkVariables) 和簡單的 {SVCNAME}_SERVICE_HOST
和 {SVCNAME}_SERVICE_PORT
變量。這裏Service
的名稱需大寫,橫線被轉換成下劃線。
舉個例子,一個名稱爲 redis-master
的Service
暴露了TCP
端口6379
, 同時給它分配了ClusterIP
地址 10.0.0.11,這個Service
生成了如下環境變量:
1REDIS_MASTER_SERVICE_HOST=10.0.0.11
2REDIS_MASTER_SERVICE_PORT=6379
3REDIS_MASTER_PORT=tcp://10.0.0.11:6379
4REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
5REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
6REDIS_MASTER_PORT_6379_TCP_PORT=6379
7REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11
但是這個環境變量只針對同Namespace
下的Service
,比如我在namespace A
下的Pod
的環境變量中是查看到namespace B
下的Service
的相關信息的。
2、DNS
通常來講我們的 k8s 集羣都會安裝相關的網絡插件,比如Calico、Flannel
等來設置 DNS 服務。
支持集羣的DNS
服務器(例如CoreDNS
)會觀察 k8s API 中的新Service
,併爲每個服務創建一組DNS
記錄。如果在整個集羣中都啓用了DNS
,則所有Pod
都應該能夠通過其DNS
名稱自動解析服務。
例如,如果你在命名空間 my-ns
中有一個名爲my-service
的服務,則 k8s 控制面板和DNS
服務共同爲my-service.my-ns
創建DNS
記錄。my-ns
命名空間中的Pod
能夠通過名稱my-service
來找到服務(這裏可以直接通過環境變量獲取my-service
的clusterIp
和port
等),當然也可以通過my-service.my-ns
來定位到具體的cluserIp
。
其他命名空間中的Pod
必須將名稱限定爲my-service.my-ns
。這個名稱將解析爲服務的clusterIP
。
k8s 還支持命名端口的DNS SRV
記錄。如果my-service.my-ns
服務具有名爲http
的端口,且協議設置爲 TCP
,則可以對_http._tcp.my-service.my-ns
執行DNS SRV
查詢,以發現該服務http
的端口號以及IP
地址。
k8s DNS
服務器是唯一的一種能夠訪問ExternalName
類型的Service
的方式。更多關於ExternalName
信息可以查看 DNS Pod 和 Service。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/oJxoB3cORf0Swi6vTYEdvg