文章

Argo Workflows 入门与实践

Argo Workflows 入门与实践

概述

Argo Workflows 是 K8s 原生的工作流引擎,每个 Step 在独立的 Pod 中运行,天然支持 DAG 编排、并行执行、条件分支、循环和入参出参传递。

为什么选择 Argo Workflows

特性JenkinsArgo Workflows
架构Master-Agent (Java)K8s 原生 CRD + Controller
资源管理Agent 常驻,资源预留浪费Pod 按需创建,用完销毁
并发受 Agent executor 数限制受 K8s 集群容量限制(弹性)
配置Groovy PipelineYAML Workflow CRD
可观测性Blue Ocean UIArgo UI + kubectl + Prometheus
GitOps 友好需要额外集成天然 WorkflowTemplate + Git 版本化
学习曲线中(Pipeline DSL)中(理解 K8s + YAML)

DAG 有向无环图 —— 核心抽象

        ┌──────────┐
        │  clone   │
        └────┬─────┘
     ┌───────┼───────┐
     ↓       ↓       ↓
  ┌────┐ ┌────┐ ┌────┐
  │lint│ │test│ │scan│        ← 并行
  └──┬─┘ └──┬─┘ └──┬─┘
     └───────┼───────┘

     ┌──────────────┐
     │  build-push  │
     └──────┬───────┘

     ┌──────────────┐
     │   deploy     │
     └──────────────┘

Workflow 基础模板

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: golang-ci-
spec:
  entrypoint: ci-pipeline
  ttlStrategy:
    secondsAfterCompletion: 3600        # 完成后 1h 清理
  podGC:
    strategy: OnPodCompletion           # Pod 完成后立即回收

  templates:
  # ── 入口 DAG ──
  - name: ci-pipeline
    dag:
      tasks:
      - name: clone
        template: git-clone
      - name: lint
        dependencies: [clone]
        template: golang-lint
      - name: test
        dependencies: [clone]
        template: go-test
      - name: scan
        dependencies: [clone]
        template: trivy-scan
      - name: build
        dependencies: [lint, test, scan]
        template: docker-build

  # ── Git Clone ──
  - name: git-clone
    container:
      image: alpine/git:latest
      command: [sh, -c]
      args:
        - git clone --depth 1 https://github.com/example/repo.git /src
    outputs:
      artifacts:                          # 输出产物(供后续 Step 使用)
      - name: source
        path: /src

  # ── Go Lint(并行 Step 1) ──
  - name: golang-lint
    inputs:
      artifacts:
      - name: source
        path: /src
    container:
      image: golangci/golangci-lint:v1.59
      workingDir: /src
      command: [golangci-lint, run, ./...]

  # ── Go Test(并行 Step 2) ──
  - name: go-test
    inputs:
      artifacts:
      - name: source
        path: /src
    container:
      image: golang:1.23
      workingDir: /src
      command: [go, test, -v, -race, -coverprofile=coverage.out, ./...]

  # ── Trivy Scan(并行 Step 3) ──
  - name: trivy-scan
    inputs:
      artifacts:
      - name: source
        path: /src
    container:
      image: aquasec/trivy:latest
      command: [trivy, fs, --severity, HIGH,CRITICAL, /src]

  # ── Docker Build ──
  - name: docker-build
    inputs:
      artifacts:
      - name: source
        path: /src
    container:
      image: gcr.io/kaniko-project/executor:latest
      args:
        - --context=/src
        - --destination=harbor.example.com/my-app:{{workflow.name}}
        - --cache=true
    env:
      - name: DOCKER_CONFIG
        value: /kaniko/.docker

常用模板类型

Step Template(串行步骤)

- name: steps-example
  steps:
  - - name: step-1               # 单横线 = 并行组开始
      template: do-something
    - name: step-2               # step-1 和 step-2 并行
      template: do-other
  - - name: step-3               # 双横线 = 等上面组完成
      template: final-step

条件执行

- name: conditional
  steps:
  - - name: deploy-staging
      template: deploy
      when: "{{workflow.parameters.env}} == staging"
    - name: deploy-prod
      template: deploy
      when: "{{workflow.parameters.env}} == prod"

