docker最佳實踐-----美團點評的分享

美團點評容器平臺簡介

本文介紹美團點評的Docker容器集羣管理平臺(如下簡稱「容器平臺」)。該平臺始於2015年,是基於美團雲的基礎架構和組件而開發的Docker容器集羣管理平臺。目前該平臺爲美團點評的外賣、酒店、到店、貓眼等十幾個事業部提供容器計算服務,承載線上業務數百個,日均線上請求超過45億次,業務類型涵蓋Web、數據庫、緩存、消息隊列等。docker

爲何要開發容器管理平臺

做爲國內大型的O2O互聯網公司,美團點評業務發展極爲迅速,天天線上發生海量的搜索、推廣和在線交易。在容器平臺實施以前,美團點評的全部業務都是運行在美團私有云提供的虛擬機之上。隨着業務的擴張,除了對線上業務提供極高的穩定性以外,私有云還須要有很高的彈性能力,可以在某個業務高峯時快速建立大量的虛擬機,在業務低峯期將資源回收,分配給其餘的業務使用。美團點評大部分的線上業務都是面向消費者和商家的,業務類型多樣,彈性的時間、頻度也不盡相同,這些都對彈性服務提出了很高的要求。在這一點上,虛擬機已經難以知足需求,主要體現如下兩點。數據庫

第一,虛擬機彈性能力較弱。使用虛擬機部署業務,在彈性擴容時,須要通過申請虛擬機、建立和部署虛擬機、配置業務環境、啓動業務實例這幾個步驟。前面的幾個步驟屬於私有云平臺,後面的步驟屬於業務工程師。一次擴容須要多部門配合完成,擴容時間以小時計,過程難以實現自動化。若是能夠實現自動化「一鍵快速擴容」,將極大地提升業務彈性效率,釋放更多的人力,同時也消除了人工操做致使事故的隱患。json

第二,IT成本高。因爲虛擬機彈性能力較弱,業務部門爲了應對流量高峯和突發流量,廣泛採用預留大量機器和服務實例的作法。即先部署好大量的虛擬機或物理機,按照業務高峯時所需資源作預留,通常是非高峯時段資源需求的兩倍。資源預留的辦法帶來很是高的IT成本,在非高峯時段,這些機器資源處於空閒狀態,也是巨大的浪費。後端

因爲上述緣由,美團點評從2015年開始引入Docker,構建容器集羣管理平臺,爲業務提供高性能的彈性伸縮能力。業界不少公司的作法是採用Docker生態圈的開源組件,例如Kubernetes、Docker Swarm等。咱們結合自身的業務需求,基於美團雲現有架構和組件,實踐出一條自研Docker容器管理平臺之路。咱們之因此選擇自研容器平臺,主要出於如下考慮。api

快速知足美團點評的多種業務需求

美團點評的業務類型很是普遍,幾乎涵蓋了互聯網公司全部業務類型。每種業務的需求和痛點也不盡相同。例如一些無狀態業務(例如Web),對彈性擴容的延遲要求很高;數據庫,業務的master節點,須要極高的可用性,並且還有在線調整CPU,內存和磁盤等配置的需求。不少業務須要SSH登錄訪問容器以便調優或者快速定位故障緣由,這須要容器管理平臺提供便捷的調試功能。爲了知足不一樣業務部門的多種需求,容器平臺須要大量的迭代開發工做。基於咱們所熟悉的現有平臺和工具,能夠作到「多快好省」地實現開發目標,知足業務的多種需求。緩存

從容器平臺穩定性出發,須要對平臺和Docker底層技術有更高的把控能力

容器平臺承載美團點評大量的線上業務,線上業務對SLA可用性要求很是高,通常要達到99.99%,所以容器平臺的穩定性和可靠性是最重要的指標。若是直接引入外界開源組件,咱們將面臨3個難題:1. 咱們須要摸熟開源組件,掌握其接口、評估其性能,至少要達到源碼級的理解;2. 構建容器平臺,須要對這些開源組件作拼接,從系統層面不斷地調優性能瓶頸,消除單點隱患等;3. 在監控、服務治理等方面要和美團點評現有的基礎設施整合。這些工做都須要極大的工做量,更重要的是,這樣搭建的平臺,在短期內其穩定性和可用性都難以保障。安全

