GitLab CI/CD · 현장에서의 파이프라인 · 실습
사고 났을 때 운영에 무엇이 나가 있었는지 아무도 몰랐다
목표
고정 환경과 브랜치별 리뷰 환경, 환경을 닫는 잡, 수동 운영 배포를 설정하고, 커밋 SHA 로 남는 배포 기록과 그 기록에서 고르는 롤백, 배포 동결 규칙을 gitlab-ci-local 로 실제로 돌립니다.
왜 중요한가
배포는 되돌릴 수 있어야 안전합니다. 무엇이 어디에 언제 나갔는지가 environment 로 남고, 나간 것이 커밋 SHA 로 식별돼야 사고 때 '그때의 것' 으로 몇 분 안에 돌아갈 수 있습니다. 리뷰 환경은 편하지만 닫는 짝이 없으면 쌓여서 비용과 노출이 되고, 운영 배포의 승인은 allow_failure 값 하나로 게이트가 되기도 장식이 되기도 합니다. 동결 기간처럼 '지금은 내보내지 않는다' 는 약속도 설정으로 새겨야 지켜집니다.
단계
1. /root/glci-deploy 을 git 저장소로 만들고(.gitignore 에 .gitlab-ci-local/) .gitlab-ci.yml 에 stages [deploy, cleanup], 전역 변수 DEPLOY_LOG: /root/glci-deploy-history/deploys.log, 그리고 main 에서만 만들어지는 잡 deploy-staging(deploy)을 두세요. environment 는 이름 staging, URL https://staging.example.com 이고 스크립트는 echo "env=$CI_ENVIRONMENT_NAME url=$CI_ENVIRONMENT_URL" 입니다. main 에 커밋하고 실행하세요.
2. main 이 아닌 브랜치에서만 만들어지는 잡 review-app(deploy)을 더하세요. environment 이름은 review/$CI_COMMIT_REF_SLUG, URL 은 https://$CI_COMMIT_REF_SLUG.review.example.com 이고 스크립트는 1단계와 같은 echo 입니다. 커밋하세요. 채점기는 사본에서 Feature/Login-Page 브랜치로 옮겨 이름이 review/feature-login-page, URL 이 https://feature-login-page.review.example.com 인지 봅니다.
3. review-app 의 environment 에 on_stop: stop-review 와 auto_stop_in: 1 day 를 더하고, 잡 stop-review(cleanup)를 만드세요. 같은 환경 이름에 action: stop, main 이 아닌 브랜치에서 when: manual, 스크립트는 echo "stopping $CI_ENVIRONMENT_NAME" 입니다. 커밋하세요. feature 브랜치에서 stop-review 는 목록에 manual 로 있고, --manual stop-review 로 돌리면 stopping review/<슬러그> 가 찍혀야 합니다.
4. main 에서 when: manual, allow_failure: false 로 만들어지는 잡 deploy-prod(deploy)를 더하세요. environment 는 production, URL 은 https://www.example.com, 스크립트는 echo "env=$CI_ENVIRONMENT_NAME" 입니다. 커밋하세요. 그냥 실행하면 deploy-prod 는 돌지 않고, --manual deploy-prod 를 주면 돌아야 합니다.
5. /root/glci-deploy/scripts/deploy.sh <환경> 을 만드세요. ROLLBACK_TO 가 비어 있으면 태그를 $CI_COMMIT_SHORT_SHA 로 정해 $DEPLOY_LOG 에 <환경> registry.example.com/app:<태그> release 한 줄을 덧붙이고 deployed ... 를 출력합니다. deploy-staging·deploy-prod 의 스크립트 끝에 bash scripts/deploy.sh staging·bash scripts/deploy.sh production 을 더해 커밋하세요. 채점기는 사본에서 커밋 둘을 차례로 배포해 기록이 커밋마다 다른 태그로 남는지 봅니다.
6. deploy.sh 가 ROLLBACK_TO 를 받으면 새 태그를 만들지 않고 그 태그를 다시 내보내게 하세요. 그 환경의 이력에 registry.example.com/app:<ROLLBACK_TO> 로 나간 기록이 없으면 이력에 없는 태그입니다 를 출력하고 실패합니다. 기록 줄의 마지막 낱말은 rollback 입니다. 채점기는 사본에서 두 번 배포한 뒤 첫 태그로 되돌리는 실행과, 없는 태그로 되돌리려는 실행을 합니다.
7. deploy-prod 의 rules 맨 앞에 if: $CI_DEPLOY_FREEZE 이면 when: never 를 두세요. 커밋하세요. --variable CI_DEPLOY_FREEZE=1 로 목록을 보면 deploy-prod 가 없고, 변수가 없으면 manual 로 있어야 합니다. deploy-staging 은 동결과 관계없이 있어야 합니다.
참고
- 이 VM 에는 GitLab 서버와 러너가 없고, gitlab-ci-local 4.75.1 이 .gitlab-ci.yml 을 GitLab 과 같은 규칙으로 해석해 shell 로 잡을 실행합니다.
image:를 적으면 도커로 돌리려 하므로 쓰지 않습니다. 보호 변수·마스킹·CI_JOB_TOKEN·러너 태그·병합 요청 파이프라인 생성은 서버 기능이라 여기서 재현되지 않습니다. - 실행: 저장소 루트에서
gitlab-ci-local --shell-isolation --no-artifacts-to-source(잡마다 따로 된 작업 디렉터리, 산출물을 저장소에 되쓰지 않음), 잡 목록:gitlab-ci-local --list-csv-all, 해석된 설정:gitlab-ci-local --preview. gitlab-ci-local 은 git 이 추적하는 파일만 잡에 넘기므로 파일을 만들면git add하세요. 채점기는 저장소를 사본으로 떠 모든 파일을 커밋한 뒤 같은 도구로 다시 돌립니다. - gitlab-ci-local 의 차이(실측): resource_group 으로 같은 환경의 배포를 줄 세우지 않습니다. manual 잡은 --manual 로 지정해야 돌고, 뒤 스테이지를 막지는 않습니다. 환경 화면·배포 이력·보호 환경 승인·동결 기간 설정은 서버 기능입니다.
- 배포 기록
/root/glci-deploy-history/deploys.log은 저장소 밖에 있습니다. 채점기는 사본을 돌릴 때--variable DEPLOY_LOG=<임시 경로>로 따로 씁니다. - [Environments](https://docs.gitlab.com/ci/environments/) · [Predefined CI/CD variables(CI_COMMIT_REF_SLUG·CI_DEPLOY_FREEZE)](https://docs.gitlab.com/ci/variables/predefined_variables/) · [Resource groups](https://docs.gitlab.com/ci/resource_groups/) · [CI/CD YAML syntax reference](https://docs.gitlab.com/ci/yaml/)
단계 7개
- 배포 잡에 이름표를 붙인다
- 브랜치마다 생기는 리뷰 환경
- 리뷰 환경은 닫는 잡과 짝을 이룬다
- 운영 배포는 사람이 누른다
- 무엇이 나갔는지 커밋 SHA 로 남긴다
- 되돌리기는 이력에 있는 태그를 다시 내보내는 것
- 배포 동결 기간에는 운영 배포를 만들지 않는다