《去哪兒網利用Mesos和Docker構建dev—beta環境》要點:
本文介紹了去哪兒網利用Mesos和Docker構建dev—beta環境,希望對您有用。如果有疑問,可以聯系我們。
大家好,我是去哪兒網的張寧,之前是做配置管理,2015年6月份轉到去哪網做運維開發,現在主要從事的工作是基于Mesos和Docker快速構建dev和beta環境,基礎架構是Mesos Marathon.
最初我們是想做一個內部的PaaS平臺,但是因為底層的架構也剛開始嘗試Docker,所以說基層架構現在不是特別完善.包括我們內部在開發的一些系統,現在基本完成的是發布這個環節,在這里主要跟大家分享一下發布這一塊,以及在使用Docker和Marathon過程中遇到的一些問題.
本次演講主要分五部分:
首先是業務線的一些期望,因為我們之前有一個發布系統,最早的時候是單模塊發布,但是我們業務上線的時候基本上需要多模塊一起上線才能組成一個完整的服務,所以大家在發布的時候就會比較頭疼,需要手工把所有的項目給發布上線.尤其是dev和開發環境,大家在準備起來的時候經常會遇到很多問題,環境比較亂,所以開發和QA在部署環境時是比較頭疼的,他們希望可以一鍵部署整套環境,包括MySQL、Redis、ZooKeeper、Memcached這些基礎模塊,同時也希望能夠快速部署環境,可以得到快速的反饋.
其次就是環境隔離,使用傳統部署方式時,大家因為部署環境特別麻煩,就經常使用公用環境,導致環境里面經常會有一些臟數據,所以他們希望每個人能有自己的環境,不受其他人的影響.
最后一點就是學習和維護成本盡量要低,希望可以讓新來的同學點一個按紐就可以發布,也不用過多地去了解里面的一些概念.總結下來要解決他們的各種環境問題.
從我們要做這個發布系統的初衷來說:
其實最早我們也調研過Kubernetes,但是因為在我們的使用場景中都是單容器,不需要兩個容器里邊的應用共享網絡或者資源的情況,用不到Kubernetes中pod的一些優勢,所以我們就直接用了Mesos Marathon,全都是單獨的Docker容器.另外一個就是因為我們更多的是多項目之間有關聯的這種情況,其實像Swarm的Compose文件可能支持編排,但是這種編排也只是順序啟動,中間沒有什么校驗的環節.還有像Kubernetes其實也可以做這種編排,但是也是缺少這種更具個性化校驗的功能,所以我們在系統之間依賴這一層做的東西全都是發布系統里面需做的一些check.現在公司的日志系統是基于Mesos和Marathon的,已經在上線使用,如果我們用這個架構的話就可以借鑒之前的一些經驗,也可以避免一些之前遇到的坑.
雖然上面我們選型基本定了,但是在落地的時候其實還是有一些細節是需要考慮的.
第一是是否每次都要build鏡像.每一個使用Docker做發布系統的團隊都會考慮的這個問題,我們是使用固定的鏡像,每次是把編譯的代碼上傳到一個共享存儲,然后是使用公共的鏡像啟動之后直接去拉取代碼,沒有每次去build鏡像,因為在我們的dev和beta環境,這兩個環境可能大家的代碼變化頻率是很大的,并沒有達到Docker最原始的初衷,就是一個Container搬到哪都能用.但是如果我們要給它打成一個鏡像的話,其實鏡像里面代碼是經常變的,這個Container并不是dev環境用完,beta就能用,所以我們就想了一個更靈活的方式,就是每次編譯完代碼上傳到一個對象存儲,然后在Docker容器啟動后去拉代碼,這樣任何時候啟動都可以拿到最新的一個版本,任何版本都可以通過相應的參數來指定.
第二是是否使用Jenkins-Mesos.其實Mesos有基于Jenkins原生的CI解決方案,我們這邊也沒有用,我也建議大家如果硬件能滿足條件的情況下還是用固定的機器會比較好.我們的編譯就統一使用的是SSD硬盤然后加大內存,這樣可以保證編譯速度.如果要是在Mesos Marathon的集群里面去完成這件事的,不可能把整個集群都做成SSD硬盤的這種硬件設施.另外一方面就是我們這邊項目比較多,如果有一個?Maven的local repo,就會加快編譯速度,如果是每次在生成的新容器里邊編譯可能也會慢.
第三是如何加快dev和beta環境構建.我們目前做的是所有模塊是并行編譯,然后分批部署,沒有做并行部署的原因是因為我們有一些依賴,所以我們會在開始部署之前根據依賴關系計算一個部署順序,然后再去分批部署.現在大概是40多個模塊的一個環境,可以在20分鐘以內完成全部編譯和部署.
第四是使用方式如何能夠平滑過渡.我們現在做的這個發布系統是基于我們公司最早的一套發布系統做的,之前的架構包括分支策略都已經確定了,我覺得之前的方案也是很好的,我們基本上是延續之前的那個發布系統來做的,只是再把Deploy里邊的很多操作給轉移到Docker里面去做,但是編譯階段是延續之前的,所以我們保留了之前發布系統里面的一些必要參數,然后簡化了一些部署階段的參數,這樣用戶學習和接受起來比較容易.
第五是如何建立容器發布的流程標準.每個公司開發的流程是不一樣的,運維體系也是不一樣的,所以說這個只是根據我們現在的一個運維體系以及開發的流程重新做了一個系統,下面會有具體的介紹.
第六是運維能否支撐.因為我們現在日志平臺已經在線上使用了,所以說我們就直接借鑒了他們的一些經驗,目前看來基于這個架構來做還是比較順暢的.
第七是資源利用率是否真的提高了.這個也是大家比較關心的,我們公司原來是OpenStack上面有KVM,一般大家會申請4G內存的機器,可以部署三個應用.然后我這邊做 Docker 的話,大概是一個Docker里面一個應用,默認是1G內存,所以說有可能少部分的主項目它占用的內存比較多,大概需要2G或者3G,但是80%的項目都1G就夠用了,我覺得大概資源利用率至少可以提高20%左右.我現在還沒有做資源的壓縮,現在系統還在試用階段,等系統穩定以后,還要把現在有富裕的一些再進行壓縮一下,資源利用率還會再細化.
下面講一下系統架構,上圖是我們這個平臺的主要架構,底層資源層是Mesos Marathon,上層封了一個OpenResty,主要是做一個泛域名,方便啟在Marathon上面的所有應用可以通過一個統一的入口進行測試.因為可能大家用Marathon的情況大多數都是用host的模式,host的模式會隨機分配主機和端口號,如果每次發布端口號都會變的話,用戶在測試的時候是很難記住它的名字的,所以我們就封裝了一個泛域名,只要這一套環境名不變、應用名不變,它訪問的域名就是固定的.上一層是我們自己開發的一個用戶入口,就是現在最基本的應用樹,基于應用樹可以錄入基礎的應用信息(后面都會有具體講解),可以在應用樹上面去做資源的管理,申請資源、環境管理.我們其實發布還是用的Jenkins,上面開發了一個插件,環境管理是直接調用的Jenkins的接口去進行config文件的同步,觸發構建這樣的操作.然后是數據庫管理,因為發布的時候大家也需要數據庫支持,我們現在使用的是一個比較粗暴的方式,是用一個標準庫是定期去同步線上的表結構,但是這個操作現在大部分還是手動的,希望以后做成自動的(數據庫管理系統來做這件事,下面也會有具體的講解).通過發布可以調用Marathon的接口,然后創建Docker容器,有各種類型的一些服務,有Web的Container這種,然后上層是接的我們公司現有的一些監控平臺,日志平臺還有可以直接訪問容器里面的客戶端,我們內部叫“八爪魚”,它有網頁版,也有客戶端版,其實這個主要就是封裝的一個Docker的EXEC,然后可以直接登陸到里面去.
上圖對系統架構圖的一個細化,這個是底層資源層,像Mesos、Marathon有一些定時任務是用Chronos,上面應用層比如說業務有部署的Canal、MySQL以及Solr,然后基礎服務比如說有Confd日志、Heka、cAdvisor做Docker自己本身的監控,Prism是我們自己內部的一個日志平臺,Watcher是做業務監控.
QAECI這個架構主要是發布系統的那一個環節,是從Git或者SVN上下載代碼,然后在編譯機上進行統一的編譯,編譯完的以后上傳到Swift上,一個共享存儲,然后就調用Marathon的接口去創建Docker容器,啟動Docker的時候去拉取代碼,然后做一些配制替換,包括某些項目一些特殊的操作,可以通過service腳本去執行,這樣就完成了部署.基礎的操作做完了以后會啟動服務,因為我們這邊大部分都是Web服務,所以我們會有一個check url的工作去來檢查這個服務是正常啟動的.我剛才說像Compose還有YAML文件的編排沒有辦法直接來做,就是因為我們為了保證服務是正常的,需要做check url,雖然Marathon有health check的功能,但是我們并沒有直接用,是因為想給用戶保留一個現場.如果health check沒有通過,Marathon會一直去重啟,這樣的話用戶沒有辦法去發現它的環境到底出了什么問題,就是說我們是通過自己的腳本去做這個檢查.
QAECI系統里面的一些關鍵點,簡單跟大家介紹一下.
第一個是使用app_code作為應用的唯一標識.因為我們之前的發布系統是每新建一個job就要把一個應用所有的參數全部填寫一遍,這樣就需要分不同的環境需要建多個job.有一些基礎信息需要變化的時候,每一個job都需要去修改,而且在系統之間做關聯的時候也沒有一個唯一的標識服務,比如說日志系統,然后還有應用中心那邊,或者監控,可能大家都沒有一個通信的ID,所以我們就統一了一個標識服務,只要它有一個唯一ID,在任何系統之間都是打通的,就是它的信息是可以帶到任何系統里面去.
第二個是基礎信息統一記錄.基礎信息不需要在每一次發布的時候再去維護,而是在一個地方統一去維護,然后發布的job上基本只需要勾選上自己要發的模塊,以及要發的分支就可以簡單的去進行發布了,沒有太多額外的參數、維護成本特別低.
第三個是配制文件模板化.這個也是比較重要的一點,之前在建多個環境的時候,Maven的Procfile文件都需要有多套,就是因為有一些環境的信息比如說連接其他環境的一些接口的地址如MySQL的地址,這些全都是寫成固定的,每一套環境里面都是不一樣,我新建一套環境就要新加一套配制文件,但是現在為了可以簡單的部署一套環境,我們把這個配制文件模板化了,這種環境相關的情況,只要按照我們提供的常量去改,然后我們在起環境的時候就可以自動進行替換,這樣就可以保證每個人有自己的環境,而不需要再去維護那么多配套文件.
第四個是計算部署順序.這個也是我們業務相關的,就是部署經常會有那種Web服務有依賴,所以我們要在發布的時候計算這個部署順序,然后以保證它起來的環境是可用的.
第五個是泛域名.我們用OpenResty做的一個域名服務,這個是可以方便大家很容易的測試自己的服務的一個工具.
上圖就是我們在記錄系統基礎信息的一個截圖,信息相對多一些.圖中有一些Java的選項要填,然后可以看到其實它最基本的就只有scm_root,就是一個版本控制的地址,編譯的結果、編譯類型還有check url,下面比較重要的是一個部署依賴,這個就是會計算它部署順序的,基本只需要這些信息.
這個是一個發布job的展示,我們做了自己的插件——Qunar Build.大家可以看到右邊上面是一些基礎信息,這個決定它的環境是什么,是dev、beta還是線上,我這里面沒有展示,其實它勾選每一個,就是每一個有check box的都是一個app_code,然后它具體的信息是通過剛才這個平臺的接口去獲取的,所以說它下面每一個app_code都不需要再填自己的基礎信息,只要填自己本次要部署的分支名稱就可以了.
上圖就是我們做的環境管理,這個環境管理其實調用的是Jenkins的一些接口,這邊展示的信息會比那邊更直觀一些,可以看到它每一個app_code后面都只有自己的tag name,就是相當于只有它的分支,其他的比如說build_type是自己這定義的,它就會覆蓋上面的,如果這邊沒有定義的話,就都只用上面公共的.
下面說一下我們在使用過程中目前系統還存在的問題以及未來的計劃,我們現在在用Marathon的時候,剛才有說現在主要用host模式,host模式它很靈活的一點就是,比較簡單,而且都不需要我們管理,IP地址直接用的是宿主機的,但是存在的一個問題就是一旦有容器掛掉,或者說有宿主機有問題,還會在飄的時候再隨機啟動,這樣如果通過固定IP或者端口號來通信的一些服務,有可能會有問題,找不到之前的服務,因為它里面可能記錄的是之前的那個接點,所以我們現在也在嘗試給 Mesos 分配固定 IP 這樣一些網絡解決方案,我們現在嘗試的是Calico.
上圖是一個網上截圖,我就主要說一下我們這邊的使用方式.發布系統根據app_code等信息自動生成一個主機名,到DNSDB里邊bind一個IP地址,Marathon需要改成bridge模式,通過Marathon的配置文件把主機名和IP地址賦給新建的容器.但是我們并沒有大規模使用這個的原因是,dev和beta環境可以這樣用,因為它基本只有一個instance,每一個Marathon上面的APP只有一個instance,但是如果是真正的線上環境的話,肯定需要多個instance,在多實例的情況下,Marathon沒有辦法確定如何指定每一個instance具體的IP地址.當然Calico可以auto的方式去分,但是采用auto的方式,我們現在遇到一些問題,也可能是設置問題,就是它會把管理IP也分給容器,這樣的話就有可能會導致整個網絡有問題.
另外如果通過auto這種方式分給Docker容器的話,這個信息是不能返回給Marathon或者Mesos接口的,所以我們是沒有辦法再次拿到這個信息.因為我們拿到這個信息是要給下面的一些依賴以及服務用的,我們現在還沒有做所有基于集群的宿主的一個Agent,所以我們拿不到這個信息,現在也沒有真正在線上用.我們現在用Calico,只有給Nginx的這種容器使用Calico,這個就是方便大家可以本地配host去測試,可以不用每次總是改IP地址.
下一個問題就是集群里面的宿主問題,應用自動飄可能會啟動失敗,它如果有強依賴的話,一旦飄有可能找不到之前已經記錄的端口.如果暫時沒有辦法通過Calico去解決的話,后面會在Entrypoint?里邊去做檢查,也會用上Marathon自己的一個Dependency功能,它其實自己有Dependency功能,但是這個Dependency功能默認是基于它的health check,如果加了health check之后啟動成功了,然后才會起后面依賴的應用,但是如果在我們沒有加health check的情況下,它只是判斷上一個應用起來了,然后下一個應用才會去啟動.這樣在啟動的時候,因為沒有去檢查上一個應用是不是真的在check url時能返回200,有可能啟動失敗,所以以后我們可能會自己做更多的一些檢查.下面就是DBCI,這個也是我們之后要做的一個系統,DBA現在有一個系統是可以發布SQL語句上線,然后我們以后要跟DBA的系統做一個打通,那邊腳本有上線的話,我們這邊會自動同步到標準庫以及基于這個標準庫創建的各個Docker容器里面.
關于數據庫使用標準庫這塊也有一個經驗,之前我們用標準庫是把標準庫里面的數據給Dump出來,然后在Docker容器里面import,這樣的話,如果一個標準庫特別大的話像我們有一個標準庫能達到四五十個庫,占用的時間就會特別長,大概17分鐘左右.后來我們做了一個改進,就是標準庫的data目錄也是打包直接上傳到對象存儲上面,MySQL的Docker容器會從它對應的標準庫的地址,從Swift 上面去拉相應的tar包,然后解壓,這樣大概能縮短至1分半左右,所以說速度有很大的提升.其實關于數據庫這塊,我覺得從根本上解決問題的辦法是數據庫版本控制,但是因為我們現在業務線特別多,推起來也比較困難,所以我們現在是采用這種解決方案.
我們后面要接進來的是日志,還有ELK查詢,然后還有監控和報警,監控是cAdvisor,主要是做Docker自身的監控,我們公司有做了一些二次開發.watcher是我們公司基于一個開源的監控系統做了一個二次開發,這個主要是做業務監控.
上圖是Kabana上查看日志的一個簡介,它可以定制一些面板,有各種搜索.
上圖是我們監控的一些展示,有一些業務的流量,還可以定制各種監控指標.
這個是我們未來要做的,考慮應用自身的擴容,就是動態Slave?.針對我們底層的集群平臺也會做一些動態的擴容,因為現在業務在慢慢往Docker上遷的時候,OpenStack的虛擬機會有一些空閑,可能以后會動態的去檢查請OpenStack的虛擬機那邊的空閑情況來做一些平衡(如果要是申請真正的實體機來作為我們的Docker集群的話,這個會要走一個采購流程).
第一點是Docker Devicemapper限制要調大.這個也是我之前遇到的一個問題,默認Docker Devicemapper只有100G的大小,如果像256G內存的一個機器上大概能啟200個容器,雖然我們是把日志還有數據比較大的都已經給掛載到宿主機上,但是啟一個容器還是要占一些空間的,所以說100G很容易就吃滿,然后會導致整個Docker就沒有辦法啟其他的進程,所以建議大家一開始在啟Docker Devicemapper的時候把限制調大.
第二點是高可用.基于Marathon和Mesos本身就有高可用的架構,大家可以直接使用.
第三點是Marathon相關的:
本文由李加慶根據2016年1月24日@Container容器技術大會·北京站上張寧的演講《去哪兒網利用Mesos和Docker構建dev—beta環境》整理而成.
文/張寧
原文出處:Docker
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4484.html