支撐大規模公有云的Kubernetes改進與優化 (3)

這一篇咱們來說網易爲支撐大規模公有云對於Kubernetes的定製化。前端

1、整體架構node

 

 

網易的Kubernetes集羣是基於網易雲IaaS平臺OpenStack上面進行部署的,在外面封裝了一個容器平臺的管理層,負責統一的帳號,計費等。算法

 

Kubernetes集羣固然是要高可用的,於是會有多個Master節點。編程

 

其中APIServer前端有負載均衡器haproxy,須要有一個VIP,在兩臺haproxy之間進行漂移,保證一臺啊掛了,另一臺可以使用同一個VIP接上。後端

 

 

這種漂移使用的協議爲VRRP。api

 

Scheduler和Controller也是有多份的,可是隻能有一個Leader,須要經過etcd進行選舉。緩存

 

另外網易自身實現的部分放在單獨的進程裏NeteaseController,用於處理和IaaS層聯動的功能。安全

 

2、一個仍是多個Kubernetes集羣?網絡

 

 

通常有IaaS平臺的公有云或者私有云部署Kubernetes採用的是左面的樣子。也即經過調用IaaS層的API,自動化部署多個Kubernetes平臺,每個Kubernetes平臺僅僅屬於一個租戶。架構

 

這樣的好處是不一樣的租戶的Kubernetes之間是徹底隔離的。

 

壞處也不少:

  • 當租戶很是多的時候,Kubernetes集羣很是多,很是難以維護

  • 每一個Kubernetes集羣的規模很是小,徹底不能發揮容器平臺的優點,容器平臺相對於IaaS平臺比較輕量級,按最佳實踐是可以管理比IaaS更大的集羣的,例如幾萬或者幾十萬個節點,然而這種方式會將Kubernetes集羣限制在很小的規模。

  • 雖然不少雲平臺提供Kubernetes集羣的自動化部署工具,可是僅僅自動化的是安裝過程,一旦這個集羣交給客戶了,雲平臺就無論了,這樣Kubernetes的升級,修復,運維所有要客戶本身來,大大提高了運維成本。

  • Kubernetes集羣規模須要提早規劃階段數目,添加新的節點數目須要手動進行。

 

網易採用的是右面的方式,整個IaaS層上面只有一個Kubernetes平臺,Kubernetes平臺的運維,升級,修復所有由雲平臺運維人員進行,運維成本較低,並且不須要用戶本身操心。

 

對於用戶來說,看到的就只是容器,不用關心容器平臺。當用戶建立容器的時候,當Kubernetes集羣資源不足的時候,Netease Controller會自動調用IaaS層API建立虛擬機,而後在虛擬機上部署容器,一切自動進行。

 

固然這種方式的一個缺點是一個Kubernetes的不一樣租戶之間的隔離問題。

 

 

採起的方式是不一樣的租戶不共享虛擬機,不一樣的租戶不共享虛擬網絡,這樣租戶之間就隔離了,容器的內核也隔離了,二層網絡也隔離了。

 

固然這個方式的另外一個問題是Kubernetes的集羣數目很是大,這在下面會詳細說這個事情。

 

還有一個問題是容器放在虛擬機裏面,虛擬機的啓動速度就成了很大的問題,若是啓動速度很慢,則會拖慢容器的敏捷性。

 

3、APIServer認證模塊接Keystone解決複雜的租戶管理問題

 

Kubernetes有基於keystone的用戶名和密碼進行認證的默認機制,然而每次用用戶名和密碼進行認證是效率很低的。

 

網易經過定製化認證流程,使得apiserver也採用相似nova的認證方式。

 

APIServer在keystone裏面註冊一個service角色的帳號,並從keystone獲取臨時管理員的Token。

 

客戶請求到來的時候,經過用戶名密碼到Keystone進行認證,獲取一個token,而且帶着這個token到APIServer進行認證,APIServer帶着這個token,連同本身的臨時管理員的Token進行聯合認證,若是驗證經過則獲取用戶信息,而且緩存到etcd裏面。

 

當客戶經過獲取的token來請求的時候,先從etcd裏面讀取這個token進行驗證,爲了使用本地緩存,加一個listwatch實時同步etcd裏面的內容到本地緩存。

 

若是token過時,則重新到keystone裏面revoke。

 

 

4、從APIServer看集羣的規模問題

 

隨着集羣規模的擴大,apiserver的壓力愈來愈大。

 

由於全部的其餘組件,例如Controller,Scheduler,客戶端,Kubelet等都須要監聽apiserver,來查看etcd裏面的變化,從而執行必定的操做。

 

不少人都將容器和微服務聯繫起來,從Kubernetes的設計能夠看出,Kubernetes的模塊設計時很是的微服務化的,每一個進程都僅僅幹本身的事情,而經過apiserver鬆耦合的關聯起來。

 

而apiserver則很像微服務中的api網關,是一個無狀態的服務,能夠很好的彈性伸縮。

 

 

