系統管理員的 7 個 CI/CD 工具

2019-03-01 10:17:00

本文是一篇簡單指南:介紹一些頂級的開源的持續整合、持續交付和持續部署(CI/CD)工具。

雖然持續整合、持續交付和持續部署(CI/CD)在開發者社群裡已經存在很多年,一些機構在其運維部門也有實施經驗,但大多數公司並沒有做這樣的嘗試。對於很多機構來說,讓運維團隊能夠像他們的開發同行一樣熟練操作 CI/CD 工具,已經變得十分必要了。

無論是基礎設施、第三方應用還是內部開發的應用,都可以開展 CI/CD 實踐。儘管你會發現有很多不同的工具,但它們都有著相似的設計模型。而且可能最重要的一點是:通過帶領你的公司進行這些實踐,會讓你在公司內部變得舉足輕重,成為他人學習的榜樣。

一些機構在自己的基礎設施上已有多年的 CI/CD 實踐經驗,常用的工具包括 AnsibleChef 或者 Puppet。另一些工具,比如 Test Kitchen,允許在最終要部署應用的基礎設施上執行測試。事實上,如果使用更高階的設定方法,你甚至可以將應用部署到有真實負載的模擬“生產環境”上,來執行應用級別的測試。然而,單單是能夠測試基礎設施就是一項了不起的成就了。設定管理工具 Terraform 可以通過 Test Kitchen 來快速建立更短暫冥等的的基礎設施設定,這比它的前輩要強不少。再加上 Linux 容器和 Kubernetes,在數小時內,你就可以建立一套類似於生產環境的設定引數和系統資源,來測試整個基礎設施和其上部署的應用,這在以前可能需要花費幾個月的時間。而且,刪除和再次建立整個測試環境也非常容易。

當然,作為初學者,你也可以把網路設定和 DDL(資料定義語言data definition language)檔案加入版本控制,然後開始嘗試一些簡單的 CI/CD 流程。雖然只能幫你檢查一下語意語法或某些最佳實踐,但實際上大多數開發的管道都是這樣起步的。只要你把腳手架搭起來,建造就容易得多了。而一旦起步,你就會發現各種管道的使用場景。

舉個例子,我經常會在公司內部寫新聞簡報,我使用 MJML 製作郵件模板,然後把它加入版本控制。我一般會維護一個 web 版本,但是一些同事喜歡 PDF 版,於是我建立了一個管道。每當我寫好一篇新聞稿,就在 Gitlab 上提交一個合併請求。這樣做會自動建立一個 index.html 檔案,生成這篇新聞稿的 HTML 和 PDF 版連結。HTML 和 PDF 檔案也會在該管道裡同時生成。除非有人來檢查確認,這些檔案不會被直接發佈出去。使用 GitLab Pages 發布這個網站後,我就可以下載一份 HTML 版,用來傳送新聞簡報。未來,我會修改這個流程,當合併請求成功或者在某個稽核步驟後,自動發出對應的新聞稿。這些處理邏輯並不複雜,但的確為我節省了不少時間。實際上這些工具最核心的用途就是替你節省時間。

關鍵是要在抽象層建立出工具,這樣稍加修改就可以處理不同的問題。值得留意的是,我建立的這套流程幾乎不需要任何程式碼,除了一些輕量級的 HTML 模板,一些把 HTML 檔案轉換成 PDF 的 nodejs 程式碼,還有一些生成索引頁面的 nodejs 程式碼

這其中一些東西可能看起來有點複雜,但其中大部分都源自我使用的不同工具的教學文件。而且很多開發人員也會樂意跟你合作,因為他們在完工時會發現這些東西也挺有用。上面我提供的那些程式碼連結是給 DevOps KC(LCTT 譯註:一個地方性 DevOps 組織) 傳送新聞簡報用的,其中大部分用來建立網站的程式碼來自我在內部新聞簡報專案上所作的工作。

下面列出的大多數工具都可以提供這種型別的互動,但是有些工具提供的模型略有不同。這一領域新興的模型是用宣告式的方法例如 YAML 來描述一個管道,其中的每個階段都是短暫而冪等的。許多系統還會建立有向無環圖(DAG),來確保管道上不同的階段排序的正確性。

這些階段一般執行在 Linux 容器裡,和普通的容器並沒有區別。有一些工具,比如 Spinnaker,只關注部署元件,而且提供一些其他工具沒有的操作特性。Jenkins 則通常把管道設定存成 XML 格式,大部分互動都可以在圖形介面裡完成,但最新的方案是使用領域專用語言(DSL)(如 Groovy)。並且,Jenkins 的任務(job)通常執行在各個節點裡,這些節點上會裝一個專門的 Java 代理,還有一堆混雜的外掛和預裝元件。

