基於OpenStack和Kubernetes構建組合雲平臺——網絡集成方案綜述

一談到雲計算,大家都會自然想到三種雲服務的模型:基礎設施即服務(IaaS),平臺即服務(PaaS)和軟件即服務(SaaS)。OpenStack已經成爲私有云IaaS的標準,而PaaS層雖然有很多可選技術,但已經確定統一的是一定會基於容器技術,並且一定會架構在某種容器編排管理系統之上。在主流的容器編排管理系統Kubernetes、Mesos和Swarm中,Kubernetes以它活躍的社區,完整強大的功能和社區領導者富有遠見的設計而得到越來越多的企業青睞。我們基於OpenStack和Kubernetes研發了全球首個實現容器和虛擬機組合服務、統一管理的容器雲平臺。在本文中我們將分享我們在集成OpenStack和Kubernetes過程中的網絡集成方案的經驗總結。

Kubernetes的優秀設計

圖片描述

圖 1 Kubernetes集羣的架構


在我們介紹網絡方案之前,先向大家簡單介紹一下Kubernetes的基礎構架。 
一個Kubernetes集羣是由分佈式存儲(etcd),服務節點(Minion)和控制節點(Master)構成的。所有的集羣狀態都保存在etcd中,Master節點上則運行集羣的管理控制模塊。Minion節點是真正運行應用容器的主機節點,在每個Minion節點上都會運行一個Kubelet代理,控制該節點上的容器、鏡像和存儲卷等。

支持多容器的微服務實例

Kubernetes有很多基本概念,最重要的也是最基礎的是Pod。Pod是一個運行部署的最小單元,他是可以支持多容器的。爲什麼要有多容器?比如你運行一個操作系統發行版的軟件倉庫,一個Nginx容器用來發布軟件,另一個容器專門用來從源倉庫做同步,這兩個容器的鏡像不太可能是一個團隊開發的,但是他們一塊兒工作才能提供一個微服務;這種情況下,不同的團隊各自開發構建自己的容器鏡像,在部署的時候組合成一個微服務對外提供服務。

自動提供微服務的高可用

Kubernetes集羣自動提供微服務的高可用能力,由複製控制器(Replication Controller)即RC進行支持。RC通過監控運行中的Pod來保證集羣中運行指定數目的Pod副本。指定的數目可以是多個也可以是1個;少於指定數目,RC就會啓動運行新的Pod副本;多於指定數目,RC就會殺死多餘的Pod副本。即使在指定數目爲1的情況下,通過RC運行Pod也比直接運行Pod更明智,因爲RC也可以發揮它高可用的能力,保證永遠有1個Pod在運行。

微服務在集羣內部的負載均衡

在Kubernetes內部,一個Pod只是一個運行服務的實例,隨時可能在一個節點上停止,在另一個節點以一個新的IP啓動一個新的Pod,因此不能以確定的IP和端口號提供服務。在Kubernetes中真正對應一個微服務的概念是服務(Service),每個服務會對應一個集羣內部有效的虛擬IP,集羣內部通過虛擬IP訪問一個微服務。

圖片描述


圖 2 Kubernetes集羣內的負載均衡


在Kubernetes集羣中,集羣管理員管理的是一系列抽象資源,例如對應一個微服務的抽象資源就是Service;對應一個微服務實例的抽象資源就是Pod。從Service到Pod的數據轉發是通過Kubernetes集羣中的負載均衡器,即kube-proxy實現的。Kube-proxy是一個分佈式代理服務器,在Kubernetes的每個Minion節點上都有一個;這一設計體現了它的伸縮性優勢,需要訪問服務的節點越多,提供負載均衡能力的kube-proxy就越多,高可用節點也隨之增多。與之相比,我們平時在服務器端做個反向代理做負載均衡,還要進一步解決反向代理的負載均衡和高可用問題。Kube-proxy對應的是Service資源。每個節點的Kube-proxy都會監控Master節點針對Service的配置。當部署一個新的Service時,計入這個Service的IP是10.0.0.1,port是1234,那每個Kube-proxy都會在本地的IP Table上加上redirect規則,將所有發送到10.0.0.1:1234的數據包都REDIRECT到本地的一個隨機端口,當然Kube-proxy也在這個端口監聽着,然後根據一些負載均衡規則,例如round robin把數據轉發到不同的後端Pod。

可替換選擇的組網方案

Kube-proxy只負責把服務請求的目標替換成目標Pod的端口,並不指定如何實現從當前節點將數據包發送到指定Pod;後面如何再發送到Pod,那是Kubernetes自身的組網方案解決的。這裏也體現了Kubernetes優秀的設計理念,即組網方式和負載均衡分式可以獨立選擇,互不依賴。Kubernetes對組網方案的要求是能夠給每個Pod以內網可識別的獨立IP並且可達。如果用flannel組網的話,那就是每個節點上的flannel把發向容器的數據包進行封裝後,再用隧道將封裝後的數據包發送到運行着目標Pod的Minion節點上。目標Minion節點再負責去掉封裝,將去除封裝的數據包發送到目標Pod上。

雲平臺的多租戶隔離

對於一個完整的雲平臺,最基礎的需求是多租戶的隔離,我們需要考慮租戶Kubernetes集羣之間的隔離問題。就是我們希望把租戶自己的虛擬機和容器集羣可以互聯互通,而不同租戶之間是隔離不能通信的。使用OpenStack的多租戶私有網絡可以實現網絡的隔離。OpenStack以前叫租戶即Tenant,現在叫項目即Project;Tenant和Project是一個意思,即把獨立分配管理的一組資源放在一起管理,與其他組的資源互相隔離互不影響。爲了提供支持多租戶的容器和虛擬機組合服務,可以把容器集羣和虛擬機放到一個獨立租戶的私有網絡中去,這樣就達到了隔離作用。這種隔離有兩個效果,一是不同租戶之間的容器和虛擬機不能通信,二是不同租戶可以重用內網IP地址,例如10.0.0.1這個IP,兩個租戶都可用。放在同一個私有網絡中的容器和虛擬機,互相訪問通過內網通信,相對於繞道公網,不僅節省公網帶寬,而且可以大大提高訪問性能。

圖片描述


圖 3 集成OpenStack和Kubernetes的多租戶支持


對外發布應用服務

虛擬機的內網IP,Kubernetes集羣節點的IP,服務的虛擬IP以及服務後端Pod的IP,這些IP在外網都是不可見的,集羣外的客戶端無法訪問。想讓外網的客戶端訪問虛擬機,最簡單是用浮動IP;例如,一個VM有一個內網IP,我們可以給它分配一個外網浮動IP;外網連接這個浮動IP,就會轉發到相應的內網固定IP上。

浮動IP的模式只適用於虛擬機,不適用於Kubernetes中的服務。在OpenStack網絡中,支持外網要利用nodePort和Load Balancer結合的方式。比如這裏有個服務,它的服務的虛擬IP(也叫Cluster IP)是10.0.0.1,端口是1234,那麼我們知道內網的客戶端就是通過這個IP和端口訪問的。爲了讓外網訪問相應的服務,Kubernetes集羣中針對每個服務端口,會設置一個node Port 31234,羣中的每個節點都會監聽這個端口,並會在通過IP Table的REDIRECT規則,將發向這個端口的數據包,REDIRECT對應服務的虛擬IP和端口。所有發向nodePort 31234這個端口的數據包,會被轉發到微服務的虛擬IP和端口上去,並進一步REDIRECT到Kube-proxy對應的端口上去。再進一步,只要從外網進來的數據包,就發送到服務節點的nodePort端口上。那我們用Load Balancer來做,Load Balancer的前端是它的內網IP和發佈端口,後端是所有內網的節點IP和nodePort。因此所有發到負載均衡器的包,會做一次負載均衡,均衡地轉發到某個節點的nodePort上去,到達節點的nodePort的數據包又會轉發給相應的服務。爲了讓外網訪問,我們要給Load Balancer綁一個外網IP,例如111.111.111.1,這樣所有來自外網,發送到111.111.111.1:11234的數據包,都會轉發給對應的微服務10.0.0.1:1234,並最終轉發給某個隨機的Pod副本。

實現了以上工作,我們部署在Kubernetes集羣中的服務就可以實現在OpenStack的基礎平臺上對外發布和訪問了。

圖片描述


圖 4 Kubernetes微服務的對外發布


基於Kuryr的組網方案

Docker從1.6版本開始,將網絡部分抽離出來成爲Libnetwork項目,使得第三方可以以插件機制爲Dockers容器開發不同網絡管理方案。Libnetwork包括4種驅動類型:

  • Null:顧名思義,就是沒有網絡支持。

  • Bridge:傳統的Docker0網橋機制,只適用於單主機容器之間的通信,不能支持跨主機通信。

  • Overlay:在下層主機網絡的上層,基於隧道封裝機制,搭建層疊網絡,實現跨主機的通信;Overlay無疑是架構最簡單清晰的網絡實現機制,但數據通信性能則大受影響。

  • Remote:Remote驅動並不真正實現驅動,而是以REST服務的方式定義了與第三方網絡驅動交互的機制和管理接口。第三方容器網絡方案主要通過這一機制與Docker集成。

