home / writing / argo-workflows-and-events

Argo Workflows and Argo Events

Argo Workflows runs each step of a pipeline as a Kubernetes pod, and Argo Events starts those pipelines when something happens. This guide shows how the templates, artifacts, sensors and triggers fit together.

Where each Argo project fits

The Argo family is a set of Kubernetes-native tools, each solving a different problem:

ProjectPurpose
Argo CDGitOps delivery of manifests
Argo RolloutsCanary and blue/green releases
Argo WorkflowsRun multi-step jobs as pods
Argo EventsReact to external events and trigger actions

This guide covers the last two. Argo Workflows is a container-native workflow engine where every step runs as a pod, which makes it a good fit for CI pipelines, data processing, batch jobs and machine-learning pipelines. Argo Events is an event-driven automation framework that can start workflows (or create any Kubernetes object) when something happens elsewhere.

Workflow basics and template types

A Workflow is a Kubernetes custom resource. Its spec names an entrypoint and a list of templates; the entrypoint is the template that starts the run.

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: hello-
spec:
  entrypoint: say-hello
  templates:
    - name: say-hello
      container:
        image: alpine:3.20
        command: [echo]
        args: ["hello world"]

Submit with argo submit -n argo --watch hello.yaml or kubectl create -f. Use argo list, argo get and argo logs to inspect runs. The main template types:

  • container: run an image. The most common type.
  • script: like a container, but with an inline source script; its stdout becomes the step's result.
  • resource: create, patch or delete a Kubernetes object from a manifest.
  • suspend: pause for a duration or until someone resumes it, useful for manual approval gates.
  • steps and dag: orchestration templates that call other templates (next section).

Steps and DAGs

A steps template is a list of stages. Stages run in order; steps inside the same stage run in parallel.

- name: pipeline
  steps:
    - - name: build
        template: build-image
    - - name: unit-tests
        template: run-tests
      - name: lint
        template: run-lint
    - - name: publish
        template: push-image

A DAG template declares tasks and their dependencies, and the controller runs everything whose dependencies are met, as early as possible. That suits fan-out and fan-in graphs, for example a diamond where A runs first, B and C run in parallel, and D waits for both.

- 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

Use steps for simple linear pipelines and dag when dependencies are irregular. Both support when conditions, withItems and withParam loops for fan-out, and retry strategies on a template.

Parameters and artifacts

Parameters are small string values. Workflow-level arguments are read as {{workflow.parameters.name}}; a template takes inputs.parameters and may expose outputs.parameters that later steps read as {{steps.build.outputs.parameters.tag}}.

Artifacts are files or directories passed between steps or stored for later, via an artifact repository such as an S3-compatible bucket, GCS or similar. A template declares an output artifact from a path; a later template declares an input artifact that references it.

- name: produce
  container:
    image: alpine:3.20
    command: [sh, -c]
    args: ["echo report > /tmp/report.txt"]
  outputs:
    artifacts:
      - name: report
        path: /tmp/report.txt

- name: consume
  inputs:
    artifacts:
      - name: report
        path: /tmp/in.txt
  container:
    image: alpine:3.20
    command: [cat, /tmp/in.txt]

In a DAG you wire them with arguments.artifacts using from: "{{tasks.produce.outputs.artifacts.report}}". Configure the default artifact repository once for the installation; credentials for it should come from a Kubernetes Secret.

WorkflowTemplates and CronWorkflows

A WorkflowTemplate is a stored, reusable set of templates, either namespaced or cluster-wide (ClusterWorkflowTemplate). Create a run from it with argo submit --from workflowtemplate/ci-pipeline -p branch=main, or reference one of its templates from another workflow through templateRef:

- name: call-shared
  templateRef:
    name: common-tasks
    template: notify

A CronWorkflow wraps a workflow spec with a cron schedule, a concurrency policy and history limits, for nightly or periodic jobs.

Argo Events architecture

Argo Events has four pieces that cooperate:

  • EventSource: connects to the outside world and turns activity into events. Supported sources include webhooks, schedules, GitHub and other Git hosts, object-storage notifications, message queues such as Kafka, NATS and SQS, and cloud pub/sub services.
  • EventBus: the transport between sources and sensors. It is backed by a message system such as NATS JetStream or Kafka, and the EventBus controller deploys it when you create an EventBus resource.
  • Sensor: declares which events it depends on and what to do when they arrive. Dependencies can be combined with conditions (for example, require both of two events).
  • Trigger: the action a sensor fires: create an Argo Workflow or any Kubernetes resource, call an HTTP endpoint, send to a message queue, invoke a serverless function, and more.

Flow: external system, EventSource, EventBus, Sensor, Trigger.

Wiring an event to a workflow

First an EventSource exposing a webhook endpoint:

apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
  name: webhook
spec:
  webhook:
    build:
      port: "12000"
      endpoint: /build
      method: POST

Then a Sensor that depends on it and submits a workflow, passing part of the event payload in as a parameter:

apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
  name: webhook-sensor
spec:
  dependencies:
    - name: build-dep
      eventSourceName: webhook
      eventName: build
  triggers:
    - template:
        name: run-workflow
        argoWorkflow:
          operation: submit
          source:
            resource:
              apiVersion: argoproj.io/v1alpha1
              kind: Workflow
              metadata:
                generateName: from-event-
              spec:
                entrypoint: main
                arguments:
                  parameters:
                    - name: message
                      value: placeholder
                templates:
                  - name: main
                    inputs:
                      parameters:
                        - name: message
                    container:
                      image: alpine:3.20
                      command: [echo, "{{inputs.parameters.message}}"]
          parameters:
            - src:
                dependencyName: build-dep
                dataKey: body
              dest: spec.arguments.parameters.0.value

The parameters block maps data from the event into a field of the resource before it is created. Expose the webhook Service through an Ingress or gateway, and protect it, since anyone who can reach it can start work.

Practical tips

  • The Workflows and Events controllers need RBAC. Give the workflow ServiceAccount only the permissions its steps need, and a separate, narrow one for sensors.
  • Set ttlStrategy and pod garbage collection so completed workflows do not pile up in etcd.
  • Set resource requests and limits on step containers, and an activeDeadlineSeconds to stop runaway jobs.
  • Large fan-outs create many pods quickly. Use parallelism limits at workflow or template level.
  • Keep workflows and sensors in Git and deploy them with a GitOps tool, so changes are reviewed like any other code.
  • Prefer artifacts for files and parameters for short strings; passing large data through parameters hits size limits.