避免重複建設私有云

美團私有云承載着美團點評全部的在線業務,是國內規模最大的私有云平臺之一。通過幾年的經營,可靠性通過了公司海量業務的考驗。咱們不能由於要支持容器,就將成熟穩定的私有云擱置一旁,另起爐竈再從新開發一個新的容器平臺。所以從穩定性、成本考慮,基於現有的私有云來建設容器管理平臺,對咱們來講是最經濟的方案。網絡

美團點評容器管理平臺架構設計

咱們將容器管理平臺視做一種雲計算模式,雲計算的架構一樣適用於容器。如前所述,容器平臺的架構依託於美團私有云現有架構,其中私有云的大部分組件能夠直接複用或者通過少許擴展開發。容器平臺架構以下圖所示。架構


美團點評容器管理平臺架構
美團點評容器管理平臺架構app

能夠看出,容器平臺總體架構自上而下分爲業務層、PaaS層、IaaS控制層及宿主機資源層,這與美團雲架構基本一致。

業務層:表明美團點評使用容器的業務線,他們是容器平臺的最終用戶。
PaaS層:使用容器平臺的HTTP API,完成容器的編排、部署、彈性伸縮,監控、服務治理等功能,對上面的業務層經過HTTP API或者Web的方式提供服務。
IaaS控制層:提供容器平臺的API處理、調度、網絡、用戶鑑權、鏡像倉庫等管理功能,對PaaS提供HTTP API接口。
宿主機資源層:Docker宿主機集羣,由多個機房,數百個節點組成。每一個節點部署HostServer、Docker、監控數據採集模塊,Volume管理模塊,OVS網絡管理模塊,Cgroup管理模塊等。
容器平臺中的絕大部分組件是基於美團私有云已有組件擴展開發的,例如API,鏡像倉庫、平臺控制器、HostServer、網絡管理模塊,下面將分別介紹。

API

API是容器平臺對外提供服務的接口,PaaS層經過API來建立、部署雲主機。咱們將容器和虛擬機看做兩種不一樣的虛擬化計算模型,能夠用統一的API來管理。即虛擬機等同於set(後面將詳細介紹),磁盤等同於容器。這個思路有兩點好處:1. 業務用戶不須要改變雲主機的使用邏輯,原來基於虛擬機的業務管理流程一樣適用於容器,所以能夠無縫地將業務從虛擬機遷移到容器之上;2. 容器平臺API沒必要從新開發,能夠複用美團私有云的API處理流程
建立虛擬機流程較多,通常須要經歷調度、準備磁盤、部署配置、啓動等多個階段,平臺控制器和Host-SRV之間須要不少的交互過程,帶來了必定量的延遲。容器相對簡單許多,只須要調度、部署啓動兩個階段。所以咱們對容器的API作了簡化,將準備磁盤、部署配置和啓動整合成一步完成,經簡化後容器的建立和啓動延遲不到3秒鐘,基本達到了Docker的啓動性能。

Host-SRV

Host-SRV是宿主機上的容器進程管理器,負責容器鏡像拉取、容器磁盤空間管理、以及容器建立、銷燬等運行時的管理工做。

鏡像拉取:Host-SRV接到控制器下發的建立請求後,從鏡像倉庫下載鏡像、緩存,而後經過Docker Load接口加載到Docker裏。

容器運行時管理:Host-SRV經過本地Unix Socker接口與Docker Daemon通訊,對容器生命週期的控制,並支持容器Logs、exec等功能。

容器磁盤空間管理:同時管理容器Rootfs和Volume的磁盤空間,並向控制器上報磁盤使用量,調度器可依據使用量決定容器的調度策略。

Host-SRV和Docker Daemon經過Unix Socket通訊,容器進程由Docker-Containerd託管,因此Host-SRV的升級發佈不會影響本地容器的運行。

鏡像倉庫

容器平臺有兩個鏡像倉庫:

  • Docker Registry: 提供Docker Hub的Mirror功能,加速鏡像下載,便於業務團隊快速構建業務鏡像;
  • Glance: 基於Openstack組件Glance擴展開發的Docker鏡像倉庫,用以託管業務部門製做的Docker鏡像。

