Introduction
최근 저희 연구실에서 진행한 프로젝트의 핵심 과제는 서버리스 워크플로우(Serverless Workflow)에서 발생하는 실행 데이터와 로그를 효율적으로 수집하는 시스템을 구축하는 것이다.
서버리스 및 컨테이너 기반의 워크플로우는 실행 시간이 짧고 상태를 저장하지 않는(Stateless) 특성 때문에, 작업이 종료되는 즉시 관련 컨텍스트가 사라진다. 때문에 기존의 폴링(Polling) 방식이나 상시 실행되는 에이전트 방식으로는 리소스 낭비가 심하거나 정확한 수집 시점을 포착하기 어려운 한계가 있다.
이를 해결하기 위해 우리는 Argo Events/Workflows로 구축하는 서버리스 워크플로우 파이프라인을 설계하고 구현했다.
시스템 아키텍처 개요
필자가 직접 그린 아키텍처
구축하고자 하는 시스템은 상시 실행되는 서버 없이, 이벤트가 발생했을 때만 파드(Pod)를 생성하여 로그를 처리하고 소멸하는 이벤트 기반 아키텍처(Event-Driven Architecture)이다.
1.
Event Generator (k6): k6로 부하 테스트를 수행한다.
2.
Event Ingestor (Argo Events):
•
EventSource: k6로부터 HTTP 요청을 수신하는 엔드포인트 제공
•
EventBus: 이벤트를 수신하는 EventSource와 이벤트를 처리하는 Sensor 사이를 연결하는 메시지 전송 계층(Transport Layer)
•
Source: 수신된 이벤트의 페이로드를 필터링하고, 사전 정의된 trigger 정책에 따라 Argo Workflow 리소스를 생성한다.
3.
Log Processor (Argo Workflows):
•
Sensor에 의해 트리거된 워크플로우(Workflow-A)가 실행된다.
•
이 워크플로우는 DAG(Directed Acyclic Graph) 구조로 실행된다.
Argo Events
구성 요소
EventSource
•
역할: 이벤트의 진입점(Entry Point)이어서 엔드포인트를 열고 외부 요청을 기다린다.
•
작동 방식: 요청이 오면, EventBus에 publish(발행)한다.
EventBus
•
역할: EventSource와 Sensor 사이의 중앙 채널 역할을 한다.
•
작동 방식: 클러스터 내부에 NATS 같은 메시지 브로커를 배포하여 EventBus로 사용한다.
Sensor
•
역할: 이벤트가 발생했을 때, 어떤 액션을 할지 정의한다.
•
작동 방식:
◦
dependencies 섹션을 통해 감지할 이벤트를 정의하고, 해당 이벤트를 인지하면 triggers 섹션에 정의된 액션을 실행함
◦
외부 요청을 받으면 WorkflowTemplate을 submit하여 실제 워크플로우를 시작함
코드 예시:
동작 방식
<전체 흐름>
외부 요청 ⇒ [EventSource Service] ⇒ (publish) ⇒ [EventBus] ⇒ (Subscribe) ⇒ [Sensor] ⇒ (Trigger) ⇒ [Workflow] ⇒ 여러 함수들 실행
1. EventSource: 외부 요청 수신
eventsource.yaml의 service 항목에 의해 생성된 Service가 외부 트래픽(POST /trigger)을 받아서 Pod에 넘겨준다.
spec:
eventBusName: default # (권장) 명시적으로 지정
service: # [필수] 이 부분이 있어야 Service 객체가 생성됨
ports:
- port: 12000
targetPort: 12000
webhook:
workflowA: # 2. 이 이름도 Sensor가 참조함
port: "12000"
endpoint: "/workflow-a"
method: "POST"
YAML
복사
•
사용자 요청: POST https://eventsource.argo-events.sl.cslab.systems/workflow-a
•
Ingress: /workflow-a 경로를 보고 workflow-a-webhook-eventsource-svc 서비스로 전달
•
EventSource: /workflow-a 엔드포인트에서 대기 중이던 웹훅이 요청을 수신 → EventBus로 이벤트 publish
2. EventBus: 버스로 전송
EventSource는 받은 요청을 eventBusName: default 로 지정된 EventBus(NATS)로 보낸다.
# eventsource.yaml
spec:
eventBusName: default # "default"라는 이름의 버스를 타고 이동
YAML
복사
3. Sensor: 버스에서 픽업
sensor-simple.yaml 의 Sensor가 EventBus를 구독하다가 이벤트를 낚아챈다.
dependencies:
- name: k6-webhook-dep
eventSourceName: workflow-a-webhook # "누가 보낸거냐?" (EventSource 이름)
eventName: workflowA # "어떤 이벤트냐?" (Webhook 이름)
YAML
복사
workflowA 라는 이벤트가 EventBus에 뜨는지 계속 감시한다. 이때, 이벤트를 감지하면 triggers 속성을 보게 된다. source 속성 아래에 있는 YAML 덩어리를 메모리에 로드하는데, 이게 새로 생성될 Workflow의 설계도 라고 생각하면 된다.
Sensor는 Workflow YAML을 K8s API Server에게 보낸다. 쿠버네티스 동작 흐름에 따라 K8s API Server는 etcd에 해당 상태들을 저장하고 Argo Workflow Controller가 “어, 새 Workflow가 생겼네?” 하고 감지하여 실제 Pod를 띄우고 작업을 시작한다.
4. Trigger: 워크플로우 실행
Sensor가 이벤트를 잡으면, 정의된 Trigger를 당긴다. 이때 이벤트에 담겨있던 데이터(Body)를 Workflow의 파라미터로 넣어준다.
triggers:
- template:
argoWorkflow:
operation: submit # 워크플로우 제출(실행)
source:
resource:
kind: Workflow
spec:
workflowTemplateRef:
name: wft-a-simple # "이 템플릿으로 실행해라"
# [데이터 전달의 핵심]
parameters:
- src:
dependencyName: k6-webhook-dep
dataKey: body # "이벤트의 Body 내용을 꺼내서"
dest: spec.arguments.parameters.0.value # "워크플로우의 첫 번째 파라미터에 넣어라"
YAML
복사
Argo Workflow
구성 요소
Argo-Server
•
역할: Argo Workflows의 웹 UI 및 API 서버이다.
•
기능: 사용자가 브라우저를 통해 워크플로우(Workflow)의 실행 상태를 시각적으로 확인하고, 로그를 조회하며, 템플릿을 관리하거나 새로운 워크플로우를 제출할 수 있게 해주는 대시보드 역할을 한다.
MinIO
•
역할: AWS S3와 호환되는 객체 스토리지(Object Storage) 서버이다.
•
기능: Argo Workflows에서 Artifact(데이터)를 저장하는 저장소로 사용된다. 워크플로우의 각 단계(Step)에서 생성된 결과물(파일, 로그 등)을 저장하거나, 다음 단계로 데이터를 전달할 때 사용하는 중간 저장소 역할을 한다. 보통 온프레미스 환경에서 S3 대신 많이 사용된다.
HTTPBin
•
역할: HTTP 요청 및 응답을 테스트하기 위한 유틸리티 서비스이다.
•
기능: 간단한 HTTP 엔드포인트(예: /get, /post)를 제공하여, 워크플로우가 외부로 HTTP 요청을 보내는 로직을 테스트하거나 데모를 실행할 때 타겟 서버로 자주 사용된다.
Workflow-Controller
•
역할: Argo Workflows의 핵심 엔진(Core Engine)이자 쿠버네티스 커스텀 컨트롤러(Custom Controller)이다.
•
기능:
◦
리소스 감지 및 조정(Reconciliation): 쿠버네티스 API 서버를 지속적으로 모니터링(Watch)하며 Workflow CR(Custom Resource)이 생성되거나 변경되는 것을 감지한다.
◦
실행 흐름 제어: 워크플로우 정의(DAG 또는 Steps)를 해석하여 순서에 맞게 파드(Pod)를 생성하고 스케줄링한다.
◦
상태 관리: 각 단계의 컨테이너 실행 상태(Success, Failed, Error)를 추적하고, 전체 워크플로우의 상태를 업데이트한다.
동작 방식
1.
누가 호출하는가? Argo Workflow Controller
쿠버네티스 클러스터 내부에 설치된 이 Argo Workflow Controller가 Workflow에 적힌 각 step에 맞는 함수들을 호출한다. 즉, 함수 A가 함수 B를 직접 부르는 것이 아니라, Workflow Controller가 함수 A가 끝난 것을 확인 후 뒤, 함수 B를 실행하는 구조이다.
2.
어떻게 호출하는가?
a.
함수 A 실행 (Pod 생성): Workflow가 시작되면 Workflow Controller는 함수 A를 실행하기 위해 쿠버네티스 Pod를 생성한다.
b.
감시 (Watch): Workflow Controller는 함수 A의 Pod 상태를 계속 지켜봅니다(Watch).
c.
완료 감지: 함수 A가 작업을 마치고 종료(Completed)되면, Workflow Controller가 이를 감지한다.
d.
다음 단계 확인 (DAG/Steps): Workflow Controller는 사용자가 작성한 YAML 파일(Workflow 정의)을 확인하여 "A 다음에는 B가 실행되어야 한다"는 순서를 파악한다.
e.
함수 B 실행 (Pod 생성): Workflow Controller는 함수 B를 실행하기 위한 새로운 Pod를 생성하도록 쿠버네티스에 명령을 내린다.
“50대의 추교현이 20대의 추교현에게 감사할 수 있도록 하루하루 최선을 다해 살고 있습니다.”
The End.





