標籤:

攜程容器雲實踐

一、在線旅游與彈性需求

近年來隨著大眾旅遊消費的火熱,攜程的業務每年呈高速增長,2016年Q4財報顯示攜程2016年全年營業收入同比增長76%,交通票務營業收入同比增長98%,酒店預訂營業收入同比增長56%,其他BU也有大幅增長,預計2018年攜程的GMV將突破10000億,並在2021年突破2萬億。

我們開發的私有雲和持續交付平台為攜程超過 20 個 BU/SBU 服務,為了同步支撐業務的高速發展,我們也需要不斷的技術革新,持續提升攜程運營、研發的效率,縮短產品從idea到交付用戶的時間。

旅遊出行的特點是季節性的,在平時流量都比較低,但節假日前一天流量會突然增高很多。因此每到節假日就會面臨成「倍」增長的擴容需求。圖 1 中可以明顯的看到流量的起伏情況。

圖 1

一般情況,臨時擴容的需求較多,縮容會比較少,因為流量一上去之後,在短時間內不會下來,另外一方面,哪怕是流量下來了,由於以往資源申請沒那麼靈活,一般都會佔用資源不釋放,只能通過一些運維手段來監測資源使用情況然後告知業務部門去主動縮容。

攜程目前大部分還是虛擬機,我們想縮短提前擴容的時間,以目前的虛擬機擴容方式,單個虛擬機擴容(從分配資源、調度、網路、os基礎環境、應用部署等)至少是十分鐘級別的,如果是每次擴容上千台的話,確實需要一定的時間,而且還得看看有無足夠的資源,比如 1 月 1 日的流量提前一周就擴容好,但這不夠靈活,業務流量下來以後需要縮容,目前的速度還是不夠快。

針對這一場景,我們需要解決的問題是,能有更快的方案嗎?如何能夠做到更快速的彈性伸縮滿足業務的需求?答案是利用容器。

圖2

再舉個例子,攜程有個深度學習的小詩機項目,將訓練好的模型,對外提供服務,用戶只要上傳照片,後台的 AI 機器人就會根據照片中的內容自動寫詩,這對於現行都市詞窮一族來說,瞬間提升了意境,蠻有意思的。

該項目希望在春節前上線,需要緊急擴容 1000 核,以滿足春節期間大流量的需求,春節過後立馬就可以縮容 90% 的資源。目前我們通過容器可以做到 1000 核的資源,5 分鐘內完成 150 個容器實例的擴容,而且這還是 API 同步創建的速度,我們正在優化成非同步的方式,相信後續提高並發能力後,速度還可以得到大大的提升。

其實攜程的容器化已經進行一年多了,容器給我們最大的感覺是看起來簡單,但要做好很難,原理不是很複雜,但是要利用這個技術做出一個產品或服務,中間有非常多的細節需要完善,比如如何做到用戶體驗更好的 UI 可視化、如何做到灰度發布、容器監控、容器基礎鏡像版本管理等等。

二、攜程容器雲定位

攜程容器雲定位有以下 4 點:

1、打造極致的妙級持續交付體驗,服務20+BU

秒級意味著所有的擴容、縮容、回滾全部是秒級的,做到秒級是很難的,有很多需要突破的地方。比如,高速的鏡像下發系統;高效的調度系統,穩定的容器服務,高度自動化的網路服務。

2、提升資源利用率

為了提高伺服器資源利用率,我們採取賬單的形式,督促業務線提高資源利用率,優化代碼架構。我們對採集到的實時監控數據進行統計分析,按照 CPU、內存、存儲、網路等多個緯度,按月計費,每個月會將賬單發給業務線的 CTO。

3、組件服務化(mysql/kv/mq/...)or PaaS 化

應用所需要依賴的很多組件能夠變成服務化,AWS 或者阿里雲也做了很多這種服務。攜程內部也在嘗試把一些公共組件服務化,例如,MySQL,Redis,RabbitMQ 等。拿 MySQL 為例,我們讓用戶可以在測試環境快速部署 MySQL 實例,並且可以選擇性的將測試數據灌入。新建的 MySQL 實例也會自動在數據訪問中間件中完成註冊,方便開發人員、測試人員快速搭建測試環境和測試數據。

4、從自動化到一定程度智能化