鏡像倉庫不只是容器平臺的必要組件,也是私有云的必要組件。美團私有云使用Glance做爲鏡像倉庫,在建設容器平臺以前,Glance只用來託管虛擬機鏡像。每一個鏡像有一個UUID,使用Glance API和鏡像UUID,能夠上傳、下載虛擬機鏡像。Docker鏡像其實是由一組子鏡像組成,每一個子鏡像有獨立的ID,並帶有一個Parent ID屬性,指向其父鏡像。咱們稍加改造了一下Glance,對每一個Glance鏡像增長Parent ID的屬性,修改了鏡像上傳和下載的邏輯。通過簡單擴展,使Glance具備託管Docker鏡像的能力。經過Glance擴展來支持Docker鏡像有如下優勢:

  • 可使用同一個鏡像倉庫來託管Docker和虛擬機的鏡像,下降運維管理成本;
  • Glance已經十分紅熟穩定,使用Glance能夠減小在鏡像管理上踩坑;
  • 使用Glance可使Docker鏡像倉庫和美團私有云「無縫」對接,使用同一套鏡像API,能夠同時支持虛擬機和Docker鏡像上傳、下載,支持分佈式的存儲後端和多租戶隔離等特性;
  • Glance UUID和Docker Image ID是一一對應的關係,利用這個特性咱們實現了Docker鏡像在倉庫中的惟一性,避免冗餘存儲。

可能有人疑問,用Glance作鏡像倉庫是「從新造輪子」。事實上咱們對Glance的改造只有200行左右的代碼。Glance簡單可靠,咱們在很短的時間就完成了鏡像倉庫的開發上線,目前美團點評已經託管超過16,000多個業務方的Docker鏡像,平均上傳和下載鏡像的延遲都是秒級的。

高性能、高彈性的容器網絡

網絡是十分重要的,又有技術挑戰性的領域。一個好的網絡架構,須要有高網絡傳輸性能、高彈性、多租戶隔離、支持軟件定義網絡配置等多方面的能力。早期Docker提供的網絡方案比較簡單,只有None、Bridge、Container和Host這四種網絡模式,也沒有用戶開發接口。2015年Docker在1.9版本集成了Libnetwork做爲其網絡的解決方案,支持用戶根據自身需求,開發相應的網絡驅動,實現網絡功能自定義的功能,極大地加強了Docker的網絡擴展能力。

從容器集羣系統來看,只有單宿主機的網絡接入是遠遠不夠的,網絡還須要提供跨宿主機、機架和機房的能力。從這個需求來看,Docker和虛擬機來講是共通的,沒有明顯的差別,從理論上也能夠用同一套網絡架構來知足Docker和虛擬機的網絡需求。基於這種理念,容器平臺在網絡方面複用了美團雲網絡基礎架構和組件。


美團點評容器平臺網絡架構
美團點評容器平臺網絡架構

數據平面: 咱們採用萬兆網卡,結合OVS-DPDK方案,並進一步優化單流的轉發性能,將幾個CPU核綁定給OVS-DPDK轉發使用,只須要少許的計算資源便可提供萬兆的數據轉發能力。OVS-DPDK和容器所使用的CPU徹底隔離,所以也不影響用戶的計算資源。

控制平面: 咱們使用OVS方案。該方案是在每一個宿主機上部署一個自研的軟件Controller,動態接收網絡服務下發的網絡規則,並將規則進一步下發至OVS流表,決定是否對某網絡流放行。

MosBridge

在MosBridge以前,咱們配置容器網絡使用的是None模式。所謂None模式也就是自定義網絡的模式,配置網絡須要以下幾步:

  1. 在建立容器時指定—net=None,容器建立啓動後沒有網絡;
  2. 容器啓動後,建立eth-pair;
  3. 將eth-pair一端鏈接到OVS Bridge上;
  4. 使用nsenter這種Namespace工具將eth-pair另外一端放到容器的網絡Namespace中,而後更名、配置IP地址和路由。

