[k8s] GitLab CI/CD pipeline — Serving/Batch 분리

Woong·2026년 4월 14일

Docker, k8s

목록 보기
34/38

개요

  • GitLab CI/CD 파이프라인으로 EKS 배포를 자동화하는 구조를 정리
    • Serving App 과 Batch App 의 파이프라인을 분리하여 운영
    • Serving: 이미지 빌드 → ECR Push → deployment repo kustomize 이미지 태그 교체 → ArgoCD 자동 동기화
    • Batch: 이미지 빌드 → ECR Push → S3 버전 정보 업로드 → Airflow 에서 읽어 실행

사전 준비

ECR Repository 생성
  • 이미지를 저장할 ECR 리포지토리를 미리 생성
    • AWS Console > ECR > Private registry > Create repository
GitLab Project Variables 등록
  • CI 에서 AWS 에 접근하기 위한 키 정보를 등록
    • Settings → CI/CD → Variables
Variable설명
AWS_ACCESS_KEY_IDAWS Access Key
AWS_SECRET_ACCESS_KEYAWS Secret Key

Serving App 파이프라인

  • 상시 운영되는 API 서버 등의 배포 파이프라인
  • 핵심: CI 에서 deployment repo 의 kustomize 이미지 태그를 교체하고 push → ArgoCD 가 자동 동기화
push to next(dev) or main(live)
    → test → build → deploy
.gitlab-ci.yml 예시
variables:
  AWS_REGION: "ap-northeast-1"
  ECR_REPOSITORY: "<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/<org>/<service>"
  DEPLOYMENT_REPO: "https://${GITLAB_USER}:${GITLAB_TOKEN}@git.example.com/team/deployment.git"

stages:
  - test
  - build
  - deploy

# ─────────────────────────────────────────
# Test
# ─────────────────────────────────────────
test:
  stage: test
  image: python:3.11
  script:
    - pip install -r requirements.txt
    - python -m pytest tests/
  only:
    - next
    - main

# ─────────────────────────────────────────
# Build & Push to ECR
# ─────────────────────────────────────────
build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  before_script:
    - apk add --no-cache aws-cli
    - aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $ECR_REPOSITORY
  script:
    - docker build -t $ECR_REPOSITORY:$CI_COMMIT_SHORT_SHA .
    - docker push $ECR_REPOSITORY:$CI_COMMIT_SHORT_SHA
  only:
    - next
    - main

# ─────────────────────────────────────────
# Deploy (DEV) - kustomize image tag 교체
# ─────────────────────────────────────────
deploy_dev:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache git curl
    - curl -sL https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv5.4.1/kustomize_v5.4.1_linux_amd64.tar.gz | tar xz -C /usr/local/bin
  script:
    - git clone $DEPLOYMENT_REPO /tmp/deployment
    - cd /tmp/deployment/k8s/overlays/dev/<app_name>
    - kustomize edit set image $ECR_REPOSITORY=$ECR_REPOSITORY:$CI_COMMIT_SHORT_SHA
    - git add .
    - git commit -m "deploy: <app_name> dev $CI_COMMIT_SHORT_SHA"
    - git push origin next
  only:
    - next

# ─────────────────────────────────────────
# Deploy (LIVE) - main 브랜치
# ─────────────────────────────────────────
deploy_live:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache git curl
    - curl -sL https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv5.4.1/kustomize_v5.4.1_linux_amd64.tar.gz | tar xz -C /usr/local/bin
  script:
    - git clone $DEPLOYMENT_REPO /tmp/deployment
    - cd /tmp/deployment/k8s/overlays/live/<app_name>
    - kustomize edit set image $ECR_REPOSITORY=$ECR_REPOSITORY:$CI_COMMIT_SHORT_SHA
    - git add .
    - git commit -m "deploy: <app_name> live $CI_COMMIT_SHORT_SHA"
    - git push origin main
  only:
    - main
동작 흐름
  1. next (DEV) 또는 main (LIVE) 에 push
  2. test → build (ECR push) → deploy 순서로 실행
  3. deploy stage 에서 deployment repo 를 clone
  4. kustomize edit set imagekustomization.yamlnewTag 를 commit hash 로 교체
  5. deployment repo 에 commit & push
  6. ArgoCD 가 Git 변경을 감지, 자동으로 클러스터에 반영
  • kustomize edit set image 가 변경하는 부분
# kustomization.yaml 의 images 섹션
images:
  - name: <account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/<org>/<service>
    newTag: a1b2c3d  # ← CI 에서 자동 교체

Batch App 파이프라인

  • 데이터 전처리/수집 등 Airflow 에서 주기적으로 실행하는 배치 작업
  • Serving 과 다른 점: deployment repo 를 건드리지 않고, S3 에 이미지 버전 정보를 업로드
push to next(dev) or main(live)
    → test → build → publish
.gitlab-ci.yml 예시
variables:
  AWS_REGION: "ap-northeast-1"
  ECR_REPOSITORY: "<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/<org>/<service>"
  DEV_IMAGE_VERSION_PATH: "s3://<bucket>/dev/version/<service>/image-version.json"
  LIVE_IMAGE_VERSION_PATH: "s3://<bucket>/live/version/<service>/image-version.json"

stages:
  - test
  - build
  - publish

# Test, Build 는 Serving 과 동일
# ...

# ─────────────────────────────────────────
# Publish (DEV) - S3 에 버전 정보 업로드
# ─────────────────────────────────────────
publish_dev:
  stage: publish
  image: amazon/aws-cli:latest
  script:
    - |
      echo '{
        "service": "<service>",
        "version": "'$CI_COMMIT_SHORT_SHA'"
      }' > image-version.json
    - aws s3 cp image-version.json $DEV_IMAGE_VERSION_PATH
  only:
    - next

# ─────────────────────────────────────────
# Publish (LIVE) - S3 에 버전 정보 업로드
# ─────────────────────────────────────────
publish_live:
  stage: publish
  image: amazon/aws-cli:latest
  script:
    - |
      echo '{
        "service": "<service>",
        "version": "'$CI_COMMIT_TAG'"
      }' > image-version.json
    - aws s3 cp image-version.json $LIVE_IMAGE_VERSION_PATH
  only:
    - tags
Airflow 에서의 사용
  • Airflow DAG 에서 S3 의 image-version.json 을 읽어 KubernetesPodOperator 로 실행
import json
import boto3

# S3 에서 버전 정보 읽기
s3 = boto3.client("s3")
obj = s3.get_object(Bucket="<bucket>", Key="dev/version/<service>/image-version.json")
version_info = json.loads(obj["Body"].read())
image_tag = version_info["version"]

# KubernetesPodOperator 로 실행
KubernetesPodOperator(
    task_id="run_batch",
    image=f"<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/<org>/<service>:{image_tag}",
    namespace="airflow",
    ...
)

Serving vs Batch 파이프라인 비교

항목Serving AppBatch App
stagestest → build → deploytest → build → publish
이미지 저장ECRECR
배포 트리거deployment repo push → ArgoCD syncS3 버전 → Airflow DAG 실행
이미지 태그 관리kustomize edit set imageS3 image-version.json
실행 방식상시 운영 (Deployment)주기/온디맨드 (KubernetesPodOperator)

reference

0개의 댓글