LabHub

CI/CD 파이프라인 · 빌드 자동화 · 실습

셸로 만드는 3단계 파이프라인

LabHub 에서 이어서 보기

이 실습은 진짜 VM 에서 돕니다

이 상자는 파드가 아니라 KubeVirt 가 띄운 가상머신입니다. 리눅스 커널이
따로 돌고 systemd 가 실제로 서비스를 관리하며, docker 는 흉내가 아니라
진짜 도커 엔진입니다. docker run 으로 띄운 컨테이너는 실제로 프로세스가
되고 docker execdocker logs 도 그대로 동작합니다.

예전에는 이 실습이 파드 안에서 돌았습니다. 커널 권한을 전부 내려놓은 상자라
컨테이너를 띄우는 단계가 막혀 있었고, 그래서 이미지 아카이브를 직접 풀어
보는 우회로 배웠습니다. 이제 우회가 필요 없습니다.

알아 둘 것이 둘 있습니다.

목표

셸 스크립트만으로 build → test → package 3단계 파이프라인을 만들고, 소스 해시로 이름 붙인 불변 아티팩트와 이미지 태그까지 직접 만들어 본다.

왜 중요한가

CI 도구는 몇 년마다 바뀌지만 원리는 바뀌지 않는다. 단계는 순서가 있고, 앞 단계가 실패하면 뒤 단계는 돌면 안 되며, 산출물은 무엇으로 만들었는지 이름만 보고 알 수 있어야 한다. 태그는 사람이 옮길 수 있는 이름표라서 tj-actions/changed-files 사건처럼 통째로 재지정될 수 있고, 그래서 배포 식별자는 커밋 SHA 처럼 변경 불가능한 값이어야 한다. 프로덕션에 latest 만 있으면 무엇이 배포됐는지 추적할 수 없고 되돌릴 대상도 없다. 이 실습은 그 원리를 벤더 UI 없이 손으로 재현한다.

단계

1. /root/ci1/pipeline.sh 를 만들고 chmod +x 로 실행 권한을 준다. 스크립트 앞부분에 set -euo pipefail 을 넣는다(채점은 set -e 계열, set -u, pipefail 을 각각 확인한다). 빌드 대상으로 /root/ci1/src/ 디렉터리를 만들고 파일을 2개 이상 넣는다.
2. 파이프라인은 각 단계 시작 때 ::stage build, ::stage test, ::stage package 를 이 순서로 한 번씩 출력하고, 끝나면 SUCCESS 를 출력한다. 성공한 실행의 출력을 /root/ci1/run1.log 에 저장한다.
3. package 단계는 /root/ci1/out/app-<해시>.tar.gz 를 정확히 1개 만든다. <해시>cat /root/ci1/src/* | sha256sum | cut -c1-12 로 계산한 12자다. 파일은 tar tzf 로 열리는 진짜 gzip tar 여야 한다.
4. 같은 소스로 다시 실행하면 이미 있는 아티팩트를 재사용한다. 이때 ::artifact-exists 를 출력하고 그 실행 로그를 /root/ci1/run2.log 에 저장한다. /root/ci1/outapp-*.tar.gz 는 여전히 1개여야 한다.
5. /root/ci1/out/build-info.json 을 만든다. 필드는 source_hash(위 12자 해시), status(문자열 success), stages(숫자 3), created_at(시각 문자열)이다.
6. /root/ci1/tests/fail-flag 파일을 만들어 test 단계가 실패하게 하고 파이프라인을 다시 실행한다. 출력은 /root/ci1/fail.log, 종료코드는 /root/ci1/fail-exit.txt 에 저장한다(0 이 아니어야 한다). fail.log 에는 ::stage test 는 있고 ::stage package 는 없어야 한다. pipeline.sh 에는 || true 를 쓰지 않는다. 확인이 끝나면 /root/ci1/tests/fail-flag 를 지워 원상복구한다.
7. 아티팩트를 담은 이미지를 labhub/ci:<해시12> 태그로 빌드한다. 베이스 이미지는 파드에 미리 있는 alpine:3.20, busybox:1.36, python:3.12-alpine, nginx:1.27-alpine 중에서만 고른다.
8. 같은 이미지에 docker taglabhub/ci:latest 를 추가로 붙인다. 그리고 build-info.jsontags 배열을 넣어 labhub/ci:<해시12>labhub/ci:latest 두 값을 모두 기록한다(2개 이상).

참고

단계 8개

  1. 파이프라인 골격과 안전 옵션
  2. build → test → package 순서
  3. 소스 해시로 이름 붙이기
  4. 같은 입력이면 다시 만들지 않기
  5. 빌드 메타데이터 남기기
  6. 실패는 삼키지 말고 멈춘다
  7. 커밋마다 바뀌는 태그로 이미지 굽기
  8. latest 는 별칭, 해시는 식별자