架構(gòu)師小組交流會(huì):每期選一個(gè)時(shí)下最熱門的技術(shù)話題進(jìn)行小組交流。
第一期主題:容器實(shí)踐。Docker 作為當(dāng)前最具顛覆性的開(kāi)源技術(shù)之一,其輕量虛擬化、可移植性是CI/CD,DevOps,微服務(wù)的重要實(shí)現(xiàn)技術(shù)。但目前技術(shù)還不夠成熟,在生產(chǎn)實(shí)踐中會(huì)遇到不少坑。本期參與小組交流的是國(guó)內(nèi)較早采用 Docker 實(shí)踐的公司。參與嘉賓:滬江架構(gòu)師黃凱、滴滴架構(gòu)師田智偉、蘑菇街架構(gòu)師張振華、蘑菇街運(yùn)維架構(gòu)師向靖、七牛技術(shù)總監(jiān)袁曉沛、扇貝技術(shù)總監(jiān)丁彥
第一輪:自由交流滬江黃凱:大家好,我是來(lái)自滬江的 Java 架構(gòu)師,我叫黃凱。在加入滬江之前,曾在 HP 和 IBM 的云計(jì)算部門擔(dān)任核心開(kāi)發(fā)和架構(gòu)職位。對(duì) IaaS、Paas、SaaS,尤其是云存儲(chǔ)有較深入的了解。2015 年加入滬江,擔(dān)任架構(gòu)師職位,主導(dǎo)的產(chǎn)品有:課件云存儲(chǔ),云轉(zhuǎn)碼等等。在這些項(xiàng)目中,我們使用 Mesos 和 Marathon 做 Docker 的編排工具,并開(kāi)發(fā)了一個(gè) Mesos Framework 做云轉(zhuǎn)碼的核心框架。
那么我們?yōu)槭裁匆褂?Docker,也是機(jī)緣巧合。由于我們的服務(wù)開(kāi)始的時(shí)候不是特別多,采用的就是一種普通的架構(gòu),后來(lái)隨著服務(wù)的增多,發(fā)現(xiàn)部署和運(yùn)維花的時(shí)間太長(zhǎng),我們想使用一些新的方式。開(kāi)始的時(shí)候研究過(guò) Openstack,后來(lái)覺(jué)得 Openstack 慢慢沒(méi)落,于是我們就選中現(xiàn)在使用的 Docker。我們并不把 Docker 當(dāng)成 VM 在用,而是使用它的原生的,在 Baremetal 上直接安裝 Docker,這樣運(yùn)行效率比在 VM 運(yùn)行 Docker 要來(lái)的快。課件云是由很多微服務(wù)組成,不光是一些存儲(chǔ),這種微服務(wù)是使用 Docker 部署,就相當(dāng)于編排,把這些微服務(wù)部署上去。轉(zhuǎn)碼這一塊是使用了 Mesos 框架,和 Docker 沒(méi)有特別大的關(guān)系,但是轉(zhuǎn)碼的應(yīng)用程序,比如說(shuō)我們現(xiàn)在應(yīng)用 FFmpeg,這個(gè)程序是運(yùn)行在 Docker 里面的。
為什么要選擇 Marathon?第一,我覺(jué)得 Mesos+Marathon 非常的容易理解。我們也研究過(guò) Kubernetes 和其他的一些方法,發(fā)現(xiàn)從運(yùn)維和研究的方面來(lái)說(shuō)的話,Kubernetes 實(shí)在是太重而且太復(fù)雜,后來(lái)選擇了Marathon。我們現(xiàn)在是內(nèi)部服務(wù)使用,兩個(gè)部門在使用轉(zhuǎn)碼集群,大概是 Baremetal 有 20 臺(tái)的物理機(jī)。除去我們 API 的一些服務(wù),還有一些第三方組件的服務(wù)的話,大概是有 400 多個(gè) Docker 容器在跑。
滴滴田智偉:大家好,我是滴滴代駕事業(yè)部架構(gòu)師,代駕事業(yè)部是公司最早嘗試 Docker 虛擬化的事業(yè)部。目前主要方向是業(yè)務(wù)系統(tǒng)及部分中間件的 Docker 化,我們做的時(shí)間也不太長(zhǎng),半年多的時(shí)間。線上是因?yàn)槲覀冇欣系囊惶装l(fā)布系統(tǒng),集成涉及的部門比較多,所以我們基于原來(lái)的發(fā)布系統(tǒng)完成了預(yù)發(fā)布環(huán)境 Docker 的部署。線下環(huán)境基于 Docker+K8s 開(kāi)發(fā)內(nèi)部的自動(dòng)化持續(xù)交付系統(tǒng)及開(kāi)發(fā)測(cè)試環(huán)境管理。我們?cè)谧鲩_(kāi)發(fā)和測(cè)試環(huán)境的自動(dòng)化,另一方面也是做環(huán)境管理的,兩套環(huán)境。對(duì)于項(xiàng)目并行的時(shí)候發(fā)現(xiàn)原來(lái)很多不夠用,原來(lái)很多配置是基于端口綁死的情況?,F(xiàn)在基于開(kāi)發(fā) Kubernetes 的話,網(wǎng)絡(luò)隔離用了一部分,然后主要是用環(huán)境變量這一部分,主要考慮是解決一個(gè)配置可以應(yīng)用到在多個(gè)環(huán)境的情況,基于這個(gè)需求才用它。開(kāi)發(fā) Kubernetes 基于 Namespace,同一個(gè)服務(wù)在不同的 Namespace 下,它其實(shí)環(huán)境變量名可以是相同的,但是IP不同,而這一部分 IP 其實(shí)是由開(kāi)發(fā) Kubernetes 自己去管理的。基于環(huán)境變量獲取一些配置的話,比如 IP 地址這種,就可以做到拿一份配置可以打出多套環(huán)境。
考慮業(yè)務(wù)的安全性和穩(wěn)定性,線上基于純 Docker 的方式在做。我們是基于裸的 Docker 來(lái)工作,主要是用資源隔離,沒(méi)有借助調(diào)度框架,也沒(méi)有自動(dòng)伸縮。我們是兩步走,一步是驗(yàn)證 Docker,其次是做開(kāi)發(fā) Kubernetes 線下使用和預(yù)研。為什么沒(méi)有考慮 Mesos?剛才跟滬江的同學(xué),我們的考慮是相反的。Mesos 側(cè)重點(diǎn)更專一一點(diǎn),首先不會(huì)有模塊的劃分,比如 Kubernetes 有 Replication controller ,Namespace 這種概念,而 Mesos 下幾乎沒(méi)有這種概念。我們拿 Kubernetes 主要是做一些編排的功能,而正好開(kāi)發(fā) Kubernetes 在整個(gè)發(fā)布和編排上,體系更全面一點(diǎn)。Mesos 最早是做資源管理,基于 Docker 做一個(gè) Framework 接進(jìn)來(lái)的話,它不是專門為編排而生。Kubernetes 首先解決我們的問(wèn)題是,我們可能不需要加多份配置就可以搭多套不同的環(huán)境,它就是基于 Namespace 做一個(gè)多租戶的概念,會(huì)對(duì) Service 做一層隔離,對(duì)于動(dòng)態(tài)配置,擴(kuò)容這一部分暫時(shí)我們沒(méi)用到,確實(shí)用到的一些場(chǎng)景比較少。主要是做不同環(huán)境的隔離,并沒(méi)有太多使用編排細(xì)節(jié)上的東西,動(dòng)態(tài)伸縮之類的目前線下沒(méi)有太大必要,線上可能會(huì)用到。
蘑菇街向靖:大家好,我是子騫,來(lái)自蘑菇街的運(yùn)維架構(gòu)師。我們接下來(lái)會(huì)做一個(gè) Paas 平臺(tái),想做 Docker 和結(jié)合虛擬機(jī)以及我們用到公有云產(chǎn)品,做成一個(gè)混合云的架構(gòu)平臺(tái)。我們現(xiàn)在 Docker 也在用,更多的是當(dāng)虛擬機(jī)用,后面我們想基于 Docker 原生的方式去用,可能會(huì)涉及資源調(diào)度,服務(wù)發(fā)現(xiàn)的問(wèn)題。除了 Docker,我們還會(huì)用到公有云,公有云更多是虛擬機(jī)的方式提供。出于混合云,想在資源層做一個(gè)抽象,對(duì)于上層業(yè)務(wù)來(lái)講它沒(méi)有關(guān)系,它是跑在 Docker 上,還是云主機(jī)上,還是 KVM 虛擬機(jī)上,那么我想在這上面做一個(gè)抽象。另外還有,剛才我也是提問(wèn)滴滴架構(gòu)師的問(wèn)題,配置怎樣和代碼做隔離,這個(gè)也是我考慮的問(wèn)題。因?yàn)槲铱?Docker 用了環(huán)境變量,通過(guò)環(huán)境變量做一些配置的參數(shù)的傳遞,但是在虛擬機(jī)上,特別是在物理機(jī)上,通過(guò)環(huán)境變量的方式,我還在考慮有沒(méi)有安全的風(fēng)險(xiǎn),Docker 可能是一個(gè)只讀的,不會(huì)被修改的,但是對(duì)于虛擬機(jī)以及物理機(jī)來(lái)說(shuō),可能會(huì)存在被修改的風(fēng)險(xiǎn)。
蘑菇街張振華:大家好,我叫張振華,花名郭嘉,我是 14 年從思科加入蘑菇街。我們算是國(guó)內(nèi)用 Docker 比較早的,我們一開(kāi)始用 Docker 是 1.3.2 的版本,當(dāng)時(shí)我們采用集群管理工具還是Openstack,因?yàn)楫?dāng)時(shí) Kubernetes 還不是很成熟。當(dāng)時(shí)也走了一些彎路,比如我們把 Docker 當(dāng)成虛擬機(jī)來(lái)用,曾經(jīng)在線上的規(guī)模也達(dá)到幾百臺(tái)虛擬機(jī)幾千個(gè)容器,但是我們逐步發(fā)現(xiàn)不能把 Docker 當(dāng)成虛擬機(jī)來(lái)使用,因此我們做了一個(gè)轉(zhuǎn)型,從去年開(kāi)始研究 Kubernetes,現(xiàn)在 Kubernetes 加 Docker 的版本開(kāi)發(fā)完成了,準(zhǔn)備逐步上線。
我們?yōu)槭裁催x用 Kubernetes?編排工具的選擇我們也是做過(guò)一番調(diào)研的,它們沒(méi)有誰(shuí)好誰(shuí)不好這一說(shuō),只能說(shuō)誰(shuí)更貼切你的需求。對(duì)于我們蘑菇街來(lái)說(shuō),我們需要解決是資源利用率的問(wèn)題,和運(yùn)維的對(duì)接,我們需要有預(yù)發(fā)和線上環(huán)境的持續(xù)集成持續(xù)部署的過(guò)程,還有我們需要有對(duì)資源的隔離,對(duì)部署的快速迭代,包括集群管理,這些方面,我們覺(jué)得 Kubernetes 更加適合于我們。
在網(wǎng)絡(luò)方面,我們研究過(guò)現(xiàn)在在開(kāi)源界比較常用的一些方案,但是我們都覺(jué)得不太適合,比較 Fannel,Caico 等等,他們一般用的技術(shù)都是 Vxlan,或者是用 BGP。因?yàn)槲覀冎皩?duì) Openstack 的網(wǎng)絡(luò)是比較有經(jīng)驗(yàn)的,然后我們發(fā)現(xiàn)有一個(gè)項(xiàng)目,具體名字不記得,Neutron 和 Kubernetes 做一個(gè)對(duì)接,我們?cè)谶@個(gè)項(xiàng)目的基礎(chǔ)上做了 Vlan 的方案,我們的網(wǎng)絡(luò)沒(méi)有用 Vxlan 來(lái)做,而是選擇 Vlan 來(lái)做,這樣的話一個(gè) Docker 它可以獲得跟一個(gè)物理理同一個(gè)網(wǎng)絡(luò)平面的 IP,我們的應(yīng)用程序可以直接對(duì)外訪問(wèn),因?yàn)槲覀儍?nèi)部業(yè)務(wù)有這個(gè)需求選擇這個(gè)方案。雖然 Docker 內(nèi)部網(wǎng)絡(luò)和外部網(wǎng)絡(luò)是通的,但 Docker 還是獨(dú)立的一個(gè)網(wǎng)段,不需要一層 NAT 的轉(zhuǎn)換。我們直接走二層的,是在交換機(jī)走 Chunk,本來(lái)物理機(jī)交換機(jī)的 Access 口,這樣的話,一臺(tái)物理機(jī)上面允許跑多個(gè)vlan的容器,比如說(shuō) A業(yè)務(wù)和 B業(yè)務(wù)要走隔離的話,通過(guò)網(wǎng)絡(luò)的 Vlan 走隔離,它們的數(shù)據(jù)之間不會(huì)有干擾。
Load Balance 我們還沒(méi)有涉及到這一塊,Load Balance 我們應(yīng)該會(huì)在 nginx 上做一層。因?yàn)閾?jù)我了解,現(xiàn)在 Kubernetes 這一塊 Proxy 還不是很成熟,這上面還存在一些問(wèn)題,因此還不敢用 Kubernetes 現(xiàn)有提供的服務(wù)。服務(wù)發(fā)現(xiàn)和注冊(cè)這一塊我們還在做開(kāi)發(fā),這塊會(huì)和配置管理中心打通。我們內(nèi)部也有其他團(tuán)隊(duì)在做這些功能,所以我們會(huì)和內(nèi)部的中間件團(tuán)隊(duì)合作。
七牛云袁曉沛:大家好,我是七牛云數(shù)據(jù)處理技術(shù)總監(jiān)袁曉沛。我們的數(shù)據(jù)處理業(yè)務(wù)包括了圖片和視頻的實(shí)時(shí)在線及異步處理。數(shù)據(jù)處理的業(yè)務(wù)量比較大,日均請(qǐng)求量達(dá)到百億級(jí)。平臺(tái)采用容器技術(shù)的原因是借助容器技術(shù)快速部署,啟動(dòng)的特性,數(shù)據(jù)處理程序可以根據(jù)數(shù)據(jù)處理量快速地彈性伸縮。借助容器技術(shù)內(nèi)核級(jí)別的資源隔離和訪問(wèn)控制,每個(gè)數(shù)據(jù)處理程序可以運(yùn)行在一個(gè)私有的環(huán)境,不被其它程序所干擾,保證其上運(yùn)行數(shù)據(jù)是安全可靠的。而且容器技術(shù)是輕量的,它以最小的資源損耗提供資源隔離和訪問(wèn)控制,而資源特別是計(jì)算資源在數(shù)據(jù)處理中是非常寶貴的。
我們?cè)谫Y源調(diào)度上采用的是 Mesos,而二層的業(yè)務(wù)調(diào)度框架則是自己自研的。七牛自身?yè)碛薪_(tái)的物理機(jī),容器是直接運(yùn)行的物理機(jī)上,可以減少虛擬層對(duì)資源的消耗,提高資源的利用率。
在網(wǎng)絡(luò)上,對(duì)于七牛的自定義數(shù)據(jù)處理服務(wù)直接使用的是 Host 模式,而對(duì)第三方數(shù)據(jù)處理服務(wù)則使用的是 Bridge 模式,因?yàn)檫@些程序是用戶自己部署運(yùn)行的,并不知道用戶是否有開(kāi)啟其他的端口使用,所以使用的是 Bridge 模式,需要對(duì)外使用端口的都需要通過(guò) NAT 進(jìn)行暴露,這樣服務(wù)內(nèi)部使用了什么端口并不會(huì)對(duì)外界環(huán)境造成影響,對(duì)平臺(tái)環(huán)境做了非常好的安全隔離。我們是使用 Consul 做注冊(cè)中心,支持跨數(shù)據(jù)中心的服務(wù)發(fā)現(xiàn)。我們?yōu)槭裁醋匝械恼{(diào)度框架,而不用 Marathon。因?yàn)?Marathon 不支持跨數(shù)據(jù)中心的內(nèi)部服務(wù)或外部服務(wù)的發(fā)現(xiàn),而七牛有多個(gè)數(shù)據(jù)中心,影響整體的調(diào)度,其次如果選用 Marathon 的話,根據(jù)我們業(yè)務(wù)的特點(diǎn),還是要再做一層對(duì) Marathon 的包裝才能作為 Dora 的調(diào)度服務(wù),這樣模塊就會(huì)變多,部署運(yùn)維會(huì)復(fù)雜。
扇貝丁彥:大家好,我是扇貝的技術(shù)總監(jiān)丁彥,之前在暴走漫畫,先后在暴走漫畫和扇貝設(shè)計(jì)和主導(dǎo)了基于 Docker 的微服務(wù)架構(gòu)系統(tǒng),以及數(shù)據(jù)收集和分析系統(tǒng)。去年來(lái)到扇貝,這里是 Python 的開(kāi)發(fā)環(huán)境。后來(lái)發(fā)現(xiàn)業(yè)務(wù)增長(zhǎng)快,水平擴(kuò)展一些機(jī)器,出現(xiàn)問(wèn)題需要換個(gè)機(jī)器等等,都需要非常熟悉業(yè)務(wù)的少數(shù)開(kāi)發(fā)去做。另外公司對(duì)預(yù)算控制嚴(yán)格,機(jī)器基本都是滿負(fù)荷運(yùn)作,平時(shí)也不可能多開(kāi)空置的機(jī)器,已有的機(jī)器還要根據(jù)負(fù)載情況調(diào)整服務(wù)分布情況,所以這種切換服務(wù),增刪服務(wù)的操作還是比較頻繁的。因此,我們用了2-3個(gè)月的時(shí)間將所有的運(yùn)行環(huán)境都切換到 Docker上,這大大提高了我們的運(yùn)維能力。
Docker 包裝有幾個(gè)好處。第一個(gè)好處是,環(huán)境升級(jí)非常方便。因?yàn)橹灰猵ull 一下最新的鏡像,啟動(dòng)一個(gè) Container,環(huán)境就升級(jí)了。而如果直接基于公有云的鏡像升級(jí)的話就很難,因?yàn)橐慌_(tái)機(jī)器上跑哪些服務(wù)其實(shí)不一定是固定的,并且之前做的鏡像只要有一臺(tái)機(jī)器是還基于它的話,就刪除不掉的,鏡像數(shù)量又有上限。所以docker 非常好地解決了我們的問(wèn)題。
其次是環(huán)境的顆粒度會(huì)更小,一臺(tái)機(jī)器上配好幾個(gè)應(yīng)用的話,往往配著配著,到最后你就不太能精確地記得上面裝的程序或者庫(kù)是給哪個(gè)應(yīng)用服務(wù)的,應(yīng)用之間如果依賴有版本的沖突也很難調(diào)和。你想做些服務(wù)的遷移,把負(fù)載比較小的放一起,把負(fù)載比較大的抽出來(lái),這個(gè)時(shí)候就非常痛苦,但你如果用 Docker 包裝后就非常簡(jiǎn)單,只要在不同的機(jī)器上起不同的 Container,就可以實(shí)現(xiàn)這一點(diǎn)。
第三,我們不光用了 Docker,還加入了服務(wù)發(fā)現(xiàn),剛剛討論配置管理這些,我們一并做了。Docker 啟動(dòng)時(shí)候,我們自己寫了一些工具,可以自定義Docker啟動(dòng)參數(shù),包括配置參數(shù),比如說(shuō),一些程序要運(yùn)行的參數(shù),我們主要用兩種方式,一種方式是通過(guò)環(huán)境變量灌進(jìn)去,還有一種方式讓程序的啟動(dòng)腳本支持參數(shù),然后拼接不同的參數(shù)灌進(jìn)去,最終都是落實(shí)到Docker的啟動(dòng)命令上。服務(wù)發(fā)現(xiàn)是基于 Consul,Docker 的啟動(dòng)命令是從 Consul 里取的。首先 Consul有 HTTP 的 API,我們是自己寫的 pip 包,只要 Include 一下這個(gè)包就可以了,Docker 的服務(wù)啟動(dòng)后會(huì)自動(dòng)注冊(cè)到 Consul。比如要在負(fù)載后加一個(gè)服務(wù),只需要找到一臺(tái)機(jī)器,啟動(dòng)對(duì)應(yīng)的container,剩下的事情它自己會(huì)到 Consul,注冊(cè)它的參數(shù)地址一系列東西,自動(dòng)把它加進(jìn)去。所以這些都是自動(dòng)化的,如果檢測(cè)那臺(tái)機(jī)器/服務(wù)掛了,Health Check 也會(huì)到 Consul 里面更新。該增加機(jī)器就增加機(jī)器,該下線就下線??傮w來(lái)說(shuō),我們的生產(chǎn)環(huán)境全部跑在 Docker 上面的,然后區(qū)分有狀態(tài)和無(wú)狀態(tài)兩種,有狀態(tài)的定死在機(jī)器上,無(wú)狀態(tài)的靈活的自由切換。還有一點(diǎn),如果是有狀態(tài)的容器要定死在機(jī)器上的時(shí)候,我們一般來(lái)說(shuō)都會(huì)采取冗余的結(jié)構(gòu),至少保證有兩個(gè)在運(yùn)行,一個(gè)掛了,保證整體的服務(wù)在運(yùn)行。其次基于 Docker,我們還做了一套數(shù)據(jù)搜集以及分析的機(jī)制。數(shù)據(jù)搜集是基于日志來(lái)搜集的,利用 Docker 的 Log driver,把日志打到 Filter,把結(jié)果存在存儲(chǔ)服務(wù)上。同時(shí)監(jiān)控也是基于日志做的。第三部分非生產(chǎn)環(huán)境,比如開(kāi)發(fā)環(huán)境跟測(cè)試環(huán)境都是 Docker 做的,因?yàn)槲覀兠恳粋€(gè)服務(wù)都做了 Image、鏡像,用容器方式跑的。通過(guò)參數(shù)來(lái)決定啟動(dòng)方式的,我們可以在開(kāi)發(fā)環(huán)境以及測(cè)試環(huán)境采用不同的參數(shù)來(lái)啟動(dòng)容器。 通過(guò) Consul 來(lái)隔離的,因?yàn)?Consul 的服務(wù)發(fā)現(xiàn),開(kāi)發(fā)、生產(chǎn)、測(cè)試環(huán)境在不同的自動(dòng)發(fā)現(xiàn)框架里不會(huì)相互影響到。目前機(jī)器在 120 臺(tái)左右,基于云服務(wù)。有些基礎(chǔ)的東西不需要依賴于 Docker,比如說(shuō)申請(qǐng)?jiān)浦鳈C(jī),申請(qǐng)的時(shí)候就可以指定它的 CPU 和內(nèi)存這些服務(wù)器資源的配置。所以這部分東西還是屬于 Human schedule,不是完全讓編排的系統(tǒng)自己決定該怎么樣。
編排工具我們現(xiàn)在在研究進(jìn)一步,我剛來(lái)這工作的時(shí)候,所有的服務(wù)沒(méi)有一個(gè)跑在 Docker 上面的,我現(xiàn)在把它遷進(jìn)來(lái)。現(xiàn)在數(shù)據(jù)增長(zhǎng),已經(jīng)有一些編排的瓶頸,現(xiàn)在在做調(diào)研,可能基于 Swarm,做自動(dòng)編排的設(shè)計(jì)。
第二輪話題交流主持人:容器多的情況下 Kubernetes 存在性能問(wèn)題,各位在這方面有沒(méi)有好的經(jīng)驗(yàn)?
扇貝丁彥:我們其實(shí)也遇到了這個(gè)問(wèn)題,找不到辦法所以放棄了 Kubernetes。我們也是用公有云,網(wǎng)絡(luò)直接依賴公有云的網(wǎng)絡(luò),有可能是因?yàn)楣性圃斐傻?,我沒(méi)有試過(guò)在祼機(jī)上試過(guò)。滬江黃凱:Kuberneters 的 Fannel 有一種模式是 Vxlan,它的封裝折包是做內(nèi)核里做的,效率會(huì)高一點(diǎn)。容器多就會(huì)效率會(huì)低是因?yàn)?,?Kubernetes 1.2 的時(shí)候,走這樣的一種模式,數(shù)據(jù)先到內(nèi)核態(tài)中,然后把數(shù)據(jù)拉回到用戶態(tài),用 Proxy的方式分發(fā)給各個(gè)容器當(dāng)中的。其實(shí)在Kubernetes 1.3以后,它直接在iptables里設(shè)規(guī)則,相當(dāng)于用戶數(shù)據(jù)不用跑到用戶態(tài),在內(nèi)核直接分發(fā)出去了,這種效率會(huì)非常高。所以可以研究一下Kubernetes新版本。扇貝丁彥:我們碰到過(guò)網(wǎng)絡(luò)方面的問(wèn)題。默認(rèn)的Docker engine的啟動(dòng)參數(shù)里面有個(gè)iptables,不知道大家有沒(méi)有定制化過(guò),如果不定制化這個(gè)參數(shù),它默認(rèn)會(huì)幫你建iptables的轉(zhuǎn)發(fā)規(guī)則,并會(huì)開(kāi)啟內(nèi)核的網(wǎng)絡(luò)追蹤的模塊。一開(kāi)始我們沒(méi)有注意這件事情,當(dāng)我們的Nginx遷到Docker的時(shí)候,Nginx服務(wù)瞬間會(huì)掛。后來(lái)查原因,是因?yàn)檫@些參數(shù)會(huì)開(kāi)啟網(wǎng)絡(luò)追蹤模塊。因?yàn)槲覀兊腘ginx流量非常大,當(dāng)時(shí)只有3臺(tái)Linux云主機(jī),分發(fā)Http請(qǐng)求的,然后會(huì)導(dǎo)致3臺(tái)Linux宿主機(jī),內(nèi)存會(huì)被刷破,網(wǎng)絡(luò)會(huì)出現(xiàn)堵塞。所以我們關(guān)掉了 iptables 參數(shù),并采用Host的網(wǎng)絡(luò)模型。所以它的容器拿到的IP就是Host的IP。我們一開(kāi)始也想上一些Kubernetes這些東西,然后發(fā)現(xiàn)簡(jiǎn)單跑個(gè)模型根本跑不起來(lái),所以一開(kāi)始就放棄了這一套東西,直接搞了個(gè)裸的Docker。
主持人:關(guān)于跨數(shù)據(jù)中心容器集群的使用,大家有經(jīng)驗(yàn)么?滬江黃凱:我們跨數(shù)據(jù)中心主要是IP分配上的問(wèn)題,我們現(xiàn)在也在嘗試使用Calico,如果Host網(wǎng)絡(luò)是通的話,那么它的內(nèi)部網(wǎng)絡(luò)也就通了,可以自由劃Vlan,這樣你就可以解決跨Data center的問(wèn)題。還有一個(gè)問(wèn)題就在跨Data center時(shí),服務(wù)注冊(cè)與發(fā)現(xiàn)的問(wèn)題。這個(gè)問(wèn)題也困擾我們很久了,我們現(xiàn)在使用Consul做服務(wù)注冊(cè)與發(fā)現(xiàn)。雖然Consul它是官方支持跨Data center,但是我們?cè)谑褂卯?dāng)中的話會(huì)發(fā)現(xiàn)注冊(cè)的IP,在另外一個(gè)注冊(cè)中心,它會(huì)發(fā)現(xiàn)的比較慢,甚至有時(shí)候出現(xiàn)IP沖突的時(shí)候。我們的做法是把 Host 的 IP 地址直接用 Environment 的形式注到 Docker 鏡像內(nèi)部,接下 來(lái) Docker 鏡像要注冊(cè),它就會(huì)讀取 app 的 IP,然后發(fā)送給 Consul,只要保證 Host 的 IP 和 Docker內(nèi)部容器的 IP 能夠互通的就行了。如果不能通的話,比如說(shuō)完全和 Host IP 隔離,那么起碼有幾臺(tái)機(jī)器要暴露出去,又比如說(shuō),Consul 它本身自己要暴露出去才能訪問(wèn)到。Host 的 IP 是容器啟動(dòng)之后注進(jìn)去的,啟動(dòng)命令中把 Host 的 IP 地址加在 -e 的后面,容器在啟動(dòng)之后,它的環(huán)境就會(huì)有這么一個(gè) IP。我們用 Mesos 就沒(méi)這個(gè)問(wèn)題,但是用 Kubernetes 就有這個(gè)問(wèn)題。Mesos 會(huì)自動(dòng)幫你把這些東西注入容器中去。滴滴田智偉:其實(shí) Kubernetes 本身也是可以解決這個(gè)問(wèn)題,我們現(xiàn)在在做線下持續(xù)交付的時(shí)候。定義完 Service 之后,容器會(huì)同一個(gè) Namespace 默認(rèn)加一個(gè)系統(tǒng)環(huán)境變量。滬江黃凱:我們?cè)囘^(guò),在 Pod 啟動(dòng)之后,Pod 里容器想訪問(wèn) host 的 IP 地址,是沒(méi)有辦法做到的。蘑菇街張振華:因?yàn)槲覀冎耙灿龅竭@個(gè)問(wèn)題,然后我們業(yè)務(wù)方,他們可能有一些程序會(huì)獲取本機(jī) IP 地址,如果是內(nèi)部的 IP 地址,他們程序可能會(huì)出現(xiàn)問(wèn)題,于是我們當(dāng)時(shí)沒(méi)有用 Docker 默認(rèn)的網(wǎng)絡(luò),而是采用 Vlan。
主持人:我們提到好多 Mesos、Kubernetes、網(wǎng)絡(luò),發(fā)現(xiàn)沒(méi)有提自動(dòng)伸縮,有沒(méi)有項(xiàng)目涉及到容器的自動(dòng)伸縮?滬江黃凱:我們滬江是基于 Mesos+Marathon 做了自己的一個(gè)服務(wù),它這個(gè)服務(wù)是干嘛的呢,就是監(jiān)測(cè),不停的監(jiān)測(cè)每一個(gè) Docker 的 CPU 和內(nèi)存的利用率,一旦超過(guò)百分之多少以后,就向Marathon發(fā)一個(gè)命令,說(shuō)我要擴(kuò)容,它還可以支持時(shí)間點(diǎn),比如 15 分鐘監(jiān)測(cè)一次,如果在 15 分鐘發(fā)現(xiàn)它超過(guò)閾值了,就馬上擴(kuò)容出來(lái),但是縮的話,不是適用于頻繁監(jiān)控,如果小于 20% 的話就會(huì)縮,一旦縮的話會(huì)影響線上用戶的請(qǐng)求。怎么辦呢?我們?cè)诳s的時(shí)候可以規(guī)定它的時(shí)間點(diǎn),比如半夜里2-3點(diǎn),訪問(wèn)量少于多少點(diǎn)時(shí)候把它縮掉。我們監(jiān)測(cè)的是 Docker 內(nèi)部的 CPU 的使用率。就是監(jiān)測(cè)一個(gè)服務(wù),它可以監(jiān)控所有同一服務(wù)的 Container,比如一個(gè)服務(wù)有100個(gè)容器,那么這一百多個(gè) CPU 利用率加起來(lái)除于一百,相當(dāng)于平均的利用率。如果平均利用率超過(guò) 80%了,那說(shuō)明這個(gè)集群到了擴(kuò)展程度了,它會(huì)以一種比例來(lái)擴(kuò)展。針對(duì)單個(gè)容器,可以設(shè)置內(nèi)存的限制。我們給每一個(gè)容器呢,比如它只能用 4 個(gè) CPU,只能用 8G 的內(nèi)存,或者更小一點(diǎn)的內(nèi)存,這些都設(shè)好,設(shè)好之后它自動(dòng)擴(kuò)展相同規(guī)格的容器。這么做是因?yàn)?Cgroup 有個(gè)問(wèn)題,當(dāng)利用率到達(dá)了啟動(dòng)的限制,Cgroup 會(huì)把這個(gè)容器 kill 掉。這個(gè)是不可理喻的問(wèn)題,所以我們想到用 Load scale 來(lái)擴(kuò)容,不讓他直接死掉。滴滴田志偉:關(guān)于自動(dòng)擴(kuò)容,我們線下的時(shí)候遇到一個(gè)問(wèn)題,我們最早的時(shí)候是用騰訊的公有云,它限制了 NET 的模塊,導(dǎo)致我們最初用 Cgroup 的方案去做,綁定端口。內(nèi)部使用所有應(yīng)用,端口是要做分配的,要不然出現(xiàn)端口沖突。然后遇到問(wèn)題是,在這種情況下,如果要做動(dòng)態(tài)擴(kuò)容的話,它每次先創(chuàng)建一個(gè),再殺掉一個(gè),導(dǎo)致每次起來(lái)的時(shí)候就起不來(lái)了,因?yàn)槎丝诘膯?wèn)題。服務(wù)啟動(dòng)的時(shí)候端口是隨機(jī),會(huì)出現(xiàn)沖突問(wèn)題,因?yàn)橛玫氖?Host 的模式。
主持人:關(guān)于自動(dòng)伸縮為什么沒(méi)有考慮到請(qǐng)求數(shù)?因?yàn)槿绻麅?nèi)存占用率如果超過(guò)一定預(yù)支,那么請(qǐng)求數(shù)也可能超過(guò)一定預(yù)支了。把單個(gè)容器所處理的請(qǐng)求數(shù)給限定了,那么它內(nèi)存自然不會(huì)超,然后也不會(huì)被干掉。滬江黃凱:我個(gè)人認(rèn)為,第一,請(qǐng)求數(shù)很難測(cè),你不知道請(qǐng)求數(shù)到多少時(shí)要擴(kuò)容,還不如根據(jù) CPU 到 80%,或者 90% 來(lái)的直觀。我們的 API 也是根據(jù) CPU 來(lái)算的。你真正是高并發(fā)的 API 的話,我也測(cè)過(guò),最后我們能夠監(jiān)測(cè)到的,其實(shí)還是 CPU 和內(nèi)存。扇貝丁彥:我們擴(kuò)容是根據(jù)響應(yīng)時(shí)間,跟請(qǐng)求數(shù)類似,請(qǐng)求數(shù)定指標(biāo)不太好定,我們是根據(jù)響應(yīng)時(shí)間,比如平時(shí)的響應(yīng)時(shí)間是 50 毫秒,當(dāng)響應(yīng)時(shí)間是 300 毫秒的時(shí)候就要擴(kuò)容了。
主持人:大家對(duì)于容器有狀態(tài)無(wú)狀態(tài)有沒(méi)有遇到什么問(wèn)題?大家一般用容器的本地磁盤還是共享磁盤呢?滬江黃凱:關(guān)于存儲(chǔ),我們是有一些研究的?,F(xiàn)在容器存儲(chǔ)問(wèn)題分為兩種,Kubernetes 官方支持一種理念,任何一種存儲(chǔ)都是一個(gè) Volume。Volume 先于 Docker 存在的,而不是 Docker 啟動(dòng)之后再掛載 Volume。不管是網(wǎng)絡(luò)存儲(chǔ)還是本地存儲(chǔ),全部以卷的形式,掛載在 Pod 里面或者是宿主機(jī)上,以 Driver mapper 來(lái)驅(qū)動(dòng)這個(gè) Volume,來(lái)讀到你所要的內(nèi)容。還有一種情況,就是 Docker 公司主導(dǎo)的存儲(chǔ)模型,任何的存儲(chǔ)都是一種驅(qū)動(dòng)。如果你想用 NFS 或者如 Ceph 這樣分布式存儲(chǔ)的話,讓 Ceph 開(kāi)發(fā) Docker 的驅(qū)動(dòng),Docker run 的時(shí)候指定存儲(chǔ)的驅(qū)動(dòng),Docker storage driver這種方式,外部的存儲(chǔ)在容器內(nèi)部它展現(xiàn)形式可以是目錄,也可以是掛載卷、塊的形式。如果用塊掛載到容器中,這個(gè)容器自己格式化它,或直接讀取它都是可以的。它只不過(guò)它是相當(dāng)于用了一個(gè) Driver 的形式,把你的容器和分布式存儲(chǔ)建立一個(gè)連接而已。對(duì)于容器,如果原本綁定塊或 Volume,容器出現(xiàn)故障的話,直接把容器殺掉,再啟動(dòng)掛在同樣一個(gè) 塊或Volume就解決了。優(yōu)點(diǎn)是直接讀取,而不是通過(guò)再轉(zhuǎn)一層,效率比較高一點(diǎn)。所有存儲(chǔ)都是Volume 的形式理解度比較高一點(diǎn),所以我們還是贊同于用 Volume 的形式。有狀態(tài)的容器。我知道k8s的新的計(jì)劃,如果你沒(méi)有用 Kubernetes 最新版本的話,一般來(lái)說(shuō)我們都是容器啟動(dòng)在固定Host 上,下次啟動(dòng)還是在這臺(tái) Host 上,它的存儲(chǔ)它的內(nèi)存,包括一些 log,全部是在這臺(tái) Host 上。還有一種是用最新的版本,有個(gè) PetSet的新kind,Kubernetes 它自己會(huì)記錄 Pod 在什么 Host 上啟動(dòng)過(guò),不用自己去指定一定要在某一臺(tái) Host 上啟動(dòng),這種方法比較智能化,但是不是特別穩(wěn)定的一種方法,因?yàn)樗莿倓傞_(kāi)發(fā)出來(lái)的新功能。
主持人:數(shù)據(jù)多副本,假設(shè)有一個(gè)節(jié)點(diǎn)故障的話,是建議它直接把原來(lái)的副本重新綁定還是重新起一個(gè)新的實(shí)例,通過(guò)分布式數(shù)據(jù)的遷移呢?滬江黃凱:我個(gè)人認(rèn)為還是在同一臺(tái)機(jī)器上起一個(gè)新的實(shí)例,不要讓它做數(shù)據(jù)遷移,因?yàn)閿?shù)據(jù)遷移會(huì)占用很多資源。而且如果你的想法是說(shuō),所有的分布式的存儲(chǔ)只是以 Volume 的形式掛載在宿主同上,這也就沒(méi)什么問(wèn)題了。因?yàn)榇鎯?chǔ)和 Docker 是完全分開(kāi)來(lái)的。如果只有一個(gè) Volume,存儲(chǔ)的可靠性會(huì)得不到保障,所以在 Kubernetes 新版本當(dāng)中,它會(huì)建立一個(gè)Volume的kind,也相當(dāng)于建立 RC kind一樣,是一個(gè) Pod,那這樣由 Kubernetes 來(lái)保障這個(gè) Volume 的高可用。
轉(zhuǎn)貼: 網(wǎng)易新聞