任务比如 k8s 概念中的 job,一般指的是短期的会结束的一个离线任务,而人物流就是将一组任务组织起来的流程。比如下面的这个流程。
最早接触任务流工具应该是在 jenkins, 实际上 CI/CD 也是任务流最常见的场景之一,不过 jenkins 并不局限于 ci/cd (大部分 ci/cd 工具也是这种设计,采用 通用工作流 + 业务插件的形式支持具体的业务)
jenkins 的任务流有几种表达方式
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Build') {
steps {
//
}
}
stage('Test') {
steps {
//
}
}
stage('Deploy') {
steps {
//
}
}
}
}
Jenkinsfile (Scripted Pipeline)
node {
stage('Build') {
//
}
stage('Test') {
//
}
stage('Deploy') {
//
}
}
事实上 Jenkins 还是 CI/CD 领域应用最多的任务流工具,其强大的社区,各种强大的插件体系,使得他在十多年后依然不过时( Jenkins 的前身 Hudson 是在 2004 发布的),最近几年 Jenkins 又支持了 容器,K8S 的支持,使得他依然是这个领域最好用的工具。
在这个领域的的工具还有很多,比如在 github 上就内置了官方的 github actions工具,circle ci 等等,在这个 容器盛行的时代,构建这样一个 CI/CD 工具远没有当年构建 Jenkins 的门槛那么高了,相关的一些基于容器、K8S 主打灵活,高性能的开源工作流工具也层出不穷。
drone 是容器时代的任务流工具中最有代表性的开源工具之一,他的任务流的表达方式和其他同时期的产品非常类型,都是 yaml 的形式。顺应时代,drone 支持在 docker, kubernetes 或者直接利用 ssh 方式运行,不过我们这里只关注 docker 和 kubernetes 类型。
name: default
kind: pipeline
type: docker
steps:
- name: backend
image: golang
commands:
- go get
- go build
- go test
- name: frontend
image: node:6
commands:
- npm install
- npm test
- name: publish
image: plugins/docker
settings:
repo: octocat/hello-world
tags: [ 1, 1.1, latest ]
registry: index.docker.io
- name: notify
image: plugins/slack
settings:
channel: developers
username: drone
argo 和 Tekton 都是 Kubernetes 原生的工具,两者的实现上也很类似。
argo 的也是用 yaml 描述工作流,除了传统的 dag 模式,argo 也支持 workflow 模式。相比而言,dag 模式一般比较简单,大部分 ci/cd 场合也比较够用,实现的事情用下面的 几行代码 就可以描述
start
for node in nodes:
if all(node's dependency is done):
do(node)
done
而 workflow 模式则是一个状态机, workflow 模式的实现更为复杂,也更灵活。用这种模式可以实现有环的任务,比如 执行一个任务,直到某条件满足。
if node's State is not start:
start(node)
if node's State is not done:
do(node's Next)
下面是 argo workflow 的一个具体例子
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: steps-
spec:
entrypoint: hello-hello-hello
# This spec contains two templates: hello-hello-hello and whalesay
templates:
- name: hello-hello-hello
# Instead of just running a container
# This template has a sequence of steps
steps:
- - name: hello1 # hello1 is run before the following steps
template: whalesay
arguments:
parameters:
- name: message
value: "hello1"
- - name: hello2a # double dash => run after previous step
template: whalesay
arguments:
parameters:
- name: message
value: "hello2a"
- name: hello2b # single dash => run in parallel with previous step
template: whalesay
arguments:
parameters:
- name: message
value: "hello2b"
# This is the same template as from the previous example
- name: whalesay
inputs:
parameters:
- name: message
container:
image: docker/whalesay
command: [cowsay]
args: ["{{inputs.parameters.message}}"]
argo 的 workflow 里面也是类似 drone,step 由容器实现,并且做得更为直接。
在 argo 上,kubeflow 社区就实现了针对机器学习领域的 pipeline 工具 KubeFlow-Pipeline
更多关于 argo 的原理可以参考这篇文章
tekton 来自Knative的build模块 做的事情和 argo 也大同小异,他扩展比较灵活,可以用来快速定制实现所需功能。tekton 的描述语法例子如下
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: echo-hello-world
spec:
steps:
- name: echo
image: ubuntu
command:
- echo
args:
- "Hello World"
除了 task,tekton 还定义了 如 PipelineResource, TaskRun 等多种资源,描述性语法。目前由于实现原理的限制(通过扩展 kubernetes api resources,watch 资源变化实现,类似 operator),决定了 argo 和 tekton 都不能水平扩容,这一点限制了系统的 scale 能力,吞吐量有一定限制,但是对于 ci/cd 的场景,应该是很够用了。
关于 tekton 的特点,这篇文章 做了详细的对比
brigade 也是一个基于 kubernetes 的 pipeline 工具,作者是大名鼎鼎的 helm(公司被微软收购) 的作者,这个工具值得一提的原因是其设计非常有趣,他的语法不使用常见的 yaml 描述,而是采用 js 的方式描述。比如下面这个例子。
const { events, Job } = require("brigadier");
events.on("simpleevent", (e, p) => { // handler for a SimpleEvent
var echo = new Job("echosimpleevent", "alpine:3.8");
echo.tasks = [
"echo Project " + p.name,
"echo event type: $EVENT_TYPE",
"echo payload " + JSON.stringify(e.payload)
];
echo.env = {
"EVENT_TYPE": e.type
};
echo.run();
});
由于 kubernetes 对于部署和标准化环境的控制,以及 kubenetes 提供基础设施的强大能力,使得在 kubernetes 上实现类似的工具变得门槛很低,笔者也在早年也做过类似的玩具项目 https://github.com/arlert/kubepipe,看一下他的语法,是不是更 tekton/argo 有些相似呢。
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
restartPolicy: Never
containers:
- name: c
image: alpine
command: ["sh", "-c", "echo running pod1"]
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
restartPolicy: Never
containers:
- name: c
image: alpine
command: ["sh", "-c", "echo running pod2"]
---
apiVersion: v1
kind: Pod
metadata:
name: pod3
spec:
restartPolicy: Never
containers:
- name: c
image: alpine
command: ["sh", "-c", "echo running pod3"]
---
apiVersion: v1
kind: Pipe
metadata:
name: pipe
spec:
stages:
- name: stage1
jobs:
- pod1
- name: stage2
jobs:
- pod2
- name: stage3
jobs:
- pod3
上面讲的工具大部分是 pipeline工具,使用的场景也在 ci/cd 上(尽管大部分工具实际也可以用来干别的事情),这种工具非常多,各大云厂商也提供了各种 workflow/pipeline 引擎比如 aws的 Simple WorkFlow,AWS Step Functions,Azure的 Pipeline 服务,ML Pipeline。
成熟的任务流引擎,应该有如下4层架构(图和分层方式来自 https://juejin.im/post/5ee2f6ece51d457848686ef8)
选择或者实现一个任务流引擎的时候需要从这四方面判断它的优劣,比如大部分开源工具 在第一层和第二层的支持较好,但是 argo 和 tekton 不能水平扩容,第三层的实现有些不足。同时 这两个工具又局限于 kubernetes 语境,其第四层的设计也比较局限。不过第四层的设计一般取决于具体的场景,比如在云上,云厂商首先会支持一个通用 serveless 函数,在机器学习平台,会支持运行一个 spark 任务等等。
由于任务流工具应用的广阔场景,CNCF 也忍不住指定了基于云原生的 workflow 标准。
看下 cncf 的 spec 可以看出 cncf的标准指定得还是比较复杂, 支持 subflow,foreach,delay, paralle 等特性,而云产商如 aws 实现的类似产品 spec 则更为简单. 目前还没有知名的 cncf 标准的 workflow 实现出现,不过可以预期,以 cncf 的影响力,类似的开源项目很快就会出现,这个领域还有很多机会。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。