Loop(循环)

- name: run-multiple
  steps:
  - - name: echo
      template: whalesay
      arguments:
        parameters:
        - name: message
          value: "{{item}}"
      withItems:                     # 循环数组
      - "hello"
      - "world"
      - "argo"

参数传递

- name: generate-version
  script:
    image: alpine:latest
    command: [sh]
    source: |
      echo "v1.0.$(date +%s)" > /tmp/version
  outputs:
    parameters:
    - name: version
      valueFrom:
        path: /tmp/version

- name: use-version
  inputs:
    parameters:
    - name: version
  container:
    image: alpine:latest
    command: [echo, "Version is {{inputs.parameters.version}}"]

WorkflowTemplate —— 复用与抽象

apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  name: golang-ci-template         # 可在其他 Workflow 中引用
spec:
  entrypoint: ci-pipeline
  arguments:
    parameters:
    - name: repo-url
    - name: image-name
  templates:
  - name: ci-pipeline
    dag:
      tasks:
      - name: clone
        template: git-clone
        arguments:
          parameters:
          - name: repo-url
            value: "{{workflow.parameters.repo-url}}"
      - name: lint
        dependencies: [clone]
        templateRef:                    # 引用另一个 WorkflowTemplate!
          name: golang-lint-template
          template: lint
      # ...
# 使用 WorkflowTemplate
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: my-service-ci-
spec:
  workflowTemplateRef:
    name: golang-ci-template
  arguments:
    parameters:
    - name: repo-url
      value: https://github.com/example/my-service.git
    - name: image-name
      value: harbor.example.com/my-service

生产环境配置要点

Workflow RBAC

apiVersion: v1
kind: ServiceAccount
metadata:
  name: argo-workflow
  namespace: argo
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: argo
  name: workflow-role
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: argo
  name: workflow-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: workflow-role
subjects:
- kind: ServiceAccount
  name: argo-workflow

资源限制

- name: resource-limited
  container:
    image: my-image:latest
    resources:
      requests:
        memory: "128Mi"
        cpu: "100m"
      limits:
        memory: "512Mi"
        cpu: "500m"

重试策略

- name: flaky-step
  retryStrategy:
    limit: 3                        # 最多重试 3 次
    backoff:
      duration: "10s"               # 首次重试延迟
      factor: 2                     # 递增倍率
      maxDuration: "5m"             # 重试上限
  container:
    image: my-image
    command: [./flaky-script.sh]

超时控制

spec:
  activeDeadlineSeconds: 3600       # Workflow 总超时 1h

  templates:
  - name: limited-step
    activeDeadlineSeconds: 600      # 单 Step 超时 10min
    container:
      image: my-image

Argo CLI 常用命令

# 提交 Workflow
argo submit workflow.yaml -n argo
argo submit --from=wftmpl/golang-ci-template -n argo

# 查看状态
argo list -n argo
argo get <workflow-name> -n argo
argo logs <workflow-name> -n argo
argo watch <workflow-name> -n argo    # 实时跟踪

# 管理
argo terminate <workflow-name> -n argo       # 终止
argo delete <workflow-name> -n argo          # 删除
argo retry <workflow-name> -n argo           # 重试
argo resubmit <workflow-name> -n argo        # 重新提交(保留原结果)

# 查看 WorkflowTemplate
argo template list -n argo
argo template get golang-ci-template -n argo

常见问题 / 坑点

问题原因解决方案
Pod 一直 Pending资源不足/节点调度问题设置合理的 Resource Request + Node Selector
Artifact 传递失败存储未配置(S3/Minio)配置 artifactRepository
Workflow 堆积导致集群压力没有 TTL 清理ttlStrategy + Cron Workflow 清理
大 Artifact 导致 OOMTar/Gzip 消耗大量内存减少 Artifact 大小或使用外部存储直接挂载
Container 无网络访问NetworkPolicy 限制开放 Workflow 所需 Egress 策略

关联知识

参考资源

学习时间

阶段时间备注
初次学习2026-07-14DAG/模板/参数/WorkflowTemplate

状态: 📖 已掌握 下次复习日期: 2026-08-14