說到這裏,必須要提到OpenStack的容器網絡管理項目Kuryr,正是一個Remote驅動的實現,集成Dockers和Openstack Neutron網絡。Kuryr英文的原意是信使的意思,本身也不是網絡配置的一個具體實現,而是來自Docker用戶操作意圖轉換爲對Openstack Neutron API的操作意圖。具體來說,容器管理平臺的操作會通過以下方式與Openstack集成:

  • Kubernetes的網絡配置管理操作(例如Kubectl命令)會由一個Kubectl操作轉換成對Dockers引擎的操作;

  • Dockers引擎的操作轉換成對Libnetwork的Remote驅動的操作;

  • 對Remote驅動的操作,通過Kuryr轉換成對Neutron API的操作;

  • 對Neutron API的操作,通過Neutron插件的機制轉換成對具體網絡方案驅動的操作。

圖片描述


圖 5 OpenStack Kuryr調用關係示意圖


相對於Docker網絡驅動,Flannel是CoreOS團隊針對Kubernetes設計的一個網絡規劃服務;簡單來說,它的功能是讓集羣中的不同節點主機創建的Docker容器都具有全集羣唯一的虛擬IP地址,並使Docker容器可以互連。

基於Flannel網絡的組網方案

在集成Kubernetes的網絡方案中,基於Flannel的網絡方案Kubernetes的默認實現也是配置最簡單直接的。在Flannel網絡中,容器的IP地址和服務節點的IP地址處於不同的網段,例如將10.1.0.0/16網段都用於容器網絡,將192.168.0.0/24網段用於服務節點。每個Kubernetes服務節點上的Pod會形成一個獨立子網,例如節點192.168.0.100上的容器子網爲10.1.15.0/24;容器子網與服務節點的對應關係保存在Etcd上。每個服務節點都會安裝flanneld程序,flanneld程序會截獲所有發向容器集羣網段10.1.0.0/24的數據包。對於發向容器集羣網段的數據包,如果是指向其他節點對應的容器地址的,flannel會通過隧道協議封裝成指向目的服務節點的數據包;如果是指向本節點對應的容器地址的,flannel將會轉發給docker0。Flannel支持不同的隧道封裝協議,常用的是Flannel UDP和Flannel VxLan,根據實際測試結果,VxLan封裝在吞吐量和網絡延時性能上都要好於UDP,因此一般推薦使用VxLan的封裝方式。

在Kubernetes集羣中的Flannel網絡非常類似於Docker網絡的Overlay驅動,都是基於隧道封裝的層疊網絡,優勢和劣勢都是非常明顯的。

層疊網絡的優勢

  • 1.對底層網絡依賴較少,不管底層是物理網絡還是虛擬網絡,對層疊網絡的配置管理影響較少;

  • 2.配置簡單,邏輯清晰,易於理解和學習,非常適用於開發測試等對網絡性能要求不高的場景。

層疊網絡的劣勢

  • 1.網絡封裝是一種傳輸開銷,對網絡性能會有影響,不適用於對網絡性能要求高的生產場景;

  • 2.由於對底層網絡結構缺乏瞭解,無法做到真正有效的流量工程控制,也會對網絡性能產生影響;

  • 3.某些情況下也不能完全做到與下層網絡無關,例如隧道封裝會對網絡的MTU限制產生影響。

圖片描述

圖 6 Flannel網絡機制示意圖


基於Calico網絡的組網方案

與其他的SDN網絡方案相比,Calico有其獨特的特點,就是非層疊網絡,不需要隧道封裝機制,依靠現有的三層路由協議來實現軟件定義網絡(SDN)。Calico利用iBGP即內部網關協議來實現對數據包轉發的控制。在基於隧道封裝的網絡方案中,網絡控制器將宿主機當作隧道封裝的網關,來封裝來自虛擬機或容器的數據包通過第四層的傳輸層發送到目的宿主機做處理;與此相對,Calico網絡中的控制器將宿主機當作內部網關協議中的網關節點,將來自虛擬機或容器的數據包通過第三層的路由發送到目的宿主機做處理。內部網關協議的一個特點是要求網關節點的全連接,即要求所有網關節點之間兩兩連接;顯然,這樣鏈路數隨節點的增長速度是平方級的,會導致鏈路數的暴漲。爲解決這個問題,當節點較多時,要引入路由反射器(RR)。路由反射器的作用是將一個全連接網絡轉變成一個星形網絡,由路由反射器作爲星形網絡的中心連接所有節點,使得其他節點不需要直接連接,從而使鏈路數從O(n2)變爲O(n)。因此Calico的解決方案是所有節點中選擇一些節點做爲路由反射器,路由反射器之間是全聯通的,非路由反射器節點之間則需要路由反射器間接連接。

