摘要:二緣起對(duì)于一個(gè)普通的屌絲創(chuàng)業(yè)公司的屌絲項(xiàng)目來說,理論上來說是沒必要用太復(fù)雜的技術(shù)的,對(duì)新技術(shù)的克制也是碼農(nóng)的一個(gè)職業(yè)操守。
Docker出現(xiàn)后,容器技術(shù)在互聯(lián)網(wǎng)領(lǐng)域得到了空前的普及,無論是大公司還是屌絲創(chuàng)業(yè)公司的碼農(nóng)基本上都會(huì)在各種技術(shù)社區(qū)或者各種演講會(huì)議上了解到過相關(guān)技術(shù),我們作為一家屌絲創(chuàng)業(yè)公司也不例外,去年對(duì)Docker做了一番了解,并在年前測(cè)試了一些方案,今天在這里總結(jié)一下遇到的各種坑以及踩坑過程中的一些思考,希望能對(duì)了解過Docker并且躍躍欲試的同學(xué)有點(diǎn)啟發(fā),當(dāng)然更歡迎在這方面有豐富經(jīng)驗(yàn)的同學(xué)給一些建議或者指點(diǎn)。
一、項(xiàng)目環(huán)境這篇文章不會(huì)提及Docker的理論知識(shí)或者基本概念相關(guān)的內(nèi)容,如果想了解Docker的基本使用,Docker的官方文檔是個(gè)不錯(cuò)的選擇,如果想了解基本的理論,可以參考下coolshell博客上的幾篇文章:Docker基礎(chǔ)技術(shù):Linux Namespace(上)、Docker基礎(chǔ)技術(shù):Linux Namespace(下)、Docker基礎(chǔ)技術(shù):Linux CGroup、Docker基礎(chǔ)技術(shù):AUFS、Docker基礎(chǔ)技術(shù):DeviceMapper。
我們項(xiàng)目用的標(biāo)準(zhǔn)的PHP技術(shù)棧:PHP-FPM + Nginx,運(yùn)行在阿里云的ECS上,數(shù)據(jù)庫也是阿里云的服務(wù)。
二、緣起對(duì)于一個(gè)普通的屌絲創(chuàng)業(yè)公司的屌絲項(xiàng)目來說,理論上來說是沒必要用太復(fù)雜的技術(shù)的,對(duì)新技術(shù)的克制也是碼農(nóng)的一個(gè)職業(yè)操守。然而我之所以在項(xiàng)目上做這個(gè)嘗試也并非是想嘗試新技術(shù),而是源自于項(xiàng)目上線以來遇到的各種問題,比如前面文章里有提到過的laravel的性能問題,而HHVM或者PHP7這些新技術(shù)都大大提到了性能,一下子全部切換風(fēng)險(xiǎn)太大,所以可以用容器來運(yùn)行某幾個(gè)服務(wù)測(cè)試一下;再比如之前有出現(xiàn)過一個(gè)BUG,某個(gè)接口出現(xiàn)問題占用內(nèi)存太高導(dǎo)致整個(gè)系統(tǒng)響應(yīng)超時(shí);再比如,看了各種技術(shù)大會(huì)上別人分享的經(jīng)驗(yàn)確實(shí)想自己試一下,哈哈。
三、牛刀小試根據(jù)Docker的理念,每個(gè)容器都是一個(gè)獨(dú)立的服務(wù),服務(wù)之間通過接口相互協(xié)作。我們采用的方案是PHP-FPM和Nginx分別跑在不同的容器中,PHP-FPM容器暴露端口給Nginx容器。
容器之間的網(wǎng)絡(luò)通信最初用的是Docker自帶的link,link雖然很簡單,但是不太好用,link是通過在容器啟動(dòng)時(shí)修改/etc/hosts文件來實(shí)現(xiàn)的,當(dāng)時(shí)用的時(shí)候遇到的一個(gè)問題是被link的容器重啟后,這個(gè)容器IP變了,但是link的容器里并沒有更新(1.10版本對(duì)link機(jī)制做了修改,不知道是否解決了這個(gè)問題,還沒具體看),還有一個(gè)問題就是當(dāng)同一個(gè)服務(wù)需要開多個(gè)容器時(shí)就搞不定了,當(dāng)然如果是用集群的方式來跑就更搞不定了,所以link只能在本地開發(fā)時(shí)玩玩,在生產(chǎn)環(huán)境沒啥用。最后這部分用的方案是用consul來做服務(wù)發(fā)現(xiàn),關(guān)于consul就不在這里展開介紹了,有興趣的同學(xué)可以看下這篇文章:Service Discovery for Docker Containers using Consul and Registrator。
然后代碼是放在host上,在容器啟動(dòng)時(shí)掛載一下代碼的目錄。根據(jù)接口使用的場景將接口分到了幾個(gè)不同的容器里面去跑,對(duì)資源隔離做了下壓力測(cè)試,符合預(yù)期,很滿意!然后選了兩個(gè)容器跑HHVM測(cè)試了下,確實(shí)性能提高了很多。整個(gè)結(jié)構(gòu)如下圖所示:
這樣可以正常使用了,然后就是日志的處理,最開始掛載了一個(gè)host上的目錄用來存放日志,但是這樣也不太符合Docker的理念,于是就又弄了個(gè)logstash容器,將各種容器的日志寫到logstash容器里面去。
然后就是對(duì)容器的監(jiān)控,我們用了oneapm提供的服務(wù),還不錯(cuò),也有其他一些開源工具的選擇,但是用oneapm的服務(wù)更方便一些。
一個(gè)完整的技術(shù)棧就這樣搞定了,跑了幾天也沒出現(xiàn)什么問題。作為一個(gè)有追求的碼農(nóng),當(dāng)然是要有更高的要求的,后來想到這樣一個(gè)問題:Docker的理念是容器即是一個(gè)完整的服務(wù),但是我們的用法是把在容器內(nèi)把PHP-FPM跑起來了,代碼并不在里面,而是通過目錄掛載的方式來實(shí)現(xiàn)的,這樣就需要在host上面部署好代碼,沒有完美的實(shí)現(xiàn)容器即服務(wù)的理念。好,我們追求下完美!
四、完美之路其實(shí)把代碼放進(jìn)容器并不只是為了去追求理念上的完美,還有另外一個(gè)用意,那就是基于Docker的CI。基本思路是每次發(fā)布都會(huì)build一個(gè)新版本的鏡像,build過程中需要把代碼更新到最新版本,然后安裝依賴的第三方庫以及其他一些業(yè)務(wù)相關(guān)的預(yù)處理,build完成后再push到registry,然后在各個(gè)節(jié)點(diǎn)pull下來,重啟容器。整個(gè)流程如下圖所示:
怎么樣?這下完美了吧!如果現(xiàn)實(shí)也是那么完美就好了,但是偏偏現(xiàn)實(shí)總是會(huì)有各種各樣的坑等著你!
首先,在沒有用這個(gè)機(jī)制之前,發(fā)布一次代碼也就幾秒鐘的事情,merge下分支,然后各個(gè)節(jié)點(diǎn)pull下代碼就可以了,但是用了Docker后,merge分支后就需要build一下鏡像,build后再push到registry,然后再到各個(gè)節(jié)點(diǎn)把鏡像pull下來,少說也是要花分鐘級(jí)別的。這時(shí)候有的同學(xué)可能會(huì)說Docker鏡像的原理不是layer機(jī)制么,對(duì),確實(shí)是layer,每次build只需要更新需要更新的layer就可以,但是還是沒辦法做到像git那樣只更新那幾個(gè)文件,至少要更新整個(gè)項(xiàng)目的代碼目錄。
其次,之前只需要更新一下代碼就可以了,現(xiàn)在卻需要把容器重啟一下!本來重啟容器是很快的,但是在容器里PHP-FPM跑起來后卻很慢,我猜測(cè)是在執(zhí)行docker stop時(shí)會(huì)發(fā)一個(gè)SIGTERM的信號(hào)到容器里的進(jìn)程,PHP-FPM在處理SIGTERM信號(hào)時(shí)會(huì)做一些清理工作。一個(gè)節(jié)點(diǎn)至少有幾十個(gè)容器,每個(gè)容器都重啟一下非常耗時(shí)!
這樣本來很簡單的一個(gè)發(fā)布,用了這個(gè)「完美」的機(jī)制后卻需要好幾分鐘。雖然整個(gè)流程完全自動(dòng)化,但是確實(shí)沒必要為了完美的理念做出這樣一個(gè)妥協(xié)。
此外還遇到了另外一個(gè)非常奇葩的問題:升級(jí)到1.10后,容器啟動(dòng)后經(jīng)常會(huì)遇到端口不通的情況,這時(shí)候如果進(jìn)入到容器里發(fā)起一次網(wǎng)絡(luò)請(qǐng)求,比如ping以下某個(gè)IP,端口就會(huì)恢復(fù)正常。用各種工具調(diào)試了很久依然沒找出來問題在哪,屌絲創(chuàng)業(yè)公司也沒精力研究這么高深的問題,只好暫時(shí)擱置了。
掙扎了很久,最后又回到了老路子。
五、面對(duì)現(xiàn)實(shí)雖然沒能理念上完美的方案,但是也要讓整套架構(gòu)更方便的擴(kuò)展,比如在流量高峰期快速上架節(jié)點(diǎn)。得益于云計(jì)算近幾年的發(fā)展,這個(gè)問題也比較容易解決。前面提到代碼是放在host的一個(gè)目錄,那么基本上每個(gè)host只需要三個(gè)條件就能夠上線:
項(xiàng)目代碼目錄
安裝Docker
配置好salt-minion(用來更新配置文件)
只需要在購買一臺(tái)ECS后,做完上面的操作,生成一個(gè)系統(tǒng)鏡像,需要上線新節(jié)點(diǎn)時(shí)用這個(gè)系統(tǒng)鏡像來直接配置服務(wù)器即可。節(jié)點(diǎn)上線后,啟動(dòng)各個(gè)容器,通過前面提到的用consul實(shí)現(xiàn)的服務(wù)發(fā)現(xiàn)機(jī)制,自動(dòng)加入集群。
六、繼續(xù)探索后面打算用Docker Swarm來簡單做下集群管理,未來對(duì)調(diào)度需求比較大時(shí)可能會(huì)嘗試下Mesos或者Kubernetes。不過關(guān)于容器的生態(tài)鏈都發(fā)展的非常快,可能等需要的時(shí)候又有更好的方案了吧。
簡單總結(jié)下整個(gè)過程的感悟吧,從架構(gòu)上來說,永遠(yuǎn)都沒有完美的架構(gòu),只有最適合自己的架構(gòu)。從碼農(nóng)角度來說,在做技術(shù)選型時(shí)最重要的是權(quán)衡當(dāng)前項(xiàng)目需求、團(tuán)隊(duì)對(duì)各種技術(shù)了解的程度以及該技術(shù)選型帶來的復(fù)雜度。切勿看了幾個(gè)大牛的技術(shù)架構(gòu)分享就在自己項(xiàng)目上躍躍欲試,最后弄的連自己都搞不定還給別人留下一個(gè)爛攤子收拾。最后,在項(xiàng)目迭代過程中保持項(xiàng)目的簡單的能力永遠(yuǎn)是衡量一個(gè)碼農(nóng)技術(shù)的水平的重要標(biāo)準(zhǔn)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/21362.html
摘要:二緣起對(duì)于一個(gè)普通的屌絲創(chuàng)業(yè)公司的屌絲項(xiàng)目來說,理論上來說是沒必要用太復(fù)雜的技術(shù)的,對(duì)新技術(shù)的克制也是碼農(nóng)的一個(gè)職業(yè)操守。 Docker出現(xiàn)后,容器技術(shù)在互聯(lián)網(wǎng)領(lǐng)域得到了空前的普及,無論是大公司還是屌絲創(chuàng)業(yè)公司的碼農(nóng)基本上都會(huì)在各種技術(shù)社區(qū)或者各種演講會(huì)議上了解到過相關(guān)技術(shù),我們作為一家屌絲創(chuàng)業(yè)公司也不例外,去年對(duì)Docker做了一番了解,并在年前測(cè)試了一些方案,今天在這里總結(jié)一下遇到...
摘要:二緣起對(duì)于一個(gè)普通的屌絲創(chuàng)業(yè)公司的屌絲項(xiàng)目來說,理論上來說是沒必要用太復(fù)雜的技術(shù)的,對(duì)新技術(shù)的克制也是碼農(nóng)的一個(gè)職業(yè)操守。 Docker出現(xiàn)后,容器技術(shù)在互聯(lián)網(wǎng)領(lǐng)域得到了空前的普及,無論是大公司還是屌絲創(chuàng)業(yè)公司的碼農(nóng)基本上都會(huì)在各種技術(shù)社區(qū)或者各種演講會(huì)議上了解到過相關(guān)技術(shù),我們作為一家屌絲創(chuàng)業(yè)公司也不例外,去年對(duì)Docker做了一番了解,并在年前測(cè)試了一些方案,今天在這里總結(jié)一下遇到...
摘要:的主要作用是自己根據(jù)基礎(chǔ)鏡像,重新定制鏡像,而不是直接從官方倉庫拿現(xiàn)成的使用。以接下來要構(gòu)建的環(huán)境來說明下,下面我將要搭建一個(gè)的開發(fā)環(huán)境,需要進(jìn)行配合。它的主要作用是持久化數(shù)據(jù),避免容器銷毀后內(nèi)部數(shù)據(jù)丟失暴露到宿主機(jī)的端口。 以前一直使用 Vagrant 作為自己的開發(fā)環(huán)境,并且在上家公司也推行大家采用 Vagrant 作為開發(fā)環(huán)境,保障公司使用的是同一套開發(fā)環(huán)境。隨著docker的流...
摘要:的主要作用是自己根據(jù)基礎(chǔ)鏡像,重新定制鏡像,而不是直接從官方倉庫拿現(xiàn)成的使用。以接下來要構(gòu)建的環(huán)境來說明下,下面我將要搭建一個(gè)的開發(fā)環(huán)境,需要進(jìn)行配合。它的主要作用是持久化數(shù)據(jù),避免容器銷毀后內(nèi)部數(shù)據(jù)丟失暴露到宿主機(jī)的端口。 以前一直使用 Vagrant 作為自己的開發(fā)環(huán)境,并且在上家公司也推行大家采用 Vagrant 作為開發(fā)環(huán)境,保障公司使用的是同一套開發(fā)環(huán)境。隨著docker的流...
閱讀 2287·2021-11-10 11:35
閱讀 899·2021-09-26 09:55
閱讀 2388·2021-09-22 15:22
閱讀 2318·2021-09-22 15:17
閱讀 3683·2021-09-09 09:33
閱讀 1821·2019-08-30 11:22
閱讀 970·2019-08-30 10:57
閱讀 641·2019-08-29 16:10