然而,在實踐中,咱們發現None模式存在一些不足:

  • 容器剛啓動時是無網絡的,一些業務在啓動前會檢查網絡,致使業務啓動失敗;
  • 網絡配置與Docker脫離,容器重啓後網絡配置丟失;
  • 網絡配置由Host-SRV控制,每一個網卡的配置流程都是在Host-SRV中實現的。之後網絡功能的升級和擴展,例如對容器添加網卡,或者支持VPC,會使Host-SRV愈來愈難以維護。

爲了解決這些問題,咱們將眼光投向Docker Libnetwork。Libnetwork爲用戶提供了能夠開發Docker網絡的能力,容許用戶基於Libnetwork實現網絡驅動來自定義其網絡配置的行爲。就是說,用戶能夠編寫驅動,讓Docker按照指定的參數爲容器配置IP、網關和路由。基於Libnetwork,咱們開發了MosBridge – 適配美團雲網絡架構的Docker網絡驅動。在建立容器時,須要指定容器建立參數—net=mosbridge,並將IP地址、網關、OVS Bridge等參數傳給Docker,由MosBridge完成網絡的配置過程。有了MosBridge,容器建立啓動後便有了網絡可使用。容器的網絡配置也持久化在MosBridge中,容器重啓後網絡配置也不會丟失。更重要的是,MosBridge使Host-SRV和Docker充分解耦,之後網絡功能的升級也會更加方便。

解決Docker存儲隔離性的問題

業界許多公司使用Docker都會面臨存儲隔離性的問題。就是說Docker提供的數據存儲的方案是Volume,經過mount bind的方式將本地磁盤的某個目錄掛載到容器中,做爲容器的「數據盤」使用。這種本地磁盤Volume的方式沒法作到容量限制,任何一個容器均可以不加限制地向Volume寫數據,直到佔滿整個磁盤空間。


LVM-Volume方案
LVM-Volume方案

針對這一問題,咱們開發了LVM Volume方案。該方案是在宿主機上建立一個LVM VG做爲Volume的存儲後端。建立容器時,從VG中建立一個LV看成一塊磁盤,掛載到容器裏,這樣Volume的容量便由LVM加以強限制。得益於LVM機強大的管理能力,咱們能夠作到對Volume更精細、更高效的管理。例如,咱們能夠很方便地調用LVM命令查看Volume使用量,經過打標籤的方式實現Volume僞刪除和回收站功能,還可使用LVM命令對Volume作在線擴容。值得一提地是,LVM是基於Linux內核Devicemapper開發的,而Devicemapper在Linux內核的歷史悠久,早在內核2.6版本時就已合入,其可靠性和IO性能徹底能夠信賴。

適配多種監控服務的容器狀態採集模塊

容器監控是容器管理平臺極其重要的一環,監控不只僅要實時獲得容器的運行狀態,還須要獲取容器所佔用的資源動態變化。在設計實現容器監控以前,美團點評內部已經有了許多監控服務,例如Zabbix、Falcon和CAT。所以咱們不須要從新設計實現一套完整的監控服務,更多地是考慮如何高效地採集容器運行信息,根據運行環境的配置上報到相應的監控服務上。簡單來講,咱們只須要考慮實現一個高效的Agent,在宿主機上能夠採集容器的各類監控數據。這裏須要考慮兩點:

  1. 監控指標多,數據量大,數據採集模塊必須高效率;
  2. 監控的低開銷,同一個宿主機能夠跑幾十個,甚至上百個容器,大量的數據採集、整理和上報過程必須低開銷。
    監控數據採集方案
    監控數據採集方案

針對業務和運維的監控需求,咱們基於Libcontainer開發了Mos-Docker-Agent監控模塊。該模塊從宿主機proc、CGroup等接口採集容器數據,通過加工換算,再經過不一樣的監控系統driver上報數據。該模塊使用GO語言編寫,既能夠高效率,又能夠直接使用Libcontainer。並且監控的數據採集和上報過程不通過Docker Daemon,所以不會加劇Daemon的負擔。

在監控配置這塊,因爲監控上報模塊是插件式的,能夠高度自定義上報的監控服務類型,監控項配置,所以能夠很靈活地適應不一樣的監控場景的需求。

支持微服務架構的設計

近幾年,微服務架構在互聯網技術領域興起。微服務利用輕量級組件,將一個大型的服務拆解爲多個能夠獨立封裝、獨立部署的微服務實例,大型服務內在的複雜邏輯由服務之間的交互來實現。

