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