滴滴彈性云:從物理機到Kubernetes的那些坑與心得
本文根據譚霖老師在〖2017 GdevOps全球敏捷運維峰會北京站〗現場演講內容整理而成。
講師介紹
譚霖,滴滴出行彈性雲架構師、雲計算專家,曾任職於英特爾從事雲計算方向研究。OpenStack Ironic 項目核心開發者,《OpenStack設計與實現》作者,多次在OpenStack Summit SRECon峰會上分享Topic。目前從事基於Kubernetes的私有雲平台的研發,專註提高服務的穩定性和研發、運維效率。
今天我將帶來一些關於滴滴彈性雲的分享,標題是從物理機到Kubernetes的那些坑與心得。
先簡單自我介紹下,我叫譚霖,之前曾在Intel從事於Open Stack相關的工作,也花了很大精力在開源社區這一方面,後來我來到滴滴的彈性雲團隊,主要從事基於Kubernetes的基礎平台建設,可以說是從一個做菜的「廚師」變成了一個「食客」。
主題簡介:
1. 整體架構
2. 產品功能
3. 方案細節
4. 心得展望
前言
在我們準備做彈性雲時,我們問了自己三個問題:
1. 為什麼要做私有雲
2. 為什麼選容器
3. 為什麼選Kubernetes
為什麼要做私有雲
這個其實是最好回答的。因為滴滴的集群規模太大,有數萬台物理機(這樣的規模量要求我們做一個私有雲平台),結果因為之前沒有一個比較好的方案,造成了資源使用率特別低、資源浪費大的問題。
另一個主要原因是滴滴的發展太快,總有新的業務,隔一段時間就聽說成立了一個新的部門,而且隨著新需求的出現,更新迭代異常頻繁,這些都對平台的穩定性提出了特別高的要求。這個問題靠堆人是解決不了的,所以需要有一個好的平台和機制來解決它。
為什麼選容器
這個問題也比較好回答。KVM / Xen這樣的傳統虛擬化已經出現多年了,很穩定,但大家也知道其弊端,就是損耗比較大。另外,傳統混部也就是滴滴現在在用的方案(即繼續保持原有的傳統混部),雖然能夠部分解決資源使用率低的問題,但因為完全沒有隔離,導致程序之間容易互相影響。
而容器是一個相對摺中的方案,具有一定的隔離性、損耗更少,這是我們選擇它的最主要原因。同時,更重要的是容器的鏡像所帶來新的玩法,因為鏡像的環境是一致的,對運維人員特別友好,因此他們不用再關心那些紛繁複雜的配置文件,也不用頻繁地走初始化流程,更不用每次上線更新都提心弔膽,擔心會對新的服務造成影響。
為什麼要選擇Kubernetes
現在這個問題就比較容易回答,但一年前是個比較艱難的選擇。大家都知道現在比較著名的容器平台有Mesos、Kubernetes 和Swarm,一年前我們在Mesos和Kubernetes之間猶豫過很久,後來主要覺得因為我們要做的是一個基於容器的平台,相比Mesos,Kubernetes更專註容器。
而Swarm當時還很年輕,很多功能不夠完善,相較之下Kubernetes更成熟。當然更關鍵的原因是Kubernetes的社區更有活力,設計架構也更清晰,可拓展性也高。
現在回過頭來看一年前的選擇,非常很慶幸我們做了正確的選擇,因為之前相較於兩者,Kubernetes還只是旗鼓相當,而現在則有一統江山的趨勢。我們目前還是基於Kubernetes1.6版本做的改造,接下來1.8版本release之後,我們會盡量跟上保持和社區同步。
一、整體架構
項目介紹
滴滴彈性雲的目標就是基於容器技術,為滴滴提供穩定高效、可伸縮的服務管理平台。先簡單看看彈性雲的項目歷程。
2016年7月,彈性雲項目正式啟動,然後10月份出了第一版,2017年4月,發布了第二版。在幾個月的使用體驗中,我們根據用戶的反饋,不管是產品形式還是底層網路方案都經過大規模優化。目前第三版也正在開發中,這一版會更側重用戶交互和可視化上。
截止到目前為止,我們總共有300多台宿主機,2000+的容器實例,不算很多,但目前有多條滴滴核心業務線跑在我們的平台上,預見2018年規模會有指數型的上升。
整體目標
我們的整體目標有四點,主要是為了解決先前提出的三個問題,如下:
實現資源按需分配,提高資源利用率;
實現資源的彈性伸縮,可以快速響應負載變化;
基礎環境保持一致,實現服務的快速交付;
保證服務的容錯性,實現基礎設施免運維。
解決方案
針對不同的產品線和需求,我們具體落地的產品解決方案主要分為兩大塊:一個是基於容器構建的輕量級虛擬機,叫做靜態容器組;第二個是更純粹的微服務類容器,我們稱之為彈性伸縮組。同時我們還整合了滴滴現有的部署監控和日誌收集系統。
這是整體的架構圖,中間最大的一塊就是我們的K8S集群,它主要分成控制節點和工作節點兩部分。上面一塊是我們的控制台和管理員入口,左邊是滴滴的一些現有的許可權認證系統和服務樹,右邊是我們的網路方案。
所以按照流程我們主要做的操作有用戶先通過許可權系統認證後,創建服務(也就是K8S的實例),實現容器的擴容縮容和部署更新。之後我們平台就會進行實時監控和日誌收集,完成監控數據的上報和鏡像拉取。
剛才說的主要是管理員相關的工作流程,現在看看用戶流量。首先我們這邊實現了每個容器通過IPAM組件,都能獲取一個獨立的IP,這個IP可以和物理機雙向互通,所以允許用戶的流量可以直接通過容器IP訪問實例。同時我們也提供了一個4層的LB,允許用戶可以通過只訪問一個VIP,自動把流量打到後面的容器里。
二、產品功能
接下來詳細講講滴滴彈性雲具體的產品功能。
功能類型
正如之前所說,我們主要提供靜態容器和動態伸縮兩大產品,同時伸縮組方面又細分為有狀態和無狀態伸縮組。
其實在剛開始時,我們只想提供K8S支持得最好的Deployment,也就是無狀態伸縮,這也是最符合容器使用習慣的產品形式。但在實際落地的過程中,我們發現完全不是那麼一回事。
首先,不是所有程序都能比較輕易地改造成Cloud-Native的服務,所以針對這樣的傳統服務,我們還是需要提供一個比較貼近物理機的用戶體驗的產品,它的問題就是不能彈性伸縮,但好處是可以掛載本地存儲,IP是恆定的。
同時為了支持有狀態的服務,我們也提高了有狀態伸縮組。既支持彈性伸縮又支持掛載網路存儲。不過比較出人意料的是,用戶選擇有狀態伸縮組的很大一部分原因並不是因為掛載Ceph,而是因為有狀態伸縮組的容器IP/HostName是不變的,這樣不管是從監控和日誌上,都是更友好的。
而無狀態伸縮我們這個當初最想推動的服務,也就只有在一些對彈性伸縮速度有特別高的要求的場景下才會用到。
功能特性
具體到產品功能的特性上,我們主要有三大塊:複雜配置簡單化、上線流程標準化和服務管理。
1.複雜配置簡單化
了解過K8S的朋友們都清楚,它上手很難,有特別多的配置,有時候反而給用戶帶來了困擾。所以我們做了減法,簡化了很多配置,只留給用戶一些介面,避免不必要的困擾。比如我們支持多種接入方式,既可以一鍵完成從Git代碼倉庫到上線鏡像的轉換過程,也支持直接通過自定義鏡像。
同時我們也對鏡像做了分層(基礎鏡像→環境鏡像→服務鏡像),實現RD和SRE每個角色負責不同的鏡像製作,這樣分工更合理、層次更清晰,做到比較好的權責分明、高效有序。監控日誌自動配置關聯也是做了減法,希望用戶較少關注這一點,從而得到更好的體驗。
2.上線流程標準化
相對於減法來說,我們也做了很多的加法,因為我們是一個嚴肅的運維平台,之所以強調嚴肅,是因為只要有人參與的地方就容易犯錯。一方面我們要盡量減少人工參與的地方,另一方面又要盡量通過各種規範來減少人犯錯的機會。
比如變更審批系統,每一次上線變更都需要開發leader的審核;同時也對它進行了改造,使其每次分組小流量灰度;每次發布更新的過程中都有強制的觀察時間,如果在觀察過程中,比如說你發布了第二組後,發現你的更新過程中代碼出了BUG,我們還支持了一鍵回滾。
3.服務管理
在服務管理方面,我們實現了服務不可用自動重啟、一鍵擴容和負載均衡等,最為重要的就是對用戶強制異地多活,必須在我們的兩個機房都有實例。
三、方案細節
現在介紹我們的方案細節,主要包括網路監控、日誌和鏡像市場。
網路打通
1.SDN
我們的網路方案主要是基於Onos+OVS的SDN網路方案,每個容器都有一個區別於機房實體機的Overlay IP,容器與容器之間實現「大二層」互通,與機房網路之間通過交換機打通。物理機可以直接通過容器Overlay IP訪問容器,反之亦然。
2.IP
在IP上,靜態容器和伸縮容器都可以進行Hostname綁定,通過容器不變的Hostname保證容器在漂移到其它宿主後IP依舊保持不變,當容器發布更新時,它永遠保持穩定。對於IP隨機分配的情況,我們還提供了IP池,保證IP只會從IP池裡出現。
3.負載均衡
我們使用彈性雲獨立的4層、7層負載均衡器,實現動態的負載均衡及故障自動剔除。
容器網路
1.架構
當前彈性雲容器網路大體上分為三種類型:同宿主間的容器通信、跨主機間的容器通信,以及容器與物理機間的通信。
每一個部署容器的宿主機,都會部署一套Ovs網路組建,其中關鍵的就是兩個Ovs Bridge,一個負責建立隧道與外界通信,叫Ovs-tunnel橋;一個負責整合本機上的容器通信,叫Ovs-int橋。所有的Ovs-tunnel都會與Onos的Controller建立連接,負責查詢流表並建立流表和其他宿主機間的隧道。因此三種通信類型就可以解釋為:
同宿主間的容器通信:直接通過Ovs-int橋通信,因此也不依賴Ovs-tunnel與外界的隧道。
跨主機間的容器通信:第一次通信時,Ovs-tunnel也會查詢Onos,Onos返回目標容器的主機信息,Ovs-tunnel通過主機間的隧道,將容器數據發送到目的容器的宿主機,目的容器宿主機上的Ovs-tunnel則會將數據繼續向上一層傳遞,經Ovs-int傳遞給容器。
容器與物理機間的通信:容器發送物理機的數據包,會被Ovs-tunnel經隧道發送給Overlay網關,Overlay網關進行Vxlan解包的操作,將數據傳遞到物理網路。相反地,物理機發送給容器的數據包,經Overlay網關把數據封包成Vxlan數據包,再通過隧道發往容器宿主,再由宿主傳遞給上一層的容器。
2.網路IP分配
具體到產品上,每個IP分配方案如下:
靜態容器組:IP和Hostname恆定;
有狀態伸縮組:IP和Hostname恆定,支持IP池;
無狀態伸縮組:支持IP池,IP隨機分配,靈活度更高。
3.創建過程
這個是容器網路創建的過程。一旦用戶有創建容器需求時,控制節點會對整個集群做一個調度,選擇一個合適的工作節點,而作為節點最重要核心的Kubelet就負責創建容器,控制節點會把需求發給它。
具體創建步驟如下:
Step1:當Kubelet收到調度到本Node的Pod信息後,會先創建一個無網路配置的Infrastructure的基礎容器,此容器用於承載Pod中所有容器的網路Namespace;
Step2:Kubelet Exec啟動CNIPlugin,並將第一步中創建的網路Namespace及Pod名稱、容器ID等作為標準輸入,傳給新啟動的Plugin進程;
Step3:CNIPlugin根據收到的參數,去IP Controller中申請容器的網路IP;
Step4:IP Controller會判斷該容器屬於哪一個子網,子網中是否有可用的IP,及是否有綁定的IP地址等,在根據計算出的IP地址及子網信息等,去SDN IPAM端申請虛擬Port(Overlay IP);
Step5:IPAM會將創建好的虛擬Port返回API調用者IP Controller,並同時將信息同步給SDN Onos;
Step6:IP Controller 會將返回的Port保存在自己的存儲庫中。如果是綁定IP類型的Pod,它還會將該Pod與該虛擬Port(Overlay IP)進行綁定,則下一次該Pod再一次進行申請時,仍會申請到該Port(Overlay IP)。數據保存後,它會把Port信息再返回給CNIPlugin;
Step7:CNIPlugin收到Port信息後,會根據其中的Overlay IP、Gateway、Vlan Tag 等信息創建Veth Pair、配置Veth信息、配置路由、添加Ovs-brdge等操作。至此,本來沒有任何網路的基礎容器,就有了網路配置(除了與外部通信的Ovs網路外,同時也會添加Lo網路);
Step8:CNIPlugin在成功配置完網路後,會將結果返回給Kubelet;
Step9:Kubelet會使用配置成功的基礎容器的網路Namespace繼續去創建其它的業務容器,如果配置失敗了,會繼續從第一步開始,繼續創建基礎容器,直到網路配置成功。
監控需求
監控主要有兩方面需求:基礎監控和業務監控。基礎監控使用了Google開源容器監控軟體Cadvisor/Cgroup作為監控數據來源,數據上報至Odin,同時可在Odin和彈性雲頁面上展開監控數據。
基礎監控:物理機監控Agent無法採集到容器有效監控數據,Cadvisor、Proc、Cgroup容器基礎監控項同物理機有明顯差異,但用戶的需求沒變。
業務監控:業務監控同物理機需求完全一致,復用物理機監控方式。
這張圖就是彈性雲配置監控和查看監控的示意圖,我們在每個物理機上有獲取容器的基礎監控指標,容器裡面也會有獲取業務指標。
日誌需求
日誌主要三個方面考慮:時效性、持久性,以及日誌展示。
日誌時效性:在線日誌採集延遲2min,滿足大多數場景,緊急情況下可以登錄到容器內查看日誌。
日誌持久性:生成的容器直接拉到遠端存儲一份,選擇分散式存儲日誌在Ceph存儲一份。
日誌展示:事後追溯有多種豐富的日誌展示、分析系統。
這是我們在彈性雲平台上創建容器的一個操作日誌,也是一個簡單的示意圖。通常用戶都打在容器里,而容器一旦發布更新,漂移之後數據都丟了,所以我們直接把日誌打到Ceph上,用戶不喜歡用這個的話可以直接打到遠端,遠端採集系統可以使用不同的系統,比如說ES和HDFS,這樣就提供了更加豐富的日誌展示和分析系統。
持久化存儲
存儲主要提供了本地卷和網路卷。
本地卷Host Path提供給靜態容器組,我們把宿主機上的目錄掛載到容器里作為數據存儲卷,優勢是穩定和讀寫性高。
網路卷Ceph的優勢是多備份更可靠,支持容器遷移,缺點是網路抖動不可避免,所以得用Ceph的服務做改造,避免網路抖動影響整個服務的進程。
OverlayFS
我們選擇Overlay FS作為存儲,一方面是因為它的性能/穩定性更好,當然它也有不足,比如DeviceMapper可以通過LVM來解決磁碟的容量限制,但Overlay FS單靠本身是解決不了的,需要靠XFS來限制。
但我們發現在某些場景中XFS因為沒有開啟ftype功能,導致系統讀寫緩慢,因此我們建議大家如果也選用了Overlay FS+XFS方式,要把ftype設置為1。
鏡像市場
鏡像市場主要還是分層,目的是讓不同的用戶可以專註於不同的事情上。如下圖所示:
基礎環境鏡像:彈性雲管理員製作的鏡像:FROM 官方鏡像,增加了服務用到的各種Agent、常用軟體、系統配置(添加User、日誌切割等)的鏡像。包攬最複雜的周邊應用的整合,併兼顧將鏡像做得更小。
服務環境鏡像:SRE 同學製作和維護的鏡像:FROM 基礎環境鏡像,安裝了服務運行所需的環境、配置。更加專註服務環境的保障,使鏡像滿足產品線的使用。
服務鏡像:使用 RD 代碼中 Dockerfile(一般只需要COPY代碼到線上所需目錄即可),FROM 服務環境鏡像,通過彈性雲系統生成的提供服務的鏡像。
四、心得與展望
心得體會
首先,特別想強調的是「雲計算拼的是運維,拼的是可靠性」。產品做得再好、運維人不靠譜,出了紕漏後就沒人敢再用你的東西了,說得再好也沒用。
其次,「線上無小事,要對線上保持敬畏感」。我之前是做開源社區的,解決方案做得多,但現在做雲計算方案時才發現實際與想像的差別特別大,可以說雲計算落地更難。
也許大家看了一些網上的分享後都會覺得搭建一套容器環境是比較容易的,可最難的就像我們這樣已經現有的體系,如果你要把它落地就需要做各種打通、妥協,甚至對一些功能做一些切割,有時這些不是我們想做的,但為了推進落地不得不去做。
此外,技術挑戰是一方面,但用戶習慣是更加大的挑戰,特別是業務方,他們肯定會說為什麼我要遷,現在用得好好的,即便你和他們說做這個是對公司省成本的,可以提高運維的便利性,他們依然會覺得我不缺錢,怕麻煩。再者,他們不是做運維的,感覺不到這些帶來的明顯好處。另一方面,有些用戶覺得我上你的雲可以,但你不要改變我的習慣,原來是什麼樣現在還得保持什麼樣。但問題是原來是物理機的用法,可現在已經上容器了 ,還想保持原來的方式,這是不可能的。
運維是一個特別苦的職業,線上無小事,一點點小改動,如果沒有考慮清楚、沒有充分驗證過回滾方案,那分分鐘要出事,相信大家也深諳此理。
未來展望
對於彈性雲的未來規劃,第一是更細粒度的隔離。大家對容器比較了解的話,就會清楚現在Docker更多的是對Memory使用量的隔離,以及對CPU使用量的隔離。但實際過程中我們會發現,比如你給用戶一個8G內存,在某種極端配置下8G內存會不斷地刷新讀寫,那你的L3 Cache很快就會被刷爆了,導致大量的Cache Miss,這樣的話還是會對程序性能造成很大影響的。
第二是靜態容器的彈性伸縮。因為靜態容器確實就像虛擬機一樣,運維成本特別高,所以一旦物理機掛了,容器也就掛了,很多東西是找不回來的。而且你要擴容也只能按照傳統的方法,先申請一個容器再去上面做部署、配置等,這些都會給運維同學帶來非常大的困擾。
第三是更智能的擴容演算法。目前我們是根據實時的使用率來進行擴容,但其實對於我們來說,很多業務高峰期是有規律的,如果能做到提前預測出高峰期,做適應的擴容,那將會極大地提高資源使用率。
最重要的一點是依託社區、回饋社區。我們打算騰出手來,把一些定製化需求不是那麼高的解決方案來回饋到社區。
※當雲服務融入分散式緩存系統架構,會擦出怎樣的火花?
※同為分散式緩存,為何Redis更勝一籌?
TAG:DBAplus社群 |