前言

随着CI/CD流水线任务不断增多,安装了很多JenKins插件,这插件运维成本很高,难以快速迁移;

大规模使用JenKins后,发现Jenkins更新完插件后,经常会导致服务重启失败,非常影响CI/CD系统运行的稳定性

JenKins和ArgoWorkflows都是流行的CI/CD工具,但它们的设计理念、架构和使用场景有所不同。以下是它们的一些关键对比:

JenKins VS ArgoWorkflows

1. 设计理念和架构

  • Jenkins

    • Jenkins是一个传统的CI/CD工具,通常运行在独立的服务器上,支持通过插件扩展功能。
    • 它的核心功能是通过Jenkins文件(Jenkinsfile)定义流水线。
    • 提供丰富的插件生态,支持多种构建、测试、部署的工具和系统。
    • 更适合传统的、基于服务器的CI/CD,尤其是在需要与多种工具和技术栈集成时。
  • Argo Workflows

    • Argo Workflows是一个Kubernetes原生的工作流引擎,主要用于在Kubernetes环境中编排和管理复杂的任务流。
    • 它基于Kubernetes的资源管理机制,通过定义YAML文件来描述工作流。
    • 更适合微服务和容器化的环境,特别是Kubernetes用户。
    • 主要应用于数据处理、模型训练、集成测试等场景。

2. 平台支持

  • Jenkins
    • 支持多种平台,包括Linux、Windows、macOS等。
    • 可以通过插件扩展到容器化和Kubernetes等环境,但本身并不原生支持Kubernetes。
  • Argo Workflows
    • 完全依赖Kubernetes平台,需要Kubernetes集群作为执行环境。
    • 原生支持容器化和云原生应用,适合Kubernetes环境中的CI/CD和工作流自动化。

3. 易用性与配置

  • Jenkins
    • 配置相对复杂,特别是在集成不同工具和插件时。
    • Jenkinsfile需要一定的DSL(领域特定语言)来编写和维护,适合有经验的用户。
  • Argo Workflows
    • 配置更为简洁,通常通过YAML文件定义工作流。
    • 更容易与Kubernetes生态集成,但对不熟悉Kubernetes的用户来说可能具有一定学习曲线。

4. 扩展性

  • Jenkins

    • 通过插件支持非常广泛,可以集成几乎所有的CI/CD工具和平台,如Docker、GitHub、Slack等。
    • 支持自定义插件开发,但可能需要维护和管理大量插件
  • Argo Workflows

    • 插件机制较弱,但通过与Kubernetes生态系统中的工具(如Helm、Prometheus、Istio等)结合,提供了很强的灵活性。
    • 更侧重于与Kubernetes原生工具和服务的集成。

5. 社区和生态

  • Jenkins
    • 拥有庞大的社区和丰富的文档,已有多年积累的生态系统。
    • 在许多企业环境中被广泛使用,拥有成熟的技术支持和插件。
  • Argo Workflows
    • 相对较新,但得到了云原生和Kubernetes社区的高度关注和支持。
    • 由于其与Kubernetes的深度集成,越来越多的公司和开发团队开始采用Argo Workflows。

6. 性能

  • Jenkins

    • 性能受限于Jenkins服务器本身,处理大规模并发任务时可能面临瓶颈。
    • 可以通过分布式构建来缓解负载,但配置和管理较为复杂
  • Argo Workflows

    • 在Kubernetes上运行,具有良好的可扩展性,能够根据集群资源自动扩展。
    • 能够处理大规模并发任务,并且有较高的容错性和可靠性。

7. 适用场景

  • Jenkins
    • 适合需要丰富插件支持、集成多个工具和系统的传统CI/CD流水线。
    • 适用于那些不完全依赖Kubernetes的项目。
  • Argo Workflows
    • 适合Kubernetes环境中的微服务和容器化应用,尤其是需要多步骤、复杂流程的工作流场景。
    • 适用于云原生应用和大规模容器化架构。

