前兩講聊了 CI/CD 中的 CI, Continuous Integration,包含建置、服務定版、測試的概念和注意事項,今天我們接著昨天談的部署環境,來繼續聊聊 CI/CD 的 CD,持續部署,以及 CI/CD 有哪些好用的工具。
我們在昨天聊的 CD 環境中知道部署的目標有分 Local、Alpha、Staging、Production 等等目的不同環境,除了 Local 是在本機開發後啟動的測試外,從 Alpha 到 Production 理論上都會是在其他機器上面。
雖然說部署的目標不見得是一台機器,可能是各種不同的第三方 PaaS(平台式服務),例如 Heroku、Netlify、Vercel 等等,但是我最偏好的方式是一台簡單的虛擬機器(VM, Virtual Machine)。
雖然一台 VM 的缺點很明顯,就是你需要自己設定 VM 的細節,從硬體規格的選擇、到作業系統,再到系統內相關套件的安裝,都需要自己來。
而使用雲服務的最大優點也就是幫你把這些瑣事包好,你通常只需要照著他們的模板把 Code 或是 Image 的設定寫好,下個指令就能部署上去。
但是這類 PaaS 的最大缺點便是彈性低,雖然能夠在初期很簡單的部署你的服務,卻無法控制硬體資源、自行架設資料庫等等。
如果你已經很熟悉某個 PaaS 所提供的服務,根據簡單原則,完全可以將服務就架設在這個平台上面,會省掉你很多瑣事。但我更偏好彈性高一點的自架服務,除了比較不會被平台牽著走,因為一旦平台提高收費,我們想將服務移往其他地方所花的成本就比一條龍的自己架設高,並且可控制性會高了許多。
如果我們的部署目標是一台 VM 的話,在 Local 做測試的部署就相當容易了。我習慣將所有服務包成一份 docker-compose.yml
,後端是一個 Image 提供 API、前端也是一個 Server Image 來提供靜態檔案,再附上一個 Database,以及任何其他我們所建置的服務。
這樣一來只要在 Image 建置完畢之後,就可以簡單下個 docker compose up
的指令將所有服務啟動,簡單的在本機端模擬實際部署環境的狀況。
而實際要部署到 Alpha、Production 時,如果目標機器有多台,例如前後端和資料庫分開,也可以將 Image 傳到這些機器,一樣透過 docker compose
或是 docker run
來啟動這些服務。
除了初始的設定機器、安裝套件等等瑣事比較麻煩之外,帶來的優點就是我們可以完全控制在這些機器上要做的事情。
例如部署完畢後要跑 E2E Tests,我們可以透過 Shell Scripts 自動處理 Setup 和 Tear Down 的事情,像是把資料庫清空,重新建立測試資料等等。而這些事情在其他 PaaS 上可能根本做不到,就算可以,也會有相當多限制。
講完了部署,整個 CI 到 CD 的流程我們就都簡單的聊過了。那麼,有那些工具適合幫助我們處理這些瑣事呢?
我自己使用過兩種模式的 CI/CD 工具,一種是彈性比較大的,Jenkins 加上 Ansible,另外一種則是比較簡單,但依賴於雲端的版控平台而彈性較差的,像是 GitHub 自己的 GitHub Actions。
由於這兩種模式的工具不會像是部署的環境比較有可能要更大的自由度,所以在 Jenkins + Ansible 或 GitHub Actions 的選擇上,我大概是五五波。
Jenkins 是個管理自動化任務的服務,搭配 Ansible 這樣適合部署的工具,可以完成非常多複雜的任務;而 GitHub Actions 則是能透過寫簡單的 YAML 檔案來完成自動測試、自動部署的工作。
如果你已經對於 GitHub,或是 GitLab、Bitbucket 等雲端平台相當熟悉了,選用他們提供的 CI/CD 工具其實就當足夠了,當然還有需要額外付費這點需要考量就是。
而如果你的版控平台是自己架設的,或是想要有更多的自由度,做更複雜的事,用 Jenkins + Ansible 會是個不錯的選擇。
但不論哪些工具及平台,我覺得簡單原則都是很值得參考的,挑一個能最基本的幫助我們處理整合、部署瑣事的好工具即可。
最後回到 CI/CD 的目的,我們會需要不斷地將開發好的程式整合進現有產品,並持續部署到目標環境上,其實是為了可以即時發現小錯誤。
如果我們一次累積了好個幾月的程式碼,在交付給客戶新版本之前才實際部署到測試的環境中,可能會發現 Build 不起來、測試發生許多錯誤,甚至連部署都出現了問題。
當一大堆的問題同時發生時,想在短時間內一次處理完就要費很大的功夫,尤其是當 Deadline 已經迫在眉睫之時。
所以持續的整合,持續的部署可以在一定程度上避免同時處理太多錯誤。有小錯誤是無可避免的,但是可以盡快抓到,並且解決。
*CI/CD Flow
透過上途中藍色的自動化過程,可以讓我們避免我們頻繁的手動做一些瑣事,讓「持續」整合和部署的動作更加輕鬆。
試想一下每次上 Code 之後都要記得在手動下兩個測試的指令、Code Merge 後也要手動下指令建置 Image,最後還要手動將 Build 好的 Image 部署到目標機器上。
就算這些指令都很小、很簡單,累積在一起也會變得稍嫌龐雜,更何況人為的操作是一定會發生錯誤,也會遺忘的。這些能夠自動化的事情交給機器來做,便可以讓產品持續變好這件事更為輕鬆。