從自動化到一定程度智能化指的是基礎設施變得更智能,比如能夠具備一定的自我修復能力,如果是從上游到下游的一整套服務都具備智能化修復能力的話,這是一個非常大的突破,對於提升運營效率和故障恢復速度至關重要;

容器部署基本原則

  • 單容器單應用

  • 單容器單 IP,可路由的 IP

  • 容器鏡像發布

  • immutable infrastructure

  • 容器內部只運行 App,所有 agent 部署在host 層面-包括監控/ES/salt等agent

以上是攜程容器部署基本原則,看起來很容易,卻是我們很長時間實踐經驗的總結。

比如單容器單應用這個原則,歷史原因我們有混合部署的情況,單個vm部署多個應用,運維的複雜度會上升很多,比如:應用之間如何做到更好的資源隔離?發布如何避免相互之間的衝突?等等,使得我們的運維工具、發布工具變得格外複雜,開發、測試的持續交付效率也受到極大影響;

容器鏡像發布也是我們做的一個比較大的突破,過去是代碼編譯成可發布的包,直接部署到vm內部,而現在是編譯時直接生成容器的鏡像,不同環境其實部署的是同一個鏡像,並且不允許部署之後單獨登陸進行配置修改,通過這種方式做到 immutable infrastructure ,保證開發、測試、生產環境的一致性,同時也保障了自動化擴容、縮容快速高效的進行。

是否在容器內部也運行各種運維agent 也是我們經過實踐確定下來的;我們希望容器盡量簡單,儘可能只包含運行的應用本身,此外將所有的agent合併到host層面,也能在很大程度上提升伺服器資源利用率,agent數量下降一到兩個數量級;但配套的管理工具(eg: salt) 需要做一次升級改造才能適配新的模式;

容器編排選型&取捨

1、OpenStack

攜程除了容器之外的東西都是用 OpenStack 來管理的,OpenStack 可以用一個模塊(nova-docker)來管理容器,攜程在OpenStack方面有多年的二次開發技術積累、也大規模的部署運維經驗,但最終沒有選用OpenStack,因為 OpenStack 整體過於複雜,調度效率也比較低,API 調度是 10 秒以上,可以進行優化,但我們覺得優化代價太大,OpenStack整體的複雜度也很高;

我們早期的胖容器(把容器當vm來使用,做代碼包發布)的確是用OpenStack來做的,原因是我們希望把注意力放在容器本身,以最低的代價將容器先用起來,積累開發、運維經驗;而到了瘦容器階段(基於容器鏡像做發布),我們發現OpenStack整體的設計理念從本質上講還是為虛擬機隔離粒度的虛擬化方案設計的,而容器本身與vm其實差別很大,玩法也相去甚遠, 於是我們對Mesos/K8s進行評估;

回顧我們的容器調度探索之旅,基本上可以用以下三個階段來總結:

第一階段,需要最快的使用起來,用最熟悉的技術來解決部署和調度。到了第二階段有新的需求,引入 mesos 和 chronos,提供分散式 cron job 調度。第三階段是使用 Python 重新實現 chronos, 並且單獨實現了CExecutor等組件。

圖3

OpenStack用於管理bm/vm是很合適的,並且在網路方面有很成熟的支持,無論是vlan+OVS 還是最新的SDN 都能適配,尤其各大廠商的支持力度都很大;這也是為什麼我們雖然不用openstack調度容器,但容器的網路其實還是用neutron來管理的;

2、K8S

K8S 有很多很先進的設計理念,比如有replication controller/Pod/Yaml 配置管理等,但這些理念在攜程都很難落地,因為跟現有的運維模式、發布流程有較大的衝突。而且當前還缺乏大規模部署案例,網路尚無比較成熟的方案, 例如 L4/L7 負載均衡; 而在攜程L4/L7服務已經比較成熟穩定, 並且與我們現有的發布系統Tars集成得非常好;

3、Mesos

Mesos 和 K8S 解決問題的思路是不一樣的,基於 Mesos 我們可以非常容易的開發出適合我們場景的調度框架,並且非常容易和我們現有的運維基礎服務對接集成;包括 L4/L7 負載均衡、發布系統等;

圖4

五、容器網路選型

  • Neutron+OVS+VLan

-DPDK

