容器、Docker與Kubernetes—從基礎的容器化談起

【摘要】本人是公司的運維,也是個對技術有深度理解的人,這篇文章是作者在實踐immutable infrastructure理念過程中對容器的理解,這是第一篇,主要講述傳統運維工具如Chef與Docker等容器化運維工具的不同以及解決的問題。

作為一名長期從事運維的工程師來說,我會時常審視維護伺服器工作的簡單性與可重現性;而我的一個最重要的工作原則便是「永遠不要手動操作伺服器」。所有伺服器都必須由工具進行啟動(provisioned)與配置以運行,同時通過工具來監控、維護伺服器的狀態——而我的選擇是Chef;當然你也可以有很多其他選擇如:Ansible、Salt與Puppet。

在Collective Idea中,Chef確實運行得非常好,它管理著公司內部與外部客戶的很多伺服器。但是,漸漸的我也意識到了Chef的一個缺陷:對變化的處理不好。生產環境的應用與基礎設施都是有很多複雜的構件(creatures)組成,這些構件都由很多變化的組件(moving parts)組成,組件之間又有大量的顯式或者隱式的依賴——它們隨時都會由於不可預知的原因發生變化。其中,有些變化容易處理,如配置文件更改或者對系統進行微調;但是其他一些就比較複雜,如,不停機升級一個應用依賴的Ruby運行時版本。而且,還有一些對伺服器的調整需要人工操作,如,升級操作系統內核后的重啟等。

Advertisements

簡而言之,以我多年使用Chef的經驗,它在搭建新的運行環境與配置系統上確實工作得非常好,而且也是我需要的;但是在處理一些升級,變更等需求的時候,就會變得非常費事而且容易出錯。有沒有工具能夠減輕伺服器升級變配帶來的痛苦呢?

  • 不變性基礎設施

解決問題的一個方案是「不變性基礎設施」應用部署模式;具體表現為,相對於一個個機器的升級(針對上面所講的情況)基礎設施,這種方式會直接丟棄掉老版本的基礎設施,然後將應用程序整體遷移到一個已經升級完畢的新的基礎設施中運行。但是,本質上「不變性基礎設施」部署方式仍然需要一個類似於Chef的工具用於初始化、配置與啟動基礎設施,不同的是一旦一個基礎設施在運行了,它的狀態與配置就不允許發生變更;如果有配置變更需求則啟動新的基礎設施來代替老的。當然,這種部署方式有其自己的複雜性,它必須能夠隨時刪除或者下線一個老的基礎設施然後啟動一個新的——任何時候都有可能發生。那麼問題就來了,對於資料庫來說怎麼升級?升級新的web伺服器后怎麼重新註冊到老的負載均衡器上?升級新的負載均衡器又如何能保持其下諸多的Web伺服器不掉線的升級?

Advertisements

實際上,要完全實現不變性基礎設施的伺服器部署是有很多技術瓶頸的,導致其在現實環境中很難實現。有些工具如:Packer能夠在一定程度上減輕創建虛擬機鏡像的工作難度的,但是你仍然需要面對一整套的環境搭建工作,這通常需要花費很長的構建與生成時間,因為你一般需要下載數G的文件來搭建一個單獨的系統。

有沒有方法能夠同時兼顧不變性基礎構架的方便直觀,而且鏡像文件又能保持足夠小呢?有沒有工具使我們打包鏡像時剔除掉操作系統與底層抽象只保留應用程序本省與其依賴呢?這樣我們就能只部署一個很小的鏡像,遷移那些發生變化的數據,最後節約大量的部署時間。這就是容器技術為我們帶來的改變,如Docker與rkt(讀音同「rocket」)。在容器為基礎的基礎環境中,底層的伺服器與虛擬機都被抽象成了資源如:CPU與內存。

因為我平時使用Docker所以在以下介紹中我用Docker為工具來講述我的觀點,當然還有其他類似的容器化工具如rkt,效果是一樣的。

  • Docker

Docker,簡單來說,它將應用程序的執行文件、命令都打包在一起,稱為鏡像(image),然後在宿主機或者虛擬機上部署運行這個鏡像;而運行起來的鏡像被稱為「容器」,反過來說,容器就是運行時的鏡像。容器在一個封閉、隔離的環境中運行,在這個環境中它認為自己是系統中唯一運行的程序,這種隔離性保證一個宿主機可以同時運行多個容器,但是互相併不知道對方的存在。

Docker鏡像文件是一次寫入的(write-once,就像一張光碟),這使得Docker基礎環境看上去就是一個不可變基礎構架。鏡像與容器永遠不會更新,新的鏡像生成伴隨著老的容器的關閉,而這個過程相對於關閉與啟動一個伺服器或者虛擬機來說只需要非常短暫的時間。

所以,你會問,那我們Collective Idea是不是把所有的服務都遷移到了Docker上了?我的回答是,沒有,現在還沒有。容器的使用有個單一職責的原則需要遵循:運行多個容器,各個容器只完成一個單一的工作。進一步說,將服務容器化的過程就是基礎構架SOA化的過程;這個過程一樣面臨很多問題與困難:

  • 容器與容器之間如何發現與通信?

  • 如何決定在哪運行以及運行多少個容器?

  • 如何獲取容器運行的日誌與運行狀態信息?

  • 如何部署新的鏡像?

  • 容器崩潰時都發生了什麼?

  • 如何只將特定的一部分容器暴露在公網或者內網環境下?

直至當下,相比現在服役的Chef工具來說,回答這些問題以及大規模在Collective Idea部署Docker應用都還不太成熟。但是,現在還是湧現出了很多解決我提出的問題的工具,而且還提供了可用於生產環境的容器化部署方案,如:Docker公司自己的Docker Compose;但是我們還是選擇了Google的方案——Kubernetes ,它號稱融合了Google在十幾年來在其超大規模數據中心運行了數十億個容器的經驗。

  • 如需了解零空信息更多資訊及最新進展,敬請關注公眾號:零空科技&魔法隧道

Advertisements

你可能會喜歡