什么是Argo Workflows?
Argo Workflows是一个开源项目,为Kubernetes提供container-native工作流程,其主要通过Kubernetes CRD实现的。
特点如下:
- 工作流的每一步都是一个容器
- 将多步骤工作流建模为一系列任务,或者使用有向无环图(DAG)描述任务之间的依赖关系
- 可以在短时间内轻松运行用于机器学习或数据处理的计算密集型作业
- 在Kubernetes上运行CI/CD Pipeline,无需复杂的软件配置
安装
安装控制器端
Argo Wordflows的安装非常简单,直接使用以下命令安装即可。
kubectl create ns argo kubectl apply -n argo -f https://raw.githubusercontent.com/argoproj/argo-workflows/stable/manifests/quick-start-postgres.yaml
安装完成后,会生成以下4个pod。
# kubectl get po -n argo NAME READY STATUS RESTARTS AGE argo-server-574ddc66b-62rjc 1/1 Running 4 4h25m minio 1/1 Running 0 4h25m postgres-56fd897cf4-k8fwd 1/1 Running 0 4h25m workflow-controller-77658c77cc-p25ll 1/1 Running 4 4h25m
其中:
- argo-server是argo服务端
- mino是进行制品仓库
- postgres是数据库
- workflow-controller是流程控制器
然后配置一个server端的ingress,即可访问UI,配置清单如下(我这里使用的是traefik):
apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: argo-ui namespace: argo spec: entryPoints: - web routes: - match: Host(`argowork-test.coolops.cn`) kind: Rule services: - name: argo-server port: 2746
UI界面如下:
再配置一个minio的ingress,配置清单如下:
apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: minio namespace: argo spec: entryPoints: - web routes: - match: Host(`minio-test.coolops.cn`) kind: Rule services: - name: minio port: 9000
UI界面如下(默认用户名密码是:admin:password):
安装Client端
Argo Workflows提供Argo CLI,其安装方式也非常简单,如下:Linux系统:
# Download the binary curl -sLO https://github.com/argoproj/argo/releases/download/v3.0.0-rc4/argo-linux-amd64.gz # Unzip gunzip argo-linux-amd64.gz # Make binary executable chmod +x argo-linux-amd64 # Move binary to path mv ./argo-linux-amd64 /usr/local/bin/argo
安装完成后,使用以下命令校验是否安装成功。
# argo version argo: v3.0.0-rc4 BuildDate: 2021-03-02T21:42:55Z GitCommit: ae5587e97dad0e4806f7a230672b998fe140a767 GitTreeState: clean GitTag: v3.0.0-rc4 GoVersion: go1.13 Compiler: gc Platform: linux/amd64
其主要的命令有:
list 列出工作流 logs 查看工作流的日志 submit 创建工作流 watch 实时监听工作流 get 现实详细信息 delete 删除工作流 stop 停止工作流
更多命令可以使用argo --help
进行查看。
然后可以使用一个简单的hello world的WorkFlow,如下:
apiVersion: argoproj.io/v1alpha1 kind: Workflow metadata: generateName: hello-world- labels: workflows.argoproj.io/archive-strategy: "false" spec: entrypoint: whalesay templates: - name: whalesay container: image: docker/whalesay:latest command: [cowsay] args: ["hello world"]
使用如下命令创建并观察workflow。
$ argo submit -n argo helloworld.yaml --watch
然后可以看到以下输出。
Name: hello-world-9pw7v Namespace: argo ServiceAccount: default Status: Succeeded Conditions: Completed True Created: Mon Mar 08 14:51:35 +0800 (10 seconds ago) Started: Mon Mar 08 14:51:35 +0800 (10 seconds ago) Finished: Mon Mar 08 14:51:45 +0800 (now) Duration: 10 seconds Progress: 1/1 ResourcesDuration: 4s*(1 cpu),4s*(100Mi memory) STEP TEMPLATE PODNAME DURATION MESSAGE ✔ hello-world-9pw7v whalesay hello-world-9pw7v 5s
还可以通过argo list来查看状态,如下:
# argo list -n argo NAME STATUS AGE DURATION PRIORITY hello-world-9pw7v Succeeded 1m 10s 0
使用argo logs来查看具体的日志,如下:
# argo logs -n argo hello-world-9pw7v hello-world-9pw7v: _____________ hello-world-9pw7v: < hello world > hello-world-9pw7v: ------------- hello-world-9pw7v: \ hello-world-9pw7v: \ hello-world-9pw7v: \ hello-world-9pw7v: ## . hello-world-9pw7v: ## ## ## == hello-world-9pw7v: ## ## ## ## === hello-world-9pw7v: /""""""""""""""""___/ === hello-world-9pw7v: ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~ hello-world-9pw7v: \______ o __/ hello-world-9pw7v: \ \ __/ hello-world-9pw7v: \____\______/
核心概念
Workflow
Workflow是Argo中最重要的资源,其主要有两个重要功能:
- 它定义要执行的工作流
- 它存储工作流程的状态
要执行的工作流定义在Workflow.spec
字段中,其主要包括templates
和entrypoint
,如下:
apiVersion: argoproj.io/v1alpha1 kind: Workflow metadata: generateName: hello-world- # Workflow的配置名称 spec: entrypoint: whalesay # 解析whalesay templates templates: - name: whalesay # 定义whalesay templates,和entrypoint保持一致 container: # 定义一个容器,输出"helloworld" image: docker/whalesay command: [cowsay] args: ["hello world"]
Templates
templates是列表结构,主要分为两类:
- 定义具体的工作流
- 调用其他模板提供并行控制
定义具体的工作流
定义具体的工作流有4种类别,如下:
- Container
- Script
- Resource
- Suspend
Container
container是最常用的模板类型,它将调度一个container,其模板规范和K8S的容器规范相同,如下:
- name: whalesay container: image: docker/whalesay command: [cowsay] args: ["hello world"]
Script
Script是Container的另一种包装实现,其定义方式和Container相同,只是增加了source
字段用于自定义脚本,如下:
- name: gen-random-int script: image: python:alpine3.6 command: [python] source: | import random i = random.randint(1, 100) print(i)
脚本的输出结果会根据调用方式自动导出到{{tasks.<NAME>.outputs.result}}
或{{steps.<NAME>.outputs.result}}
中。
Resource
Resource主要用于直接在K8S集群上执行集群资源操作,可以 get, create, apply, delete, replace, patch集群资源。如下在集群中创建一个ConfigMap类型资源:
- name: k8s-owner-reference resource: action: create manifest: | apiVersion: v1 kind: ConfigMap metadata: generateName: owned-eg- data: some: value
Suspend
Suspend主要用于暂停,可以暂停一段时间,也可以手动恢复,命令使用argo resume
进行恢复。定义格式如下:
- name: delay suspend: duration: "20s"
调用其他模板提供并行控制
调用其他模板也有两种类别:
- Steps
- Dag
Steps
Steps主要是通过定义一系列步骤来定义任务,其结构是"list of lists",外部列表将顺序执行,内部列表将并行执行。如下:
- name: hello-hello-hello steps: - - name: step1 template: prepare-data - - name: step2a template: run-data-first-half - name: step2b template: run-data-second-half
其中step1和step2a是顺序执行,而step2a和step2b是并行执行。
还可以通过When
来进行条件判断。如下:
apiVersion: argoproj.io/v1alpha1 kind: Workflow metadata: generateName: coinflip- spec: entrypoint: coinflip templates: - name: coinflip steps: - - name: flip-coin template: flip-coin - - name: heads template: heads when: "{{steps.flip-coin.outputs.result}} == heads" - name: tails template: tails when: "{{steps.flip-coin.outputs.result}} == tails" - name: flip-coin script: image: python:alpine3.6 command: [python] source: | import random result = "heads" if random.randint(0,1) == 0 else "tails" print(result) - name: heads container: image: alpine:3.6 command: [sh, -c] args: ["echo \"it was heads\""] - name: tails container: image: alpine:3.6 command: [sh, -c] args: ["echo \"it was tails\""]
提交这个Workflow,执行效果如下:
除了使用When进行条件判断,还可以进行循环操作,示例代码如下:
apiVersion: argoproj.io/v1alpha1 kind: Workflow metadata: generateName: loops- spec: entrypoint: loop-example templates: - name: loop-example steps: - - name: print-message template: whalesay arguments: parameters: - name: message value: "{{item}}" withItems: - hello world - goodbye world - name: whalesay inputs: parameters: - name: message container: image: docker/whalesay:latest command: [cowsay] args: ["{{inputs.parameters.message}}"]
提交Workflow,输出结果如下: