人人都愛Kubernetes,Docker難道就不香了嗎?

讀位元組發表於2021-05-20

開篇

提起Docker,有很多人第一印象會認為它就是一個虛擬化容器,所以大家特別容易陷入到一種誤區,就是覺得Docker只是在Linux作業系統之上又增加了一層,就跟OS上跑了一個VMWare一樣。Docker一定變得又慢又複雜。還不如原生安裝的服務看起來舒服。

實際上這是誤區,Docker管理的各種服務,都是作業系統原生的程式,並不是一個虛擬化產物,它的正確定義是應用容器引擎。

那怎麼去理解這個應用容器引擎呢?就要說說Docker的核心原理了——其中主要機制之一,通過Linux的namespace機制實現了資源隔離,這個資源隔離就包括了:

  1. UTS,對主機名和域名的隔離
  2. IPC,對訊號量、訊息佇列和共享記憶體的隔離
  3. PID,對程式編號的隔離
  4. Network,對網路裝置、網路協議棧、網路埠對隔離
  5. Mount,對掛載點(檔案系統)的隔離
  6. User,對使用者和使用者組的隔離。

這些隔離機制都是Linux核心的namespace機制實現,也是Docker容器設計的精髓。

就好像原來是一個300平米的大house,就住著一家人,臥室、廚房、衛生間這一家人獨享。可是房子太大完全可以住三個家庭,不僅能公攤一部分費用,還能為主家帶來額外的收益。那麼就要對這個大house重新進行規劃設計,滿足三個家庭的需要,制定一些生活制度,有些資源是可以共享的,但關鍵資源就必須隔離開,保護隱私嘛!其實大家說到底還是在一個大房子內平等的生活。

用了這個比喻其實就是告訴大家,你就把Docker理解為一個房子多個家庭的規劃安排包租婆,Docker管理了很多的容器服務,容器服務就是在宿主機上跑著的,例如MySQL、Nginx、微服務等等都是容器服務,大家都是在一個OS上平等的執行著,只不過進了自己房間,你對別人房間的情況就一無所知了。那麼這不僅保護了各個服務之間不會產生對資源爭用,而且還能根據預先入戶的協議,分配好CPU、記憶體、磁碟的容量。這樣大家住在一起也是明明白白的,誰也不能沾了誰的便宜。當然了對外的網路埠還是需要各家分配不同的。

有了這個本事,你就能在有限的雲資源上跑很多服務啦!我自己做的公司網站跑在阿里雲的ECS CentOS7,就跑了三個Docker容器:Nginx、MySQL、Wordpress,我才給分配了512M記憶體,夠摳門吧,但是執行地妥妥的,只是實體記憶體是在太小,有時候重啟服務,OS報記憶體資源就不夠了,必須把Docker也重啟,清空一下記憶體就好了。

我給當時老東家的兩個網際網路平臺產品用了三臺ECS效能不錯的伺服器,4核,16G記憶體,足足跑了50多個微服務和其他基礎服務,真的是把資源榨得是乾乾淨淨。關鍵還有服務日誌隔離、環境變數隔離、全域性配置隔離等待,好處實在太多了。關鍵對我們產品在網際網路架構上的Devops提供了良好的基礎支撐,我可以在一臺虛擬機器上跑兩套微服務,一套生產、一套測試,測試好的微服務升級版本號,變成新的生產微服務,老的微服務進入過渡替換期。詳見:構建網際網路醫療平臺的Devops應用架構

問題集錦

1. Docker必須聯網嗎?

連線網際網路不是必要的。可以內部搭建Docker Registry服務。我曾經就是在阿里雲的多臺機器的其中一臺做了Registry服務,然後讓其他機器通過內網的5000埠訪問就可以了,記得給每臺伺服器的docker服務都配置一下都不走SSL。

我們也只有遠端釋出才讓自己的開發客戶端,訪問Nginx的HTTP SSL埠,反向代理到Registry倉庫,那麼就需要在服務端裝一個Docker版的nginx,因為公網儘量走HTTPS。如下圖所示:

人人都愛Kubernetes,Docker難道就不香了嗎?

關於內網怎麼裝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閘道器重定向微服務新版本跳轉,實現最小升級抖動。

人人都愛Kubernetes,Docker難道就不香了嗎?

具體意思我簡要說一下,就是讓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了。

這些都並不是說會用Docker就夠了,實際上面對更復雜的K8s,熟悉Linux這個問題一樣是繞不過去的。因此還是關鍵的那一步,容器時代,用好容器引擎是從簡單的Docker開始,並且在搞定程式之外歷練自己的Linux功力,你的技術將提升得更快!

 

 可以閱讀另一篇關於分散式和大資料技術的詳細文章: 

相關文章