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