Jenkins 在自己的工具裡引入了管道的概念,但使用起來卻並不輕鬆,甚至包含一些禁區。最近,Jenkins 的創始人決定帶領社群向新的方向前進,希望能為這個專案注入新的活力,把 CI/CD 真正推廣開(LCTT 譯註:詳見後面的 Jenkins 章節)。我認為其中最有意思的想法是構建一個雲原生 Jenkins,能把 Kubernetes 叢集轉變成 Jenkins CI/CD 平台。

當你更多地了解這些工具並把實踐帶入你的公司和運維部門,你很快就會有追隨者,因為你有辦法提升自己和別人的工作效率。我們都有多年積累下來的技術債要解決,如果你能給同事們提供足夠的時間來處理這些積壓的工作,他們該會有多感激呢?不止如此,你的客戶也會開始看到應用變得越來越穩定,管理層會把你看作得力幹將,你也會在下次談薪資待遇或參加面試時更有底氣。

讓我們開始深入了解這些工具吧,我們將對每個工具做簡短的介紹,並分享一些有用的連結。

GitLab CI

GitLab 可以說是 CI/CD 領域裡新登場的玩家,但它卻在權威調研機構 Forrester 的 CI 整合工具的調查報告中位列第一。在一個高水平、競爭充分的領域裡,這是個了不起的成就。是什麼讓 GitLab CI 這麼成功呢?它使用 YAML 檔案來描述整個管道。另有一個功能叫做 Auto DevOps,可以為較簡單的專案用多種內建的測試單元自動生成管道。這套系統使用 Herokuish buildpacks 來判斷語言的種類以及如何構建應用。有些語言也可以管理資料庫,它真正改變了構建新應用程式和從開發的開始將它們部署到生產環境的過程。它原生整合於 Kubernetes,可以根據不同的方案將你的應用自動部署到 Kubernetes 叢集,比如灰度發布、藍綠部署等。

除了它的持續整合功能,GitLab 還提供了許多補充特性,比如:將 Prometheus 和你的應用一同部署,以提供操作監控功能;通過 GitLab 提供的 Issues、Epics 和 Milestones 功能來實現專案評估和管理;管道中整合了安全檢測功能,多個專案的檢測結果會聚合顯示;你可以通過 GitLab 提供的網頁版 IDE 線上編輯程式碼,還可以快速檢視管道的預覽或執行狀態。

GoCD

GoCD 是由老牌軟體公司 Thoughtworks 出品,這已經足夠證明它的能力和效率。對我而言,GoCD 最具亮點的特性是它的價值流檢視(VSM)。實際上,一個管道的輸出可以變成下一個管道的輸入,從而把管道串聯起來。這樣做有助於提高不同開發團隊在整個開發流程中的獨立性。比如在引入 CI/CD 系統時,有些成立較久的機構希望保持他們各個團隊相互隔離,這時候 VSM 就很有用了:讓每個人都使用相同的工具就很容易在 VSM 中發現工作流程上的瓶頸,然後可以按圖索驥調整團隊或者想辦法提高工作效率。

為公司的每個產品設定 VSM 是非常有價值的;GoCD 可以使用 JSON 或 YAML 格式儲存設定,還能以視覺化的方式展示資料等待時間,這讓一個機構能有效減少學習它的成本。剛開始使用 GoCD 建立你自己的流程時,建議使用人工稽核的方式。讓每個團隊也採用人工稽核,這樣你就可以開始收集資料並且找到可能的瓶頸點。

Travis CI

我使用的第一個軟體既服務(SaaS)型別的 CI 系統就是 Travis CI,體驗很不錯。管道設定以原始碼形式用 YAML 儲存,它與 GitHub 等工具無縫整合。我印象中管道從來沒有失效過,因為 Travis CI 的線上率很高。除了 SaaS 版之外,你也可以使用自行部署的版本。我還沒有自行部署過,它的元件非常多,要全部安裝的話,工作量就有點嚇人了。我猜更簡單的辦法是把它部署到 Kubernetes 上,Travis CI 提供了 Helm charts,這些 charts 目前不包含所有要部署的元件,但我相信以後會越來越豐富的。如果你不想處理這些細枝末節的問題,還有一個企業版可以試試。

假如你在開發一個開源專案,你就能免費使用 SaaS 版的 Travis CI,享受頂尖團隊提供的優質服務!這樣能省去很多麻煩,你可以在一個相對通用的平台上(如 GitHub)研發開源專案,而不用找伺服器來執行任何東西。

Jenkins

