自從山姆鍋決定採用容器化技術作為應用部署的方案後 , 很多的細節需要設計跟決定 , 為了避免太專注細節 , 決定先設計出計畫採用的持續軟體交付流程 。 由於每個團隊的使用的工具跟系統可能差異很大 , 為了讓本文可以適用其他團隊 , 先以抽象流程來描述然後才說明山姆鍋採用的方案 。

此流程在完成軟體持續整合 、 部署與交付所需要的支援 。 為了減低人為的錯誤以及強化軟體品質 , 軟體部署的流程需加以自動化且在其中加入自動功能測試的步驟 。

流程概觀

整個流程故意以抽象的概念表示 , 並沒有提到具體使用的工具或系統 , 因為這些跟個別團隊有關 。 底下是流程步驟的簡短說明 :

  1. 開發人員提交程式碼到 「 源始碼儲存庫 」 後 ,「 源始碼儲存庫 」 會透過 webhook 通知 「 持續整合系統 (CI)」 有新的程式碼 。
  2. 「 持續整合系統 」 會啟動並排程軟體建置任務來完成取出源始碼 、 編譯 、 單元測試 、 包裝與整合測試 。
  3. 「 持續整合系統 」 將應用容器發佈到 「 容器映像儲存庫 」。
  4. 「 持續整合系統 」 通知 「 部署機器人 」 有新的應用容器發佈 。
  5. 「 部署機器人 」 會將發佈的應用容器自動部署到 「QA 環境 」, 容器映像是由部署環境直接由 「 容器映像儲存庫 」 下載到主機節點 。

有個系統沒有呈現在圖中 , 但卻扮演至關重要的角色 :「 群組訊息系統 」, 之所以沒有呈現出來是擔心圖形過於複雜 , 因為基本上 , 其它系統或工具都會跟它有互動 。 當 「 開發人員 」 將程式碼提交到 「 源始碼儲存庫 」 時 ,「 源始碼儲存庫 」 便會通知相關群組此訊息 , 而 「 持續整合系統 」 在建置過程如有任何錯誤也會將此事件回報給相關群組成員 , 如果沒有問題則會通知容器發佈的消息 。「 自動部署機器人 」 會從 「 群組訊息系統 」 監聽容器發佈的消息 , 一旦有容器發佈會立刻自動將該容器部署到 「QA 環境 」。

幾個特別注意的事項 :

  • 目前部署到 「 生產環境 」 須由維運人員指示 「 自動部署機器人 」 來執行 , 但部署的動作仍舊是自動完成 。
  • 容器映像的標籤 (tag) 需要能夠讓開發人員很容易回推當初建置該映像 (image) 所使用的程式碼版本跟分支 。
  • 根據部署環境的複雜度而定 ,「 自動部署機器人 」 的功能也可以整合到 「 持續整合系統 」 中 。

了解了流程抽象概念後 , 後續小節說明具體使用的工具或系統 。

群組訊息系統

這個系統是讓開發團隊內不同的群組 (groups) 可以即時的訊息溝通 , 而群組的成員並不限制只有人 , 自動系統也會參與 。 因為需要整合自動化系統 , 使得常見的即時訊息服務 , 如 Line, QQ, Skype 等 , 無法勝任這個角色 。 因此 , 有特別針對這個需要提供的雲端服務 , 目前主要的 :Slack, HipChat, Gitter, 按照跟其它系統的整合支援度排序 。

許多人會選擇 Slack, 但因為有整合的考量 , 本團隊選擇使用同樣由 Atlassian 公司提供的 HipChat 服務 。 群組訊息系統可以說是團隊的神經系統 , 讓團隊可以更快有效地彼此同步訊息 , 這對於像本團隊一樣 , 成員分散在不同地區與工作時間的團隊尤其重要 。 另外 , 我們也改用此系統做 Scrum 的 standup 會議 , 當然實際形式上有所不同 。

源始碼管理系統

