Chap 17. Workflow 관리

ka8main.png

Argo workflow

쿠버네티스 core API에는 일회성 배치 작업을 수행하는 Job 리소스가 존재한다. 간단한 retry정책이나 parallel 실행이 가능하지만 작업간 종속성 부여, 조건부 실행, 에러 핸들링 등 고급 워크플로우 관리 기능은 부재한다.

이를 해결하고자 Argo Project에서 Argo workflow를 개발했다. Argo workflow는 쿠버네티스 워크플로우 엔진으로 CNCF의 incubating 프로젝트로 등록되어 있다.

사용자가 원하는 Workflow를 직접 구성할 수 있으며 작업간 종속성을 만들어 순차적으로 실행할 수 있다. 또한 병렬실행이나 에러 핸들링 등과 같은 고급 워크플로우 관리 기능과 사용자를 위한 웹 UI도 제공한다. 사용자는 쿠버네티스 내장 리소스처럼 워크플로우를 생성, 삭제 및 관리할 수 있다.

동작 방법

Argo workflow도 다른 Operator와 마찬가지로 사용자 정의 리소스에 따라 사용자 컨트롤러가 해당 정의를 보고 특정 동작을 수행한다. Argo workflow에서 특정 동작이란 순차적인 작업의 실행을 의미한다.

Argo workflow의 장점

  1. 실행의 단위가 컨테이너 레벨에서 이루어지기 때문에 고립성이 높다. 개별 Job마다 실행 환경이 다른 경우 실행 환경이 서로 뒤엉키지 않고 각각 독립 환경을 제공할 수 있다.
  2. 하나의 역할만을 담당하는 Job을 단일하게 개발할 수 있기 때문에 재사용성을 무척 높일 수 있다. 데이터의 입출 인터페이스만 잘 맞춰 놓는다면 단일한 역할을 담당하는 Job을 여러 개 만든 다음 레고 블럭처럼 쌓아 올릴 수 있다.

Argo workflow의 단점

  1. Pod을 생성하고 삭제하는 비용이 적지 않으므로 작은 일을 처리하는 많은 Pod을 생성할 경우 오히려 성능 저하가 일어난다. 작업이 간단하고 리소스가 많이 필요하지 않은 경우에는 차라리 컨테이너 내부 프로세스나 쓰레드 레벨에서 처리하는 것이 더 효율적일 수 있다.
  2. 스텝마다 개별적인 컨테이너를 실행하기에 Job간의 데이터를 빠르게 공유하는 것이 비교적 쉽지 않다.(볼륨 연결을 통해 해소 가능)

설치 방법

# Argo Workflow 설치

# 1. 네임스페이스 생성
kubectl create namespace argo
# Argo 관련 리소스를 격리하여 관리하기 위한 전용 네임스페이스 생성

# 2. Argo Workflow 매니페스트 적용
kubectl apply -n argo -f https://github.com/argoproj/argo-workflows/releases/latest/download/install.yaml
# 공식 GitHub에서 최신 install.yaml 파일을 적용하여 필요한 CRD 및 리소스를 생성

# 3. 설치된 리소스 확인
kubectl get all -n argo
# Argo Controller, Server, 관련 서비스 등이 정상적으로 생성되었는지 확인

# 4. Argo Server 포트포워딩 (웹 UI 사용 시)
kubectl -n argo port-forward deployment/argo-server 2746:2746
# localhost:2746 주소를 통해 Argo 웹 UI에 접근할 수 있음

# 5. 기본 서비스 계정에 admin 권한 부여
kubectl create clusterrolebinding argo-default-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=argo:default
# argo 네임스페이스 내의 default 서비스 계정에 클러스터 관리자 권한 부여

# 6. Ingress 리소스 설정 (Ingress Controller가 설치되어 있어야 작동)
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argo-server-ingress
  namespace: argo
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
    - host: argo.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: argo-server
                port:
                  number: 2746
EOF
# argo-server에 대한 외부 접근을 Ingress로 설정함. argo.example.com 으로 접속 가능

Workflow 구성하기

workflow 리소스를 이용하면 다양한 워크플로우 구성이 가능하다. 몇가지 에제를 소개한다.

단일 Job 실행