总结:

  • 如果你已经在Kubernetes环境中工作,Argo Workflows是一个很好的选择,因为它与Kubernetes深度集成,支持容器化工作负载。
  • 如果你需要一个更加通用的CI/CD解决方案,且能够与各种工具和系统集成,Jenkins可能是更适合的选择。

两者的选择主要取决于你的应用场景和平台需求。

什么是CI/CD流水线?

Argoworkflow是1种基于云原生的CI/CD流水线;

那么想要构建出完美的CI/CD应该做那些具体的工作呢?

无非就是准备流水线需要的镜像

使用workflow模板写CI/CD逻辑输出用户期望镜像

把业务用户期望的镜像运行到k8s环境

两大核心功能

1条完美的CI/CD流水线应当具备以下2大核心功能:

  • 构建出用户期望的Docker镜像;(CI环节)
  • 让这些用户期望的镜像在K8s正常运行起来;(CD环节)

四大镜像类型

实现以上2大核心功能需要具备以下4类镜像(4类镜像具有继承衍生关系);

  • 基础镜像:源至Docker官方Registry
  • 构建镜像:源至基础镜像,用于构建出用户期望的镜像,在Argoworkflow中使用;
  • 用户参考镜像:一般会在Argoworkflow构建用户镜像时引用(FROM)一些用户参考镜像,加速最终用户镜像的构建,降低用户使用Dockerfile的难度,
  • 用户镜像:由Argoworkflow,使用构建镜像启动的Pod,构建出来用户镜像即用户期望的镜像;

最终用户期望的镜像经过CD环节,正常运行到K8s环境中形成云原生应用;

安装Argoworkflow

$ argo version
argo: v2.12.3
  BuildDate: 2021-01-05T00:50:06Z
  GitCommit: 93ee530126cc1fc154ada84d5656ca82d491dc7f
  GitTreeState: clean
  GitTag: v2.12.3
  GoVersion: go1.13
  Compiler: gc
  Platform: windows/amd64

1.基本概念

ArgoWorkflow 中包括以下几个概念:

  • Workflow:流水线,真正运行的流水线实例,类似于 Tekton 中的 pipelinerun
  • WorkflowTemplate:流水线模板,可以基于模板创建流水线,类似于 Tekton 中的 pipeline

    • ClusterWorkflowTemplate:集群级别的流水线模板,和 WorkflowTemplate 的关系类似于 K8s 中的 Role 和 ClusterRole
  • templates:Workflow 或者 WorkflowTemplate/ClusterWorkflowTemplate 的最小组成单位,流水线由多个 template 组成,可以理解为流水线中的某一个步骤。
WorkflowTemplate 和 ClusterWorkflowTemplate 暂时统称为 Template。

Workflow、Template(大写)、template(小写)之间的关系如下:

arg-workflow-template-ref.png

三者间关系比较复杂,官方也有提到这块因为一些历史遗留问题导致命名上比较混乱

个人感觉下面这种方式比较好理解:

  • template(小写):为 Template(大写)的基本组成单位,可以理解为流水线中的步骤
  • Template(大写):一条完整的流水线,一般由多个 template(小写) 组成
  • Workflow:真正运行的流水线实例,一般由 Template 直接创建,类似于流水线运行记录,每一条记录就是一个 Workflow

理清基本概念之后,接下来就看下看具体对象的分析。

2.Workflow

Workflow 是Argo中最重要的资源,具有两个重要功能:

  • 1)工作流定义
  • 2)工作流状态存储

先看下 Workflow 是怎么样的,以下是一个简单的 Workflow 例子:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: steps-
spec:
  entrypoint: hello           # We reference our first "template" here
  templates:
  - name: hello               # The first "template" in this Workflow, it is referenced by "entrypoint"
    steps:                    # The type of this "template" is "steps"
    - - name: hello
        template: whalesay    # We reference our second "template" here
        arguments:
          parameters: [{name: message, value: "hello"}]

  - name: whalesay             # The second "template" in this Workflow, it is referenced by "hello"
    inputs:
      parameters:
      - name: message
    container:                # The type of this "template" is "container"
      image: docker/whalesay
      command: [cowsay]
      args: ["{{inputs.parameters.message}}"]