以目前發展的態勢以及雲端服務的多寡來判斷 ,Git 作為源始碼管理系統的首選應該是大勢底定 。 使用 Git 的主要原因 :

  • 有成熟的雲端託管服務商 (GitHub, BitBucket, etc)。
  • 快速方便的源始碼分支 (branch) 與合併 (merge) 功能 。
  • 可以離線提交 (commit), 避免一次性提交一大段難以理解的源始碼 。
  • 除了中央源始碼儲存庫外 , 開發者的本機也是源始碼的完整備份 。

源始碼託管服務 / 源始碼儲存庫

主要的雲端源始碼託管服務有 : GitHub, BitBucket, 因為整體考量 , 本團隊採用 BitBucket 作為源始碼託管服務供應商 。 不管採用哪種源始碼管理系統 , 交付流程都需要有一個中央源始碼儲存庫來存放平台所有源始碼 , 自動建置系統會從此儲存庫取出並建置要部署的軟體元件 。 使用源始碼託管服務還有個好處 , 就是可以很好地支援 Pull request, 讓 code review 的流程更順暢 。

容器映像儲存庫 (Image Repository)

當採用以容器化 (containerized) 方式來發行軟體元件時 , 便需要一個容器映像儲存庫 。 此儲存庫 , 顧名思義是用來存放打包好的應用程式或者服務模組 。 本團隊後端的服務或應用皆是以容器來包裝跟交付 , 即使是前端開發人員 , 為了整合測試需要仍舊要對容器技術有基本的了解 。 目前雲端的容器映像儲存庫 , 除了 Google Cloud Platform 跟 AWS 有提供外 , 另外兩個考慮的就是 :

  • Docker Hub
  • Quay.io

本團隊目前採用的是 Docker Hub, 原因無他 , 只是比較習慣而已 。 但未來如果需要更好的團隊權限控管與 HipChat 更好的整合 , 會考慮轉換為 Quay.io。

自動建置系統 / 持續整合系統

自動建置系統會在開發者提交源始碼後 , 自動 check out 源始碼並編譯 、 測試並產生二元檔案或者映像檔 。 軟體的部署只能使用由建置系統所產生的二元檔案或者映像檔 , 不能直接連上服務器進行修改動作 。 每個應用 / 元件 / 模組在自動建置階段需按照順序完成下列階段才算成功 :

  1. 單元測試 (unit test)

    元件需具備足夠的單元測試以確保功能正確並且避免 regression 的發生 。 每個語言的單元測試方法或框架也許不同 , 但基本概念是一樣的 。

  2. 元件包裝 (packaging)

    經過單元測試後 , 元件需要包裝成可以發佈的二進位形式 , 以傳統 Java 應用為例 , 這可以是一個 Jar 或者 War 檔 。 以本團隊的作法 , 後端服務都是以 Docker 容器形式包裝 。 行動應用則是根據支援的平台有所不同 , 如 Android 的 apk 檔 ,iOS 的 ipa 檔 。Webapp 則是以 tgz 格式發佈 。

  3. 整合測試 (integration test)

    針對後端元件 , 整合測試需要在本地採用 docker-compose 部署一個測試環境後執行相關的自動測試 。 針對行動應用 , 這個階段需將應用發佈到 「 裝置測試系統 」 來以實際裝置執行自動測試 。

  4. 元件發佈 (release)

    經過單元與整合測試後的元件 , 已經可以發佈 。 注意這裡 「 發佈 」 是指將包裝後的元件推送至 「 容器映像儲存庫 」 , 並不表示發佈給終端用戶 。

  5. 元件部署 (deployment)

    針對後端元件 ,「 部署 」 代表將包裝好的元件上載到應用部署環境後設定並啟用 。 這裡的部署環境可能是開發或者 QA 環境 。 部署的方式是自動建置系統會向 "Operations" 這個 HipChat 聊天室發佈元件已經發佈的消息 , 然後部署機器人會接續後續部署工作 。 也就是說 , 部署的工作並不是整個在自動建置系統內完成 。 針對行動應用 ,「 部署 」 意味著行動應用可以讓 QA 人員下載 、 安裝到手機或者平板來進行測試 。 針對這點 , 也有雲端服務來提供行動應用發佈以方便 QA 人員下載跟安裝 。

自動部署機器人 (DevOps Bot)

