kubernetes기반으로 작동하는 모니터링 서비스 개발과 배포를 최대한 자동화 하기 위해서 Git Flow와 CI/CD를 도입해보았다.
Git Flow를 이해하기 위해 다음의 아티클을 참고하였다.
http://dogfeet.github.io/articles/2011/a-successful-git-branching-model.html
https://woowabros.github.io/experience/2017/10/30/baemin-mobile-git-branch-strategy.html
CI/CD인 경우는 circleci 와 helm 을 이용하였다.
대상 git repo에는 소스코드와 helm chart가 모두 있다. 그래서 실제 빌드에서부터 Chart배포까지 모두 한 곳에서 이루어진다. (원래는 분리하는 것이 맞다고 생각한다. 그 이유는 디렉토리별로 빌드/배포를 구분해야하기 때문에 스크립트 및 PR/Commit시의 액션이 복잡해지기 때문이다)
Git Flow와 CI/CD의 연결은 다음과 같이 처리하였다.
PR -> develop/release
docker image build 와 chart-testing 을 실행한다.
여기서 docker image build는 multi-stage를 적용하여, Dockerfile에서 직접 유닛테스트,lint,stylecheck 등을 실행한다.Image push 는 하지 않는다. 왜냐하면 실제 배포까지 이루어지는 것이 아니기 때문이다.(PR단계에서의 단순 체크)
chart-testing(https://github.com/helm/chart-testing) 의 경우 version increment 체크를 제외한 나머지를 진행한다.
Merge -> develop
아무것도 하지 않는다. 실제 배포와는 전혀 관계가 없는 브랜치 이기 때문이고, Image 빌드 및 유닛테스트 등 사전에 체크할수 있는 부분은 PR단계에서 끝났기 때문이다.
Merge -> release
실제 stage환경에 배포가 이루어져야하기 때문에 Image 빌드후 registry 에 push 처리를 한다. 그리고 나서 helm 을 이용해 stage환경에 배포한다.
push가 이루어지기 때문에 image tag(version)과 chart 버전이 일치해야 한다. 필자의 경우 각 sourcecode root에 VERSION 텍스트파일을 생성하여 여기에 tag용 버전을 관리하고, 이를 Chart의 appVersion과 통일시켜 사용하는 정책을 적용하였다.(bumpup-version.sh 등의 스크립트를 만들어서 일괄 처리할 수도 있다)
여기서 몇가지 다른 정책을 가져갈 수 있다. 배포 후 Integration test가 종료된 후 stage를 초기화하는 작업이 필요하다. 매뉴얼로 진행할 수 도 있겠지만, 배포 직전 할수도 있고, 다양한 방법이 적용될 수 있다. 다만 필자는 초기화작업 까지는 필요하지 않아 적용하지 않았다.
PR -> master
chart-testing만 실행한다. 추가적으로 chart version이 올라갔는지까지 확인한다. docker image의 빌드와 테스트는 최종적으로 release 단계에서 했기때문에 하지 않는다(master에서 다시 빌드하면 다시 이미지를 검증해야하기 때문이다).
master 브랜치에 PR을 올렸을때 이 PR의 base branch가 master인지 아닌지 확인이 필요한다. circleci 자체로는 확인이 불가능하다. 필자는 github API 를 이용하여 base branch를 가져오는 스크립트를 이용하였다.
(https://circleci.com/orbs/registry/orb/narrativescience/ghpr : get-base-branch)
Merge -> master
아무것도 하지 않는다.
정책에 따라 release 브랜치를 삭제하거나 유지할 수 있다. 오픈소스 기준으로는 배포부분이 빠져 있고 버전관리가 필요하기 때문에 release 브랜치를 계속 유지하지만, master가 배포기준인 상용 개발에서는 release브랜치를 유지할 필요가 없을 수도 있다.
Tag push -> master (github release)
production 환경에 배포한다. 최종 배포 직전, 한번 더 담당자의 수동 승인을 거쳐 배포한다.
master 브랜치에 최종 배포를 한 후 에는 develop에 다시 반영해 주어야 하며, 머지를 할때는 --no-ff 를 이용하여 순서가 꼬이지 않게 한다. 그리고 브랜치간 머지 시에는 히스토리 추적을 위해 rebase가 아닌 그냥 merge로 진행하는것이 좋다.
브랜치간 머지는 upstream에서 이루어지는 것이 아니고, commiter 가 origin에서 PR을 날려 진행하는 것이다. upstream 내에서 이루어지면 circleci가 동작하지 않는다(이 부분은 왜그런지 필자도 좀 더 확인이 필요하다)
CI/CD를 적용하기전에 각 k8s클러스터에 모니터링을 먼저 설치하였다(helm install). CI/CD에서는 helm upgrade로만 진행한다.
helm chart를 이용하기 위해서 k8s클러스터에 tiller 와 타겟 namespace에만 접근가능한 service account를 생성하여 이 account의 token을 circleci env에 적용하였다. circleci 에서 helm upgrade를 동작시키기 전에 kubectl 을 이용해 config을 구성하면 된다.
(env로의 설정은 보안에 문제가 될수도 있으니 시나리오에 따라 유출가능성을 고려해봐야한다)
dev환경도 파이프라인에 넣을 수도 있겠으나 필자 생각으로는 dev는 개발자들이 개발할 때 편하게 사용하는 공간이 맞는것 같아 포함하지 않았다.
위 정책 및 시나리오는 한가지 예일 뿐이며,
git repo 구성방식, 배포환경, 팀/서비스 정책에 따라 케이스 바이 케이스로 다양하게 나올 수 있다.
'Development' 카테고리의 다른 글
nginx reload와 keep-alive (부제: zero-downtime은 사기일까?) (1) | 2021.01.16 |
---|---|
SW설계 시 고려해야 하는 사항 (0) | 2020.11.18 |
Thanos Tips (2) | 2020.02.11 |
빈번한 No data alert 벗어나기(in Grafana) (1) | 2019.12.12 |
Shared Informer (0) | 2019.12.11 |