Skip to content

Latest commit

 

History

History
 
 

CI-CD

CI/CD - 持续集成与持续部署

当下 CI/CD 工具众多,有开源的也有 Online 的,有的复杂但功能强大(Jenkins),有的虽然简单却也五脏俱全。

功能强大(大而全),可能也意味着更高的学习使用成本。 另外新出的很多 CI/CD 是完全 GitOps 的,算是小而美,使用简单,但是某些功能可能就无法通过它们实现(比如定时任务、手动指定参数进行构建等)。

可以考虑使用一个功能强大的 CI/CD 工具 hold 住全场,也可以组合一些小而美的 CI/CD 工具实现需求。 想知道具体要应该选择哪些 CI/CD 工具,就需要先分析清楚自己的需求,以及各工具都提供了什么东西给我们。

CI/CD 功能对比

1. Jenkins

Jenkins 无疑是目前市面上最强大的 CI/CD 工具,可以 hold 住绝大部分的 CI/CD 使用场景。

它使用 Jenkins Pipeline 编写任务流程,有众多插件支持各类 CI/CD 功能。

每个任务都提供多种构建方式:

  1. 手动设定参数,启动构建。
  2. 定时使用默认参数构建,可用于各类定时任务。
  3. 通过 webhook 等方式启动构建,常用于让 Git 操作自动触发构建。
  4. 通过 http api 启动构建,适合于 python 等编程使用。

可以使用 Jenkins+Python 代码,打造出一个自动化运维平台。包含:

  1. 前后端代码的 CI/CD
  2. 自动化测试平台,通过定时任务进行自动化测试,使用 ningx/ftp 仓库进行测试记录的保存与查看,通过邮件通知或钉钉插件实现告警,。
  3. 运维平台:提供数据定时清理、服务器维护、k8s集群维护、其他资源维护等等运维功能。
    1. 比如通过 Jenkins 调用 ansible/terraform/kubeadm 等工具,进行服务器/云资源/kubernetes集群的维护。

但是 Jenkins 也存在很多问题,详见 Jenkins Notes

因为 Jenkins 本身的这些问题,我目前正在寻找替代方案——能不能用多个工具来实现上述的所有功能。

2. Gitlab-CI

Gitlab 去年相比 Jenkins 还有很多欠缺,今年(2020)加入了多项新功能,也许有希望替换掉 Jenkins:

  1. Multi-project pipelines(仅付费版): 同一个 Git 仓库可以有多个独立的 Pielines
  2. Parent-Child Pipelines:可以实现层次化的 CI/CD

另外 Gitlab-CI 和 Gitlab 无缝融合,CI/CD 很方便。

Gitlab-CI 也支持定时任务、通过 API 运行 Pipeline(可自定义参数)等功能。原生支持通过邮件发送通知。

和 Jenkins 区别比较大的地方,是它没有「视图-文件夹-任务」这样的层次结构,所有的 Pipeline 其实都是附属于一个 Git 仓库的。 而且每个 git 仓库只能有一个 .gitlab-ci.yaml 文件。。。

这样的话一些批量构建的任务,可能只能附在运维代码仓库上,这导致所有的流水线都非常分散。而且好像没有一个地方可以查看所有的流水线状态。

对拥有大量流水线的团队而言,如此分散的流水线很可能也意味着难以维护。 对前后端开发人员而言,使用体验可能也并不是很好,尤其是各个仓库之间有依赖关系的情况下。

另外感觉 Gitlab CI 不太适合用于搭建自动化测试平台和运维平台,因为:

  1. 一个仓库貌似只能有一个流水线?不能定义多个。
  2. 流水线依附于 Git 仓库太散乱,没有统一的使用平台。

