Argo Workflows是一个用于在Kubernetes上编排并行作业的开源容器本地工作流引擎。Argo Workflows以Kubernetes CRD(自定义资源定义)的形式实现。主要特性:
安装过程较为简单,安装脚本执行完毕后,会在指定的namespace下多出两个pod
root@argo-control-plane:/# kubectl get po -n argo
NAME READY STATUS RESTARTS AGE
argo-server-5974946f76-5h9bt 1/1 Running 2 (16h ago) 16h
workflow-controller-f58c79-ljtff 1/1 Running 2 (16h ago) 16h
实际上它们是两个deployment管理的pod,分别对应controler和server,前者负责所有协调工作,后者提供 API 服务,比如一些web hook和事件监听机制。
argo 将所有的 workflow 存储到 etcd 中,不依赖 MySQL等数据库,因此在上述列表中没有存储相关的POD。此机制会限制每个resource最多占用1MB的空间,如果经压缩后依然超过1MB,argo会尝试放到别处,比如SQL 数据库里。所以在argo的config map中有一个可选参数,用于配置SQL存储服务,支持PostgressSQL或MySQL,如果未配置,那么此时就会触发一个“offload node status is not supported”错误。配置如下:
#at: https://argoproj.github.io/argo-workflows/workflow-controller-configmap.yaml
# Optional config for mysql:
# mysql:
# host: localhost
# port: 3306
# database: argo
# tableName: argo_workflows
# userNameSecret:
# name: argo-mysql-config
# key: username
# passwordSecret:
# name: argo-mysql-config
# key: password
有两种方式可以操作argo,CLI或web页面。给argo-server配置好端口转发后,可以通过浏览器访问:

工作流(workflow)及其生成的容器运行在哪个ns下,取决于安装时的配置,采用默认的安装方式,则其都会在argo下执行。比如提交了quick start页的示例workflow并等待其完成之后,可以看到argo下多了一个pod:
NAME READY STATUS RESTARTS AGE
argo hello-world-s6d5s 0/2 Completed 0 36h
argo的设计架构可以参考这里 argo: architecture ,每个Step和每个DAG Task都会生成一个Pod,每个Pod由3个容器组成:

控制器架构

示例:
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: hello-world- # Name of this Workflow
spec:
entrypoint: whalesay # Defines "whalesay" as the "main" template
templates:
- name: whalesay # Defining the "whalesay" template
container:
image: docker/whalesay
command: [cowsay]
args: ["hello world"] # This template runs "cowsay" in the "whalesay" image with arguments "hello world"
要执行的工作流程在Workflow.spec(注意首字母大写)字段中定义。工作流规范的核心结构是一个列表templates和一个entrypoint.
templates可以粗略地认为是“函数”:它们定义要执行的指令。该entrypoint字段定义“主”函数是什么——即将首先执行的模板。
其中template有6种类型,分属两个类别:
定义一个容器,规范与Kubernetes 容器规范相同:
- name: whalesay
container:
image: docker/whalesay
command: [cowsay]
args: ["hello world"]
规范与容器相同,但添加了允许就地定义脚本的字段:source。该脚本将保存到文件中并为您执行。根据调用方式不同,脚本的结果会自动导出到Argo 变量,或{{tasks..outputs.result}}或{{steps..outputs.result}}。
- name: gen-random-int
script:
image: python:alpine3.6
command: [python]
source: |
import random
i = random.randint(1, 100)
print(i)
不同于k8s的资源,这里定义的是直接对集群资源执行的操作。可用于获取、创建、应用、删除、替换或修补集群上的资源。
此示例在集群上创建一个ConfigMap:
- name: k8s-owner-reference
resource:
action: create
manifest: |
apiVersion: v1
kind: ConfigMap
metadata:
generateName: owned-eg-
data:
some: value
挂起模板将挂起执行一段时间或直到手动恢复。可以从 CLI(使用argo resume)、API 端点或 UI 恢复挂起的模板,个人理解可以用于debug或者特殊情况下的同步。
- name: delay
suspend:
duration: "20s"
step模板通过一系列步骤定义任务。模板的结构是“列表的列表”。外部列表将顺序运行,内部列表将并行运行。想逐一运行内部列表,可以使用同步功能。也可以设置多种选项来控制执行,例如when:有条件地执行步骤的子句。
在此示例中,step1首先运行。一旦完成,step2a将step2b并行运行:
- name: hello-hello-hello
steps:
- - name: step1
template: prepare-data
- - name: step2a
template: run-data-first-half
- name: step2b
template: run-data-second-half
定义依赖关系:
- name: diamond
dag:
tasks:
- name: A
template: echo
- name: B
dependencies: [A]
template: echo
- name: C
dependencies: [A]
template: echo
- name: D
dependencies: [B, C]
template: echo
此外,在argo workflow的用户指南中,还有几种特殊的 template types。
在官方示例中根据inputs.parameters中的url参数发起了一个请求。至于如何将HTTP的response保存到argo变量或输出输入的产物中,没找到相关介绍;对于异常捕获、重试机制也未有提及。此类模板完全可以通过Script或Container模板替代。
在一个pod中定义多个容器,以安排到同一台主机上执行。 优点:
主要的缺点是开销比DAG大,原因有以下几点:
该POD申请的资源为所有容器申请的总和,如果有依赖关系,则某些容器在等待的时候,也占用资源
所有容器都并行启动,等到某些依赖关系满足时,argo才会在容器中启动主进程
Data Sourcing and Transformations
用于将一些外部资源引入到workflow当中,并且可以插入一些数据转换的操作