爲了應對listwatch,apiserver用了watchcache來緩解壓力,然而最終的瓶頸仍是在etcd上。

 

最初用的是etcd2,這個時候listwatch每次只能接受一個事件,因此壓力很大。爲了繼續使用etcd2,則須要使用多個etcd2的集羣來解決這個問題,經過不一樣的租戶分配到不一樣的etcd2集羣來分擔壓力。

 

未來會遷移到etcd3有了事件的批量推送,可是從etcd2到etcd3須要必定的遷移工做。

 

5、經過優化Scheduler解決並行調度的問題

 

對於大的資源池的調度是一個很大的問題,由於一樣一個資源只能被一個任務使用,若是並行調度,則存在兩個並行的調度器同時認爲某個資源空閒,因而同時將兩個任務調度到同一臺機器,結果出現競爭的狀況。

 

當OpenStack遇到這種問題,採起的方法是從新調度的方式進行。

 

而Mesos則採起了更爲聰明的兩層調度的算法。

 

 

詳情見文章號稱瞭解mesos雙層調度的你,先來回答下面這五個問題!

 

Mesos首先經過第一層的調度Allocator,將不一樣的節點分給不一樣的Framework,則不一樣的Framework就能看到不一樣的節點了,不一樣Framework裏面的調度器是第二層調度,是可以並行調度的,而且即使並行調度,不一樣的Framework也是不會調度到衝突的節點的。

 

Mesos的雙層調度策略,使得Mesos可以管理大規模的集羣,例如tweeter宣稱的幾十萬的節點,由於對於某一個Framework來說,不會同時在幾十萬個節點中選擇運行任務的節點,而是僅僅在其中mesos分配給他的一部分中進行調度,不一樣的framework能夠並行調度。

 

還記得前面咱們提到的,爲了租戶隔離,不一樣的租戶是不共享虛擬機的,這樣不一樣的租戶是能夠參考Mesos的機制進行並行調度的。由於不一樣的租戶即使進行並行調度,也不會出現衝突的現象,每一個租戶不是在幾萬個節點中進行調度,而僅僅在屬於這個租戶的有限的節點中進行調度,大大提升了調度策略。

 

而且經過預過濾無空閒資源的Node,調整predicate算法進行預過濾,進一步減小調度規模。

 

6、經過優化Controller加快新任務的調度速度

 

 

Kubernetes採用的是微服務常使用的基於事件的編程模型。

 

當有增量事件產生的時候,則controller根據事件進行添加,刪除,更新等操做。

 

可是基於事件的模型的一個缺點是,老是經過delta進行事件觸發,過了一段時間,就不知道是否同步了,於是須要週期性的Resync一下,保證全量的同步以後,而後再進行增量的事件處理。

 

然而問題來了,當Resync的時候,正好遇到一個新容器的建立,則全部的事件在一個隊列裏面,拖慢了新建立容器的速度。

 

經過保持多個隊列,而且隊列的優先級ADD優於Update優於Delete優於Sync,保證相應的實時性。

 

7、經過優化虛擬機啓動速度加速容器啓動速度

 

前面說了,爲了保證安全性,容器是啓動在虛擬機裏面的,然而若是虛擬機的啓動速度慢了,容器的啓動速度就會被拖慢。

 

那麼虛擬機的啓動速度爲何會慢呢?

 

 

比較慢的一個是網卡的初始化速度比較慢,在OpenStack裏面,每每須要經過訪問DHCP Sever獲取IP地址和路由信息,把IP靜態化能夠解決這個問題。

 

 

另一個比較慢的是Cloud-init,這個是在虛擬機啓動以後作初始化的一個工具,是爲了可以在虛擬機啓動後作靈活的配置,好比配置key,或者執行一些腳本。

 

在AWS裏面,cloudformation編排工具在虛擬機啓動後的一些編排工做是經過cloud-init來作的,彈性伸縮機制經過虛擬機鏡像複製多份,複製後作的少許的配置工做也是cloud-init來作的。

 

OpenStack繼承了AWS的這個機制,是經過Metadata Server來對虛擬機進行靈活的配置,包括OpenStack編排機制Heat也是經過Cloud-init進行配置。

 

 

對於Metadata Server的機制,能夠看這篇文章當發現你的OpenStack虛擬機網絡有問題,不妨先試一下這16個步驟

 

然而在虛擬機裏面跑容器的方式,是不須要cloud-init的,由於靈活定製化的事情由裏面的容器來作,用戶使用的也是裏面的容器,而不是虛擬機,於是虛擬機能夠作的十分的精簡,將不須要的服務所有刪除。

 

8、經過使用IaaS層的高性能網絡提供給容器高速互聯能力

 

上一節咱們講過,使用Flannel和Calico都僅僅適用於裸機容器,並且僅僅用於容器之間的互通。

 

 