가장 기본이 되는 Workflow 실행이다. 단일 작업을 실행한다. 기능적으로 쿠버네티스 기본 배치 작업인 Job 리소스와 크게 다르지 않다.

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: hello-world-
spec:
  entrypoint: whalesay
  templates:
    - name: whalesay
      container:
        image: docker/whalesay
        command: [cowsay]
        args: ["hello world"]
  • kind: 이 리소스의 종류를 나타냄. Argo에서 제공하는 Custom Resource Definition(CRD) 중 하나로, 일련의 Job을 정의하고 실행함

  • apiVersion: 이 리소스가 속한 API 그룹 및 버전. Argo Workflow의 CRD는 ‘argoproj.io’ 그룹에 속하며, 현재는 ‘v1alpha1’ 버전 사용

  • metadata.generateName: Workflow 이름을 자동 생성할 때 사용할 prefix. 실제 이름은 ‘hello-world-’ 뒤에 무작위 문자열이 붙어서 생성됨 (예: hello-world-xyz12)

  • spec.entrypoint: 실행 시작점으로 사용할 템플릿 이름. 아래 templates 목록 중 name: whalesay 템플릿을 첫 단계로 실행함

  • spec.templates: 워크플로우 내에서 사용할 작업(step)을 정의하는 영역. 여러 개의 작업을 정의할 수 있음

  • templates.name: 템플릿 이름. entrypoint에서 참조되며 이 템플릿이 실제로 실행되는 컨테이너 작업을 정의함

  • templates.container.image: 실행할 컨테이너 이미지. 여기서는 말풍선 캐릭터를 출력하는 whalesay 이미지를 사용함

  • templates.container.command: 컨테이너 내에서 실행할 명령어. cowsay는 인자로 주어진 텍스트를 말풍선 형태로 출력함

  • templates.container.args: 명령어에 넘겨줄 인자. 이 경우 cowsay "hello world" 명령이 실행됨

CICD 파이프라인 구축

Argo Workflow를 사용하면 코드 클론, 테스트, 빌드, 배포 등의 단계를 자동화하여 쿠버네티스 기반의 CI/CD 파이프라인을 구성할 수 있다. 다음은 간단한 Argo 기반 CI/CD 예제로, GitHub 저장소에서 코드를 가져와 테스트한 후 컨테이너 이미지로 빌드하는 워크플로우이다.

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: cicd-pipeline-
spec:
  entrypoint: main
  templates:
    - name: main
      steps:
        - - name: clone
            template: git-clone
        - - name: test
            template: run-tests
        - - name: build
            template: build-image

    - name: git-clone
      container:
        image: alpine/git
        command: ["sh", "-c"]
        args: ["git clone https://github.com/example/repo.git && ls repo"]

    - name: run-tests
      container:
        image: node:18
        workingDir: /src
        command: ["sh", "-c"]
        args: ["cd repo && npm install && npm test"]

    - name: build-image
      container:
        image: docker:dind
        command: ["sh", "-c"]
        args: ["cd repo && docker build -t myapp:latest ."]

설명

  1. clone 단계: alpine/git 이미지를 사용해 지정된 Git 저장소의 코드를 클론함
  2. test 단계: Node.js 환경에서 테스트 실행 (예: Jest)
  3. build 단계: Docker-in-Docker 환경에서 이미지 빌드 수행

위 예제는 기본적인 CI/CD 흐름을 보여주는 것으로, 실제 배포까지 확장하려면 이미지 푸시 및 배포 리소스 업데이트 등의 단계를 추가할 수 있다. 또한 공용 레지스트리에 푸시하려면 docker login 등의 인증 처리도 필요하다.

부록: Argo Workflow 자동 트리거 구성

실제 CI/CD 환경에서는 워크플로우를 수동으로 실행하기보다는 자동으로 트리거되도록 구성하는 것이 일반적이다. Argo Workflow에서는 아래 두 가지 방법이 널리 사용된다.

1. Argo Events를 이용한 GitHub Webhook 트리거

Argo Events는 다양한 외부 이벤트(GitHub Push, Cron, Kafka 등)를 감지하여 Argo Workflow를 트리거할 수 있는 이벤트 프레임워크이다.

  • Argo Events 설치:

    kubectl create namespace argo-events
    kubectl apply -n argo-events -f https://github.com/argoproj/argo-events/releases/latest/download/install.yaml
  • 그 후, 다음 리소스를 정의한다:

    • EventSource: GitHub webhook 이벤트를 수신
    • Sensor: 이벤트 수신 시 워크플로우 실행
    • WorkflowTemplate: 실행할 워크플로우 정의

참고: GitHub 리포지토리에서 webhook을 등록하고, 인증 토큰과 함께 push 이벤트를 전송해야 한다.

2. CronWorkflow를 통한 시간 기반 자동 실행

CronWorkflow는 일정한 시간 간격으로 워크플로우를 실행할 수 있게 해주는 Argo의 내장 리소스이다.

예시:

apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
  name: daily-build
spec:
  schedule: "0 9 * * *" # 매일 오전 9시
  timezone: "Asia/Seoul"
  concurrencyPolicy: "Replace"
  startingDeadlineSeconds: 30
  workflowSpec:
    entrypoint: main
    templates:
      - name: main
        container:
          image: alpine
          command: ["sh", "-c"]
          args: ["echo 'Daily build triggered'"]

이 방식은 테스트나 빌드를 주기적으로 실행하고자 할 때 유용하다.