美團點評的不少在線業務是微服務架構的。例如美團點評的服務治理框架,會爲每個在線服務配置一個服務監控Agent,該Agent負責收集上報在線服務的狀態信息。相似的微服務還有許多。對於這種微服務架構,使用Docker能夠有如下兩種封裝模式。

  1. 將全部微服務進程封裝到一個容器中。但這樣使服務的更新、部署很不靈活,任何一個微服務的更新都要從新構建容器鏡像,這至關於將Docker容器看成虛擬機使用,沒有發揮出Docker的優點。
  2. 將每一個微服務封裝到單獨的容器中。Docker具備輕量、環境隔離的優勢,很適合用來封裝微服務。不過這樣可能產生額外的性能問題。一個是大型服務的容器化會產生數倍的計算實例,這對分佈式系統的調度和部署帶來很大的壓力;另外一個是性能惡化問題,例若有兩個關係緊密的服務,相互通訊流量很大,但被部署到不一樣的機房,會產生至關大的網絡開銷。

對於支持微服務的問題,Kubernetes的解決方案是Pod。每一個Pod由多個容器組成,是服務部署、編排、管理的最小單位,也是調度的最小單位。Pod內的容器相互共享資源,包括網絡、Volume、IPC等。所以同一個Pod內的多個容器相互之間能夠高效率地通訊。

咱們借鑑了Pod的思想,在容器平臺上開發了面向微服務的容器組,咱們內部稱之爲set。一個set邏輯示意以下圖所示。


Set邏輯示意圖
Set邏輯示意圖

set是容器平臺的調度、彈性擴容/縮容的基本單位。每一個set由一個BusyBox容器和若干個業務容器組成, BusyBox容器不負責具體業務,只負責管理set的網絡、Volume和IPC配置。


set的配置json
set的配置json

set內的全部容器共享網絡,Volume和IPC。set配置使用一個JSON描述(如圖6所示),每個set實例包含一個Container List,Container的字段描述了該容器運行時的配置,重要的字段有:

  • Index,容器編號,表明容器的啓動順序;
  • Image,Docker鏡像在Glance上的name或者ID;
  • Options,描述了容器啓動時的參數配置。其中CPU和MEM都是百分比,表示這個容器相對於整個set在CPU和內存的分配狀況(例如,對於一個4核的set而言,容器CPU:80,表示該容器將最多使用3.2個物理核)。

經過set,咱們將美團點評的全部容器業務都作了標準化,即全部的線上業務都是用set描述,容器平臺內只有set,調度、部署、啓停的單位都是set。
對於set的實現上咱們還作了一些特殊處理:

  • Busybox具備Privileged權限,能夠自定義一些sysctl內核參數,提高容器性能。
  • 爲了穩定性考慮,用戶不容許SSH登錄Busybox,只容許登錄其餘業務容器。
  • 爲了簡化Volume管理,每個set只有一個Volume,並掛載到Busybox下,每一個容器相互共享這個Volume。

不少時候一個set內的容器來自不一樣的團隊,鏡像更新頻度不一,咱們在set基礎上設計了一個灰度更新的功能。該功能容許業務只更新set中的部分容器鏡像,經過一個灰度更新的API,便可將線上的set升級。灰度更新最大的好處是能夠在線更新部分容器,並保持線上服務不間斷。

Docker穩定性和特性的解決方案:MosDocker

衆所周知,Docker社區很是火熱,版本更新十分頻繁,大概2~4個月左右會有一個大版本更新,並且每次版本更新都會伴隨大量的代碼重構。Docker沒有一個長期維護的LTS版本,每次更新不可避免地會引入新的Bug。因爲時效緣由,通常狀況下,某個Bug的修復要等到下一個版本。例如1.11引入的Bug,通常要到1.12版才能解決,而若是使用了1.12版,又會引入新的Bug,還要等1.13版。如此一來,Docker的穩定性很難知足生產場景的要求。所以十分有必要維護一個相對穩定的版本,若是發現Bug,能夠在此版本基礎上,經過自研修復,或者採用社區的BugFix來修復。

