2020年 CI 工具選型指南

持續集成(Continuous integration,CI)是一種每天數次將所有開發人員的工作副本合併到一條共享主線上的實踐。聽起來,持續集成也沒有做很多事情,只是集成並自動化了一系列任務,以便所有開發人員的工作都可以每時每刻地進行合併。但其實持續集成中有很多門道,而且工具選型也有很多值得思考的地方。

談到 CI,就不得不說 Jenkins!

爲了幫助 DevOps 新手加深認識,我們先來快速回顧一下 Jenkins 的歷史:

Jenkins 起源於 Hudson 項目。Hudson 始於 2004 年夏天,由 Sun Microsystems 公司創建,於 2005 年 2 月在 java.net 中首次發佈。

在 2007 年前後,Hudson 成爲了 Cruise Control 和其他開源構建服務器的更好替代品。在 2008 年 5 月的 JavaOne 會議上,該軟件獲得了“開發人員解決方案”類別的“ Duke’s Choice Award。

2010 年 11 月,Oracle 收購了 Sun Microsystems 之後,Hudson 社區出現了一個有關其使用基礎設施的問題,這個問題逐漸擴展到對 Oracle 管理和控制的質疑。主要項目貢獻者和 Oracle 進行了談判,儘管在很多方面達成了一致,但關鍵的癥結在於商標名稱“ Hudson”,這是 Oracle 聲稱在 2010 年 12 月就擁有該名稱的權利並申請了商標。因此,在 2011 年 1 月,項目在投票之後將名稱從“Hudson”更改爲“Jenkins”。

Jenkins 歷史悠久,同時還有龐大的用戶羣,大家可能就有疑問了,使用 Jenkins 不就行了,爲什麼還要去找其它的 CI 工具呢?難道是 Jenkins 出現什麼問題了嗎?… 事實上,這個問題很難回答,但我認爲 Jenkins 沒有任何問題,甚至可以說任何 CI 工具都沒有錯。

CI 只是用於執行一些自動化任務的工具,可以與源代碼管理工具集成在一起,可以根據某些條件自動觸發作業,並執行一些可配置的命令。Jenkins 就是這樣做的,並且已經完美地做了 15 年了。

然而,這可能正是問題所在:

在 Hudson 以及 Jenkins 時代的初期,許多東西尚未被髮明,或者至少沒有被廣泛使用。比如,VM、公有云、容器、Kubernetes 等。因此,爲了處理我們現在使用的新功能,一個多年前設計的工具,如今必須依賴一些附加的組件和插件。

作爲 Jenkins 的管理員和用戶,我們必須要更瞭解 Jenkins,確切的知道某個插件做了什麼,正確的配置方法,甚至有時爲了正常運行 Jenkins,我們需要編寫的 CI 代碼比功能實現代碼更多。

CI 的目標是以自動化的方式進行頻繁地集成。如果我們花費了大量的時間來配置用於實現這一目標的工具,那麼它就沒什麼意義了。

舉個例子,爲了使 Jenkins Slave 服務器能夠在 Kubernetes 中運行,我們需要使用 Jenkins 的 Kubernetes 插件,並且需要配置:

/**
     * 這個管道描述了一個多容器作業,用於運行 Maven 和 Golang 構建
     */

    podTemplate(yaml: """
    apiVersion: v1
    kind: Pod
    spec:
      containers:
      - name: maven
        image: maven:3.3.9-jdk-8-alpine
        command: ['cat']
        tty: true
      - name: golang
        image: golang:1.8.0
        command: ['cat']
        tty: true
    """
      ) {

      node(POD_LABEL) {
        stage('Build a Maven project') {
          git 'https://github.com/jenkinsci/kubernetes-plugin.git'
          container('maven') {
            sh 'mvn -B clean package'
          }
        }

        stage('Build a Golang project') {
          git url: 'https://github.com/terraform-providers/terraform-provider-aws.git'
          container('golang') {
            sh """
            mkdir -p /go/src/github.com/terraform-providers
            ln -s `pwd` /go/src/github.com/terraform-providers/terraform-provider-aws
            cd /go/src/github.com/terraform-providers/terraform-provider-aws && make build
            """
          }
        }
      }
    }

簡而言之,爲了同時使用 Maven 和 Golang,必須先在管道代碼中定義容器。在本例中,定義命令將在何處運行的代碼行數幾乎與管道本身的代碼行數相同。在大多數情況下,如果我們將 Pod 作爲 Jenkins 的 Slave 運行,那麼可能需要第三個容器來存放 JNLP。

如果我們構建一個更復雜的管道,那麼它勢必會有更多的步驟,使用更多的工具,需要更多的容器。整個項目就會變得複雜無比,難以維護。

CI 工具選型的考慮事項

那麼問題來了,在選擇 CI 工具時,我們應該考慮哪些事項呢?一般來說,需要考慮以下幾點:

  • 易於安裝(如果不打算使用 SAAS/PAAS 解決方案)
  • 易於使用
  • SAAS/PAAS 解決方案
  • 安裝在雲上
  • 安裝在 K8s 上
  • 安裝在本地(on-premise)
  • 開源

作爲一款工具,易於使用是最重要的,只有這樣才能提高我們的工作效率。另外,它還要易於安裝,如果這個工具安裝很複雜,無法自動化或很難做到自動化,那麼它就不能很好地擴展到多個項目和環境中。對於小型團隊而言,他們根本不想維護自己的 CI,更傾向於使用現有的雲服務,而大型公司更希望自己控制 CI,無論是在雲上還是在本地。Kubernetes 現在如此熱門,用戶當然希望 CI 工具鏈作爲容器運行在 K8s 上,如果這個工具是開源的就更好了,還可以獲得更多的社區支持。

