日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

DockOne微信分享(八十四):Docker在B站的实施之路

發(fā)布時(shí)間:2024/4/13 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DockOne微信分享(八十四):Docker在B站的实施之路 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
本文講的是DockOne微信分享(八十四):Docker在B站的實(shí)施之路【編者的話】B站一直在關(guān)注Docker的發(fā)展,去年成功在核心SLB(Tengine)集群上實(shí)施了Docker。今年我們對(duì)比了各種Docker實(shí)施方案后選擇了Mesos。結(jié)合CI&CD,打通了整個(gè)業(yè)務(wù)的Docker上線流程,并實(shí)現(xiàn)了全自動(dòng)擴(kuò)縮容。這次結(jié)合我們的實(shí)施之路,分享一下遇到的重點(diǎn)與難點(diǎn):
  • 自研Docker網(wǎng)絡(luò)插件的介紹;
  • Bili PaaS平臺(tái)中的CD實(shí)現(xiàn)與優(yōu)化;
  • 應(yīng)用全自動(dòng)擴(kuò)縮容的實(shí)現(xiàn)方案;
  • Nginx動(dòng)態(tài)Upstream跟Docker的配合使用。

  • B站一直在關(guān)注Docker的發(fā)展,去年成功在核心SLB(Tengine)集群上實(shí)施了Docker,規(guī)模不大但訪問量大、沒有CI & CD的工作。隨著業(yè)務(wù)量的增長(zhǎng),應(yīng)用擴(kuò)縮需求越來越多。但在沒有docker標(biāo)準(zhǔn)化的情況下,應(yīng)用擴(kuò)容需要擴(kuò)服務(wù)器,操作繁重。同時(shí)為了減少因測(cè)試、線上環(huán)境不一致導(dǎo)致的問題,我們計(jì)劃將業(yè)務(wù)全部Docker化,并配合CI & CD,打通整個(gè)業(yè)務(wù)上線流程,達(dá)到秒級(jí)動(dòng)態(tài)擴(kuò)縮容。

    下面是我們的實(shí)施之路,整體架構(gòu)圖如下:

    為什么選擇Mesos?

    Kubernetes太重,功能繁多。我們主要看中Mesos的調(diào)度功能,且輕量更易維護(hù)。另外和我們選擇了Macvlan的網(wǎng)絡(luò)有關(guān)。

    Docker網(wǎng)絡(luò)選擇

    Docker自帶的網(wǎng)絡(luò)都不能滿足我們的需求。

    Bridger:Docker分配私有IP,本機(jī)通過bridge跟容器通信。不同宿主機(jī)如果要通信需要iptables映射端口。隨著容器的增多,端口管理會(huì)很混亂,iptables規(guī)則也越來越多。

    Host:使用宿主機(jī)的網(wǎng)絡(luò),不同容器不能監(jiān)聽相同端口。

    None:Docker不給容器分配網(wǎng)絡(luò),手動(dòng)分配。

    正當(dāng)我們無(wú)法選定Docker的網(wǎng)絡(luò)方案時(shí),發(fā)現(xiàn)最新的Docker 1.12版本提供了另外兩種網(wǎng)絡(luò)驅(qū)動(dòng):Overlay和Macvlan。

    Overlay:在原來的TCP/IP數(shù)據(jù)包基礎(chǔ)上再封裝成UDP的數(shù)據(jù)包傳輸。當(dāng)網(wǎng)絡(luò)出現(xiàn)問題需要抓包時(shí),會(huì)比較麻煩。而且,Overlay依靠服務(wù)器的CPU來解UDP數(shù)據(jù)包,會(huì)導(dǎo)致Docker網(wǎng)絡(luò)性能非常不穩(wěn)定,性能損耗比較嚴(yán)重,在生產(chǎn)環(huán)境中難以使用。

    Macvlan:在交換機(jī)上配置VLAN,然后在宿主機(jī)上配置物理網(wǎng)卡,使其接收對(duì)應(yīng)的VLAN。Docker在創(chuàng)建Network時(shí)driver指定Macvlan。對(duì)Docker的Macvlan網(wǎng)絡(luò)進(jìn)行壓測(cè),跑在Macvlan網(wǎng)絡(luò)的容器比跑在host網(wǎng)絡(luò)的容器性能損失10~15%左右,但總體性能很穩(wěn)定,沒有抖動(dòng)。這是能接受的。

    基于Macvlan,我們開發(fā)了自己的IPAM Driver Plugin—底層基于Consul。
    Docker在創(chuàng)建Macvlan網(wǎng)絡(luò)時(shí),驅(qū)動(dòng)指定為自己研發(fā)的Consul。Consul中會(huì)記錄free和used的IP。如下圖:

    IPAM Driver在每臺(tái)宿主機(jī)上都存在,通過Socket的方式暴露給Docker調(diào)用。Docker在創(chuàng)建容器時(shí),IPAM Plugin會(huì)從Consul申請(qǐng)一個(gè)free的IP地址。刪除容器時(shí),IPAM Plugin會(huì)釋放這個(gè)IP到Consul。因?yàn)樗兴拗鳈C(jī)上的IPAM Plugin連接到的是同一個(gè)Consul,就保證了所有容器的IP地址唯一性。

    我們用IPAM Plugin遇到的問題:

    1)?Consul IPAM Plugin在每臺(tái)宿主機(jī)上都存在,通過Socket方式調(diào)用,目前使用容器啟動(dòng)。

    當(dāng)Docker daemon重啟加載Network時(shí),因?yàn)槿萜鬟€未啟動(dòng),會(huì)找不到Consul IPAM Plugin的Socket文件,導(dǎo)致Docker daemon會(huì)去重試請(qǐng)求IPAM,延長(zhǎng)daemon的啟動(dòng)時(shí)間,報(bào)錯(cuò)如下:
    level=warning?msg="Unable?to?locate?plugin:?consul,?retrying?in?1s" level=warning?msg="Unable?to?locate?plugin:?consul,?retrying?in?2s" level=warning?msg="Unable?to?locate?plugin:?consul,?retrying?in?4s" level=warning?msg="Unable?to?locate?plugin:?consul,?retrying?in?8s" level=warning?msg="Failed?to?retrieve?ipam?driver?for?network?\"vlan1062\"

    解決方案:Docker識(shí)別Plugin的方式有三種:
  • sock files are UNIX domain sockets.
  • spec files are text files containing a URL, such as unix:///other.sock or tcp://localhost:8080.
  • json files are text files containing a full json specification for the plugin.

  • 最早我們是通過.sock的方式識(shí)別IPAM Plugin。現(xiàn)在通過.spec文件的方式調(diào)用非本地的IPAM Plugin。這樣Docker daemon在重啟時(shí)就不受IPAM Plugin的影響。

    2)?在通過Docker network rm 刪除用Consul IPAM創(chuàng)建的網(wǎng)絡(luò)時(shí),會(huì)把網(wǎng)關(guān)地址釋放給Consul,下次創(chuàng)建容器申請(qǐng)IP時(shí)會(huì)獲取到網(wǎng)關(guān)的IP,導(dǎo)致網(wǎng)關(guān)IP地址沖突。

    解決方案:在刪除容器釋放IP時(shí),檢測(cè)下IP地址,如果是網(wǎng)關(guān)IP,則不允許添加到Consul的free列表。

    基于以上背景,我們剛開始選型的時(shí)候,測(cè)試過Docker 1.11 + Swarm 和Docker 1.12集成的SwarmKit。Docker 1.11 + Swarm網(wǎng)絡(luò)沒有Macvlan驅(qū)動(dòng),而Docker 1.12集成的SwarmKit只能使用Overlay網(wǎng)絡(luò),Overlay的性能太差。最終我們采用了Docker 1.12 + Mesos。

    CI & CD

    對(duì)于CI,我們采用了目前公司中正在大量使用的Jenkins。 Jenkins通過Pipeline分為多個(gè)step,step 1 build出要構(gòu)建war包。Step 2 build Docker 鏡像并push到倉(cāng)庫(kù)中。

    第一步: build出想要的war,并把war包保存到固定的目錄。第二步:build docker鏡像,會(huì)自動(dòng)發(fā)現(xiàn)前面build出的war包,并通過寫好的Dockerfile build鏡像,鏡像名即為應(yīng)用名。鏡像構(gòu)建成功后會(huì)push到我們的私有倉(cāng)庫(kù)。每次鏡像構(gòu)建都會(huì)打上一個(gè)tag,tag即為發(fā)布版本號(hào)。后續(xù)我們計(jì)劃把CI從jenkins獨(dú)立出來,通過自建的Paas平臺(tái)來build war包和鏡像。

    我們自研了基于Docker的PaaS平臺(tái)(持續(xù)開發(fā)中)。該平臺(tái)的功能主要包括信息錄入、應(yīng)用部署、監(jiān)控、容器管理、應(yīng)用擴(kuò)縮等。CD就在Paa上。

    當(dāng)要部署一個(gè)新的業(yè)務(wù)系統(tǒng)時(shí),要先在Paas系統(tǒng)上錄入應(yīng)用相關(guān)信息,比如基礎(chǔ)鏡像地址、容器資源配置、容器數(shù)量、網(wǎng)絡(luò)、健康檢查等

    CD時(shí),需要選擇鏡像的版本號(hào),即上文提到的tag

    我們同時(shí)支持控制迭代速度,即迭代比例的設(shè)置

    這個(gè)設(shè)置是指,每次迭代20%的容器,同時(shí)存活的容器不能低于迭代前的100%。

    我們遇到的問題:控制迭代比例。

    Marathon有兩個(gè)參數(shù)控制迭代比例:
    • minimumHealthCapacity(Optional. Default: 1.0)處于health狀態(tài)的最少容器比例;
    • maximumOverCapacity(Optional. Default: 1.0)可同時(shí)迭代的容器比例。

    假如有個(gè)Java應(yīng)用通過Tomcat部署,分配了四個(gè)容器,默認(rèn)配置下迭代,Marathon可以同時(shí)啟動(dòng)四個(gè)新的容器,啟動(dòng)成功后刪除四個(gè)老的容器。四個(gè)新的Tomcat容器在對(duì)外提供服務(wù)的瞬間,因?yàn)檎?qǐng)求量太大,需要立即擴(kuò)線程數(shù)預(yù)熱,導(dǎo)致剛進(jìn)來的請(qǐng)求處理時(shí)間延長(zhǎng)甚至超時(shí)(B站因?yàn)檎?qǐng)求量大,請(qǐng)求設(shè)置的超時(shí)時(shí)間很短,在這種情況下,請(qǐng)求會(huì)504超時(shí))。

    解決方法:

    對(duì)于請(qǐng)求量很大需要預(yù)熱的應(yīng)用,嚴(yán)格控制迭代比例,比如設(shè)置maximumOverCapacity為0.1,則迭代時(shí)只能同時(shí)新建10%的容器,這10%的容器啟動(dòng)成功并刪除對(duì)應(yīng)老的容器后才會(huì)再新建10%的容器繼續(xù)迭代。

    對(duì)于請(qǐng)求量不大的應(yīng)用,可適當(dāng)調(diào)大maximumOverCapacity,加快迭代速度。

    動(dòng)態(tài)擴(kuò)縮容

    節(jié)假日或做活動(dòng)時(shí),為了應(yīng)對(duì)臨時(shí)飆高的QPS,需要對(duì)應(yīng)用臨時(shí)擴(kuò)容。或者當(dāng)監(jiān)控到某個(gè)業(yè)務(wù)的平均資源使用率超過一定限制時(shí),自動(dòng)擴(kuò)容。我們的擴(kuò)容方式有兩種:1、手動(dòng)擴(kuò)容;2、制定一定的規(guī)則,當(dāng)觸發(fā)到規(guī)則時(shí),自動(dòng)擴(kuò)容。我們的Bili PaaS平臺(tái)同時(shí)提供了這兩種方式,底層是基于Marathon的Scale API。這里著重講解下基于規(guī)則的自動(dòng)擴(kuò)縮容。

    自動(dòng)擴(kuò)縮容依賴總架構(gòu)圖中的幾個(gè)組件:Monitoring Agent、Nginx+UpSync+Consul、Marathon Hook、Bili PaaS。

    Monitor Agent:我們自研了Docker的監(jiān)控Agent,封裝成容器,部署在每臺(tái)Docker宿主機(jī)上,通過docker stats的接口獲取容器的CPU、內(nèi)存、IO等信息,信息錄入InfluxDB,并在Grafana展示。

    Bili PaaS:應(yīng)用在錄入PaaS平臺(tái)時(shí)可以選擇擴(kuò)縮容的規(guī)則,比如:平均CPU > 300% OR MEM > 4G。PaaS平臺(tái)定時(shí)輪詢判斷應(yīng)用的負(fù)載情況,如果達(dá)到擴(kuò)容規(guī)則,就按一定的比例增加節(jié)點(diǎn)。本質(zhì)上是調(diào)用Marathon的API進(jìn)行擴(kuò)縮。

    Marathon Hook:通過Marathon提供的/v2/events接口監(jiān)聽Marathon的事件流。當(dāng)在Bili PaaS平臺(tái)手動(dòng)擴(kuò)容或觸發(fā)規(guī)則自動(dòng)擴(kuò)容時(shí),Bili Paas平臺(tái)會(huì)調(diào)用Marathon的API。Marathon的每個(gè)操作都會(huì)產(chǎn)生事件,通過/v2/events接口暴露出來。Marathon Hook程序會(huì)把所有容器的信息注冊(cè)到Consul中。當(dāng)Marathon刪除或創(chuàng)建容器時(shí),Marathon Hook就會(huì)更新Consul中的Docker容器信息,保證Consul中的信息和Marathon中的信息是一致的,并且是最新的。

    Nginx+UpSync+Consul:當(dāng)Marathon擴(kuò)容完成時(shí),新容器的IP:PORT一定要加到SLB(Tengine/Nginx)的Upstream中,并reload SLB后才能對(duì)外提供服務(wù)。但Tengine/Nginx reload時(shí)性能會(huì)下降。為了避免頻繁reload SLB導(dǎo)致的性能損耗,我們使用了動(dòng)態(tài)Upstream:Nginx + UpSync + Consul。Upsync是Weibo開源的一個(gè)模塊,使用Consul保存Upstream的server信息。Nginx啟動(dòng)時(shí)會(huì)從Consul獲取最新的Upstream server信息,同時(shí)Nginx會(huì)建立一個(gè)TCP連接hook到Consul,當(dāng)Consul里的數(shù)據(jù)有變更時(shí)會(huì)立即通知到Nginx,Nginx的worker進(jìn)程更新自己的Upstream server信息。整個(gè)過程不需要reload nginx。注意:UpSync的功能是動(dòng)態(tài)更新upstream server,當(dāng)有vhost的變更時(shí),還是需要reload nginx。

    我們遇到的問題:

    1)?Nginx + UpSync 在reload時(shí)會(huì)產(chǎn)生shutting down。因?yàn)镹ginx Hook到Consul的鏈接不能及時(shí)斷開。曾在GitHub上因這個(gè)問題提過issue,作者回復(fù)已解決。個(gè)人測(cè)試發(fā)現(xiàn)shuttding down還是存在。并且UpSync和Tengine的http upstream check模塊不能同時(shí)編譯。

    解決方案:Tengine + Dyups。我們正在嘗試把Nginx + Dyups替換為Tengine + Dyups。Dyups的弊端就是Upstream信息是保存在內(nèi)存里的。Reload/Restart Tengine時(shí)就會(huì)丟失。需要自己同步Upstream信息到磁盤中?;诖?#xff0c;我們對(duì)Tengine + Dyups做了封裝,由一個(gè)代理進(jìn)程Hook Consul,發(fā)現(xiàn)有更時(shí)則主動(dòng)更新Tengine,并提供了Web管理界面。目前正在內(nèi)部測(cè)試中。

    2)Docker Hook —> Marathon Hook,最早我們是去Hook Docker的events。這需要在每臺(tái)宿主機(jī)上起一個(gè)Hook服務(wù)。當(dāng)應(yīng)用迭代時(shí),Docker會(huì)立即產(chǎn)生一個(gè)create container的事件。Hook程序監(jiān)控到后去更新Consul,然后Consul通知Nginx去更新。導(dǎo)致問題就是:容器里的服務(wù)還沒啟動(dòng)成功(比如Tomcat),就已經(jīng)對(duì)外提供服務(wù)了。這會(huì)導(dǎo)致很多請(qǐng)求失敗,產(chǎn)生重啟請(qǐng)求。

    解決方案:Marathon Hook。Marathon中有一個(gè)health check的配置。如下圖

    我們規(guī)定所有的Web服務(wù)必須提供一個(gè)Health Check接口,這個(gè)接口隨著服務(wù)一同起來,這個(gè)接口任何非200的http code都代表應(yīng)用異常。Marathon剛啟動(dòng)容器時(shí),顯示此容器的Health狀態(tài)是uknow。當(dāng)Health Check成功時(shí),Marathon顯示此容器的Health狀態(tài)Healthy,并會(huì)產(chǎn)生一個(gè)事件。Marathon Hook程序通過Hook這個(gè)事件,就能準(zhǔn)確捕獲容器中應(yīng)用啟動(dòng)成功的時(shí)間,并更新Consul,同步Nginx,對(duì)外提供服務(wù)。

    3)Marathon Failover后會(huì)丟失command health check,通過Marathon給容器添加Health Check時(shí),有三種方式可以選擇:HTTP TCP COMMAND

    當(dāng)使用HTTP TCP時(shí),Check是由Marathon發(fā)起的,無(wú)法選擇Check時(shí)的端口,Marathon會(huì)用自己分配的PORT進(jìn)行Check。實(shí)際上我們并未使用marathon映射的端口。我們選擇了COMMAND方式,在容器內(nèi)部發(fā)起curl請(qǐng)求來判斷容器里的應(yīng)用狀態(tài)。當(dāng)Marathon發(fā)生failover后,會(huì)丟失COMMAND health check,所有容器狀態(tài)都顯示unknow。需要重啟或者迭代應(yīng)用才能恢復(fù)。

    Q&A

    Q:你好 問下貴公司的自動(dòng)擴(kuò)容是針對(duì)應(yīng)用的吧 有沒有針對(duì)Mesos資源池監(jiān)控并做Mesos Agent的擴(kuò)容?
    A:目前的自動(dòng)擴(kuò)容是針對(duì)應(yīng)用的。Mesos Agent擴(kuò)容時(shí),先把物理機(jī)信息錄入PaaS平臺(tái),手動(dòng)在PaaS平臺(tái)點(diǎn)擊擴(kuò)容,后臺(tái)會(huì)調(diào)用Ansible,分鐘快速級(jí)擴(kuò)Mesos Agent。 Q:現(xiàn)在是確定Nginx+UpSync+Upsteam check是無(wú)法一起用的么?貴公司的Nginx版本是多少哇?
    A:測(cè)試過Nginx 1.8和1.10,確認(rèn)無(wú)法一同編譯。我們用的最多的Nginx(SLB)是Tengine 2.1.1,部署在Docker上。 Q:既然是封裝, 那底層用Mesos比Kubernets并沒有太大的靈活性吧?
    A:對(duì)于PaaS平臺(tái),目前我們希望的只需要資源調(diào)度這個(gè)功能,其他功能我們還是希望可以自己實(shí)現(xiàn),而Mesos是專注于調(diào)度資源,而且已經(jīng)歷經(jīng)了大量級(jí)的考驗(yàn)。而Kubernetes目前提供的很多服務(wù),我們并不需要,所以選擇了Mesos。 Q:容器是采用Monitor Agent監(jiān)控,那容器內(nèi)的呢?也還是內(nèi)部埋點(diǎn)?還是EFK嗎?監(jiān)控是采用Prometheus嗎?
    A:Prometheus沒有使用,我們是用自己的監(jiān)控Agent -> InfluxDB。容器內(nèi)有多種監(jiān)控方式。有用ELK,也有其他埋點(diǎn),比如StatsD,基于Dapper論文實(shí)現(xiàn)的全鏈路追蹤。 Q:網(wǎng)絡(luò)選型這塊,還調(diào)研過其他網(wǎng)絡(luò)方案嗎?譬如Calico、Weave等,為什么會(huì)選用Macvlan?
    A:我們的選型第一步是先選擇標(biāo)準(zhǔn)的,要從CoreOS主導(dǎo)的cni還是Docker官方主導(dǎo)cnm里面選擇,目前由于我們?nèi)萜鞣桨高€是走的Docker,所以選擇了cnm,那從cnm的標(biāo)準(zhǔn)里面的選擇基本是:1. 基于XVLAN的Overlay;2. 基于三層路由的Calico;3. 基于二層隔離的Macvlan,實(shí)際以上的方案我們都調(diào)研使用過,基于希望盡量簡(jiǎn)單的原則最終選型還是Macvlan。 Q:Bili PaaS平臺(tái),自動(dòng)擴(kuò)容和手動(dòng)擴(kuò)容,應(yīng)用多的是哪種方式?自動(dòng)擴(kuò)容后,資源會(huì)重調(diào)度么?是否會(huì)中斷已有業(yè)務(wù)呢?
    A:用的更多的是根據(jù)制定好的策略,自動(dòng)擴(kuò)容。通過Nginx 動(dòng)態(tài)Upstream對(duì)外提供服務(wù),不會(huì)中斷業(yè)務(wù)。 Q:關(guān)于日志收集每個(gè)容器里都跑一個(gè)Logstash嗎?好像ELK不能搜索展示上下文的啊?
    A:容器里面沒有跑Logstash。目前是在遠(yuǎn)端的Logstash集群上監(jiān)聽一個(gè)UDP端口,應(yīng)用直接把日志推送到Logstash的UDP端口,然后Logstash把日志推送到Kafka,Kafka的消費(fèi)者有兩個(gè),一個(gè)是Elasticsearch,一個(gè)是HDFS。一般用ELK足以。需要詳細(xì)日志時(shí),由運(yùn)維通過HDFS查詢。 Q:我想請(qǐng)教下Nginx的一些動(dòng)態(tài)配置文件是封裝在容器內(nèi)部了?還是通過volume的方式掛載了?有沒有配置中心類似的服務(wù)?這塊想了解下是怎么實(shí)現(xiàn)的?
    A:Nginx的Upstream是從Consul動(dòng)態(tài)獲取生成在本地的,通過Volume掛載,持久化到宿主機(jī)。有配置中心。業(yè)務(wù)Docker化時(shí),就會(huì)推動(dòng)業(yè)務(wù)配置接配置中心,Docker中不在保存業(yè)務(wù)依賴的配置。

    以上內(nèi)容根據(jù)2016年9月27日晚微信群分享內(nèi)容整理。分享人武安闖,Bilibili 運(yùn)維工程師,目前主要負(fù)責(zé)B站運(yùn)維和業(yè)務(wù)Docker化的實(shí)施。一直關(guān)注于Docker的發(fā)展,Docker與Mesos結(jié)合的容器平臺(tái)實(shí)施?。DockOne每周都會(huì)組織定向的技術(shù)分享,歡迎感興趣的同學(xué)加微信:liyingjiesz,進(jìn)群參與,您有想聽的話題或者想分享的話題都可以給我們留言。

    原文發(fā)布時(shí)間為:2016-09-29

    本文作者:武安闖

    本文來自云棲社區(qū)合作伙伴Dockerone.io,了解相關(guān)信息可以關(guān)注Dockerone.io。

    原文標(biāo)題:DockOne微信分享(八十四):Docker在B站的實(shí)施之路

    總結(jié)

    以上是生活随笔為你收集整理的DockOne微信分享(八十四):Docker在B站的实施之路的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。