除了穩定性的需求以外,咱們還須要開發一些功能來知足美團點評的需求。美團點評業務的一些需求來自於咱們本身的生產環境,而不屬於業界通用的需求。對於這類需求,開源社區一般不會考慮。業界許多公司都存在相似的狀況,做爲公司基礎服務團隊就必須經過技術開發來知足這種需求。

基於以上考慮,咱們從Docker 1.11版本開始,自研維護一個分支,咱們稱之爲MosDocker。之因此選擇從版本1.11開始,是由於從該版本開始,Docker作了幾項重大改進:
Docker Daemon重構爲Daemon、Containerd和runC這3個Binary,並解決Daemon的單點失效問題;

  • 支持OCI標準,容器由統一的rootfs和spec來定義;
  • 引入了Libnetwork框架,容許用戶經過開發接口自定義容器網絡;
  • 重構了Docker鏡像存儲後端,鏡像ID由原來的隨即字符串轉變爲基於鏡像內容的Hash,使Docker鏡像安全性更高。

到目前爲止,MosDocker自研的特性主要有:

  1. MosBridge,支持美團雲網絡架構的網絡驅動, 基於此特性實現容器多IP,VPC等網絡功能;
  2. Cgroup持久化,擴展Docker Update接口,可使更多的CGroup配置持久化在容器中,保證容器重啓後CGroup配置不丟失。
  3. 支持子鏡像的Docker Save,能夠大幅度提升Docker鏡像的上傳、下載速度。

總之,維護MosDocker使咱們能夠將Docker穩定性逐漸控制在本身手裏,而且能夠按照公司業務的需求作定製開發。

在實際業務中的推廣應用

在容器平臺運行的一年多時間裏,已經接入了美團點評多個大型業務部門的業務,業務類型也是多種多樣。經過引入Docker技術,爲業務部門帶來諸多好處,典型的好處包括如下兩點。

  • 快速部署,快速應對業務突發流量。因爲使用Docker,業務的機器申請、部署、業務發佈一步完成,業務擴容從原來的小時級縮減爲秒級,極大地提升了業務的彈性能力。
  • 節省IT硬件和運維成本。Docker在計算上效率更高,加之高彈性使得業務部門沒必要預留大量的資源,節省大量的硬件投資。以某業務爲例,以前爲了應對流量波動和突發流量,預留了32臺8核8G的虛擬機。使用容器彈性方案,即3臺容器+彈性擴容的方案取代固定32臺虛擬機,平均單機QPS提高85%, 平均資源佔用率下降44-56%(如圖7,8所示)。
  • Docker在線擴容能力,保障服務不中斷。一些有狀態的業務,例如數據庫和緩存,運行時調整CPU、內存和磁盤是常見的需求。以前部署在虛擬機中,調整配置須要重啓虛擬機,業務的可用性不可避免地被中斷了,成爲業務的痛點。Docker對CPU、內存等資源管理是經過Linux的CGroup實現的,調整配置只須要修改容器的CGroup參數,沒必要重啓容器。


某業務虛擬機和容器平均單機QPS
某業務虛擬機和容器平均單機QPS

某業務虛擬機和容器資源使用量
某業務虛擬機和容器資源使用量

結束語

本文介紹了美團點評Docker的實踐狀況。通過一年的推廣實踐,從部門內部本身使用,到覆蓋公司大部分業務部門和產品線;從單一業務類型到公司線上幾十種業務類型,證實了Docker這種容器虛擬化技術在提升運維效率,精簡發佈流程,下降IT成本等方面的價值。

目前Docker平臺還在美團點評深刻推廣中。在這個過程當中,咱們發現Docker(或容器技術)自己存在許多問題和不足,例如,Docker存在IO隔離性不強的問題,沒法對Buffered IO作限制;偶爾Docker Daemon會卡死,無反應的問題;容器內存OOM致使容器被刪除,開啓OOM_kill_disabled後可能致使宿主機內核崩潰等問題。所以Docker技術,在咱們看來和虛擬機應該是互補的關係,不能期望在全部場景中Docker均可以替代虛擬機,所以只有將Docker和虛擬機並重,才能知足用戶的各類場景對雲計算的需求。

相關文章
相關標籤/搜索