Jenkins 在 CI/CD 界絕對是元老級的存在,也是事實上的標準。我強烈建議你讀一讀這篇文章:“Jenkins: Shifting Gears”,作者 Kohsuke 是 Jenkins 的創始人兼 CloudBees 公司 CTO。這篇文章契合了我在過去十年裡對 Jenkins 及其社群的感受。他在文中闡述了一些這幾年呼聲很高的需求,我很樂意看到 CloudBees 引領這場變革。長期以來,Jenkins 對於非開發人員來說有點難以接受,並且一直是其管理員的重擔。還好,這些問題正是他們想要著手解決的。

Jenkins 設定既程式碼(JCasC)應該可以幫助管理員解決困擾了他們多年的設定複雜性問題。與其他 CI/CD 系統類似,只需要修改一個簡單的 YAML 檔案就可以完成 Jenkins 主節點的設定工作。Jenkins Evergreen 的出現讓設定工作變得更加輕鬆,它提供了很多預設的使用場景,你只管套用就可以了。這些發行版會比官方的標準版本 Jenkins 更容易維護和升級。

Jenkins 2 引入了兩種原生的管道功能,我在 LISA(LCTT 譯註:一個系統架構和運維大會) 2017 年的研討會上已經討論過了。這兩種功能都沒有 YAML 簡便,但在處理複雜任務時它們很好用。

Jenkins X 是 Jenkins 的一個全新變種,用來實現雲端原生 Jenkins(至少在使用者看來是這樣)。它會使用 JCasC 及 Evergreen,並且和 Kubernetes 整合的更加緊密。對於 Jenkins 來說這是個令人激動的時刻,我很樂意看到它在這一領域的創新,並且繼續發揮領袖作用。

Concourse CI

我第一次知道 Concourse 是通過 Pivotal Labs 的夥計們介紹的,當時它處於早期 beta 版本,而且那時候也很少有類似的工具。這套系統是基於微服務構建的,每個任務執行在一個容器裡。它獨有的一個優良特性是能夠在你本地系統上執行任務,體現你原生的改動。這意味著你完全可以在本地開發(假設你已經連線到了 Concourse 的伺服器),像在真實的管道構建流程一樣從你本地構建專案。而且,你可以在修改過程式碼後從本地直接重新執行構建,來檢驗你的改動結果。

Concourse 還有一個簡單的擴充套件系統,它依賴於“資源”這一基礎概念。基本上,你想給管道新增的每個新功能都可以用一個 Docker 映象實現,並作為一個新的資源型別包含在你的設定中。這樣可以保證每個功能都被封裝在一個不可變的獨立工件中,方便對其單獨修改和升級,改變其中一個時不會影響其他構建。

Spinnaker

Spinnaker 出自 Netflix,它更關注持續部署而非持續整合。它可以與其他工具整合,比如 Travis 和 Jenkins,來啟動測試和部署流程。它也能與 Prometheus、Datadog 這樣的監控工具整合,參考它們提供的指標來決定如何部署。例如,在金絲雀發布canary deployment裡,我們可以根據收集到的相關監控指標來做出判斷:最近的這次發布是否導致了服務降級,應該立刻回滾;還是說看起來一切 OK,應該繼續執行部署。

談到持續部署,一些另類但卻至關重要的問題往往被忽略掉了,說出來可能有點讓人困惑:Spinnaker 可以幫助持續部署不那麼“持續”。在整個應用部署流程期間,如果發生了重大問題,它可以讓流程停止執行,以阻止可能發生的部署錯誤。但它也可以在最關鍵的時刻讓人工稽核強制通過,發布新版本上線,使整體收益最大化。實際上,CI/CD 的主要目的就是在商業模式需要調整時,能夠讓待更新的程式碼立即得到部署。

Screwdriver

Screwdriver 是個簡單而又強大的軟體。它採用微服務架構,依賴像 Nomad、Kubernetes 和 Docker 這樣的工具作為執行引擎。官方有一篇很不錯的部署教學文件,介紹了如何將它部署到 AWS 和 Kubernetes 上,但如果正在開發中的 Helm chart 也完成的話,就更完美了。

Screwdriver 也使用 YAML 來描述它的管道,並且有很多合理的預設值,這樣可以有效減少各個管道重複的設定項。用組態檔可以組織起高階的工作流,來描述各個任務間複雜的依賴關係。例如,一項任務可以在另一個任務開始前或結束後執行;各個任務可以並行也可以序列執行;更讚的是你可以預先定義一項任務,只在特定的拉取請求時被觸發,而且與之有依賴關係的任務並不會被執行,這能讓你的管道具有一定的隔離性:什麼時候被構造的工件應該被部署到生產環境,什麼時候應該被稽核。


以上只是我對這些 CI/CD 工具的簡單介紹,它們還有許多很酷的特性等待你深入探索。而且它們都是開源軟體,可以自由使用,去部署一下看看吧,究竟哪個才是最適合你的那個。