-https硬體加速

-單容器單IP,可路由

  • vxlan+SDN controller

-vxlan offload TOR解封裝

Neutron+OVS+VLan,這個模式非常穩定,對於網路管理也是非常的透明的。這也是攜程的選擇,現在的網路無論是胖容器還是容器輕量發布都用這種模式。我們也在測試 DPDK 和 https 硬體加速的效果。

我們也評估過類似flannel的網路,要求每個物理機獨立網段,通過這個特性來做路由;非常不靈活的一點是容器如果遷移到另外一台物理機就需要換IP,無法滿足我們的需求;

接下來會走 vxlan+ 基於BGP EVPN協議自研輕量級SDN controller的路線,vxlan offload TOR 解封裝提高性能;對於openstack可見的還是大二層網路(vlan), 而實際上是通過underlay的三層路由進行轉發;openstack與我們的控制器能實現元數據的一致性;關於這塊,後續我們也會有相應的分享單獨進行探討;

如何配置容器網路

圖 5

如圖 5 用dwait 和 dresponse,基於 Go 開發,dwait 會通過 unix socket 請求外部服務dresponse 做容器的初始化。當這個容器起來的時候,它的網路沒有那麼獨立,在 Docker 裡面是需要依賴外部提供信息的,所以需要知道哪個網段或者說創建的 neutronport 再配置到 Docker 容器內。這樣做後就不會有網路丟失的情況。

六、Docker遇到的問題

接下來分享一下我們碰到的一些比較經典的Docker/Mesos相關的問題

1、Docker Issue

圖 6

在我們嘗試使用 Chronos 跑 cronjob 時,由於我們的 Job 執行頻率非常高,導致物理機上出現非常頻繁地容器創建和銷毀,容器的創建和銷毀比單個進程的創建和銷毀代價大,會產生很多次內核的調用,磁碟的分配銷毀,這對內核是一個非常大的壓力考驗。

我們在實際操作過程中就遇到了一個 bug,如圖 6 這台機器逐步失去響應,產生了 kernel soft lockup,慢慢的導致所有進程都死鎖了,最終物理機重啟了。為了避免頻繁創建銷毀容器,我們沒有在 Chronos這種一個 task 一個容器的路上繼續走下去,我們自己研發了 mesos framework,改成了一個Job,一個容器的調度方式。

2、Mesos Issue

  • running的容器數量較多以後,無法再啟動新的容器

    kernel.keys.root_maxkeys debian default 200,centos default 1M

  • mesos docker inspect 執行低效,尤其是單機容器數量大

  • MESOS_GC_DELAY:6h 20K->1h

  • MESOS_DOCKER_REMOVE_DELAY 1m

  • docker force pull false

  • API 性能差,功能不完善,獲取非同步 event 困難

  • overall,很穩定,調度性能足夠

Mesos 性能很穩定,基本上不需要修改 Mesos 代碼,只需要在我們自己寫的Framework進行控制調度,控制如何啟動容器。

3、CExecutor

圖7

1)自定義 CExecutor,Go 語言實現

-避免過於頻繁創建刪除容器,帶來的副作用

-cpuload 高而且抖動很大

-頻繁啟停容器引發的 docker 和 kernel 的 bug

2)task:container

-1:1->N:1

3)容器持久化

如圖 7,可以觀察得到前段抖動非常厲害(如果過渡頻繁地創建刪除容器,會帶來非常大的負擔,抖動會非常高),在用 1:1 調度之後就變得平緩了。所以攜程自定義 CExecutorr(Go 語言實現),避免過於頻繁創建刪除容器,帶來的副作用(抖動非常強、load非常高),之後就基本上處於水平線了。

七、容器監控方案

1、Mesos 監控

圖 8

圖 9

如圖 8-9 攜程用了很多開源技術,Telegraf、influxdb、Grafana 並做了一些擴展來實現mesos集群的監控,採集mesos-master狀態、task執行數量、executor狀態等等,以便當mesos集群出現問題時能第一時間知道整個集群狀態,進而進行修復,此外, 我們還從mesos調度入手,做了一些應用層的監控,比如: 針對cron job類型的應用,讓用戶可以看到 job 應該在什麼時候執行,執行的過程,整個 job 的成功率,job 還有多個實例在跑等;