整个 Workflow 对象核心内容分为以下三部分:

  • templates:模板列表,此处定义了流水线中的所有步骤以及步骤之间的先后顺序。
  • entrypoint: 流水线入口,类似于代码中的 main 方法,此处一般引用某一个 template invocators 即可。
  • parameters:流水线中用到的参数,包括 arguments 块中的全局参数和 inputs 块中的局部参数两种

entrypoint

Workflow 中必须要指定 entrypoint,entrypoint 作为任务的执行起点,类似于程序中的 main 方法。

templates

ArgoWorkflow 当前支持 6 种 template,接下来挨个分析一下。

container

和 Kubernetes container spec 是一致的,这个类型的 template 就是启动一个 container,用户可以指定image、command、args 等信息来控制具体执行的动作。

  - name: whalesay
    container:
      image: docker/whalesay
      command: [cowsay]
      args: ["hello world"]

script

script 实际上是 container 的封装,spec 和 container 一致,同时增加了 source 字段,用于定义一个脚本,脚本的运行结果会记录到{{tasks.<NAME>.outputs.result}} or {{steps.<NAME>.outputs.result}}

script 可以理解为简化了使用 container 来执行脚本的配置
  - name: gen-random-int
    script:
      image: python:alpine3.6
      command: [python]
      source: |
        import random
        i = random.randint(1, 100)
        print(i)

resource

Resource 类型的 template 用于操作集群中的资源,action 参数表示具体的动作,支持 get, create, apply, delete, replace, patch。

  - name: k8s-owner-reference
    resource:
      action: create
      manifest: |
        apiVersion: v1
        kind: ConfigMap
        metadata:
          generateName: owned-eg-
        data:
          some: value

suspend

Suspend 类型的 template 比较简单,就是用于暂停流水线执行。

默认会一直阻塞直到用户通过argo resume命令手动恢复,或者通过duration 参数指定暂停时间,到时间后会自动恢复。
  - name: delay
    suspend:
      duration: "20s"

steps

Steps 用于处理模版之间的关系,具体包含两方面:

  • 1)哪些任务需要运行
  • 2)这些任务按照什么先后顺序运行

看下面这个例子:

  - name: hello-hello-hello
    steps:
    - - name: step1
        template: prepare-data
    - - name: step2a
        template: run-data-first-half
      - name: step2b
        template: run-data-second-half

哪些任务需要运行?

该 steps 则定义了要运行 step1、step2a、step2b 3 个 template。

这些任务按照什么先后顺序运行?

steps 中元素定义的先后顺序就是各个任务的执行先后顺序,在这里就是 step1 先运行,然后 step2a、step2b 并行运行。

注意:仔细看 yaml 中 step2a 和 step2b 是同一个元素中的,steps 是一个二维数组, 定义如下:

type Template struct {
    Steps []ParallelSteps `json:"steps,omitempty" protobuf:"bytes,11,opt,name=steps"`
}
type ParallelSteps struct {
    Steps []WorkflowStep `json:"-" protobuf:"bytes,1,rep,name=steps"`
}

转换为 json 形式就像这样:

{
    "steps": [
        ["step1"],
        ["step2a", "step2b"]
    ]
}
这样应该比较清晰了,先后顺序一目了然

dag

Dag template 的作用和 steps 是一样的。

这里的 DAG 就是 Directed Acyclic Graph 这个 DAG。

DAG 和 Steps 区别在于任务先后顺序的定义上:

  • Steps 以定义先后顺序作为 template 执行先后顺序
  • DAG 则可以定义任务之间的依赖,由 argo 根据依赖自行生成最终的运行的先后顺序

看下面这个例子:

  - 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

DAG 中新增了 dependencies 字段,可以指定当前步骤依赖的的依赖。

哪些任务需要运行?

该 steps 则定义了要运行 A、B、C、D 4 个任务。

这些任务按照什么先后顺序运行?

不如 Steps 那么直接,需要根据 dependencies 分析依赖关系。

A 没有依赖,因此最先执行,B、C 都只依赖于 A,因此会再 A 后同时执行,D 则依赖于 B、C,因此会等B、C都完成后才执行。

转换为 json 形式如下:

{
    "steps": [
        ["A"],
        ["B", "C"],
        ["D"]
    ]
}

ps:相比之下 steps 方式更为直接,任务先后顺序一目了然。如果整个 Workflow 中所有任务先后顺序理清楚了就推荐使用 steps,如果很复杂,只知道每个任务之间的依赖关系那就直接用 DAG,让 ArgoWorkflow 计算。

template definitions & template invocators

大家可以发现,steps、dag 模板和另外 4 个不一样,他们都是可以指定多个 template 的。

前面分别介绍了 ArgoWorkflow 中的 6 种 template,实际上可以按照具体作用将这 6 个 template 分为 template definitions(模板定义)以及 template invocators(模板调用器)两种。

  • template definitions(模板定义):该类型 template 用于定义具体步骤要执行的内容,例子中的 whalesay 模板就是该类型

    • 包含 containerscriptresourcesuspend 等类型
  • template invocators(模板调用器):该类型 template 用于组合其他 template definitions(模版定义) ,定义步骤间的执行顺序等,例子中的 hello 模板就是该类型。

    • 一般 entrypoint 指向的就是该类型的模板
    • 包含dag 和 steps 两种类型,例子中的 hello 模板就是 steps 类型。
吐槽一下:template 这里有点绕,如果能将 模板定义 、模板调用器 拆分为两个不同的对象就比较清晰。

了解完 template 分类之后再回头看之前的 Workflow 例子就比较清晰了:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: steps-
spec:
  entrypoint: hello           # We reference our first "template" here
  templates:
  - name: hello               # The first "template" in this Workflow, it is referenced by "entrypoint"
    steps:                    # The type of this "template" is "steps"
    - - name: hello
        template: whalesay    # We reference our second "template" here
        arguments:
          parameters: [{name: message, value: "hello"}]

  - name: whalesay             # The second "template" in this Workflow, it is referenced by "hello"
    inputs:
      parameters:
      - name: message
    container:                # The type of this "template" is "container"
      image: docker/whalesay
      command: [cowsay]
      args: ["{{inputs.parameters.message}}"]
  • 1)首先 whalesay 模板是一个 container 类型的 template,因此是 template definitions(模板定义)
  • 2)其次 hello 是一个 steps 类型的 template,因此是 template invocators(模板调用器)

    • 在该调用器中 steps 字段中定义了一个名为 hello 的步骤,该步骤引用的就是 whalesay template
  • 3)entrypoint 指定的是 hello 这个 template invocators(模板调用器)

接下来就是 Workflow 中另一重要对象 entrypoit。

entrypoint

entrypoint 作为任务的执行起点,类似于程序中的 main 方法,每个 Workflow 中都必须要指定 entrypoint。

注意:只有被 entrypoint 指定的任务才会运行,因此,entrypoint 一般只会指定 Steps 和 DAG 类型的 template,也就是template invocators(模板调用器)。然后由 Steps 中的 steps 或者 DAG中的 tasks 来指定多个任务。

因此,并不是 Workflow 中写了的 templates 都会执行。

看下面这个例子:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: steps-
spec:
  entrypoint: hello           # We reference our first "template" here
  templates:
  - name: hello               # The first "template" in this Workflow, it is referenced by "entrypoint"
    steps:                    # The type of this "template" is "steps"
    - - name: hello
        template: whalesay    # We reference our second "template" here
        arguments:
          parameters: [{name: message, value: "hello"}]
  - name: whalesay             # The second "template" in this Workflow, it is referenced by "hello"
    inputs:
      parameters:
      - name: message
    container:                # The type of this "template" is "container"
      image: docker/whalesay
      command: [cowsay]
      args: ["{{inputs.parameters.message}}"]

Entrypoint 指定 hello,然后 hello 是一个 steps 类型的 template,也就是template invocators。然后在 hello template 的 steps 中指定了 whalesay 这个 template,最终 whalesay template 为 container 类型,也就是 template definitions。这里就是最终要运行的任务。

当然,entrypoint 也可以指定 template definitions(模板定义)类型的 template,不过这样只能运行一个任务,就像这样:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: steps-
spec:
  entrypoint: whalesay
  templates:
  - name: whalesay    
    container:
      image: docker/whalesay
      command: [cowsay]
      args: ["hello"]

至此,我们应该基本搞清楚了 Workflow 对象(参数部分除外)。接下来就看一下最后一部分,parameters。

Demo

列出几个复杂一点点的 Workflow,看一下是不是真的搞懂 Workflow 了。

下面是一个包含 4个任务的 Workflow:

  • 1)首先打印 hello
  • 2)然后执行一段 python 脚本,生成随机数
  • 3)sleep 20s
  • 4)创建一个 Configmap
提供了 steps 和 dag 两种写法,可以对比下
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: steps-
spec:
  entrypoint: hello
  templates:
  - name: hello              
    steps:          
    - - name: hello
        template: whalesay
        arguments:
          parameters: [{name: message, value: "hello"}]
    - - name: runscript
        template: gen-random-int
    - - name: sleep
        template: delay
    - - name: create-cm
        template: k8s-owner-reference
  # - name: diamond
  #   dag:
  #     tasks:
  #     - name: hello
  #       template: whalesay
  #       arguments:
  #         parameters: [{name: message, value: "hello"}]
  #     - name: runscript
  #       dependencies: [hello]
  #       template: gen-random-int
  #     - name: sleep
  #       template: delay
  #       dependencies: [runscript]
  #     - name: create-cm
  #       template: k8s-owner-reference
  #       dependencies: [sleep]
  - name: whalesay
    inputs:
      parameters:
      - name: message
    container:
      image: docker/whalesay
      command: [cowsay]
      args: ["{{inputs.parameters.message}}"]
  - name: gen-random-int
    script:
      image: python:alpine3.6
      command: [python]
      source: |
        import random
        i = random.randint(1, 100)
        print(i)
  - name: k8s-owner-reference
    resource:
      action: create
      manifest: |
        apiVersion: v1
        kind: ConfigMap
        metadata:
          generateName: owned-eg-
        data:
          host: lixueduan.com
          wx: 探索云原生
  - name: delay
    suspend:
      duration: "20s"

parameters

Workflow 中的参数可以分为以下两种:

  • 形参:在 template(template definitions) 中通过 inputs 字段定义需要哪些参数,可以指定默认值
  • 实参:在 template(template invocators) 中通过 arguments 字段为参数赋值,覆盖 inputs 中的默认值
以上仅为个人理解

inputs 形式参数

template 中可以使用 spec.templates[*].inputs 字段来指定形式参数,在 template 中可以通过{{inputs.parameters.$name}} 语法来引用参数。

下面这个例子则是声明了 template 需要一个名为 message 的参数,这样调用方在使用该 template 时就知道需要传哪些参数过来。

  templates:
    - name: whalesay-template
      inputs:
        parameters:
          - name: message
      container:
        image: docker/whalesay
        command: [cowsay]
        args: ["{{inputs.parameters.message}}"]

当然也可以指定默认值

  templates:
    - name: whalesay-template
      inputs:
        parameters:
          - name: message
            value: "default message"
      container:
        image: docker/whalesay
        command: [cowsay]
        args: ["{{inputs.parameters.message}}"]

注意:如果未指定默认值,则调用该 template 时必须指定该参数,有默认值则可以不指定。

arguments 实际参数

spec.arguments用于定义要传递的实际参数,这部分参数在当前 Workflow 下的所有 Template 中都可以使用,可以使用 {{workflow.parameters.$name}} 语法来引用。

例如下面这个例子中指定了一个名为 message 的参数,并赋值为 hello world。

  arguments:
    parameters:
      - name: message
        value: hello world

参数复用

除了在 steps/dag 中指定 arguments,甚至可以直接在 Workflow 中指定,然后 steps/dag 中通过{{workflow.parameters.$name}} 语法进行引用。这样即可实现参数复用,Workflow 中定义一次,steps/dag 中可以多次引用。

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: example-
spec:
  entrypoint: main
  arguments:
    parameters:
    - name: workflow-param-1
  templates:
  - name: main
    dag:
      tasks:
      - name: step-A 
        template: step-template-A
        arguments:
          parameters:
          - name: template-param-1
            value: "{{workflow.parameters.workflow-param-1}}"

  - name: step-template-A
    inputs:
      parameters:
        - name: template-param-1
    script:
      image: alpine
      command: [/bin/sh]
      source: |
          echo "{{inputs.parameters.template-param-1}}"

Demo

通过下面这个 Demo 来理解参数传递:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: steps-
spec:
  entrypoint: hello           # We reference our first "template" here
  templates:
  - name: hello               # The first "template" in this Workflow, it is referenced by "entrypoint"
    steps:                    # The type of this "template" is "steps"
    - - name: hello
        template: whalesay    # We reference our second "template" here
        arguments:
          parameters: [{name: message, value: "hello"}]

  - name: whalesay             # The second "template" in this Workflow, it is referenced by "hello"
    inputs:
      parameters:
      - name: message
    container:                # The type of this "template" is "container"
      image: docker/whalesay
      command: [cowsay]
      args: ["{{inputs.parameters.message}}"]

上述例子中,template whalesay 定义了需要一个名为 message 的参数,同时在 steps template 中引用 whalesay 时通过 arguments 指定了参数 message 的值为 hello。因此最终会打印出 hello。

3.WorkflowTemplate

官方原文:

A WorkflowTemplate is a definition of a Workflow that lives in your cluster.

WorkflowTemplate 就是 Workflow 的定义,WorkflowTemplate 描述了这个流水线的详细信息,包括有哪些任务,任务之间的先后顺序等等。

根据前面对 Workflow 的描述可知,我们能直接创建 Workflow 对象来运行流水线,不过这种方式存在的一些问题:

  • 1)如果 template 比较多的话,Workflow 对象就会特别大,修改起来比较麻烦
  • 2)模板无法共享,不同 Workflow 都需要写一样的 template,或者同一个 template 会出现在不同的 Workflow yaml 中。

因此,关于 Workflow 和 WorkflowTemplate 的最佳实践:将 template 存到 WorkflowTemplate,Workflow 中只引用 Template 并提供参数即可。

而 ArgoWorkflow 中的工作流模板根据范围不同分为 WorkflowTemplate 和 ClusterWorkflowTemplate 两种。

  • WorkflowTemplate:命名空间范围,只能在同一命名空间引用
  • ClusterWorkflowTemplate:集群范围,任意命名空间都可以引用

WorkflowTemplate

下面是一个简单的 WorkflowTemplate:

apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  name: workflow-template-submittable
  namespace: default
spec:
  entrypoint: whalesay-template
  arguments:
    parameters:
      - name: message
        value: tpl-argument-default
  templates:
    - name: whalesay-template
      inputs:
        parameters:
          - name: message
            value: tpl-input-default
      container:
        image: docker/whalesay
        command: [cowsay]
        args: ["{{inputs.parameters.message}}"]

可以看到 WorkflowTemplate 和 Workflow 参数是一模一样,这里就不在赘述了。

只需要将 kind 由 Workflow 替换为 WorkflowTemplate 即可实现转换。

workflowMetadata

workflowMetadata 是 Template 中独有的一个字段,主要用于存储元数据,后续由这个 Template 创建出的 Workflow 都会自动携带上这些信息。

通过这些信息可以追踪到 Workflow 是由哪个 Template 创建的。

使用方式就像下面这样,workflowMetadata 中指定了一个 label

apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  name: workflow-template-submittable
spec:
  workflowMetadata:
    labels:
      example-label: example-value

然后由该 Template 创建的 Workflow 对象都会携带这个 label:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  annotations:
    workflows.argoproj.io/pod-name-format: v2
  creationTimestamp: "2023-10-27T06:26:13Z"
  generateName: workflow-template-hello-world-
  generation: 2
  labels:
    example-label: example-value
  name: workflow-template-hello-world-5w7ss
  namespace: default

ClusterWorkflowTemplate

类似于 WorkflowTemplate,可以理解为 k8s 中的 Role 和 ClusterRole 的关系,作用域不同罢了。

和 WorkflowTemplate 所有参数都一致,只是将 yaml 中的 kind 替换为 ClusterWorkflowTemplate 即可。

4.TemplateRef

创建好 WorkflowTemplate 之后就可以在 Workflow 中使用 TemplateRef 直接引用对应模板了,这样 Workflow 对象就会比较干净。

对于 WorkflowTemplate 的引用也有两种方式:

  • 1)workflowTemplateRef:引用完整的 WorkflowTemplate,Workflow 中只需要指定全局参数即可
  • 2)templateRef:只引用某一个 template,Workflow 中还可以指定其他的 template、entrypoint 等信息。

workflowTemplateRef

可以通过workflowTemplateRef字段直接引用 WorkflowTemplate。

注意📢:这里需要 Workflow 和 WorkflowTemplate 在同一个命名空间。

就像这样:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: workflow-template-hello-world-
spec:
  arguments:
    parameters:
      - name: message
        value: "from workflow"
  workflowTemplateRef:
    name: workflow-template-submittable

workflowTemplateRef 指定要引用的 Template 名字即可,这一句就相当于把对应 Template 中 spec 字段下的所有内容都搬过来了,包括 entrypoint、template 等。

Workflow 中一般只需要通过 argument 字段来实现参数覆盖,当然也可以不指定,若 Workflow 中不指定参数则会使用 Template 中提供的默认值

一个最精简的 Workflow 如下:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: workflow-template-hello-world-
spec:
  workflowTemplateRef:
    name: workflow-template-submittable

只有 workflowTemplateRef 字段,未提供 argument 参数。

和前面的 Workflow 对比起来,内容就更少了,因为大部分都写在 WorkflowTemplate 里了,Workflow 中一般只需要指定参数就行。

clusterWorkflowTemplateRef

和 workflowTemplateRef 类似,只需要增加 clusterScope: true 配置即可。

默认为 false,即 WorkflowTemplate

就像这样:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: workflow-template-hello-world-
spec:
  entrypoint: whalesay
  templates:
  - name: whalesay
    steps:                              # You should only reference external "templates" in a "steps" or "dag" "template".
      - - name: call-whalesay-template
          templateRef:                  # You can reference a "template" from another "WorkflowTemplate or ClusterWorkflowTemplate" using this field
            name: cluster-workflow-template-whalesay-template   # This is the name of the "WorkflowTemplate or ClusterWorkflowTemplate" CRD that contains the "template" you want
            template: whalesay-template # This is the name of the "template" you want to reference
            clusterScope: true          # This field indicates this templateRef is pointing ClusterWorkflowTemplate
          arguments:                    # You can pass in arguments as normal
            parameters:
            - name: message
              value: "hello world"

核心部分:

  workflowTemplateRef:
    name: cluster-workflow-template-submittable
    clusterScope: true

当指定为集群范围时,ArgoWorkflow 会去搜索 ClusterWorkflowTemplate 对象,否则会在当前命名空间搜索 WorkflowTemplate。

templateRef

除了使用 workflowTemplateRef / clusterWorkflowTemplateRef 引用整个 WorkflowTemplate 之外,还可以使用 templateRef 参数来实现引用 WorkflowTemplate 中的某一个 template。

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: workflow-template-hello-world-
spec:
  entrypoint: whalesay
  templates:
  - name: whalesay
    steps:                              # You should only reference external "templates" in a "steps" or "dag" "template".
      - - name: call-whalesay-template
          templateRef:                  # You can reference a "template" from another "WorkflowTemplate" using this field
            name: workflow-template-1   # This is the name of the "WorkflowTemplate" CRD that contains the "template" you want
            template: whalesay-template # This is the name of the "template" you want to reference
          arguments:                    # You can pass in arguments as normal
            parameters:
            - name: message
              value: "hello world"

核心为:

          templateRef:
            name: workflow-template-1
            template: whalesay-template

参数分析:

  • name 指的是 WorkflowTemplate 名称,即 workflow-template-1 这个 WorkflowTemplat
  • template 指的就是 template 的名称 ,即 workflow-template-1 这个 WorkflowTemplat 中的名为 whalesay-template 的 template

注意📢:根据官方文档,最好不要在 steps 和 dag 这两个template invocators(模板调用器)之外使用 templateRef 。

原文如下:

You should never reference another template directly on a template object (outside of a steps or dag template). This behavior is deprecated, no longer supported, and will be removed in a future version.

Parameters

WorkflowTemplate 中使用参数和 Workflow 基本一致,没有太大区别。

  • template definitions 中通过 inputs 字段定义需要的参数
  • template invocators 中通过 arguments 字段为参数复制

Workflow 中引用 WorkflowTemplate 时可以再次定义 arguments 以覆盖 WorkflowTemplate 中的默认参数。

sidecars

你可以在 Argo 工作流中定义 sidecars;

做一些docker和git的认证工作

ArgoWorkflow命令行

#查看所有alived模板
kubectl get WorkflowTemplate -n argo | grep 流水线ID
#查看某1个模板输出为yaml格式
kubectl get WorkflowTemplate 模板名称 -n argo -o yaml
#输出到.yaml文件
kubectl get WorkflowTemplate 模板名称-n argo -o yaml > file.yaml
#重新生成argoWorkflow资源
kubectl apply -f file.yaml
#删除生成argoWorkflow资源
kubectl delete -f file.yaml
#列出所有工作流
argo list -n argo
#提交工作流
argo submit -n argo helloworld.yaml --watch 
#查看具体工作流的日志
argo logs 工作流名称 -n argo
#查看工作流运行过程,运行工作流的Pod等详细信息
argo get 工作流名称 -n argo
#删除工作流
argo delete 工作流名称 -n argo
#停止工作流
argo stop 工作流名称 -n argo
#暂停工作流
argo suspend 工作流名称 -n argo
#恢复工作流
argo resume 工作流名称 -n argo

最佳实践

根据 workflowTemplateRef 和 templateRef 描述可以得出以下最佳实践:

  • 1)workflowTemplateRef 使用:WorkflowTemplate 中定义完整流水线内容,包括 entrypoint、template,Workflow 中通过 workflowTemplateRef 引用并通过 argument 指定参数覆盖默认值。
  • 2)templateRef 使用:WorkflowTemplate 中不定义完整流水线内容,只定义常用 template,Workflow 中需要使用该类型 template 时,通过 templateRef 引用,而不是在 Workflow 中再定义一次该 template。

第一种情况 WorkflowTemplate 可以称为流水线模板,第二种情况下 WorkflowTemplate 充当 template-utils 角色。

 

参考

posted on 2024-08-31 06:12  Martin8866  阅读(19)  评论(0编辑  收藏  举报