人人都愛Kubernetes,難道Docker就不香了嗎?
一、開篇
提起Docker,有很多人第一印象會(huì)認(rèn)為它就是一個(gè)虛擬化容器,所以大家特別容易陷入到一種誤區(qū),就是覺得Docker只是在Linux操作系統(tǒng)之上又增加了一層,就跟OS上跑了一個(gè)VMWare一樣。Docker一定變得又慢又復(fù)雜。還不如原生安裝的服務(wù)看起來舒服。
實(shí)際上這是誤區(qū),Docker管理的各種服務(wù),都是操作系統(tǒng)原生的進(jìn)程,并不是一個(gè)虛擬化產(chǎn)物,它的正確定義是應(yīng)用容器引擎。
那怎么去理解這個(gè)應(yīng)用容器引擎呢?就要說說Docker的核心原理了——其中主要機(jī)制之一,通過Linux的namespace機(jī)制實(shí)現(xiàn)了資源隔離,這個(gè)資源隔離就包括了:
- UTS,對(duì)主機(jī)名和域名的隔離
- IPC,對(duì)信號(hào)量、消息隊(duì)列和共享內(nèi)存的隔離
- PID,對(duì)進(jìn)程編號(hào)的隔離
- Network,對(duì)網(wǎng)絡(luò)設(shè)備、網(wǎng)絡(luò)協(xié)議棧、網(wǎng)絡(luò)端口對(duì)隔離
- Mount,對(duì)掛載點(diǎn)(文件系統(tǒng))的隔離
- User,對(duì)用戶和用戶組的隔離。
這些隔離機(jī)制都是Linux內(nèi)核的namespace機(jī)制實(shí)現(xiàn),也是Docker容器設(shè)計(jì)的精髓。
就好像原來是一個(gè)300平米的大房子,就住著一家人,臥室、廚房、衛(wèi)生間這一家人獨(dú)享??墒欠孔犹笸耆梢宰∪齻€(gè)家庭,不僅能公攤一部分費(fèi)用,還能為主家?guī)眍~外的收益。那么就要對(duì)這個(gè)大房子重新進(jìn)行規(guī)劃設(shè)計(jì),滿足三個(gè)家庭的需要,制定一些生活制度,有些資源是可以共享的,但關(guān)鍵資源就必須隔離開,保護(hù)隱私嘛!其實(shí)大家說到底還是在一個(gè)大房子內(nèi)平等的生活。
用了這個(gè)比喻其實(shí)就是告訴大家,你就把Docker理解為一個(gè)房子多個(gè)家庭的規(guī)劃安排包租婆,Docker管理了很多的容器服務(wù),容器服務(wù)就是在宿主機(jī)上跑著的,例如MySQL、Nginx、微服務(wù)等等都是容器服務(wù),大家都是在一個(gè)OS上平等的運(yùn)行著,只不過進(jìn)了自己房間,你對(duì)別人房間的情況就一無所知了。那么這不僅保護(hù)了各個(gè)服務(wù)之間不會(huì)產(chǎn)生對(duì)資源爭(zhēng)用,而且還能根據(jù)預(yù)先入戶的協(xié)議,分配好CPU、內(nèi)存、磁盤的容量。這樣大家住在一起也是明明白白的,誰也不能沾了誰的便宜。當(dāng)然了對(duì)外的網(wǎng)絡(luò)端口還是需要各家分配不同的。
有了這個(gè)本事,你就能在有限的云資源上跑很多服務(wù)啦!我自己做的公司網(wǎng)站跑在阿里云的ECS CentOS7,就跑了三個(gè)Docker容器:Nginx、MySQL、Wordpress,我才給分配了512M內(nèi)存,夠摳門吧,但是運(yùn)行地妥妥的,只是物理內(nèi)存是在太小,有時(shí)候重啟服務(wù),OS報(bào)內(nèi)存資源就不夠了,必須把Docker也重啟,清空一下內(nèi)存就好了。
我給當(dāng)時(shí)老東家的兩個(gè)互聯(lián)網(wǎng)平臺(tái)產(chǎn)品用了三臺(tái)ECS性能不錯(cuò)的服務(wù)器,4核,16G內(nèi)存,足足跑了50多個(gè)微服務(wù)和其他基礎(chǔ)服務(wù),真的是把資源榨得是干干凈凈。關(guān)鍵還有服務(wù)日志隔離、環(huán)境變量隔離、全局配置隔離等待,好處實(shí)在太多了。關(guān)鍵對(duì)我們產(chǎn)品在互聯(lián)網(wǎng)架構(gòu)上的Devops提供了良好的基礎(chǔ)支撐,我可以在一臺(tái)虛擬機(jī)上跑兩套微服務(wù),一套生產(chǎn)、一套測(cè)試,測(cè)試好的微服務(wù)升級(jí)版本號(hào),變成新的生產(chǎn)微服務(wù),老的微服務(wù)進(jìn)入過渡替換期。
二、問題集錦
1、Docker必須聯(lián)網(wǎng)嗎?
連接互聯(lián)網(wǎng)不是必要的??梢詢?nèi)部搭建Docker Registry服務(wù)。我曾經(jīng)就是在阿里云的多臺(tái)機(jī)器的其中一臺(tái)做了Registry服務(wù),然后讓其他機(jī)器通過內(nèi)網(wǎng)的5000端口訪問就可以了,記得給每臺(tái)服務(wù)器的Docker服務(wù)都配置一下都不走SSL。
我們也只有遠(yuǎn)程發(fā)布才讓自己的開發(fā)客戶端,訪問Nginx的HTTP SSL端口,反向代理到Registry倉庫,那么就需要在服務(wù)端裝一個(gè)Docker版的nginx,因?yàn)楣W(wǎng)盡量走HTTPS。如下圖所示:
關(guān)于內(nèi)網(wǎng)怎么裝Docker的問題,你需要先找一個(gè)能上網(wǎng)的機(jī)器,通過Docker hub做好你自己的Docker images,最好會(huì)dockfile怎么做,這是個(gè)腳本技術(shù),主要有一些本地化和參數(shù)優(yōu)化需要再做一下Docker images,然后Docker push到內(nèi)網(wǎng)私有register服務(wù)倉庫就可以了,其他內(nèi)網(wǎng)機(jī)器只要Docker pull命令,就可以使用你制作的Docker images了。
windows系統(tǒng)下開發(fā),就下載安裝windows的Docker desktop使用和mac版本一樣。
2、Docker里面的程序如何實(shí)現(xiàn)熱更新?
用Dockerfile構(gòu)建一個(gè)鏡像,并生成了一個(gè)容器來運(yùn)行程序,現(xiàn)在程序代碼發(fā)生了變更,想要實(shí)現(xiàn)熱更新如何實(shí)現(xiàn)呢?
一般Docker更新的方式,都是pull下來新的images,然后重啟容器,當(dāng)然也有一些討巧的辦法,通過對(duì)Docker內(nèi)的發(fā)布程序目錄鏡像到本地目錄,那么每次只上傳程序包,更新服務(wù)器本地目錄之后再進(jìn)行Docker重啟,這種方式免去了Docker體量太大,上傳慢的問題。
但是這些都需要重啟容器,不算真正意義上的熱更新,在線業(yè)務(wù)系統(tǒng)往往允許的抖動(dòng)時(shí)長(zhǎng)會(huì)很嚴(yán)苛,而且即便是Docker鏡像在測(cè)試環(huán)境都已經(jīng)測(cè)試的沒有問題了,放到生產(chǎn)服務(wù)器上也不能沒有經(jīng)過驗(yàn)證就直接替換,若是web系統(tǒng),我建議用api網(wǎng)關(guān)+Docker-compose+多版本運(yùn)行的方式來實(shí)現(xiàn)熱更新,而且這也會(huì)使得升級(jí)抖動(dòng)的影響降到最低。如下圖所示:T 為測(cè)試,P為生產(chǎn),v1、v2就是Docker-compose的多版本發(fā)布,通過API網(wǎng)關(guān)重定向微服務(wù)新版本跳轉(zhuǎn),實(shí)現(xiàn)最小升級(jí)抖動(dòng)。
具體意思我簡(jiǎn)要說一下,就是讓Docker-compose作為你的應(yīng)用發(fā)布的整體,這樣無論是微服務(wù)也好,單體應(yīng)用也好,就都統(tǒng)一作為一個(gè)單元部署管理了!
然后對(duì)需要更新的新版本程序,發(fā)布出新版本的Docker-compose,qa驗(yàn)證無誤后,再由api網(wǎng)關(guān)實(shí)現(xiàn)動(dòng)態(tài)切換,Docker熱更新的大體思路就是這樣。
3、Docker掛載數(shù)據(jù)卷的時(shí)候映射文件會(huì)出現(xiàn)不同步?
學(xué)習(xí)Docker的時(shí)候發(fā)現(xiàn) 映射redis.conf 會(huì)出現(xiàn)這種情況 難道一定要先從容器中拷貝一份再運(yùn)行yml嗎?
Docker映射配置文件的時(shí)候,一定是先要有這個(gè)文件,記住,而不是等其內(nèi)部會(huì)創(chuàng)建這個(gè)文件,否則它只會(huì)創(chuàng)建出目錄。
因此Docker映射文件不存在就走映射目錄了。
所以第一種方式:是配置文件已經(jīng)存在,也就是自己上傳到服務(wù)器自定義配置目錄,然后Docker直接映射過去,這時(shí)候映射文件或者映射目錄一個(gè)道理。
第二種方式:配置目錄映射到自定義目錄,容器運(yùn)行過程腳本自動(dòng)化寫入,那么配置目錄的各項(xiàng)文件就需要在容器初始化過程中,由腳本對(duì)鏡像內(nèi)的打包配置文件完成寫入。
其實(shí)我做過一個(gè)Redis的優(yōu)化過的生產(chǎn)級(jí)的Docker,走的是第一種方式,需要你自己上傳一下配置,可以看看我的gitee源代碼倉庫,gitee倉庫也就做了這一個(gè)面向Redis中文化、性能調(diào)參過的Dockerfile以及配置文件。在gitee中搜索“讀字節(jié)” 有個(gè)我寫的不錯(cuò)的單機(jī)版Redis Dockerfile文件,里面對(duì)性能做過優(yōu)化,大家可以用來學(xué)習(xí)。
三、結(jié)束語
總之在目前Kubernetes如日中天的時(shí)代,我們有時(shí)候要冷靜思考一下,到底我們有必要搞得那么復(fù)雜嗎?難道Docker還不夠用嗎?如果配合上Portainer這種在線免費(fèi)的Docker管理工具,能讓你的云上服務(wù)群管理的很好。
但是有一點(diǎn)是有門檻的,那就是玩Docker一定要不斷歷練自己的Linux能力,包括腳本編寫能力,因?yàn)橛行〥ocker Images并不能按照你的實(shí)際環(huán)境滿足你的使用需求,需要自建Dockerfile,我就在以前的工程中配合Maven編寫了自己的Dockerfile和Shell腳本,微服務(wù)從打包到發(fā)布,一氣呵成,而且可以靈活去選擇哪個(gè)微服務(wù)進(jìn)行更新。這就真的需要深刻的去理解Linux了。
實(shí)際上面對(duì)更復(fù)雜的K8s,熟悉Linux這個(gè)問題一樣是繞不過去的。因此還是關(guān)鍵的那一步,容器時(shí)代,用好容器引擎是從簡(jiǎn)單的Docker開始,并且在搞定程序之外歷練自己的Linux功力,你的技術(shù)將提升得更快!