2、容器監控

圖 10

攜程監控團隊全新開發了一套監控系統hickwall(2016.qconshanghai.com/s),也實現了對容器的監控支持;hickwall agent部署在容器物理機上,通過docker client 、cgroup等採集容器的運行情況,包括 CPU 、Memory、Disk IO等常規監控項;由於容器鏡像發布會非常頻繁的創建、刪除容器,因此我們把容器的監控也做成自動發現,由hickwall agent發現到新的容器,分析容器的label信息(比如: appid、版本等)來實現自動註冊監控;在單個容器監控的基礎上,還可以按照應用集群來聚合顯示整個集群的監控信息;

除此之外,攜程還做了各個業務訂單量的監控,比如說今天有多少出票量、酒店間夜數,而我們可以非常精準地根據歷史的信息預測未來的數據,比如說明天的這個時間點訂單量應該在多少、準確性在 95% 以上,一旦比預估的偏差太大的話,就會告警有異常,它把一個綜合的業務運行健康度提供給業務研發團隊,而不僅僅是單個容器的運行情況。

我們在線也會做一些壓測,比如說這個集群下面有 10 台機器,這 10 台機器的負載均衡權重都是 0.1,我們會把其中一台調高,看它的吞吐和響應的情況。測出它到了一定極限能提供的QPS,就可以知道這個集群還剩多少性能高容量,這個容量就是這個集群還能承載多大的壓力,比如說有 25% 的富餘,根據訂單的變化就可以知道還多多少或者還缺多少,這樣就能做到更好的擴縮容調度;目前基於vm的應用已經能基於容量規劃和預測實現自動擴容,後續容器的擴縮容也會接入,並且做到更實時的擴容和縮容調度;

此外,容器監控對於攜程創新工場的團隊是很有意義的,這些新孵化的BU對成本控制更嚴格,隨著容器上線,我們能為其提供性價比更高的基礎設施。

八、CDOS Overview

圖 11

CDOS 全稱是 CtripData Center Operating System, 我們希望通過CDOS來調度多個數據中心的資源,就好比一個操作系統調度各種資源給各個進程一樣,CDOS會調度多個數據中心的計算、網路、存儲的資源給到不同的應用,滿足各個應用所需的冗餘度,並且會動態的維持這個冗餘度,一旦出現異常,可以自動嘗試修復,刪除出現問題的容器實例,並部署新的實例;這裡面會涉及到非常多的模塊。

如圖 11 最上層是持續交付的發布系統,這一層是跟應用交付相關的東西,開發人員、測試人員都會用的發布系統。下面是針對不同運行模式的應用定製的兩套調度管理模塊,一個是cron Job,另一個是long running service;兩者在管理、部署、發布方面都有一些差異化;

底層資源分配是用Mesos 來實現,歷史原因,我們還有大量的服務部署在windows上, 因而需要同時支持windows server container 和 docker。長期來看未必是繼續使用 Docker,因為 Docker 太激進了,目前已經有多種container實現方式可以選擇。Windows 容器方面攜程也已經做了一些POC,實現類似前面提到的ovs + vlan的網路接入,遵循單容器單ip等原則,並且投入覆蓋了部分的測試環境。

圖中右邊有很多服務,比如L4/L7負載均衡、 SOA 的服務,CMS應用元數據管理、監控、日誌收集、鏡像管理和推送等模塊;由於我們採用容器鏡像發布,要實現秒級交付,對於鏡像推送速度有很高的要求,當base image沒有變化時,只需要把應用新版本build出來的app層通過我們開發的Ceph同步模塊推送的多個數據中心;當base image也變更時,情況會更複雜,除了同步到各個數據中心的Ceph對象存儲,還需要預先下發到可能用到的Docker伺服器,才能以最快的方式啟動容器。

以上就是攜程容器雲的概況介紹,歡迎大家一起來交流和探討。

【作者簡介】吳毅挺,攜程系統研發部高級總監。2012年加入攜程,從零組建攜程雲平台團隊,目前負責攜程私有雲、虛擬桌面雲、網站應用持續交付等研發。

沒看夠?更多來自攜程技術人的一手乾貨,歡迎搜索關注「攜程技術中心」微信公號哦~


推薦閱讀:

TAG:容器云 |