多雲環境下的DevOps與CI/CD
企業會使用雲端的原因就是 — 雲端可以加速程式的開發速度與迭代。因為現代企業的業務需求會跟著市場不斷變動。而在雲端運算,一切都是代碼化。企業所開發的程式也需要連同其運作的Infra configuration一起在雲端中不斷進行測試。而在開發與部署在雲端之後,接下來就是維運團隊接收並使其正常運作。
而為了加速上述所說的整個流程,企業根據精實文化發展出了DveOps模式,使用持續性代碼發佈,每週甚至每天多次測試、除錯和部署代碼的可能性,這樣企業的程式就可以不斷持續進化與優化。有一點是重要的,哪就是代碼的"一致性":代碼必須至於嚴格的版控之下。
而這就 CI/CD 流水線做的事: 持續整合(CI — Continuous integration)與持續佈署(Continuous Deployment),其中Deployment也可以是Delivery。
本文中,我們將會討論DevOps的基本原則,CI/CD流水線如何使用推(push)與拉(Pull)的機制來作業,如何設計這個CI/CD流水線是符合多雲環境。還有各種DevOps與CI/CD的工作。
本文中我們討論的重點如下:
- 甚麼是CI/CD與流水線
- 在CI/CD中的推(push)與拉(pull)的原則
- 設計多雲管道
- 各種CI/CD工具
甚麼是CI/CD與流水線
在我們討論CI/CD與流水線之前,我們需要對DevOps有一個基本的認知。雖然對DevOps這一個詞彙,有非常多的大神、專家、組織有不一樣的定義。但本文這裡會使用DASA(DevOps Agile Skills Association)這一個組織所定義的DevOps。這個組織定義了DevOps框架是基於以下六個原則:
- 以客戶為中心的行動:
應用程式與系統最終就是要做給客戶使用的。所以客戶要甚麼以及他們期望在這個系統有甚麼樣的功能才是最終目的。這也帶出另一個概念Domain-driven design。 - 以終為始:
應用程式完全完成後會是什麼樣子? - 端點到端點的責任:
團隊要能對應用程式的整個週期負責。著名的座右銘是 — 你建立的,你來維運。你弄壞了,你要修好它。你摧毀掉的,你要能重建它。 - 跨職能的自治團隊:
團隊需要能夠並被允許在開發過程中自己做出決定。 - 持續精進
- 盡可能的自動化:
但不是每一件事都自動化,而是要辨認這個自動化能帶來甚麼效益
DevOps將"快速迭代"視為一種新的工作方式、一種文化,這也是取自精實文化而來的。它是打破傳統以來開發團隊與維運團隊哪種穀倉式的運作,DevOps希望開發與維運團隊融為一體,這樣子在整體的IT系統就能在運作上得到快速的反饋。在雲端中一切都是代碼化的,包含了基礎設施。所以才有IaC(Infrastructure as Code)的概念產生,更多IaC的介紹可以參閱什麼是IaC(Infrastructure as Code)一文的介紹。既然一切都是代碼,哪麼具結構性與高度管控代碼的管理方式就必然要介入。而這就是CI/CD 流水線的目的 — 結構化與高度管控。
CI(Continuous Integration) 是建立在團隊有一個共享的代碼存儲庫的原則之上,團隊是根據這個共享的存儲庫來建立、修改或調整雲端中的環境。CI讓開發人員能在同一個時間在同一組代碼上作業。代碼上的任何變動都能直接整合在一起並且隨時準備好在不同的雲端環境上進行完整測試。
CD(Continuous Deployment or Delivery)則聚焦在能全自動化的在各個階段環境(Test/UAT/Production等)之間的佈署,而針對在環境佈署完成之後也能進行相對應的自動化測試。因為這樣的全自動化作業,開發人員能以最快的速度收到反饋,進而對代碼做出調整。
CI/CD 支援DevOps 。 結合 CI/CD,從代碼的計劃到管理的所有責任都由團隊承擔,並且任何的代碼變更都可以通過自動化和穩健的開發流程更快地傳遞到客戶手中。以下是CI/CD支援DevOps的流程圖:
CI/CD的基本概念
很多企業導入DevOps文化與CI/CD的工具,但要嘛導入失敗要不就是做成四不像。這裡,我們將解釋企業如何成功導入CI/CD並且避開一些陷阱。第一的要點是"一致性"。這對企業在雲端上的運作與CI/CD一樣重要。
開發團隊在代碼上的變動也將導致CI與CD的觸發與運作的頻率。當企業有多個開發團隊並且使用多雲環境時,作業的一致性就變得非常重要。而全自動化的CI/CD 流水線就是讓我們多雲環境達成一致性的關鍵。如同我們之前說過,DevOps是一種文化。用甚麼樣的工具視乎團隊人員的技能與業務需求,DevOps最重要的嚴格遵守"流程"的文化。
為了讓企業能成功的實行DevOps,以下是建議的實行步驟:
- 成功的CI/CD是在與所有的利害關係人達成一個具一致性的DevOps流程。一個關鍵原則是 : 團隊是具有"自治性(有權下決定並行動)"的並且負責整個流程的端到端(end-to-end)。DevOps是從精實文化延伸出來的,意思是每一次完成的事項都是"短時間的作業衝刺",至於多短視團隊的能力與DevOps的成熟度。
- CI/CD工具的選擇。市面上有一大多的CI/CD工具可以選擇,要錢的、不要錢的。這些工具是團隊每天都會用到的,並且這些工具能讓團隊朝向"試駕(test drive)"的作業方式運作。一致性在這裡依然很重要。
- 進行概念驗證(Proof of concept)。CI/CD的一個重要元素是"自動化測試",所以第一步是建立一個自動化流程管道。企業通常會有一個品質測試計畫,可能是存在於GTA(Generic Test Agreement)中。GTA 的主要目的是為了保證測試過程的一致性。不過,在DevOps中更多組織使用的是DoD(Definition of Done)。
Definition of Done (DoD) 是一種軟體開發流程中的概念,指的是在軟體開發中,每個任務或功能都必須符合的完成條件。這些條件通常包括軟體代碼的編寫、測試、文件、安裝和部署等方面。
DoD 是在軟體開發流程中確保軟體品質的重要工具,因為它描述了在將軟體功能交付給使用者之前必須完成的所有任務。它有助於確保軟體符合使用者需求,並且能夠正常運行。
DoD 通常會在軟體開發團隊的管理者或Q&A人員中決定,並且會在整個軟體開發流程中保持不變。這樣可以確保軟體在每個階段都能得到適當的檢查和測試,並且能夠符合使用者的期望。
下圖展示了實現具有不同測試階段的build pipeline和release pipeline的概念。 代碼在build pipeline中開發,然後送到release pipeline,在release pipeline中配置代碼並發布以用於生產環境。 在release stages,完整構建在測試或Q&A(Quality and Assurance)環境中進行測試。 在Q&A中,Build被接受並發布以部署到生產環境中。
4. DevOps另一個原則是:盡可能的自動化。意思是企業需要適應代碼化的作業,不再需要管理實際硬體的配置(取代的是IaC)。
版控(version control)之下進行作業
由於所有的團隊都在同一個代碼庫內作業,以致於在CI/CD的版控變得非常重要。版控系統可以組織不同類型的檔案,從程式代碼、測試腳本、佈署腳本與配置腳本。由於一切都是代碼,意味著系統內會有很多個的code packages。版控的另一個效益是我們可以看到整個代碼的歷程,以方便我們查詢為何佈署失敗或是被駭客入侵,甚至重建整個系統。
在DevOps中,任何的異動都被稱為commits(提交)。而提交可以分為推與拉的機制,這會讓CI/CD 流水線中對代碼產生分支(forking)或合併(merging)。一個提交會包含除了代碼本身,還有相關的metadata。這個metadata通常會包含的資訊有: 誰變更、變更的理由。這再一次顯示了達成作業的"一致性"的重要性。因為一致性的作業可以讓我們重複相同的作業流程並且其結果是可以預期的。
在版控系統中通常會包含的代碼項目通常會有:
- 程式代碼
- API 腳本
- 基礎設施組件
- 基礎設施的配置包
- 雲端配置範本,像是AWS的 CloudFormation,Azure的DSC(Desired State Configuration)或Terraform
- 容器的代碼定義,如Docker檔案
- 容器的編排腳本(Orchestration scripts),如K8S或Docker Swarm
- 測試腳本
一旦我們建立這些流程/系統之後,我們需要持續的維護它。我們必須確定在一切雲端運算都內都代碼的情況,所有代碼都必須在版控的管理之下。因為這樣才可以達成運作的一致性:可以讓企業快速部署其程式與系統,並且這些都是安全與可靠的。
在CI/CD中的推與拉的原則
CI/CD pipeline中一定會有branches。 master branches有時被稱為主線,如果在GCP,有些開發團隊會稱為truck。 最重要的原則是每一個開發團隊都會有一個master branches。 接下來,有兩種方法可以將新代碼推送到該 master branches。
直接推送到主線
使用這種方法,開發人員會直接在主代碼中作業; 他們會小量的修改代碼並將它們直接合併回 master branch。 將代碼推回到 master 稱為commit。 這些commit可能每天有好幾次。 以這種方式工作可以確保代碼發布可以非常頻繁的完成。 下圖顯示了直接推送到master branch的作業方式:
CI 背後的理念是企業擺脫了冗長、複雜的代碼整合。 開發人員是用小批次的代碼變更來作業的,這些代碼會經常提交給 master。 最大的好處是開發人員可以立即看到變更是否正確完成,並且可以在不對整個master產生巨大影響的情況下回到變更之前的狀態。 這就是 DevOps — — 開發人員負責建立、提交和看到結果:你弄壞它,你修復它。 在代碼提交後執行的自動化測試對於確保系統保持無故障運行至關重要。
將代碼推送到master的分支
團隊從 master 複製代碼並建立另一個單獨的(或功能的)分支。 這也稱為分叉(forking):開發人員通過從原始代碼 master 中有一個副本來建立一個功能分支。 他們在這個分叉代碼上進行開發。 這被稱為功能驅動開發(feature-driven development)。
這種方法通常用於重大開發,建立新功能。 開發人員可以在分叉代碼上進行隔離,當他們完成後,將代碼提交回 master,新功能或new build與 master 合併。 缺點是這會整合很複雜, 而且不能經常進行合併,因為需要在合併之前進行密集測試。下圖顯示此種作業方式:
使用 CI/CD 的最佳實踐
CI/CD 的最佳實踐其實很少,主要是每間公司的組織架構與文化都不同。所以產生的實際作業流程也可能不同。 但是CI/CD最大的陷阱之一是code review太多人要看,這意味著開發人員在將代碼推向生產環境之前必須取得不同利害關係人的批准,也就是回到一般傳統專案管理,waterfall的作業模式。 這將會花費大量時間並減緩 DevOps 流程。 採用 DevOps 的公司應該實施兩個原則:
- 四隻眼睛原則:一邊寫代碼同時進行code review。 採用兩個開發人員一同作業,第二個開發人員審查第一個開發人員的代碼。 這也稱為Extreme Programming。但如果企業如果很龐大,這將會產生相當大的人力費用。 Peer review是另一種方法:跟前者不同的是,這種方式通常在開發過程結束時才會進行。也就不用一對一的盯著看代碼開發。
- 運行自動化測試腳本: 這些腳本必須在代碼實際提交到 master branch之前執行,以確保企業的系統在新代碼提交後能繼續運作。
上面的兩種原則如果都有遵守,哪麼waterfall的開發模式就不再需要了。
設計多雲管道
應用程式代碼的開發跟用哪一朵雲沒有絕對的關係,這意味著代碼被推送到哪裡並不重要:代碼的功能保持不變。 然而,許多開發人員會發現它確實很重要,而且以真正的多雲方式進行開發其實會很複雜。 對於 DevOps 流程本身,代碼放在哪個平台上可能並不重要,但一旦團隊將代碼推送到雲端中的生產環境,它就很重要了。 然後是需要考慮的雲端平台的各種細節。
在多雲環境中,開發人員用的還是一個存儲庫作業,但在部署期間,就會加上和測試特定於這個雲端平台的專屬配置。 這是Staging階段。 AWS、Azure 和 GCP 都有其特定的配置功能,需要使用應用程式代碼進行測試。 在Staging階段,代碼包與infrastructure configuration合併會在目標的雲端平台運作並進行測試。
開發人員必須採取幾個步驟才能取得成功。 首先,無論應用程式最終運作在哪個雲端平台,DevOps 的工作方式應該是一致的。 企業可能希望在 Azure、AWS、GCP 甚至地端機房運來跑應用程式,但在 DevOps 的週期中開發應用程式代碼的方式應該是相同的。 這些雲端平台中的每一個都將具有運作代碼的特定功能,但這是配置問題。 Staging 階段旨在查明整個代碼包是否已準備好發佈到生產環境。
我們在定義多雲環境下的自動化工具與流程中,我們已經了解到開發人員需要層次式思考:他們需要從基礎架構層和配置層的資源中抽像出應用層。 這是通過 CI/CD 獲得一致性的應用程式開發方式的唯一途徑。 開發人員在多雲環境中需要應對的另一個挑戰是各種雲端平台的高度變化。 DevOps 工具必須能夠適應部署中的這些變化,而不必一直更改應用程式代碼本身。
然而,開發人員需要對要使用的雲端平台及其具體情況有很好的理解。 研究這些雲端平台中 DevOps 的最佳實踐和推薦的工具也很有意義。 最常見的工具通常可以適用在大多數的雲端平台,因為這些平台利用Native API的方式。
因此,成功實施 DevOps 的基本規則如下:
- 只有一個代碼來源儲存庫
- 一種框架或作業方式
- 一套可以適用在所有雲端平台的工具
如果要提到DevOps的框架的話,就不得不提SAFe(Scaled Agile Framework)。SAFe其中的一個特點是 Agile Release Train。
Agile Release Train是圍繞應用程式開發的標準化和代碼的發布管理原則建立。而 這是通過自動化一切來完成的:
- 自動化的代碼編譯流程
- 測試單元、驗收、效能和負載的自動化
- CI,自動化是靠著運作整合測試和可以部署到生產環境中發布單元(releaseing units)
- CD,不同版本的代碼靠著自動化佈署到不同的雲端平台
- 另外其他的自動化工具還針對configuration、provisioning、security by design、code review、audit trial、logging與management
以上這些都支援了程式的生命週期管理,持續精進,與代碼發布管理。
各種CI/CD工具
現今市面上有一大堆的CI/CD工具。這個網址可以讓我們一覽目前市面上所有相關的工具並且是持續有在維護其內容的https://digital.ai/learn/devops-periodic-table/。由於工具太多了,本文只討論三大雲所提供的CI/CD工具。
AWS CodePipeline
AWS提供這一個工具可以從程式到基礎設施的資源佈署。CodePipeline有以下特點:
- Workflow modeling: 提供了代碼如何佈署的計畫型工具。基本就是一個佈署流程,可以分為幾個階段發布我們的代碼: build/test/deploy。團隊可以創建需要在不同階段執行的任務。
- Integration: 這讓開發人員可以整合來自不同的代碼庫,例如GitHub也能完整整合自家的代碼庫(Code Commit)。或是其他的AWS服務,如ECR(Elastic Container Registry)、S3、Cloudformation、SAM(Serverless Application Model)等等,基本上AWS的與自家服務還有第三方工具的整合度算是三朵雲最高的了(也就是plugin的能力很強)。
下圖為CodePipeline的功能表:
如上圖所式,當我們從Codepipeline建立一個pipeline之後,它就會開始要將代碼從Code Commit拉出來。這個pipeline會有CI(AWS的CodeBuild)與CD(CodeDeploy)。
Azure DevOps
這個與AWS CodePipeline統包整個DevOps的開發週期。Azure DevOps的特點如下:
- Boards: 一樣是一個計畫式的工具,並且這個工具可以搭配Kanban與Scrum。
- Repos: 這是在Azure Devops基於Git或TFVC(Team Foundation Version Control)的代碼庫。
- Pipeline
- Test Plans: 可以設定測試腳本(自動或手動)
- Artifacts: 這個功能可以讓開發人員針對不同的來源分享他們的代碼包,並且整合到pipeline或其他的CI/CD工具。Artifacts支援Maven,NPM(Node Packet Manage)與NuGet package。
下圖為 Azure DevOps 的功能單,其中有一個定義為 Scrum 的項目,它將工作項劃分為backlog items和sprints:
當我們開始使用Azure DevOps時,第一件事就是要設定一個project並且給予編號。接下來專案或產品經理要定義開發方法。不一樣的選擇會呈現可能需要定義的工作項目,像是features,backlog item與tasks還有在board要計劃如何執行這些項目。工作項目可以是一段可以部署的代碼; 在 DevOps 中,這可以通過 Azure Pipelines 實現自動化,它在審查後實際將代碼部署到目標環境。
開發人員也可以使用 Azure DevOps for AWS,使用適用於 Azure DevOps 的 AWS 工具包。 該工具包甚至接受使用 AWS CloudFormation template在 Azure DevOps 中配置和更新 AWS 資源。
GCP Cloud Build
以下是GCP的CI/CD的工具:
- Cloud Source Repositories: 這是一個託管的私有Git repo。開發人員將代碼在這裡進行儲存、存取與代碼拉取。而代碼在Cloud Build完成之後,可以使用Cloud Pub/Sub進行自動化回應。在Cloud build建立repo可以用GUI或Cloud shell的gcloud命令(gcloud source repos create git push)。之後,開發人員可以在gcloud console使用 git add/git commit/git push。
- Artifact Registry: 這一個功能與Azure DevOps中的Artifacts相同。可以支援的Maven與NPM package。同時也支援Docker container images。
- Cloud Build: 這是GCP的CI/CD 的引擎。這裡是我們定義流水線的地方。代碼可以從Cloud Source Repo拖(pull)過來,或是第三方來源(例如GitHub)。Cloud Build也可以整合其他第三方的工具,如Jenkis或Spinnaker來進行自動化的測試與佈署。
如同之前我們提到的,市面上有一大堆的CI/CI工具。雲端業者自己也提供自己的解決方案。但其基本原則是一樣的,不一樣的是這些工具部署代碼的方式,尤其是它們如何以自動化方式測試和驗證代碼。但是用過的人應該都知道,三大雲提供的CI/CD工具有時不是能完全符合需求,還是需要其他第三方軟體來搭配。
其他文件連結: