以我的經驗來講,理解Kubernetes集群服務的概念,是比較不容易的一件事情。尤其是當我們基于似是而非的理解,去排查服務相關問題的時候,會非常不順利。
這體現在,對于新手來說,ping不通服務的IP地址這樣基礎的問題,都很難理解;而就算對經驗很豐富的工程師來說,看懂服務相關的iptables配置,也是有相當的挑戰的。
今天這篇文章,我來深入解釋一下Kubernetes集群服務的原理與實現,便于大家理解。
Kubernetes集群服務的本質是什么
概念上來講,Kubernetes集群的服務,域名購買,其實就是負載均衡、或反向代理。這跟阿里云的負載均衡產品,有很多類似的地方。和負載均衡一樣,服務有它的IP地址以及前端端口;服務后邊會掛載多個容器組Pod作為其“后端服務器”,這些“后端服務器”有自己的IP以及監聽端口。
當這樣的負載均衡和后端的架構,與Kubernetes集群結合的時候,我們可以想到的最直觀的實現方式,就是集群中某一個節點專門做負載均衡(類似LVS)的角色,而其他節點則用來負載后端容器組。
這樣的實現方法,有一個巨大的缺陷,就是單點問題。Kubernetes集群是Google多年來自動化運維實踐的結晶,這樣的實現顯然與其智能運維的哲學相背離的。
自帶通信員
邊車模式(Sidecar)是微服務領域的核心概念。邊車模式,換一句通俗一點的說法,就是自帶通信員。熟悉服務網格的同學肯定對這個很熟悉了。但是可能比較少人注意到,其實Kubernetes集群原始服務的實現,也是基于Sidecar模式的。
在Kubernetes集群中,服務的實現,實際上是為每一個集群節點上,部署了一個反向代理Sidecar。而所有對集群服務的訪問,都會被節點上的反向代理轉換成對服務后端容器組的訪問。基本上來說,節點和這些Sidecar的關系如下圖所示。
把服務照進現實
前邊兩節,我們看到了,Kubernetes集群的服務,本質上是負載均衡,即反向代理;同時我們知道了,在實際實現中,這個反向代理,并不是部署在集群某一個節點上,而是作為集群節點的邊車,部署在每個節點上的。
在這里把服務照進反向代理這個現實的,是Kubernetes集群的一個控制器,即kube-proxy。關于Kubernetes集群控制器的原理,請參考我另外一篇關于控制器的文章。簡單來說,kube-proxy作為部署在集群節點上的控制器,它們通過集群API Server監聽著集群狀態變化。當有新的服務被創建的時候,kube-proxy則會把集群服務的狀態、屬性,翻譯成反向代理的配置。
那剩下的問題,就是反向代理,即上圖中Proxy的實現。
一種實現
Kubernetes集群節點實現服務反向代理的方法,目前主要有三種,即userspace、iptables以及IPVS。今天我們只深入分析iptables的方式,底層網絡基于阿里云Flannel集群網絡。
過濾器框架
現在,我們來設想一種場景。我們有一個屋子。這個屋子有一個入水管和出水管。從入水管進入的水,是不能直接飲用的,因為有雜質。而我們期望,從出水管流出的水,可以直接飲用。為了達到目的,我們切開水管,在中間加一個雜質過濾器。