一旦有IaaS層,就會存在網絡二次虛擬化的問題。

 

虛擬機之間的互聯是須要經過一個虛擬網絡的,例如vxlan的實現,而使用Flannel或者Calico至關於在虛擬機網絡虛擬化的上面再作一次虛擬化,使得網絡性能大幅度下降。

 

並且若是使用Flannel或者Calico,那容器內的應用和虛擬機上的應用相互通訊的時候,則須要出容器平臺,多使用node port,經過NAT的方式訪問,或者經過外部負載均衡器的方式進行訪問。在現實應用中,不可能一會兒將全部的應用所有容器化,部分應用容器化,部分應用部署在虛擬機裏面是常有的現象。然而經過NAT或者外部負載均衡器的方式,對應用的相互調用有侵入,是的應用不能像原來同樣相互調用,尤爲是當應用之間使用Dubbo或者SpringCloud這種服務發現機制的時候尤爲如此。

 

 

網易開發了本身的NeteaseController,在監聽到有新的Pod建立的時候,調用IaaS的API建立IaaS層的虛擬網卡,而後在虛擬機內部,經過調用Netease CNI插件將虛擬網卡添加到容器裏面。添加的技術用的就是上一節提到的setns命令。

 

 

經過這個圖咱們能夠看出,容器的網卡是直接鏈接到虛擬私有網絡的OVS上的,和虛擬機是一個平的二層網絡,在OVS來看,容器和虛擬機是在同一個網絡裏面的。

 

這樣一方面沒有了二次虛擬化,只有OVS一層虛擬化。另外容器和虛擬機網絡打平的好處是,當部分應用部署容器,部分應用部署虛擬機的時候,對應用沒有侵入,應用原來如何相互訪問,如今仍是如何訪問,有利於應用逐步容器化。

 

容器還能夠有一個網卡直接鏈接到公網,這一點可以保持公網IP在容器內部可見,容易使用,並且能夠保證在容器的生命週期內,公網IP能夠保持。

 

另外這個網卡在負載均衡可使用,下面咱們詳細說。

 

使用OVS的二層網絡,能夠很好的實現多租戶,高性能互聯,QoS,安全過濾,放ARP和IP欺騙等。

 

9、經過優化kube-proxy優化內部相互訪問

 

 

默認的容器之間的相互訪問經過服務進行。

 

一旦建立一個服務,就會建立一個Endpoint,kube-proxy可以在api-server監聽到這個服務的建立,則須要監聽服務的端口,而且設置iptables將對這個服務對應的VIP的訪問轉發到kube-proxy的這個端口上。

 

當一個客戶端要訪問這個服務的時候,首先經過DNS,將服務名轉化爲VIP,而後VIP經過iptables規則轉發到kube-proxy的監聽端口,kube-proxy將這個包隨機轉發給後端的一個Pod。

 

當Pod不管IP如何變,如何彈性伸縮,只要有服務名,都可以訪問到。

 

僅僅經過DNS,是可以作的服務名和IP的對應,也是能夠基於DNS進行負載均衡的,這就是基本的基於DNS的服務發現。然而這種方式的缺點是不可以流控,因此最好中間有一個proxy,這就是kube-proxy。

 

就像Mesos中原來的服務發現是經過Mesos-DNS進行,後來改用了minuteman作這件事情,minuteman的實現機制和kube-proxy很像很像。

 

然而這種方式的問題是,當集羣規模很大的時候,服務建立的不少的時候,kube-proxy會牽扯到大量的iptables和監聽端口。

 

然而在咱們的設計中,租戶之間的容器網絡應該是徹底隔離的,在某個租戶的虛擬機上的Kube-proxy是無需包含另外一個租戶的轉發規則的。

 

因此這裏作的一個優化是隻監聽本租戶的service,而且建立轉發規則就好,由於每一個租戶的節點數目有限,轉發規則也不會不少。

 

10、經過LVS和haproxy進行外部負載均衡器優化

 

 

Kubernetes默認的外部負載均衡是用ingress作的,性能不是很高。

 

通常公有云要求負載均衡可以承載的吞吐量很是的大,不能用純軟的方式。

 

在網易的方案中,最外層有兩個LVS,部署在物理機上,經過多個萬兆上行口進行轉發,能夠承載很是大的吞吐量。

 

對於不一樣的租戶,能夠建立不一樣的軟負載均衡,經過建立多個haproxy,構成一個集羣,因爲haproxy是基於虛擬機的,能夠彈性伸縮,使得他也不會成爲瓶頸。

 

haproxy是後端和容器進行二層互聯,是經過虛擬網絡進行的,然而haproxy鏈接LVS是須要經過物理網絡的,這就須要haproxy經過上面的機制,經過兩張網卡,一張卡鏈接到物理網絡,做爲前端,一張卡鏈接到虛擬網絡,做爲後端鏈接容器。

 

 

最後給一張優化總圖。

相關文章
相關標籤/搜索