Docker化運維方式
應用遷移需求
應用運維需要考慮的一個重要問題就是遷移, 在不同機器、機房、環境間遷移。遷移的原因有很多, 比如硬件過保(硬件故障), 機房遷移, 應用擴縮容等。
應用遷移的核心需求是:
簡單。遷移操作必須足夠簡單, 沒有學習成本, 點擊一下即可。
快速。遷移過程能在極短的時間內完成。
無損。遷移之后應用與原應用一模一樣, 不丟失任何配置和數據。遷移之后應用功能和業務邏輯與原部署應用一模一樣,無任何業務風險。
許多公司還在使用古老的 rhel 5/6 和 linux 2.6.x 內核, 難以充分發揮現代操作系統和硬件的能力, 部分原因也是受制于應用遷移技術不成熟, 不能保證快速無損遷移應用, 不敢遷移。
具備快速遷移的能力, 同樣可將應用快速切換到任意版本, 實現快速回滾。
tomcat webapp 部署結構
我們看一下一個基于 tomcat 部署的 java webapp 應用部署結構如下:
apache-tomcat-8.0.35/ ├── bin/ ├── conf/ ├── lib/ ├── logs/ ├── temp/ ├── webapps/ ├── work/ ├── LICENSE ├── NOTICE ├── RELEASE-NOTES └── RUNNING.txt
其主要分為兩個部分:
- 靜態二進制文件。包含 bin/, lib/。這部分是三方軟件包 tomcat 自帶的內容。對應用而言, 這部分內容是只讀訪問的, 不會修改。
- 外部配置和數據。包含 conf/, logs/, temp/, webapps/, work/。這里的“外部”是指從 tomcat 軟件包的角度來看, 對應用來說, 這部分才是真正的應用軟件包。
注意: tomcat 軟件包也包含 conf/。但應用可能會對 conf/ 進行修改, 所以應用使用了一個獨立維護的 conf/ 副本, 而不是 tomcat 軟件包自帶的 conf/ 內容。
很顯然, 要遷移這個應用, 只需要遷移第 2 部分, 即外部配置和數據即可。為了簡化遷移, 許多應用被設計為無狀態的, 即 logs/, temp/, work/ 等外部數據目錄不包含任何影響應用功能的配置或數據, 這部分內容不需要遷移。只需要遷移 conf/, webapps/ 目錄, 這部分內容可打包為應用軟件包。
這樣, 在新環境部署應用, 只需要安裝 tomcat 軟件包和應用軟件包即可。
新環境部署
在新環境上完成應用部署, 有兩種玩法:
- 列一個軟件包清單 (如上例中的 tomcat 和應用), 在新環境上按照清單完成軟件包安裝, 這是 juju 的玩法。
- 將所有軟件包安裝好并打包成一個二進制鏡像, 拷貝到新環境上部署運行, 這是 docker 的玩法。Dockerfile 描述如何創建鏡像, 類似于軟件包清單。
docker 鏡像不止是預安裝軟件包, 還包含基礎操作系統環境, 統一的日志、數據路徑, 環境變量等標準化應用運行環境。這可難不倒 juju, juju 同樣基于一個標準鏡像創建 vm 或 lxc 容器, 再安裝軟件包, 同樣提供標準化的運行環境。這兩種方式各有優缺點, 在此不作深究。但就使用成本來說, docker 目前在國內外發展火熱, 技術和實踐經驗相對成熟, 更容易使用。
單機多實例隔離部署
使用 docker 應用容器部署應用, docker 容器為應用提供了標準一致且相互獨立的運行環境, 這樣應用使用相同的配置和路徑, 也可以在單個宿主機上實現多實例部署。與 vm 的單機單部署模式相比, 應用容器要做的足夠輕, 消除 vm 的額外開銷, 并且完美支持微服務編排。
軟件包與配置分層
有些軟件包很好的實現了軟件包默認配置與應用自定義配置的分離, 如 tomcat, 只需指定 CATALINA_BASE 目錄與 CATALINA_HOME 目錄分開, 將應用部署到 CATALINA_BASE 下, 即可實現應用自定義配置和 tomcat 軟件包默認配置分離, 兩者獨立維護, 互不影響。
許多軟件包沒有實現這樣的能力, docker 通過分層文件系統解決這個問題, 同時可以避免每個軟件包都去考慮設計配置分離功能。
應用自定義配置在軟件包安裝層的上層, 運行容器時覆蓋默認配置, 但在軟件包安裝層升級軟件包時看不到應用自定義配置, 不會受應用自定義配置影響。需要注意的是, 軟件包升級后是否兼容舊的應用自定義配置, 是否需要更新自定義配置, 需要應用負責人關注和測試。
按照 docker 的分層設計思想, 越基礎越固定不變的東西越要放到底層, 越容易變化的東西越要放到上層, 因此應用依賴的軟件包和基礎配置要放到底層, 可以獨立為一個 base 鏡像, 應用本身和自定義配置放在上層。如果應用本身或配置更新更頻繁, 可將這兩者再分成兩層。
配置管理
假設我們要修改一個應用配置, 一種方式是登陸一臺機器修改, 測試 ok 后將修改同步到所有其他機器。這種方式很原始并且缺乏監管, 容易出錯。比如新擴容了 100 臺機器每臺都要更新一遍, 如果操作有遺漏, 哪些機器配置已經更新, 哪些機器還是舊的配置也缺乏監管。
按 docker 的玩法, 應該是先更新鏡像, 測試 ok 后分發鏡像到所有機器更新容器。docker 監管了所有容器部署的鏡像版本和容器狀態, 從而可以很方便的檢查哪些容器更新了, 哪些沒有更新。對于很少變化的靜態配置, 應該固化到鏡像中。
對于一些經常變化的配置, 重新打鏡像和更新容器成本太高, 應該設計成預定義的開關, 使用開關平臺進行監控和管理, 或者使用 diamond 等配置管理平臺管理。
docker 容器數據卷
docker 容器內的文件系統伴隨容器而生, 銷毀或更新容器時 (如升級鏡像或修改容器配置), 原有數據將會丟失。并且受分層文件系統設計影響, 其性能可能更差(與存儲引擎實現有關)。
因此, 需要持久化保存的配置和數據, 或有高寫性能要求的, 如 logs/, data/ 等外部數據目錄, 應使用 docker 數據卷 掛載到宿主機上。
Dockerfile 中使用 VOLUME 指定容器中需要掛載為數據卷的目錄列表。
docker 化運維方案
綜上所述, docker 化運維需要將應用拆分為 3 部分:
- 基礎環境, 應用所有依賴, 應用軟件包和靜態配置, 固化到鏡像。
- 需要動態修改的配置, 通過開關平臺或 diamond 等配置平臺進行管理。
- 需要持久化保存或頻繁寫需求的配置或數據目錄, 掛載為數據卷。
部署運維時, 使用 docker 分發鏡像, 配置平臺推送配置, 即可實現應用快速部署、遷移、更新、回滾、擴縮容等運維操作。