新聞中心
隨著容器技術(shù)的流行,作為線上應(yīng)用 Docker 的鋪墊,喜馬拉雅 FM 從 2016 年開(kāi)始推進(jìn)測(cè)試環(huán)境的 Docker 化。本文重點(diǎn)介紹筆者在 Docker 化的過(guò)程中如何進(jìn)行技術(shù)選型、環(huán)境搭建,和實(shí)踐中碰到的一些問(wèn)題及其解決方案。

為什么要Docker化?
1.標(biāo)準(zhǔn)化
- 配置標(biāo)準(zhǔn)化,以部署 Tomcat 為例,實(shí)際物理環(huán)境中,通常一臺(tái)物理機(jī)部署多個(gè) Tomcat,這就存在 Tomcat 的端口及目錄管理問(wèn)題。理想狀態(tài)下:一個(gè)項(xiàng)目一個(gè)主機(jī) Tomcat,Tomcat 永遠(yuǎn)位于/ usr / local / tomcat(或其他你喜歡的位置)下,對(duì)外端口是 8080,debug 端口是 8000。
- 部署標(biāo)準(zhǔn)化,現(xiàn)在云平臺(tái)越來(lái)越流行,同時(shí),也不會(huì)立即丟棄物理環(huán)境,因此必然存在著同時(shí)向云環(huán)境和物理環(huán)境部署的問(wèn)題。這就需要一系列工具,能夠屏蔽物理環(huán)境和云環(huán)境的差異,Docker 在其中扮演重要角色。
2.API 化
通過(guò)API接口操作項(xiàng)目的部署(CPU、內(nèi)存分配、機(jī)器分配、實(shí)例數(shù)管理等),而不是原來(lái)物理機(jī)環(huán)境的的手工命令行操作。
3.自動(dòng)化
調(diào)度系統(tǒng)可以根據(jù)API進(jìn)行一些策略性的反應(yīng),比如自動(dòng)擴(kuò)容縮容。
上述工作,原有的技術(shù)手段不是不可以做,可是太麻煩,可用性和擴(kuò)展性都不夠好。
Docker 化的四個(gè)小目標(biāo)
1.業(yè)務(wù)之間不互相干擾
- 一個(gè)項(xiàng)目/ war 一虛擬機(jī)/容器
- Ip-pert-task
2.容器之間、容器與物理機(jī)之間可以互通
3.容器編排:健康檢查、容器調(diào)度等
4.使用方式:通過(guò) yaml / json 來(lái)描述任務(wù),通過(guò) API 部署
總結(jié)一下,基于 n 臺(tái)物理機(jī)搭建容器環(huán)境,整個(gè)工作的主線:
一個(gè)項(xiàng)目一個(gè)主機(jī) ==>物理機(jī)資源不夠 ==>虛擬化 ==>輕量級(jí)虛擬化 ==> Docker ==>針對(duì) Docker 容器帶來(lái)的網(wǎng)絡(luò)、存儲(chǔ)等問(wèn)題 ==>集群編排 ==>對(duì) CI / CD 的影響。
虛擬化網(wǎng)絡(luò)的兩種思路
Overlay
- 隧道,通常用到一個(gè)專門(mén)的解封包工具。
- 路由,每個(gè)物理機(jī)充當(dāng)一個(gè)路由器,對(duì)外,將容器數(shù)據(jù)路由到目標(biāo)機(jī)器上;對(duì)內(nèi),將收到的數(shù)據(jù)路由到目標(biāo)容器中。
通常需要額外的維護(hù)物理機(jī)以及物理機(jī)上容器 IP(段)的映射關(guān)系。
Underlay
不準(zhǔn)確的說(shuō),容器的網(wǎng)卡暴露在物理網(wǎng)絡(luò)中,直接收發(fā),通常由外部設(shè)備(交換機(jī))負(fù)責(zé)網(wǎng)絡(luò)的連通性。
經(jīng)過(guò)對(duì)比,我們采用了 MacVLAN,主要是因?yàn)椋?/p>
- 簡(jiǎn)單
- 效率高
- 可將容器“當(dāng)成”虛擬機(jī)用,容器之間互通就行,不需要支持復(fù)雜的網(wǎng)絡(luò)伸縮、隔離、安全等策略。
IP 分配問(wèn)題
對(duì)于物理機(jī)、KVM 等虛擬機(jī)來(lái)說(shuō),它的生命周期很長(zhǎng),IP 一經(jīng)分配便幾乎不變,因此通常由人工通過(guò)命令或 Web 界面手動(dòng)分配。而對(duì)于 Docker 容器來(lái)說(shuō),尤其是測(cè)試環(huán)境,容器的創(chuàng)建和銷毀非常頻繁,這就涉及到頻繁的 IP 分配和釋放。因此,IP 分配必須是自動(dòng)的,并且有一個(gè) IP 資源池來(lái)管理 IP。
在 Docker 網(wǎng)絡(luò)中,CNM(Container Network Management)模塊通過(guò) IPAM(IP address management)driver 管理 IP 地址的分配。我們基于 TalkingData/Shrike 改寫(xiě)了自己的 IPAM 插件,fix 了在多實(shí)例部署模式(一個(gè) Docker host 部署一個(gè) IPAM,以防止單實(shí)例模式出現(xiàn)問(wèn)題時(shí),整個(gè)系統(tǒng)不可用的問(wèn)題)下的重復(fù)存取問(wèn)題。
Docker之外的編排工具
Docker 解決了單機(jī)的虛擬化,但當(dāng)一個(gè)新部署任務(wù)到達(dá),由集群中的哪一個(gè) Docker 執(zhí)行呢?因此,Docker 之外,需要一個(gè)編排工具,實(shí)現(xiàn)集群的資源管理和任務(wù)調(diào)度。
這些工具均采用 Master / Slave 架構(gòu),假設(shè)我們將物理機(jī)分為 Master 和 Slave,這些工具在 Slave 上運(yùn)行一個(gè) Agent(任務(wù)執(zhí)行和數(shù)據(jù)上報(bào)),在 Master 上運(yùn)行一個(gè) Manager(任務(wù)分發(fā)和數(shù)據(jù)匯總)。從功能上說(shuō),任務(wù)分發(fā)和容器資源匯總,這些工具可以滿足要求。它們的根本區(qū)別就是:發(fā)展歷程的不同。
- 從一個(gè) Docker / 容器化調(diào)度工具, 擴(kuò)展成一個(gè)分布式集群管理工具
- 從一個(gè)分布式資源管理工具,增加支持 Docker 的 Feature
到目前為止,根據(jù)喜馬拉雅FM測(cè)試環(huán)境的實(shí)踐,發(fā)現(xiàn)有以下特點(diǎn):
- 對(duì)編排的需求很弱,基本都是單個(gè)微服務(wù)項(xiàng)目的部署。微服務(wù)項(xiàng)目的協(xié)同、服務(wù)發(fā)現(xiàn)等由公司的服務(wù)治理框架負(fù)責(zé)。
- 基礎(chǔ)服務(wù),比如 MySQL、Hadoop 等暫不上 Docker 環(huán)境。
- 需要查詢編排工具的 API 接口,同時(shí)有一個(gè)良好的 Web 界面,對(duì)編排工具的數(shù)據(jù)匯總、資源管理能力有一定要求。
因此我們決定使用 Marathon + Mesos 方案。在后面實(shí)踐的過(guò)程中,因?yàn)榫W(wǎng)絡(luò)和編排工具的選擇,IP 變化的問(wèn)題帶來(lái)很大的困擾,我們甚至專門(mén)開(kāi)發(fā)了幾個(gè)小工具,參見(jiàn)下文。
image 的組織
Docker 的厲害之處,不在于發(fā)明了一系列新技術(shù),而在于整合了一系列老技術(shù),廣為人知的阿里、騰訊等大廠在 Cgroups、Namespace 等基礎(chǔ)上搞了一套自己的容器工具。對(duì)于阿里,使用 Docker 初衷是 Docker 鏡像化,也就是其帶來(lái)的應(yīng)用環(huán)境標(biāo)準(zhǔn)化,而不是容器化。
Docker鏡像的實(shí)踐主要涉及到以下三個(gè)問(wèn)題:
1.搭建私有 imagerepository
2.對(duì) layer 進(jìn)行組織
3.鏡像的分發(fā)較慢
- 預(yù)分發(fā),但這不解決根本,只適用部分場(chǎng)景
- 對(duì) layer 進(jìn)行壓縮,京東目前采用該方案
4.鏡像化帶來(lái)容器重啟
因?yàn)殓R像是一體的,哪怕只有一點(diǎn)更改,鏡像的發(fā)布都必須銷毀之前的容器,然后按照新鏡像創(chuàng)建新容器。耗時(shí)是一方面,對(duì)以下場(chǎng)景也很不友好:
- 只是更新一個(gè)文件,項(xiàng)目、容器均需要重啟
- 因?yàn)榧虞d緩存等原因,項(xiàng)目、容器啟動(dòng)比較耗時(shí)
對(duì)于具體的場(chǎng)景,可以有具體的辦法規(guī)避。對(duì)于通用的解決方案,阿里通過(guò)改寫(xiě) Docker,對(duì)鏡像支持 HotFix 標(biāo)識(shí),deploy 這類鏡像,不再創(chuàng)建新容器,而是更新容器。
我們要對(duì)鏡像的 layer 進(jìn)行組織,以***化的復(fù)用 layer。
因?yàn)橹皇窃跍y(cè)試環(huán)境使用,鏡像較慢的矛盾還不是太突出。這里有一個(gè)技術(shù)之外的問(wèn)題。阿里對(duì)于 docker image feature 的改造,實(shí)現(xiàn)了如下優(yōu)化:
- 可以減少容器的重啟次數(shù),進(jìn)而減少 IP 的分配和釋放。
- 影響到容器的編排策略,即 deploy 新的任務(wù)不再是選擇一個(gè)機(jī)器運(yùn)行容器,而是找到原來(lái)的容器應(yīng)用變更。
- 對(duì) Docker 的各種特性的認(rèn)識(shí),一則認(rèn)為天經(jīng)地義,二則逆來(lái)順受。出現(xiàn)問(wèn)題,要么想辦法規(guī)避,要么在外圍造個(gè)輪子去解決(還是規(guī)避)。
CI
Jenkins 如何跟 Marathon 結(jié)合,現(xiàn)成的方案很多。關(guān)鍵是提供幾套不同的模板,方便不同業(yè)務(wù)的使用。
容器變化帶來(lái)四大問(wèn)題
使用 Docker 后,容器在物理機(jī)之間自由漂移,物理機(jī)的角色弱化成了:?jiǎn)渭兊奶峁┯?jì)算資源。但帶來(lái)的問(wèn)題是,影響了許多系統(tǒng)的正常運(yùn)行。
1.IP 變化
許多系統(tǒng)的正常運(yùn)行依賴 IP,但 IP 不穩(wěn)定帶來(lái)一系列的問(wèn)題。而解決IP的變化問(wèn)題主要有以下方案:
- 新增組件屏蔽 IP 變化
- 提供 DNS 服務(wù)(有緩存和多實(shí)例問(wèn)題)
- 不要改變 IP
既然重啟后,IP 會(huì)改變,就減少容器重啟
服務(wù)與 IP 綁定(這個(gè)方案非常不優(yōu)雅)
對(duì)于 Web 服務(wù),IP的變化導(dǎo)致要經(jīng)常更改 Nginx 配置,為此,我們專門(mén)改寫(xiě)了一個(gè) Nginx 插件來(lái)解決這個(gè)問(wèn)題。
對(duì)于 RPC 服務(wù),技術(shù)團(tuán)隊(duì)有獨(dú)立開(kāi)發(fā)的服務(wù)治理系統(tǒng),實(shí)現(xiàn)服務(wù)注冊(cè)和發(fā)現(xiàn)。但該系統(tǒng)有審核機(jī)制,對(duì)于跨語(yǔ)言調(diào)用,因?yàn)閞pc客戶端不通用,仍有很多不便。
2.文件存儲(chǔ)
有許多項(xiàng)目會(huì)將業(yè)務(wù)數(shù)據(jù)存儲(chǔ)在文件中,這就意味著項(xiàng)目 deploy 進(jìn)而容器重啟之后,要能找到并訪問(wèn)這些文件。在 Docker 環(huán)境下主要有以下兩種方案:
- Dockervolumn + cluster fs
- Dockervolume plugin
我們當(dāng)下主要采用***種,將 cluster fs mount 到每臺(tái) Docker host 的特定目錄(例如 / data),打通 container / data ==> docker host / data == cluster fs / data,任意容器即可共享訪問(wèn) /data 目錄下的數(shù)據(jù)。
3.日志采集與查看
為了日志持久化存儲(chǔ),技術(shù)將容器的日志目錄映射到了物理機(jī)上。but,一個(gè)項(xiàng)目的日志分散在多個(gè)物理機(jī)中。
原有的日志采集報(bào)警系統(tǒng),負(fù)責(zé)日志采集、匯總、報(bào)警。因此容器化后,并不會(huì)有什么影響。但該系統(tǒng)只采集錯(cuò)誤日志,導(dǎo)致開(kāi)發(fā)人員要查看日志以調(diào)試程序時(shí),比較麻煩。
最初,提供了一個(gè) Web Console 來(lái)訪問(wèn)容器,操作步驟為:login ==> findcontainer ==> input console ==> op。
但依然過(guò)于繁瑣,并且 Web Console 的性能也不理想。而直接為每個(gè)容器配置 ssh server,又會(huì)對(duì) safe shutdown 等產(chǎn)生不良影響。因此:
- 登陸測(cè)試環(huán)境,90%是為了查看日志。
- 和開(kāi)發(fā)約定項(xiàng)目的日志目錄,并將其映射到物理機(jī)下。
- 間接配置 SSH。每個(gè)物理機(jī)啟動(dòng)一個(gè)固定 IP 的 SSHContainer,并映射日志目錄。
- 使用 Go 語(yǔ)言實(shí)現(xiàn)了一個(gè) essh 工具,essh-imarathon_app_name 即可訪問(wèn)對(duì)應(yīng)的 SSH Container 實(shí)例并查看日志。
當(dāng)然,日志的問(wèn)題,也可以通過(guò) elk 解決。
其他問(wèn)題
1.Base image 的影響
- 時(shí)區(qū)、Tomcat PermGensize、編碼等參數(shù)值的修正。
- base image 為了盡可能精簡(jiǎn),使用了 alpine。它的一些文件缺失,導(dǎo)致一些Java代碼無(wú)法執(zhí)行。比如,當(dāng)去掉 / etc / hosts 中 ip 和容器主機(jī)名的映射后,加上 /etc/sysconfig/network 的缺失,導(dǎo)致 Java 代碼 InetAddress.getLocalHost()執(zhí)行失敗。
2.Safeshutdown,部分服務(wù)退出時(shí)要保存狀態(tài)數(shù)據(jù)
3.支持 sshd,以方便大家查看日志文件
使用 supervisord(管理 SSH 和 Tomcat),需要通過(guò) supervisord 傳導(dǎo) 。SIGTERM 信號(hào)給 Tomcat,以確保 Tomcat 可以 safeshutdown。該方法經(jīng)常發(fā)生 supervisord 讓 Tomcat 退出,但自己不退出的情況。
每臺(tái)機(jī)器啟動(dòng)跟一個(gè)專門(mén)的容器,映射一些必要的 volume,以供大家查看日志等文件。
4.Marathon 多機(jī)房主備問(wèn)題
5.容器的漂移對(duì)日志采集、分析系統(tǒng)的影響
6.對(duì)容器提供 DNS 服務(wù),以使其可以正確解析外部服務(wù)的 hostname
7.如何更好的推廣與應(yīng)用的問(wèn)題
todo
1.日志采集,簡(jiǎn)化日志搜索
2.一個(gè)集中式的 DC
當(dāng)下,項(xiàng)目部署的各個(gè)階段分散在不同的組件中。呈現(xiàn)出來(lái)的使用方式,不是面向用戶的。
- Jenkins 負(fù)責(zé)代碼的編譯和 Marathonjob 的觸發(fā)
- Marathon 負(fù)責(zé)任務(wù)調(diào)度、銷毀和回滾等
- Portainer 負(fù)責(zé)容器數(shù)據(jù)的界面化以及 WebConsole
這樣帶來(lái)的問(wèn)題是:
對(duì)于運(yùn)維人員來(lái)說(shuō),一些操作不能固化下來(lái),比如回滾等,手工操作易出錯(cuò)。
對(duì)于用戶來(lái)說(shuō),容易想當(dāng)然的通過(guò) portainer 進(jìn)行增刪改容器的操作,進(jìn)而引起系統(tǒng)的不一致。
因?yàn)槭乾F(xiàn)成系統(tǒng),很難加入技術(shù)自己的邏輯,這使得配置上經(jīng)常出現(xiàn)一些語(yǔ)義沖突的情況。
李乾坤
喜馬拉雅 FM Java 開(kāi)發(fā)工程師
李乾坤,喜馬拉雅 FM Java 開(kāi)發(fā)工程師。2014 年開(kāi)始接觸 Docker,2015 年?yáng)|南大學(xué)碩士畢業(yè),隨即加入喜馬拉雅 FM,從事后臺(tái)開(kāi)發(fā),2016 年參與測(cè)試環(huán)境 Docker 化,目前負(fù)責(zé)平臺(tái)支持業(yè)務(wù)的維護(hù)與開(kāi)發(fā)。
網(wǎng)站名稱:踩坑小結(jié)!喜馬拉雅FM測(cè)試環(huán)境的Docker化實(shí)踐
文章來(lái)源:http://m.fisionsoft.com.cn/article/cdciiej.html


咨詢
建站咨詢
