【編者的話】PaaS的抽象邏輯使得其網絡模型與IaaS有所不一樣,本次經過重點說明Kubernetes和Docker的網絡,從而來探究PaaS的網絡模型設計。docker
概念上來講,IaaS是基礎架構即服務,PaaS是平臺即服務。從服務化角度來講二者對於網絡的需求有共同點:微信
實現上來講,IaaS是VM管理,PaaS是容器編排,二者的網絡也會有些不一樣:網絡
以上部分咱們討論了PaaS網絡需求,總結來講PaaS須要解決宿主機的網絡隔離和環境變動後的訪問一致性問題,而後在靈活性上須要更加註重,私有云的定位能夠減小由於安全和隔離的代價,保證高性能。架構
網絡隔離最基本問題就是要解決端口衝突,一種思路是容器經過端口映射訪問,宿主機的端口由系統分配避免端口衝突,這種方式對使用的便利性是有意義的,但並不理想,由於須要對各類端口進行映射,這會限制宿主機的能力,在容器編排上也增長了複雜度。負載均衡
端口是個稀缺資源,這就須要解決端口衝突和動態分配端口問題。這不但使調度複雜化,並且應用程序的配置也將變得複雜,具體表現爲端口衝突、重用和耗盡。分佈式
NAT將地址空間分段的作法引入了額外的複雜度。好比容器中應用所見的IP並非對外暴露的IP,由於網絡隔離,容器中的應用實際上只能檢測到容器的IP,可是須要對外宣稱的則是宿主機的IP,這種信息的不對稱將帶來諸如破壞自注冊機制等問題。工具
因此就要引入一層網絡虛擬層來解決網絡隔離,如今說的比較多的大二層網絡,L2 over L3,好比OVS、Flannel、Calico等等。性能
一個通用方案來講經過代理層提供不變的訪問入口,像OpenStack的網絡節點就是一個L3(IP)的訪問入口,而PaaS更多的是提供L4(TCP、UDP)和L7(HTTP)的訪問,L4比較流行的開源方案有LVS,L7的是Nginx和Haproxy。優化
所以PaaS的網絡結構有:
Kubernete Docker做爲目前最流行的開源PaaS實現,經過其實現細節能夠更加理解PaaS的網絡模型實踐。
Docker使用Linux橋接,在宿主機虛擬一個Docker容器網橋(docker0),Docker啓動一個容器時會根據Docker網橋的網段分配給容器一個IP地址,稱爲Container-IP,同時Docker網橋是每一個容器的默認網關。由於在同一宿主機內的容器都接入同一個網橋,這樣容器之間就可以經過容器的Container-IP直接通訊。
Kubernetes中Pod是容器的集合,Pod包含的容器都運行在同一個宿主機上,這些容器將擁有一樣的網絡空間,容器之間可以互相通訊,它們可以在本地訪問其餘容器的端口。
實際上Pod都包含一個網絡容器,它不作任何事情,只是用來接管Pod的網絡,業務容器經過加入網絡容器的網絡從而實現網絡共享。
Pod的啓動方式相似於:$ docker run -p 80:80 --name network-container -d <network-container-image> $ docker run --net container:network-container -d <image>
因此Pod的網絡實際上就是Pod中網絡容器的網絡,因此每每就能夠認爲Pod網絡就是容器網絡,在理解Kubernetes網絡的時候這是必需要須要清楚的,好比說Pod的Pod-IP就是網絡容器的Container-IP。
Kubernetes網絡模型是一個扁平化網絡平面,在這個網絡平面內,Pod做爲一個網絡單元同Kubernetes Node的網絡處於同一層級。
爲此須要實現:
Flannel由CoreOS團隊設計開發的一個覆蓋網絡工具,Flannel 經過在集羣中建立一個覆蓋網絡,爲主機設定一個子網,經過隧道協議封裝容器之間的通訊報文,實現容器的跨主機通訊。Flannel將會運行在全部的Node之上,Flannel實現的網絡結構如圖所示:
Kubernetes中的Service就是在Pod之間起到服務代理的做用,對外表現爲一個單一訪問接口,將請求轉發給Pod,Service的網絡轉發是Kubernetes實現服務編排的關鍵一環。
Service都會生成一個虛擬IP,稱爲Service-IP, Kuberenetes Porxy組件負責實現Service-IP路由和轉發,在容器覆蓋網絡之上又實現了虛擬轉發網絡。
Kubernetes Porxy實現瞭如下功能:
Kubernetes Porxy是一種分佈式L3代理轉發, 默認是基於Iptables實現,這從設計上很值得借鑑,可是性能部分有待驗證。
Kubernetes中的Ingress提供了一個統一的對外代理入口配置,好比HTTP的訪問配置,而後經過實現Ingress-Controller,Ingress-Controller的實現能夠用Nginx、LVS等等,以Nginx來講,就Ingress-Controller監控Kubernetes API,生成Nginx配置,而後加載生效,而Nginx跟Pod的通訊,能夠走Service,可是考慮到Kubernetes Porxy的性能問題,建議直接和Pod通訊。下面就是一個實現圖:
Q:有這麼多虛擬網絡,覆蓋網絡,會不會有網絡延遲?
A:網絡虛擬會帶來性能損耗,好比Flannel須要將報文封裝到UDP包中傳輸,這中間的封包解包就會帶來損耗。因此網絡虛擬化的部分,軟件的實現還有待優化,其實更好的方式是硬件支持,好比如今提的不少的SDN網絡。
Q:Pod爲何要有個網絡容器?
A: 一方面這是解耦,經過網絡容器來負責網絡配置,這樣對於業務容器來講穩定性會更高,好比在多個業務容器中,某一個業務容器斷了,這樣就不會致使網絡中斷。
Q:Calico默認全網是打通的,怎麼作基於網段之間的隔離?
A:目前來講要作網段隔離,可能偏向安全性比較高的場景,咱們目前是作私有云場景,對隔離的要求沒那麼高。因此若是要作隔離的話,能夠參考OpenStack的OVS方案。
Q:在某些應用場景下,Pod的IP須要固定,而不是重啓以後IP可能會變化,請問如何知足這種場景的需求?
A:Pod的IP須要固定的話,一種方式是修改Docker的代碼,據我所知騰訊有實現過。另外的方案就是作L3的代理,給Pod一個浮動IP,有點像OpenStack的實現。
Q:Ingress的流量默認是先走Service而後到Pod,仍是直接到Pod?
A:取決你的實現,官方的實現是先走Sevice再到Pod,咱們是直接到Pod。
Q:Ingress-Controller實現除了使用LVS和Nginx外,可否採用商用負載設備來實現?實現是否取決於和Kubernetes API的對接?
A:能夠,只要有接口均可以實現,經過實現Ingress-Controller,好比對接F5的硬件設備,只要F5支持相關的API。
Q:代理入口上有哪些方法解決單點失效的問題呢?
A:這個比較傳統了,軟件實現就Keepalived之類的。
Q:Igress-Cntroller比較好的庫都有哪些,分別基於Nginx Haproxy LVS的?
A:GitHub有蠻多實現的,其實仍是比較簡單的,像go語言的話,直接套用官方提供的demo便可,其餘語言能夠對接Kubernetes的API實現。
Q:這麼多層的網絡,多層轉發後網絡性能怎麼樣?有沒有辦法實現高速數據轉發解決方案?
A:代理層,虛擬層都會有損耗,這個就是要考慮管理成本和性能的權衡了。如何要實現高性能的話,就是要往SDN網絡研究,經過硬件層的支持來實現虛。
以上內容根據2017年07月11日晚微信羣分享內容整理。分享人吳龍輝,網宿科技雲計算架構師,負責設計開發PaaS平臺,《Kubernetes實戰》做者。 DockOne每週都會組織定向的技術分享,歡迎感興趣的同窗加微信:liyingjiesa,進羣參與,您有想聽的話題或者想分享的話題均可以給咱們留言。