Argo Workflows란?
Argo Workflows는 Kubernetes 네이티브 워크플로 엔진으로, 복잡한 CI/CD 파이프라인, 데이터 처리, ML 학습 등 다단계 작업을 DAG(Directed Acyclic Graph) 형태로 오케스트레이션합니다. CRD 기반으로 동작하며, 각 스텝이 독립 Pod로 실행되어 자원 격리와 확장성을 보장합니다.
ArgoCD가 배포 동기화에 집중한다면, Argo Workflows는 작업 오케스트레이션에 특화되어 있습니다. CI 빌드, 테스트, 이미지 빌드, 통합 테스트를 하나의 워크플로로 연결할 수 있습니다.
핵심 개념: Workflow CRD 구조
Argo Workflows의 기본 단위는 Workflow CRD입니다. 템플릿 기반으로 스텝을 정의하고, 의존성 그래프를 선언합니다.
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: ci-pipeline-
spec:
entrypoint: main
arguments:
parameters:
- name: repo-url
value: "https://github.com/org/app.git"
- name: branch
value: "main"
templates:
- name: main
dag:
tasks:
- name: checkout
template: git-clone
arguments:
parameters:
- name: repo
value: "{{workflow.parameters.repo-url}}"
- name: test
template: run-tests
dependencies: [checkout]
- name: build-image
template: docker-build
dependencies: [checkout]
- name: deploy
template: deploy-staging
dependencies: [test, build-image]
dag 블록에서 dependencies로 실행 순서를 제어합니다. test와 build-image는 checkout 완료 후 병렬 실행되고, deploy는 둘 다 끝난 뒤 실행됩니다.
템플릿 유형별 활용
Argo Workflows는 4가지 템플릿 유형을 제공합니다.
- Container: 단일 컨테이너 실행 (가장 기본)
- Script: 인라인 스크립트 실행 (bash, python 등)
- DAG: 의존성 기반 병렬 실행 그래프
- Steps: 순차·병렬 스텝 조합
# Container 템플릿
- name: git-clone
inputs:
parameters:
- name: repo
container:
image: alpine/git:latest
command: [git, clone, "{{inputs.parameters.repo}}", /work]
volumeMounts:
- name: workdir
mountPath: /work
# Script 템플릿
- name: run-tests
script:
image: node:20-alpine
command: [sh]
source: |
cd /work
npm ci
npm test -- --coverage
volumeMounts:
- name: workdir
mountPath: /work
Artifact Passing: 스텝 간 데이터 전달
워크플로에서 가장 중요한 패턴 중 하나는 스텝 간 아티팩트 전달입니다. Argo Workflows는 S3, GCS, MinIO 등을 아티팩트 저장소로 사용합니다.
templates:
- name: docker-build
inputs:
artifacts:
- name: source
path: /src
container:
image: gcr.io/kaniko-project/executor:latest
args:
- --dockerfile=/src/Dockerfile
- --context=/src
- --destination=registry.example.com/app:{{workflow.uid}}
- --digest-file=/tmp/digest
outputs:
artifacts:
- name: build-digest
path: /tmp/digest
parameters:
- name: image-tag
valueFrom:
path: /tmp/digest
- name: deploy-staging
inputs:
parameters:
- name: digest
container:
image: bitnami/kubectl:latest
command: [sh, -c]
args:
- |
kubectl set image deployment/app
app=registry.example.com/app@{{inputs.parameters.digest}}
outputs.artifacts로 파일을 내보내고, 다음 스텝의 inputs.artifacts에서 받습니다. 파라미터도 valueFrom.path로 파일 내용을 변수화할 수 있어, 이미지 다이제스트 같은 동적 값 전달에 유용합니다.
WorkflowTemplate: 재사용 가능한 템플릿
반복되는 워크플로 로직을 WorkflowTemplate으로 분리하면 DRY 원칙을 지킬 수 있습니다.
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: docker-build-template
spec:
templates:
- name: kaniko-build
inputs:
parameters:
- name: dockerfile
default: Dockerfile
- name: context
- name: destination
container:
image: gcr.io/kaniko-project/executor:latest
args:
- --dockerfile={{inputs.parameters.dockerfile}}
- --context={{inputs.parameters.context}}
- --destination={{inputs.parameters.destination}}
- --cache=true
- --cache-repo={{inputs.parameters.destination}}-cache
---
# Workflow에서 참조
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: app-build-
spec:
entrypoint: build
templates:
- name: build
steps:
- - name: build-image
templateRef:
name: docker-build-template
template: kaniko-build
arguments:
parameters:
- name: context: s3://artifacts/source
- name: destination
value: registry.example.com/app:v1.2.0
templateRef로 외부 WorkflowTemplate를 참조하면, 빌드 로직 변경 시 템플릿만 수정하면 모든 워크플로에 반영됩니다.
Retry·Timeout 전략
CI/CD 파이프라인에서 일시적 실패(네트워크 오류, 이미지 풀 실패 등)는 흔합니다. Argo Workflows의 재시도 전략으로 안정성을 높일 수 있습니다.
templates:
- name: flaky-integration-test
retryStrategy:
limit: 3
retryPolicy: "OnError" # OnError | OnFailure | Always
backoff:
duration: "30s"
factor: 2
maxDuration: "5m"
activeDeadlineSeconds: 600 # 10분 타임아웃
container:
image: app-test:latest
command: [npm, run, test:e2e]
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1"
- retryPolicy:
OnError는 시스템 오류(OOM 등)만,OnFailure는 exit code ≠ 0,Always는 모든 실패 - backoff: 지수 백오프로 재시도 간격 증가 (30s → 60s → 120s)
- activeDeadlineSeconds: 전체 실행 시간 제한
Sensor + EventSource: 이벤트 기반 트리거
Argo Events와 결합하면 Git push, webhook, cron 등 이벤트로 워크플로를 자동 트리거할 수 있습니다.
# EventSource: GitHub webhook 수신
apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
name: github-webhook
spec:
github:
app-repo:
repositories:
- owner: org
names: [app]
webhook:
endpoint: /push
port: "12000"
events: [push, pull_request]
apiToken:
name: github-token
key: token
---
# Sensor: push 이벤트 → 워크플로 트리거
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
name: ci-trigger
spec:
dependencies:
- name: github-push
eventSourceName: github-webhook
eventName: app-repo
filters:
data:
- path: body.ref
type: string
value: ["refs/heads/main"]
triggers:
- template:
name: run-ci
argoWorkflow:
operation: submit
source:
resource:
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: ci-
spec:
workflowTemplateRef:
name: ci-pipeline-template
parameters:
- src:
dependencyName: github-push
dataKey: body.after
dest: spec.arguments.parameters.0.value
이 구성으로 main 브랜치 push 시 자동으로 CI 파이프라인이 실행됩니다. filters로 특정 브랜치만 필터링하고, 커밋 SHA를 워크플로 파라미터로 전달합니다.
Volume·캐시 전략
스텝 간 대용량 데이터 공유나 빌드 캐시에는 PVC 볼륨이 효과적입니다.
spec:
volumeClaimTemplates:
- metadata:
name: work
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 10Gi
storageClassName: fast-ssd
templates:
- name: checkout
container:
image: alpine/git
command: [git, clone, --depth=1, "{{workflow.parameters.repo}}", /work/src]
volumeMounts:
- name: work
mountPath: /work
- name: build
container:
image: node:20
command: [sh, -c, "cd /work/src && npm ci --cache /work/.npm && npm run build"]
volumeMounts:
- name: work
mountPath: /work
volumeClaimTemplates로 워크플로 전용 PVC를 생성하면, 모든 스텝이 같은 볼륨을 마운트하여 git clone 결과를 재사용합니다. npm 캐시도 볼륨에 저장해 반복 빌드 속도를 높입니다.
실전 CI/CD 파이프라인 완성본
지금까지의 개념을 조합한 실전 파이프라인입니다.
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: full-ci-
labels:
app: myapp
spec:
entrypoint: ci-pipeline
serviceAccountName: argo-workflow
ttlStrategy:
secondsAfterCompletion: 86400 # 24시간 후 정리
arguments:
parameters:
- name: repo
- name: commit-sha
- name: branch
value: main
volumeClaimTemplates:
- metadata:
name: workspace
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 5Gi
templates:
- name: ci-pipeline
dag:
tasks:
- name: clone
template: git-checkout
- name: lint
template: eslint
dependencies: [clone]
- name: unit-test
template: jest-test
dependencies: [clone]
- name: build
template: kaniko
dependencies: [lint, unit-test]
- name: scan
template: trivy-scan
dependencies: [build]
- name: deploy
template: kubectl-apply
dependencies: [scan]
when: "{{workflow.parameters.branch}} == main"
- name: git-checkout
container:
image: alpine/git
command: [sh, -c]
args: ["git clone --depth=1 -b {{workflow.parameters.branch}} {{workflow.parameters.repo}} /workspace/src"]
volumeMounts:
- { name: workspace, mountPath: /workspace }
- name: eslint
container:
image: node:20-alpine
command: [sh, -c, "cd /workspace/src && npm ci && npx eslint src/"]
volumeMounts:
- { name: workspace, mountPath: /workspace }
- name: jest-test
retryStrategy:
limit: 2
retryPolicy: OnFailure
container:
image: node:20-alpine
command: [sh, -c, "cd /workspace/src && npm ci && npm test -- --ci --coverage"]
volumeMounts:
- { name: workspace, mountPath: /workspace }
- name: kaniko
container:
image: gcr.io/kaniko-project/executor:latest
args:
- --context=/workspace/src
- --destination=registry.example.com/app:{{workflow.parameters.commit-sha}}
- --cache=true
volumeMounts:
- { name: workspace, mountPath: /workspace }
- name: trivy-scan
container:
image: aquasec/trivy:latest
command: [trivy, image, --severity, HIGH,CRITICAL, --exit-code, "1",
"registry.example.com/app:{{workflow.parameters.commit-sha}}"]
- name: kubectl-apply
container:
image: bitnami/kubectl:latest
command: [sh, -c]
args:
- |
kubectl set image deployment/app
app=registry.example.com/app:{{workflow.parameters.commit-sha}}
-n production
kubectl rollout status deployment/app -n production --timeout=300s
이 파이프라인은 clone → lint/test 병렬 → 이미지 빌드 → 보안 스캔 → 배포 순서로 진행됩니다. when 조건으로 main 브랜치만 배포하고, ttlStrategy로 완료된 워크플로를 자동 정리합니다.
운영 팁: 모니터링·디버깅
- argo CLI:
argo list,argo get,argo logs로 워크플로 상태와 로그 확인 - Argo UI: DAG 시각화로 병목 스텝 식별, 재실행 버튼으로 실패 스텝만 재시도
- Prometheus 메트릭:
argo_workflows_count,argo_workflows_error_count등으로 성공률 모니터링 - 리소스 제한:
parallelism필드로 동시 실행 Pod 수 제한, 클러스터 과부하 방지
관련 글
- K8s ArgoCD GitOps 배포 — ArgoCD와 Argo Workflows를 함께 사용하는 GitOps 전략
- K8s Argo Rollouts 배포 전략 — Canary/Blue-Green 배포와 워크플로 통합