개요
- 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_ID | AWS Access Key |
AWS_SECRET_ACCESS_KEY | AWS 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:
stage: test
image: python:3.11
script:
- pip install -r requirements.txt
- python -m pytest tests/
only:
- next
- main
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:
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:
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
동작 흐름
next (DEV) 또는 main (LIVE) 에 push
- test → build (ECR push) → deploy 순서로 실행
- deploy stage 에서 deployment repo 를 clone
kustomize edit set image 로 kustomization.yaml 의 newTag 를 commit hash 로 교체
- deployment repo 에 commit & push
- ArgoCD 가 Git 변경을 감지, 자동으로 클러스터에 반영
kustomize edit set image 가 변경하는 부분
images:
- name: <account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/<org>/<service>
newTag: a1b2c3d
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
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:
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 = 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(
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 App | Batch App |
|---|
| stages | test → build → deploy | test → build → publish |
| 이미지 저장 | ECR | ECR |
| 배포 트리거 | deployment repo push → ArgoCD sync | S3 버전 → Airflow DAG 실행 |
| 이미지 태그 관리 | kustomize edit set image | S3 image-version.json |
| 실행 방식 | 상시 운영 (Deployment) | 주기/온디맨드 (KubernetesPodOperator) |
reference