CI/CD 파이프라인
Lumie의 CI/CD는 Tekton Pipelines로 구성됩니다. Gitea(github.lumie-infra.com)에 코드가 푸시되면 웹훅이 Tekton EventListener를 호출하고, Kaniko로 컨테이너 이미지를 빌드하여 Zot 레지스트리에 푸시한 뒤, lumie-infra 레포의 common-values.yaml을 업데이트하면 ArgoCD가 자동으로 클러스터를 동기화합니다.
중요: Tekton의
git-update-values태스크는 내부 Gitea 서비스 URL(http://gitea-http.gitea.svc.cluster.local:3000/Lumie-Edu/lumie-infra.git)을 사용합니다.github.lumie-infra.com(Teleport 경유)이 아닙니다. 커밋 author는Tekton CI입니다.
전체 흐름
파이프라인 목록
| 파이프라인 이름 | 대상 | 빌드 도구 |
|---|---|---|
lumie-springboot-build-deploy | lumie-backend (Spring Boot 모노리스) | Kaniko |
fastapi-build-deploy | Worker 서비스 (grading, report, analysis, chatbot 등) | Kaniko |
nextjs-build-deploy | lumie-frontend, lumie-document | Kaniko |
lumie-springboot-build-deploy
백엔드 모노리스 전용 파이프라인입니다. lumie-backend 레포에 푸시되면 단일 PipelineRun이 생성됩니다. springboot-ci 태스크가 Gradle 테스트 → Kaniko 빌드를 순서대로 수행합니다.
# 파이프라인 파라미터 (TriggerTemplate에서 주입)
params:
- git-url: https://github.com/Lumie-Edu/lumie-backend.git
- git-revision: main # 브랜치명 (이미지 태그로도 사용)
- service-name: lumie-backend
- context-dir: . # 레포 루트에서 빌드
- dockerfile-path: Dockerfile
- image-prefix: applications/
- update-values: "true"
- values-file-path: applications/lumie/backend/common-values.yaml
- informational: "false" # false = 테스트 실패 시 빌드 중단
빌드 타임아웃: 45분 (tasks.ci.timeout: "40m")
informational 파라미터가 "true"이면 Gradle 테스트 실패가 경고로 기록되고 Kaniko 빌드는 계속됩니다. "false"(기본값)이면 테스트 실패 시 파이프라인이 중단됩니다.
fastapi-build-deploy
lumie-worker 레포 내 서비스별 디렉토리 변경을 CEL 필터로 감지하여 개별 PipelineRun을 실행합니다.
| 서비스 | 감지 경로 | values 파일 |
|---|---|---|
grading-svc | services/grading/ | applications/lumie/worker/grading-svc/common-values.yaml |
report-svc | services/report/ | applications/lumie/worker/report-svc/common-values.yaml |
analysis-svc | services/analysis/ | applications/lumie/worker/analysis-svc/common-values.yaml |
chatbot-svc | services/chatbot/ | applications/lumie/worker/chatbot-svc/common-values.yaml |
temp-omr-grading | services/temp-omr-grading/ | (values 업데이트) |
빌드 타임아웃: 30분
nextjs-build-deploy
lumie-frontend, lumie-document 레포를 처리합니다.
Tekton 트리거 구성
EventListener
모든 Gitea 레포에서 오는 웹훅은 단일 github-listener EventListener로 수신됩니다.
# 트리거 목록 (주요)
triggers:
- github-push-lumie-backend # lumie-backend 레포 → lumie-backend-build-template
- github-push-lumie-frontend # lumie-frontend 레포 → lumie-frontend-build-template
- github-push-lumie-document # lumie-document 레포 → lumie-document-build-template
- github-push-fastapi # joossam(AI) 레포 → fastapi-build-template
- github-push-lumie-grading-svc
- github-push-lumie-report-svc
- github-push-lumie-chatbot-svc
- github-push-lumie-analysis-svc
필터링 (CEL)
모든 트리거는 두 개의 CEL 인터셉터를 통과합니다:
- 이벤트 + 브랜치 필터:
header.match('X-Gitea-Event', 'push') && body.ref.startsWith('refs/heads/main')— Gitea push 이벤트 + main 브랜치만 처리 - 레포/경로 필터: 레포 이름 또는 변경 파일 경로를 기준으로 라우팅
# Worker 서비스 경로 기반 필터 예시 (grading)
- name: "filter"
value: >
body.repository.name in ['lumie-worker'] &&
body.commits.exists(c,
c.added.exists(f, f.startsWith('services/grading/')) ||
c.modified.exists(f, f.startsWith('services/grading/'))
)
HMAC 검증
Gitea 웹훅 시크릿은 github-webhook-secret Kubernetes Secret에 저장됩니다. 모든 요청은 서명 검증 후 처리됩니다.
Tekton Task 상세
kaniko-clone-build-github
소스 코드를 Gitea에서 clone하고 Kaniko로 이미지를 빌드하여 Zot에 푸시합니다.
# 주요 파라미터
params:
- GIT_URL: 소스 레포 URL
- GIT_REVISION: 브랜치명 (이미지 태그로 사용됨)
- IMAGE: zot.lumie-infra.com/applications/<app-name>
- TAG: git-revision 값 (브랜치명)
- CONTEXT: 빌드 컨텍스트 디렉토리
- DOCKERFILE: Dockerfile 경로
# 결과
results:
- IMAGE_TAG: 푸시된 이미지 태그 (다음 태스크로 전달)
Docker 데몬 없이 컨테이너 내부에서 이미지를 빌드합니다.
git-update-values
Kaniko 빌드 성공 후 lumie-infra 레포의 values 파일에서 image.tag 값을 업데이트하고 커밋/푸시합니다.
params:
- VALUES_FILE_PATH: 업데이트할 values 파일 경로 (콤마 구분 다중 지원)
- IMAGE_DIGEST: 새 이미지 태그 (kaniko-clone-build-github 결과)
- APP_NAME: 앱 이름 (커밋 메시지에 사용)
- YQ_PATH: 업데이트할 YAML 경로 (기본: .image.tag)
커밋 메시지 형식: CHORE(app): update <app-name> image to <tag> (author: Tekton CI, email: tekton@lumie.local)
동시 푸시 충돌 시 최대 5회 재시도 + git pull --rebase로 자동 복구합니다.
이미지 태그 전략
이미지 태그는 Git 브랜치명을 사용합니다. main 브랜치에서 빌드하면 태그는 main입니다.
zot.lumie-infra.com/applications/lumie-backend:main
values 파일에 기록되는 실제 태그는 커밋 SHA입니다 (kaniko 빌드 결과 IMAGE_TAG):
# common-values.yaml 업데이트 후
common:
image:
tag: "3ba13d48" # 커밋 SHA 앞 8자리
네임스페이스 및 리소스 쿼터
모든 파이프라인은 tekton-pipelines 네임스페이스에서 실행됩니다. 리소스 쿼터가 설정되어 동시 빌드 수를 제한합니다.
# 실행 중인 PipelineRun 확인
kubectl get pipelinerun -n tekton-pipelines
# 완료된 PipelineRun (자동 삭제: onSuccessfulCompletion: delete)
# 실패한 PipelineRun은 보존됩니다
# 실패한 PipelineRun 로그 확인
kubectl logs -n tekton-pipelines -l tekton.dev/pipelineRun=<run-name>
# Tekton Dashboard 접근 (Teleport App Access)
# https://tekton.lumie-infra.com
새 서비스 CI/CD 추가 방법
eventlistener.yaml에 새 트리거 추가:
- name: github-push-my-service
interceptors:
- ref:
name: "github"
params:
- name: "secretRef"
value:
secretName: github-webhook-secret
secretKey: webhook-secret
- name: "eventTypes"
value: ["push"]
- ref:
name: "cel"
params:
- name: "filter"
value: "body.ref.startsWith('refs/heads/main')"
- ref:
name: "cel"
params:
- name: "filter"
value: "body.repository.name in ['my-service-repo']"
bindings:
- ref: github-push-binding
template:
ref: my-service-build-template
-
triggertemplate.yaml에 TriggerTemplate 추가 (파이프라인 파라미터 정의) -
Gitea 레포의 Webhook 설정에 EventListener URL 등록
-
lumie-infra에 해당 서비스ArgoCD Application추가