圖片描述

圖 7 包含路由反射器的Calico網絡結構圖

Calico網絡的優勢

  • 1.沒有隧道封裝的網絡開銷;

  • 2.相比於通過Overlay構成的大二層層疊網絡,用iBGP構成的扁平三層網絡擴展模式更符合傳統IP網絡的分佈式結構;

  • 3.不會對物理層網絡的二層參數如MTU引入新的要求。

Calico網絡的劣勢

  • 1.最大的問題是不容易支持多租戶,由於沒有封裝,所有的虛擬機或者容器只能通過真實的IP來區分自己,這就要求所有租戶的虛擬機或容器統一分配一個地址空間;而在典型的支持多租戶的網絡環境中,每個租戶可以分配自己的私有網絡地址,租戶之間即使地址相同也不會有衝突;

  • 2.不容易與其他基於主機路由的網絡應用集成。

不同網絡方案對OpenStack和Kubernetes的影響

總結一下引入Kuryr,Overlay和Calico技術對雲平臺解決方案的作用和帶來的影響。如果我們形象地比喻一下不同的組網技術的話,基於Overlay的組網技術是最重的,開銷最大的,但也是最穩定的,就像一隻烏龜;基於Calico的組網技術較爲輕量級,但與複雜的網絡環境集成就不太穩定,就像一隻蹦蹦跳跳的兔子;基於Kuryr的技術,因爲Kuryr本身並不提供網絡控制功能,而只是提供下面一層網絡控制功能到容器網絡的管理接口封裝,就像穿了一件馬甲或戴了一頂帽子。

圖片描述

表1 不同組網方案的作用與影響


在一個集成了OpenStack和Kubernetes的平臺,分別在OpenStack層和Kubernetes層要引入一種網絡解決方案,OpenStack在下層,Kubernetes在上層。考慮作爲IaaS層服務,多租戶隔離和二層網絡的支持對OpenStack網絡更爲重要,某些組合的網絡方案基本可以排除:例如,Kuryr作爲一個管理容器網絡的框架,一定要應用在Kubernetes層,而不是在下面的OpenStack層,於是,所有將Kuryr作爲OpenStack層組網的方案都可以排除。

綜合OpenStack層和Kubernetes層網絡,較爲合理的網絡方案可能爲以下幾種: 
圖片描述

表2 不同網絡集成方案的比較


圖片描述

圖 8 使用不同網絡技術集成OpenStack與Kubernetes


如上圖所示,第一種組合,底層用Calico連通OpenStack網絡,上層用Kuryr將容器網絡與IaaS網絡打通,像一個小兔子戴帽子;這種組網方式無疑性能開銷是最少的,但因爲沒有方便的多租戶隔離,不適合需要多租戶隔離的場景。第二種組合,底層用Overlay進行多租戶隔離,上層用Kuryr將容器網絡與IaaS網絡打通,像一個烏龜戴帽子;這種組網方式兼顧了性能和多租戶隔離的簡便性,比較適合統一管理容器和虛擬機的網絡方案。第三種組合,底層用Overlay進行多租戶隔離,上層用Calico實現容器集羣組網,像小兔子站在烏龜上;這種組網方式下,性能較好,容器層的網絡管理基本獨立於IaaS層,有利於實驗驗證Calico跟Kubernetes的集成,但實踐中Calico的組網方式還是稍顯複雜。第四種組合,上下兩層都是Overlay網絡,好像兩個烏龜壘在一起,是一種性能開銷最大的方式,但同時也是初期最容易搭建和實現的組網方式,比較適合於快速集成和驗證Kubernetes的整體功能。

總結

本文探討了基於OpenStack和Kubernetes構建雲平臺過程中,網絡層面的技術解決方案。特別的,我們介紹瞭如何在基於OpenStack和Kubernetes的雲平臺中,實現租戶隔離和服務對外發布。同時,我們介紹了Kubernetes的可替換集羣組網模型,探討了幾種不同技術特點的組網方式,分析了Kuryr、Flannel和Calico這些網絡技術的特點和對系統的技術影響,並探討了OpenStack和Kubernetes不同組網方案的適用場景。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章