Drone 是目前 Github 上最火的 CICD 项目,它以容器为核心,每个构建步骤都可以使用不同的容器镜像。 不过它在某些方面实现地比较简单,导致它无法胜任复杂场景:

  1. 它不支持 Gitlab 的多层目录结构,只支持 Github 式的单层目录。
  2. 流水线完全没有任何分类,我们有数量众多的流水线,不分类不方便管理。
  3. 它被设计为一个简单的应用构建平台,不支持 Workflow 等功能。
    1. 也就是说,用它来实现自动化测试平台、运维平台,可能是「歪门邪道」hhh

5. 云原生流水线 - Tekton/Argo Workflows

Tekton 和 Argo 都是用 Kubernetes 自定义资源来声明流水线的项目,值得研究。

各大厂(京东、字节跳动)目前好像都是选择了 tekton 来搭建自己的 CI/CD 平台,替换掉陈旧的 jenkins, 因为 tekton 对 CI/CD 来说功能刚好够用,也能很方便地以它为基础做一些自定义。

另外我也很看好功能比 tekton 更强大的 Argo Workflows,阿里云目前有深度使用这个工具。

argo 和 tekton 的 UI 面板,目前来说功能都比较弱,而且和 Kubernetes 结合比较紧密,对不了解 kuberentes 的人员而言就不太友好。

不过我觉得它们肯定是未来。

6. Jenkins-X

Jenkins-X 的部署太复杂了,比 Istio 还要复杂得多。 尤其是在国内的特殊网络环境下,我尝试部署了很多次,一次都没成功。。。

而且到现在它仍然没有一个很好的 UI 界面,重度依赖 cli,显然目前并不适合替代我们的「自动化运维平台 - Jenkins」

我想要的 CI/CD 特性

1. 声明式语法

声明式语法使我们专注于具体的 CI/CD 流程,不再需要考虑实现细节。 这其实就是分离了关注点,底层的实现让别人去考虑,而我可以专注于 CI/CD 流程。

我很喜欢声明式语法,Kubernetes 的配置本身也是声明式的。 但是在 CI/CD 中,目前 jenkins pipeline 的声明式语法还是有诸多问题,越用越是不喜欢。

声明式语法需要注意的问题:

  1. 错误提示一定要清晰:有些工具(Jenkins)因为使用了声明式语法,报错时直接抛出底层异常,让使用者不知所云,体验极差。
  2. 语法检查与补全:Jenkins 的 DSL 基本没有什么好的语法检查工具,只能靠肉眼 Debug.
    1. 目前看来最佳的流水线语言应该是 yaml

1.2 流水线的重用/集中式管理

另外很多项目的流水线往往是同质化的,没有任何区别,或者只有少量区别。 这部分流水线分散在所有的 Git 仓库中,但都是由运维团队统一维护的。

对于运维人员来说,如果能重用这部分流水线,或者集中式管理它们,就很棒了。 或者说,同一个工作流可以输入不同的 Git 仓库,这样也能实现流水线的重用(但是这种方式,可能导致各种仓库的构建历史混杂在一起,没法查看)。

2. Python/Go SDK / RESTful API / CLI

CI/CD 工具需要提供一个良好的 Python/Go SDK 或者 RESTful API,供开发者进行更高阶的操作。 比如说设计更高级的 Pipelines 调度方式,自动检测流水线的状态,自动重试等。

3. Kubernetes/Docker 支持

最好要能集成 Kubernetes/Docker,方便快捷地扩缩容构建节点,也能更方便地完成高可用部署。

4. 缓存/数据卷

在容器化的 CI/CD 工具中,每次构建都是全新的容器环境。 这避免了因为长期使用导致的环境混乱,但是也导致构建缓存无法重用,构建速度变慢。

这类 CI/CD 工具应该提供友好的缓存重用方案,避免因为使用了先进的工具,构建速度变慢的问题。

5. 定时任务

一个完善的 CI/CD 平台,定时任务是不可或缺的。

6. 手动触发构建,并且支持自定义参数

因为我们的运维代码比较多,而且通用性很高,目前是分类存放在多个专用 Git 仓库中的。 有时候后端的 Git 仓库没有变更,但是修改了运维 Git 仓库的代码,就需要手动触发构建。

