CI/CD 파이프라인 · 배포 전략: 블루그린과 카나리 · 실습
블루그린 전환과 카나리 분석
이 실습은 진짜 VM 에서 돕니다
이 상자는 파드가 아니라 KubeVirt 가 띄운 가상머신입니다. 리눅스 커널이
따로 돌고 systemd 가 실제로 서비스를 관리하며, docker 는 흉내가 아니라
진짜 도커 엔진입니다. docker run 으로 띄운 컨테이너는 실제로 프로세스가
되고 docker exec 도 docker logs 도 그대로 동작합니다.
예전에는 이 실습이 파드 안에서 돌았습니다. 커널 권한을 전부 내려놓은 상자라
컨테이너를 띄우는 단계가 막혀 있었고, 그래서 이미지 아카이브를 직접 풀어
보는 우회로 배웠습니다. 이제 우회가 필요 없습니다.
알아 둘 것이 둘 있습니다.
- 처음 뜨는 데 1분 남짓 걸립니다. VM 이 부팅하고 도커를 설치하기
- 브라우저 미리보기가 없습니다. VM 으로 들어오는 연결은 채점 포트
때문입니다. 파드 실습(보통 40초)보다 느립니다.
하나만 열려 있습니다. 웹 서버를 띄웠다면 VM 안에서 curl 로 확인하세요.
목표
컨테이너 두 개로 블루그린 환경을 만들고, 트래픽 전환·헬스체크·자동 롤백·카나리 비율 분배·자동 중단 판정을 셸로 구현한다.
왜 중요한가
배포 전략의 차이는 결국 롤백 속도와 트래픽 제어 정밀도의 교환이다. 블루그린은 두 환경을 동시에 띄우므로 리소스가 Pod 2배로 들지만 문제가 보이면 트래픽을 통째로 즉시 되돌릴 수 있다. 카나리는 1% 단위로 정밀하게 노출하지만 되돌릴 때 단계가 필요하다. 그래서 대부분의 서비스에는 카나리를, 결제나 인증처럼 한 건의 오류도 비용이 큰 서비스에는 블루-그린을 쓴다. 이 실습에서 활성 대상은 파일 한 줄로 표현된다. 그 한 줄을 누가 언제 바꾸고, 바꾼 뒤 무엇을 확인하고, 확인이 실패하면 어떻게 되돌리는지가 배포 자동화의 전부다.
단계
1. 응답 본문에 version=blue 가 들어가는 컨테이너를 이름 ci3-blue 로 띄우고 127.0.0.1:8091 로 게시한다. curl http://127.0.0.1:8091/ 에서 그 문자열이 보여야 한다.
2. 같은 방식으로 ci3-green 을 127.0.0.1:8092 에 띄우되 본문은 version=green 으로 한다. 이때 ci3-blue 는 계속 running 이어야 한다.
3. /root/ci3/switch.sh <blue|green> 을 만든다. 활성 대상 이름을 /root/ci3/active 에 쓰되, ACTIVE_FILE 환경변수가 설정돼 있으면 그 경로에 쓴다. blue/green 이외의 값이면 아무것도 쓰지 않고 0 이 아닌 코드로 끝낸다. 이 단계를 마칠 때 /root/ci3/active 의 내용은 green 이어야 한다.
4. /root/ci3/health.sh <URL> 을 만든다. 대상이 정상 응답하면 종료코드 0, 아무도 없거나 실패하면 0 이 아닌 코드를 낸다. 채점은 8091, 8092, 그리고 아무도 없는 8099 로 확인한다.
5. /root/ci3/deploy.sh <대상> 을 만든다. 현재 활성 값을 기억해 두고 대상으로 전환한 뒤 그 대상의 포트로 헬스체크한다. 실패하면 활성 값을 이전 값으로 되돌리고 0 이 아닌 코드로 끝낸다. 성공하면 활성 값은 대상으로 남고 종료코드 0 이다. 포트는 PORT_BLUE(기본 8091), PORT_GREEN(기본 8092) 환경변수로 덮어쓸 수 있어야 하고, ACTIVE_FILE 도 존중해야 한다.
6. /root/ci3/canary.sh <퍼센트> 를 만든다. 요청 100건을 보내고 어디로 갔는지 세어 blue=<수> green=<수> 를 출력한다. 두 수의 합은 항상 100 이고, 인자가 0 이면 blue=100 green=0, 100 이면 blue=0 green=100 이어야 한다.
7. /root/ci3/analyze.sh <지표파일> <임계퍼센트> 를 만든다. 지표 파일에는 total=1000 과 errors=10 이 각각 한 줄씩 들어 있다. 에러율은 errors * 100 / total 이고 임계 이하면 종료코드 0, 초과하면 실제 에러율을 출력하고 0 이 아닌 코드를 낸다. total=0 이면 표본이 없으므로 통과시키지 말고 실패로 처리한다.
8. /root/ci3/deploy-report.json 을 만든다. 필드는 strategy(blue-green 또는 canary), active(현재 /root/ci3/active 내용과 같아야 한다), previous(active 와 달라야 한다), rollback_used, error_rate_pct, abort_threshold_pct 다. rollback_used 에는 이번 배포에서 롤백이 실제로 일어났는지를 JSON 불리언(true 또는 false)으로 적는다 — 문자열 "true" 는 안 된다. error_rate_pct 는 abort_threshold_pct 이하여야 한다.
참고
- 본문 만들기 예:
/root/ci3/blue/index.html에version=blue를 넣고docker run -d --name ci3-blue -p 127.0.0.1:8091:80 -v /root/ci3/blue:/usr/share/nginx/html:ro nginx:1.27-alpine. - 1024 미만 포트는 바인딩할 수 없다. 반드시 8091/8092 처럼 높은 포트를 127.0.0.1 에 게시한다.
rollback_used는true든false든 사실대로 적으면 된다. 다만 반드시 JSON 불리언이어야 하고"false"처럼 따옴표를 두르면 타입 검사에서 걸린다.- 카나리 분배는 난수 대신 순번(예: 100 으로 나눈 나머지)을 쓰면 결과가 재현된다.
- 흔한 실수: green 을 띄우면서 blue 를 내리기, switch.sh 가
ACTIVE_FILE을 무시하고 항상 고정 경로에 쓰기, active 와 previous 를 같은 값으로 기록하기.
단계 8개
- blue 환경 띄우기
- green 환경을 나란히 띄우기
- 활성 대상 전환 스크립트
- 헬스체크
- 실패하면 자동 롤백
- 비율 분배
- 자동 중단 판정
- 배포 리포트