Docker是云技術(shù)和IT技術(shù)的未來,這一點正在被越來越多的公司認識到,但是對于傳統(tǒng)企業(yè)來說,如何將傳統(tǒng)的應(yīng)用遷移到Docker是一個迫切需要解決的問題。傳統(tǒng)企業(yè),尤其是國內(nèi)的傳統(tǒng)企業(yè),IT建設(shè)普遍滯后,當(dāng)大多數(shù)互聯(lián)網(wǎng)公司都在大面積使用Docker的時候,傳統(tǒng)企業(yè)還在為虛擬化、公有云和敏捷開發(fā)掙扎。很多企業(yè)都在提工業(yè)4.0,但是信息化建設(shè)卻沒有提高到一定的高度。企業(yè)的信息化程度,很大程度上決定了企業(yè)的生產(chǎn)效率,而Docker則從應(yīng)用層面提出了非常好的解決方案。本文也將從遷移的角度來闡述如何在傳統(tǒng)企業(yè)中使用Docker。
傳統(tǒng)應(yīng)用容器化遷移的思考
對于傳統(tǒng)應(yīng)用來說,使用和不使用Docker可能并不能直接給企業(yè)帶來好處,相反使用中遇到了問題肯定會給企業(yè)帶來麻煩。那我們?yōu)槭裁匆褂肈ocker呢?Docker最大的好處是標(biāo)準(zhǔn)化應(yīng)用交付,當(dāng)然隨之提高了工作效率,并節(jié)約了成本,據(jù)國外的統(tǒng)計使用Docker平均可以提升60%的效率,同時節(jié)約40%的成本。我們可以把Docker比作一條軟件的生產(chǎn)線,當(dāng)你有了這條生產(chǎn)線后,帶來的效率提升是質(zhì)的飛躍。不過,當(dāng)你在引進Docker這條生產(chǎn)線的時候,你肯定會有很多的疑慮,比如:
如何能保證現(xiàn)有生產(chǎn)線到Docker的平滑過渡?
如何確保員工能夠快速的上手?
如何合理利用現(xiàn)有的資源,比如數(shù)據(jù)庫、網(wǎng)絡(luò)等?
如何使用新的服務(wù)框架?
如何重新定義軟件層的依賴?
如何處理操作系統(tǒng)的問題?
如何重新定義軟件的生命周期?
傳統(tǒng)應(yīng)用的容器化遷移建議
當(dāng)我們需要遷移一個應(yīng)用的時候,首先需要了解一個應(yīng)用當(dāng)前正在使用的資源有哪些。你需要了解當(dāng)前系統(tǒng)的拓撲結(jié)構(gòu),現(xiàn)有的拓撲結(jié)構(gòu)是遷移的最好參考,傳統(tǒng)的單體模式下,很多應(yīng)用程序運行在一臺主機之上,但在微服務(wù)體系下,我們更傾向于通過容器來解耦合,實際上,并不是所有系統(tǒng)都適合于解耦合,我們的進程間通訊是必須要考慮的因素,任何一個企業(yè)在遷移過程中都不愿意去重新對一個模塊進行重編碼,因為有的程序可能根本就找不到代碼。本文結(jié)合我們的實際經(jīng)驗闡述傳統(tǒng)應(yīng)用在容器化遷移中需要考慮的一些因素。
操作系統(tǒng)
如果你的應(yīng)用是基于Windows系統(tǒng),并且不打算使用Linux,可以直接忽略本文(很多應(yīng)用是可以遷移到Linux的,比如Java、PHP、Python等)。對于進程來說,它是只工作在Ring 3還是工作在Ring 0-3是至關(guān)重要的,如果你進程涉及到內(nèi)核的操作,需要非常的小心,因為他可能會引起系統(tǒng)崩潰。我們知道通常system call是會從用戶態(tài)轉(zhuǎn)到內(nèi)核態(tài),所以基本都會涉及到內(nèi)核操作。我所說的內(nèi)核操作是指你自己寫了相應(yīng)的驅(qū)動或者內(nèi)核模塊,因為你的kernel代碼肯定是更容易出問題的。因此,我們需要了解容器并不是虛擬機,它本身是一個進程,一個受到諸多管控的進程。即使你的容器里面的內(nèi)核版本很高,但骨子里都是你的Host內(nèi)核。因此,容器的隔離并不會像虛擬機一樣徹底,對于一個虛擬機,即使你的內(nèi)核操作引起的崩潰,也不會導(dǎo)致其他虛擬機崩潰,但是,容器則會和大家一起崩潰。所以,我們應(yīng)當(dāng)盡量通過容器來隔離不涉及內(nèi)核操作的應(yīng)用。如果您不清楚是否涉及內(nèi)核,也不用擔(dān)心,目前基本上95%以上的Linux應(yīng)用都不直接涉及內(nèi)核操作。我們一般的web服務(wù)器,后端服務(wù),基本都不涉及內(nèi)核操作。
CPU
對于單個應(yīng)用程序,首先需要考慮的是CPU問題,需要幾個CPU,需要多強的CPU。如果是CPU消耗性的程序,要在不影響其他應(yīng)用情況下,盡可能多的分配CPU。CPU一般是稀缺資源,需要結(jié)合實際使用的上限值、下限值和均值做規(guī)劃。最好的方法就是利用ps、top、htop等工具進行跟蹤,最好能跟蹤一個軟件運行周期,得到軟件的CPU上限和下限。CPU的跟蹤結(jié)果會左右后續(xù)的容器資源限定值。
內(nèi)存的大小
使用容器的一大目的就是要限定應(yīng)用的資源使用,因此我們需要獲得容器的初始內(nèi)存大小,運行中內(nèi)存大小以及最大內(nèi)存。這一部分可以通過vmstat等工具來獲得。需要指出的是,內(nèi)存和CPU都是利用CGroup內(nèi)核技術(shù)進行控制的,所以控制的是使用上限,并不是分配以后就專屬于某個容器。只不過如果你的應(yīng)用使用內(nèi)存超過了上限,程序會觸發(fā)OOM(out of memory),可能會被Kill掉,例如你是通過tomcat來封裝應(yīng)用的,由于啟動時候需要使用更多的內(nèi)存,可能會存在被Kill的可能性。這些都可以通過docker log和系統(tǒng)日志來進行查看。
進程模型
隨著高級語言的出現(xiàn),熟悉操作系統(tǒng)進程模型的人越來越少。父進程是什么,子進程是什么,進程樹是怎么樣的,線程是怎么構(gòu)建的都需要弄清楚。這有助于理解應(yīng)用在一臺服務(wù)器中所處的位置,以及它能帶來的影響。這一部分是通過ps命令來查看的。
網(wǎng)絡(luò)部分
應(yīng)用使用的是TCP還是UDP,使用了哪些端口,同時數(shù)據(jù)包的大小是怎么樣的,網(wǎng)絡(luò)的上下行負載在什么程度。這些可以通過tcpdump、 sar和netstat來獲得,有了這些才能設(shè)計出容器將要使用的網(wǎng)絡(luò)模型,是橋接、Host、Overlay、自定義還是網(wǎng)絡(luò)插件,每一種容器網(wǎng)絡(luò)都有一定的特點,性能和復(fù)雜度也各不相同,我們需要選擇最合適的模型來進行規(guī)劃,而不是選擇最復(fù)雜的。
用戶管理及安全
傳統(tǒng)應(yīng)用系統(tǒng)里面可能有自己的一套安全體系,比如ldap、 active directory等,因此這一部分也是需要考慮的,而安全這部分,也需要考慮證書、防火墻等問題。容器可以有效的提升用戶管理的效率,我們可以把ldap做到容器里面,同時也可以只暴露需要的端口,降低被攻擊的可能性。
日志處理
傳統(tǒng)的應(yīng)用有的可能沒有日志管理,有的可能使用syslog或者rsyslog,然后通過中心日志服務(wù)器來進行日志匯總。有了容器以后,我們可以借助諸如Ghostcloud的第三方平臺,集中化收集日志??梢栽赿aemon層面,也可以在容器層面來進行收集。有了容器之后,你可以很方便的收集全系統(tǒng)日志,如果你有一個基于日志的大數(shù)據(jù)平臺,可以在改動很小的情況下做分析。
共享存儲及數(shù)據(jù)庫
很多傳統(tǒng)應(yīng)用都會使用跨主機的文件服務(wù),比如NFS、CIFS。當(dāng)遷移含有這些服務(wù)的應(yīng)用時,需要添加外部掛在卷。對于MySQL或者Mongo等數(shù)據(jù)庫,在遷移的時候需要考慮是否將數(shù)據(jù)持久化進容器,還是通過外部的掛在卷。如果通過外部掛在卷,需要考慮容器的HA。同時,如果你的數(shù)據(jù)庫沒有辦法提供Linux平臺的支持,你的數(shù)據(jù)庫肯定是不能做遷移的,當(dāng)然如果數(shù)據(jù)庫提供Linux下的客戶端,你可以將數(shù)據(jù)庫和應(yīng)用做一次拆分,再做遷移。對于存儲和磁盤的跟蹤也是必須注意的,Host的RAID怎么做,是否需要支持動態(tài)擴展,應(yīng)用程序的運行目錄大小及層次結(jié)構(gòu),應(yīng)用程序的運行時磁盤操作,應(yīng)用程序的持久化操作以及應(yīng)用的日志及Crash Core都是需要考慮的地方。這一部分,需要一些專業(yè)的知識,同時借助于strace等跟蹤工具來進行分析,這些將決定后續(xù)容器的掛載卷及空間分配,同時也會決定容器文件系統(tǒng)設(shè)計方案。
服務(wù)發(fā)現(xiàn)
傳統(tǒng)企業(yè)或者應(yīng)用可能會用到諸如ESB的服務(wù)總線,但是隨著開源技術(shù)的出現(xiàn)和微服務(wù)架構(gòu)的興起,我們完全可以借助于開源項目或者第三方服務(wù)來實現(xiàn),用的比較多的是consul、etcd 和Zookeeper,其中ZK也是使用非常多的高可用中間件,只不過前兩者更專注于服務(wù)發(fā)現(xiàn),后者是一個通用的組件,并不僅針對服務(wù)發(fā)現(xiàn)。以前企業(yè)里面涉及到服務(wù)發(fā)現(xiàn),很多時候都需要對微服務(wù)的方式進行統(tǒng)一約定,而由于容器本身有一個外部的daemon引擎,其服務(wù)發(fā)現(xiàn)方式可以通過Registrator內(nèi)置到daemon里面,跟傳統(tǒng)模式也有區(qū)別。
持續(xù)集成
很多傳統(tǒng)應(yīng)用出現(xiàn)的時候還沒有敏捷、DevOps和CI/CD,但是隨著移動互聯(lián)網(wǎng)的高速發(fā)展,軟件的更新越來越頻繁,很多時候一個系統(tǒng)需要在一天內(nèi)部署幾十次。通過不斷重復(fù)的部署和測試,可以極大的提高軟件的穩(wěn)定性。Docker的快速啟動和鏡像倉庫是天生為CI/CD設(shè)計的,以前我們啟動一個虛擬機需要幾分鐘,而啟動容器只需要幾秒鐘,有了這種能力以后集群式的和并行的持續(xù)集成才能成為可能。對于持續(xù)集成目前業(yè)界也沒有一個通用的模式,而且每個團隊可能習(xí)慣的方式和關(guān)注點都不一樣,因此存在很多定制的地方,有的以鏡像為引導(dǎo),有的以代碼為引導(dǎo),沒有最好的方式,只有最適合團隊的方式;同時,持續(xù)集成的流程也沒有最好的,只有更好的。需要不斷在開發(fā)過程中進行優(yōu)化。以前國內(nèi)很多企業(yè)受一些國外廠商的影響,花了巨資去購買流程及其復(fù)雜的流程軟件,其實現(xiàn)在看來并不都適合國內(nèi)的開發(fā)環(huán)境。一個簡單的例子就是,由于眾所周知的原因,國內(nèi)訪問外網(wǎng)的速度就很慢,而現(xiàn)在很多開源項目都放在github上,國外很多看似理所當(dāng)然的事情,并不適合國內(nèi)環(huán)境。