另外我们每个开发测试人员都有自己的 kuberntes namespace,他们需要按需部署某些服务到自己的 namespace 来测试。 开发人员需要构建部署某个测试分支的时间不能预测,因此这是一个只能手动触发的任务,而且还需要给出自定义参数「Git 仓库位置」和「测试分支」。

还有一个需要通过 API 自动触发构建的重要场景,是更新依赖包。 csharp/golang 这两种语言的依赖包更新后,需要手动修改 csrpoj/go.mod 中的依赖版本号。 但是数百个仓库的依赖包需要更新,每次都手动修改过于繁琐。我们需要批量自动化的依赖版本更新。

上述的功能,目前通过 Jenkins 都能实现,但是很多新潮的基于 Git 仓库 Web_Hook 的 CI/CD 工具,貌似都不支持手动触发构建。

6.1 Git 仓库的 Web_Hook 可靠性如何?

假设 Web_Hook 被触发时突然断网了,或者 CI/CD 系统宕机了。 这个 Git 仓库的 CI/CD 任务没执行成功,有没有什么显眼的通知? 如果这个错误就这样藏起来了,镜像或者 Library 没更新,可能会导致很严重的问题(比如测试人员使用旧版本做测试,测试不完全时甚至可能导致旧版本直接上了生产环境)。

Web Hook 在触发失败时,最起码得有一个明显的错误信息,能提示到 DevOps 人员。 其次 Web Hook 的回调触发成功后,CI/CD 这边就需要保证构建任务能被触发!出了问题也必须出现明显的提示。

7. 友好 UI 界面

CI/CD 流水线主要是提供给前后端人员使用的,因此需要一个友好的 UI 界面给他们使用。

7.1 流水线的分类(Group/Category)

常见的微服务项目,往往会拆分成众多 Git 仓库(微服务)进行开发,众多的 Git 仓库会使我们创建众多的 CI/CD 流水线。 如果没有任何的分类,这一大堆的流水线如何管理,就成了一个难题。

最显见的需求:前端和后端的流水线最好能区分一下,往下细分,前端的 Web 端和客户端最好也能区分,后端的业务层和中台最好也区分开来。

另外我们还希望将运维、自动化测试相关的任务也集成到这个系统中来(目前我们就是使用 Jenkins 完成运维、自动化测试任务的), 如果没有任何分类,这一大堆流水线将混乱无比。

注:或者说,创建多个 CI/CD 实例,前后端、运维、测试分别使用不同的实例?

8. Go/Python 语言编写

最好是使用 Go/Python 编写的,方便我们自己深入底层去了解它的内部逻辑。

9. 支持复杂的「任务编排」

能够将多个 Pipelines/Workflows/Jobs 通过一些手段编排起来,实现按依赖顺序分批地运行流水线等高级功能。

总结

翻遍 Github 上的 CI/CD/Pipeline 项目,发现目前最符合我期望的是:Argo Workflows,正在深入调研。

画外

我发现 CI/CD 工具、机器学习的 Workflow 工具、运维领域的 task 调度工具,它们都存在一个共性:一次性任务、支持定时触发、手动触发,还有失败重试等功能。

  • 任务调度系统:就如 xxl-job 之类的工具,提供友好的 UI 界面,支持 shell/python 等多种语言。运行的任务 Job/Task 通常都比较简单。
  • CI/CD 工具:如 Jenkins/Gitlab-CI/Tekton 这类工具,它的调度单位是流水线 Pipeline,通常由多个 Task 组成。也就是说要比 Task 复杂一些。
  • 机器学习工作流 Workflow: 如 Argo/Airflow,这东西支持通过 DAG 定义 Task 之间的依赖关系来完成编排,功能比 CI/CD 工具要更复杂/强大一些。

这三种工具,貌似主要的区别,只在于调度的粒度不同而已。 Workflow 最复杂也最强大,CI 工具居中,Job 调度系统最简单。