CI 工具的優劣勢對比

1 Jenkins

前文我們已經講過 Jenkins 了,Jenkins 是一款開源免費產品,在 GitHub 上有 1.5 萬顆 stars,同時也有很多人使用,如果在 Stack Overflow 中搜索 Jenkins,你會發現有超過 40 萬個問題。但正如前文所說,Jenkins 是一個很久之前設計的工具,如果想要兼容現在的架構,就必須依賴一些附加的組件和插件。

2 CircleCI

CircleCI 相對來說比較便宜,有免費計劃,易於使用(配置是基於 YAML 的,雖然並不是每個人都喜歡 YAML)並易於閱讀。

不推薦使用它的理由:

  • 有限的企業級部署選項:僅在具有 Terraform 的 AWS 中支持
  • 很難在本地部署
  • 不支持在 K8s 中部署
  • 核心組件是用 Clojure 編寫的,雖然很酷,但是使用羣體相對較少,而且 Clojure 也比 Java 慢

3 TeamCity

TeamCity 是一款使用 Java 編寫的免費產品。其缺點是如果要在 K8s 中將其作爲容器運行,那麼鏡像會很大。一般來說,由於 JRE/JVM 的存在,Java 應用程序不適合容器化。

4 Bamboo

Bamboo 是使用 Java 編寫的,是由澳大利亞公司 Atlassian 開發的產品,與 TeamCity 類似。

5 GitLab CI

GitLab CI 的優勢是支持在 Kubernetes 中創建 Runner,如果你的源代碼管理工具使用的不是 GitLab,那麼不建議 CI 工具選型 GitLab CI。

6 Buddy

如果使用 Buddy,那麼對於預置型本地(on-prem)安裝,需要按用戶數量付費,這可能會非常昂貴,考慮到有許多免費的開源選項,不建議選擇 Buddy。

7 TravisCI

Travis CI 是使用 Ruby 編寫的,性能不如 Java,而且本地 / 雲(on-premise/cloud)部署選項也很有限。

8 Codeship

Codeship 的“硬傷”在於不是開源產品,而且不能部署到雲或本地。

9 GoCD

GoCD,看到這個名字你可能會覺得它是使用 Go 語言編寫的,但實際上它是用 Java 和 Ruby 編寫的。同時,它也是一款免費開源軟件,支持 Kubernetes 部署。

唯一的缺點是不適合在 Kubernetes 中部署 Java 應用程序。

10 Wercker

Wercker 已經被 Oracle 收購了,使用 Go 語言編寫的。但是與其它 Go 語言編寫的開源項目相比,Wercker 的 stars 數很少,我猜它的用戶基數應該很少。

11 Drone

Drone 是一款開源產品,GitHub 上的 stars 數超過了 2 萬,鏡像較小,使用 Go 語言編寫,支持雲、本地和 Kubernetes 部署,尤其適合運行在 Kubernetes 上,並能與 Kubernetes 進行很好的集成,例如在 CI 作業中使用的 secrets 可以作爲 secret 存儲在 K8s 中。

Drone 沒有明顯缺點,如果硬要說一個的話,我覺得它的示例 / 官方文檔還不是很完善。

12 Semaphore

直到今天,Semaphore 仍然沒有開源,也不支持本地(on-prem)部署。

13 Nevercode

Nevercode 也不是開源產品,同時不支持本地部署。

14 Spinnaker

Spinnaker 是由 Netflix 創建的開源產品,支持多雲。在功能方面基本沒有缺點,唯一遺憾的是在 K8s 上進行本地試運行部署,它需要拉取很多鏡像,安裝起來非常緩慢,並且它是用 Java 編寫的。

15 Buildbot

Buildbot 是用 Python 編寫的,易於閱讀,性能不如比 Java/Golang,stars 比其他選項少,主頁的 UI也不是很好,我個人是不會信任那些對自己的臉面都不關注的人的。

https://buildbot.net/

16 Bitrise

Bitrise 似乎是專門爲移動應用程序設計的,可能不適用於一般用途,而且它也不是開源的。

17 CodePipeline/CodeBuild

這兩款產品都是由 AWS 開發的,出於供應商鎖定的考慮,我會擔心這個項目無法遷移到其它雲供應商,因此建議謹慎使用。

結論

截至 2020 年,市場上的 CI 工具肯定有超過 17 種,當然本文可能也會遺漏一些比較出名的 CI 工具,例如 Google CloudBuild。但是工具選型沒有放之四海而皆準的規則,每個人的新需求也不同,大家可以根據我們提到的考慮事項逐條考慮。

當然,在最後我還是想總結一下關於 CI 工具選型的內容:

  • 對很多人來說,CircleCI 或 TravisCI 已經足夠好了,也沒有很大的缺點;
  • 對於那些追求敏捷和快速的人來說,drone.io 可能更適合,因爲它易於安裝、配置、使用,它能靈活地部署在本地並能在雲上使用,適合更廣泛的受衆。同時它是開源的,在 GitHub 上很受歡迎,也有很好的社區支持,並且它具有云原生 /12 要素應用(cloud-native/12-factor-app)的屬性:鏡像小,設置迅速,用 Golang 編寫的,與 Ruby/Python 等編寫的某些選項相比,具有更高的性能。
  • 不過,對於大多數人來說,Jenkins 仍然是一個不錯的選擇,因爲它非常靈活,可以彌補了配置方面的相對複雜性。儘管 Jenkins 使用的是 Java,不適合在 K8s 上運行,但與其他選項相比,它並不差。
  • 如果您使用 Jenkins 有痛點的話,可以嘗試 Travis/Circle/Drone。

原文鏈接:

An Introduction to CI, with Comparison of 17 Major CI Tools in 2020, and How to Choose the best CI

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章