由於本團隊採用 Kubernetes 作為應用部署平台 , 現有的 「 持續整合系統 」 對它的整合度不高 , 加上考量到生產環境要支援人工審核部署的步驟 , 才有了這樣的設計 。 對於一般常見的部署環境 , 自動部署也可以在 「 持續整合環境 」 中完成 , 不少服務也針對部署有特別的支援 。 本團隊的 「 自動部署機器人 」, 英文叫 Sammy, 中文叫 「 蝦米 」, 會監聽某個 HipChat 特定地聊天室 (Operations) 的訊息 ,「 持續整合系統 」 在應用容器發佈成功後在此聊天室發佈訊息 , Sammy 收到該訊息後便會自動進行部署 。

在 「QA 環境 」 測試過沒問題的版本 , 會由管理人員下指令給 Sammy 來部署到 「 生產環境 」。 使用機器人有另一個好處 : 由於不是透過 Webhook 來取得通知 ,Sammy 可以部署在防火牆後 , 實際上 Sammy 同樣以容器形式被部署在應用平台中 。 除了第一次啟動 (bootstrap) 需要手動外 , Sammy 也可以用來部署自己新的版本 。

應用部署平台 (Deployment Platform)

這個平台主要是針對後端服務跟網站 , 容器化的應用元件在生產與 QA 環境的需要跟開發階段在本機以及自動建置環境不同 。 應用部署平台提供應用的高可用性 、 擴充性以及其它非功能面的需求 。 目前團隊是採用 Kubernetes 來管理應用部署平台 。

在此部署平台可以同時有多個部署環境 (environments), 至少會有 QA 跟生產 (Production) 兩個環境 。

  • QA 環境 : 是用來驗證開發中的應用功能正確也用來驗證一些非功能需求 。
  • 生產環境 : 應用的正式執行環境 , 支援應用的可用性 、 動態擴充 、 服務發現與負載均衡等 。

目前 「QA 環境 」 與 「 生產環境 」 共用同一組基礎設施 (infrastructure), 這樣做的幾個理由 :

  • 管理彈性 , 主機節點可以在不同環境間挪用或共用 。
  • 確保環境之間的相似性 , 不用因應不同環境有不同的部署方式 。

平台基礎設施 (infrastructure)

「 應用部署平台 」 提供應用的部署環境 , 但畢竟它是由軟體組成 , 最終還是需要伺服器來執行 。 透過 Kubernetes 應用部署平台理論上可以採用不同的雲端基礎設施服務 , 但本團隊實際使用的是 AWS。 經過評估後 , 以 CoreOS 提供的虛擬機映像為基礎 , 實現 Kubernetes 需要的環境 。 採用 CoreOS 的理由 :

  • 需要方便可以在本地測試 : 需要的話 , 開發跟運營人員可以在本機複製一個叢集 (cluster) 環境來測試 。
  • 有較多的文件跟支援 : 使用 Google Cloud Platform 的支援度最廣 , 但本團隊使用的是 AWS 。
  • 可以跨不同的基礎設施 : 實務上可能不會用到 , 但不被綁住在特定供應商總是一件好事 。

山姆鍋希望基礎設施可以類似 AWS CloudFormation 一樣可以自動建立 , 但又不想被綁定在 CloudFormation。 評估過 Ansible, SaltStack 這類組態管理工具後 , 發現 Terraform 比較適合這個工作 , 目前正在研究中 。

小結

本文所提的流程是山姆鍋所屬團隊所採用 , 但仍在建置中的方案 , 目前主要是 「 自動部署機器人 」 跟 「 應用部署平台 」 有技術上的瓶頸 。 要特別說明的是 : 本文假設採用微服務架構 (Microservices), 每個應用容器都是可以獨立部署的單元 , 不管該容器是用來部署一個應用 、 微服務或者批次工作 (batch job)。


知識不會因為傳播而減少,喜歡這篇文章請幫忙分享。


本篇文章由 Sampot (山姆鍋) 發表,下面是有關他的連結:

評論

您的反饋是我寫作的最大動力,歡迎參與討論。P.S. 我會優先回答張貼在這裡的問題。

comments powered by Disqus