持续集成(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,更倾向于使用现有的云服务,而大型公司更希望自己控制 CI,无论是在云上还是在本地。Kubernetes 现在如此热门,用户当然希望 CI 工具链作为容器运行在 K8s 上,如果这个工具是开源的就更好了,还可以获得更多的社区支持。
1 Jenkins
前文我们已经讲过 Jenkins 了,Jenkins 是一款开源免费产品,在 GitHub 上有 1.5 万颗 stars,同时也有很多人使用,如果在 Stack Overflow 中搜索 Jenkins,你会发现有超过 40 万个问题。但正如前文所说,Jenkins 是一个很久之前设计的工具,如果想要兼容现在的架构,就必须依赖一些附加的组件和插件。
2 CircleCI
CircleCI 相对来说比较便宜,有免费计划,易于使用(配置是基于 YAML 的,虽然并不是每个人都喜欢 YAML)并易于阅读。
不推荐使用它的理由:
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也不是很好,我个人是不会信任那些对自己的脸面都不关注的人的。
16 Bitrise
Bitrise 似乎是专门为移动应用程序设计的,可能不适用于一般用途,而且它也不是开源的。
17 CodePipeline/CodeBuild
这两款产品都是由 AWS 开发的,出于供应商锁定的考虑,我会担心这个项目无法迁移到其它云供应商,因此建议谨慎使用。
截至 2020 年,市场上的 CI 工具肯定有超过 17 种,当然本文可能也会遗漏一些比较出名的 CI 工具,例如 Google CloudBuild。但是工具选型没有放之四海而皆准的规则,每个人的新需求也不同,大家可以根据我们提到的考虑事项逐条考虑。
当然,在最后我还是想总结一下关于 CI 工具选型的内容:
原文链接:
An Introduction to CI, with Comparison of 17 Major CI Tools in 2020, and How to Choose the best CI
领取专属 10元无门槛券
私享最新 技术干货