有狀態應用程序能夠被容器化嗎?或者容器只適合無狀態的應用程序嗎?本文帶你一見分曉。html
Docker Engine 等容器技術爲應用提供了標準打包和運行時環境。數據庫
容器能快速部署,並有效地利用系統資源。開發人員使用容器技術,換取的是應用程序的可移植性和可編程的鏡像管理。運維團隊使用容器,能夠以標準化的方式部署和管理運行時單元。編程
除了這些已知的優勢,咱們對容器都有一個廣泛的誤解:容器是短暫的,因此只能運行無狀態的微服務應用,而不能運行有狀態的服務。下面咱們看看這個觀點是否成立。緩存
應用程序的狀態是應用程序組件完成他們工做(即執行一個任務 )所需的數據。任何應用程序都有狀態。軟件編程架構模式、範式和語言從根本上描述如何管理應用程序的行爲(任務,操做等)和狀態(數據)。安全
即使微服務應用也有狀態!網絡
在微服務架構中,每一個服務能夠有多實例,每一個服務實例都被設計成無狀態的。這意味着,任何一個實例存儲跨操做的數據。session
無狀態,只是意味着服務實例不能爲了執行一個行爲,從其它地方獲取數據。架構
這是微服務式應用的一個重要架構限制,由於它強化了敏捷和彈性,並容許任何可用的服務實例來執行任何任務。app
一般狀況下,應用程序狀態被存儲在數據庫、緩存、文件或其餘存儲的形式中。任何須要跨操做使用的狀態變化都必須被寫回到存儲中。運維
所以,任何應用都有狀態,但若是把程序行爲和數據分離開,應用程序的組件能夠是無狀態的,它在執行行爲時可以獲取到數據便可。可是,這彷佛只是簡單地把問題傳給其餘東西-其餘組件如何管理狀態?爲了方便更深刻地討論,首先看看狀態的五個分類:
要回答上面的問題,讓咱們考慮一下應用程序可能會有的5種狀態類型,以及咱們如何應對每個狀態的應用容器化:
1.持久狀態 (persistent state)
2.配置狀態 (configuration state)
3.會話狀態 (session state)
4.鏈接狀態 (connection state)
5.集羣狀態 (cluster state)
持久應用的狀態須要在應用重啓和停用時仍然保留。該類型的狀態一般存儲在一個冗餘的數據庫層中,並在數據庫層上執行按期備份。
你能夠將應用程序和數據庫放在同一個容器中,可是最好將它們分開,由於你的應用程序組件更改更頻繁。另外,分離數據庫之後,多應用實例能夠共享數據。
若是你已經使用了外部數據庫,無論它們以service方式存在,仍是部署在不一樣組的物理或虛擬機上,你均可以保留現有架構,只要把業務邏輯的應用容器化便可。大多數容器管理系統都容許將數據庫信息做爲配置狀態傳給應用運行容器(後面會談到「配置狀態」)。
固然,你也能夠選擇用容器化的數據庫。容器化之後,恢復和部署都更快,同時能夠享受容器帶來的其它好處。這種狀況下,你須要考慮下面幾個問題:
一、 數據庫如何管理集羣化和複製以獲取較高的可用性和伸縮性?副本是否有特定的角色?是否能加入新成員,併爲其動態分配一個角色?
二、數據量有多大?添加新節點時,對數據進行 full-sync 是否實際?
三、基於以上兩條,當運行數據庫的容器中止時,存在於另外一個副本上的數據須要保留嗎?若是宿主機中止,數據會保留嗎?
當容器終止時,爲了可以保留數據,你將須要使用存儲機制來管理容器之外的數據。使用主機volumes並把他們映射到容器中很容易作到這一點。
一樣,當宿主機終止時,爲了可以保留數據,你將須要使用存儲機制來管理主機外的數據。大多數的雲平臺支持共享(網絡)文件系統或塊存儲器(volumes),能夠獨立管理並附加或分離到任何主機。假設你的容器編排工具提供生命週期事件來管理存儲組件,這也是至關簡單的。
但若是數據須要 attach 到特定的容器,怎麼處理?不少狀況下,這是都是必要的 - 例如咱們的一個客戶想要管理大量的不能複製的視頻內容。若是他們的容器宕掉並在其餘主機重啓,他們但願相同的數據對容器是可用的。
若是你有許多這樣的應用, volume 插件能夠簡化數據的編排。 從軟件分層上來說,volume 插件在容器引擎下面,做用是協助編排存儲。一些 volume 插件只是對IaaS / CMP調用進行了一層封裝。但有一些插件目的是是提供一組豐富的功能,如QoS 、分層存儲,這些是爲了支持企業存儲而設計的,也許值得研究。
讓咱們總結一下volume選項:
主機卷:這對於小型數據集能很好地工做,若是數據庫支持副本,能夠加入一個集羣並與其餘成員動態同步啓動。
共享卷或文件系統:當你的數據須要獨立於主機之外生存時。這對於大型數據集是一個好的選擇。例如當一個新節點加入數據庫集羣時,你不想執行一個完整的數據同步。
Volume 插件:數據須要 attach 到容器中的應用程序,或者你的編排不容許管理外部系統。
應用程序一般須要正確配置非域數據,好比外部服務的IP地址,或鏈接到數據庫的憑證。
Heroku 寫的12-factor app 指南中主張在運行時環境中存儲配置數據,目前大多數指定PaaS解決方案都採用了這種方式。在容器的世界裏,大多數配置數據能做爲環境變量管理,能夠很方便地注入到容器中。
然而,一些須要保密的信息,好比憑證、密碼、鍵和其餘機密數據,最好經過其餘的安全機制處理,儘可能不讓祕密數據在主機、網絡、或存儲上可見。對於這類數據,可使用KeyWhiz、Vault等工具管理,容器在初始化時將數據解密。使用支持key-value存儲的 volume插件也能夠實現一樣的目的。
咱們協助客戶容器化應用時,遇到了各類有趣的狀況。例如,一個應用程序讀取本地 MAC 地址,並用它做爲一種方式來惟一地識別本身!顯然,若是容器重啓,並獲得一個不一樣的MAC地址。
幸運的是,Docker如今容許指定容器的MAC地址。對於這種狀況,當運行容器時,你須要確保你的編排系統能靈活的指定自定義設置。
本文中,咱們討論了什麼是」狀態」、你可能遇到的狀態類型、以及容器化環境下如何管理。大多數狀況,咱們都有不止一個選擇。所以,雖然容器是短暫的,但應用的」狀態」不須要如此!