도커와 Devops, Kubernetes 에 관심이 많은 대학교 2학년 주니어 개발자입니다.
이 글은 부스트캠프 4기 풀스텍 과정을 진행하면서 도입했던 CI / CD에 대해 정리한 글입니다. 주니어의 입장에서 CI / CD 를 구현하면서 경험했던 것을 공유하려고 합니다.
7주동안 부스트캠프 과정을 진행하면서 수행한 프로젝트입니다. 7주간의 짧은 기간동한 많은 기술적인 과제를 만들고 도전하는 것은 이도저도 아닌 결과가 나올 것 같아서 딱 기본적인 웹의 본질이라고 생각하는 프로젝트를 선정했는데 바로 Festa!의 클론 프로젝트입니다.
이벤트를 만들고, 관리하고, 구매할 수 있는, 다른 조에 비해서는 그렇게 어렵지 않은 모습이었습니다.
프로젝트에서 가장 중요하게 생각한 것은 코드에 대한 TEST와 도입했던 기술의 안정적인 사용, 이벤트 구매시 신뢰도가 높은 예약 환경을 구성하는 것이었습니다.
빌드와 테스트를 통한 코드의 품질을 유지하면서 통합하는 과정을 말합니다.
쉽게 말하면, 코드에 대한 사소한 테스트를 수행하고 코드를 빌드해서 완제품을 만들어내는 프로세스를 따로 두고, 이것을 자동화해서 개발자가 좀 더 코드 생산에 집중할 수 있는 환경을 만드는 것입니다.
간단하게 코드를 QA를 따로 두고 직접 테스트를 하는 것이 아닌 자동화된 프로세스에 의해 빠르고 주기적으로 빌드하고 테스트하며 이것을 바로바로 출시하는 것을 말하는 것인데, 기능을 작은 단위로 추가할 때마다 배포가 가능할 수 있게 해주는 것입니다.
위의 두가지는 빨리 테스트하고 빨리 빌드해서 빨리 배포하는 것이죠.(빨리 빨리 빨리!!)
부스트캠프는 매주 금요일마다 데모 시연을 했습니다. 매주 월요일 데모 시나리오를 정하고 이것을 금요일에 시연하는, 에자일 프로세스를 적용한 것입니다.
7주 짜리 매우 짧은 프로젝트에 CI/CD를 도입하는 것은 사실 너무나 큰 비용을 요구하는 작업일 수도 있습니다. 아직 배포할 것도 없어서 CD가 의미가 없을수도 있고요.
그러나 주니어의 입장에서, 금요일 배포날 통합적 규모의 테스팅이 하나도 진행되어있지 않은 상태에서 갑자기 1시간도 안되는 시간안에 파일을 서버로 올리고 이것 저것 하는 시간동안 어떤 문제가 터질지 예상 조차 못했습니다. (금요일의 제가 수요일 즈음의 저에게 Stay... 를 외치고 있었을 수도 있죠.(그거 추가하면 큰일나!!))
그래서 도입했습니다. 차라리 맨날 테스트하고 필요할 때 언제든 배포할 수 있는 코드가 나오면 좋겠죠. 이왕이면 롤백도 금방금방 할 수 있으면 좋고요.
마지막으로 저희팀엔 TDD 신봉자가 있었습니다. Test에 깊은 감명을 받고 모두에게 전파시키려는 무서우신 분이었죠. 그 분을 위해서 깔끔한 테스트 / 배포가 가능한 프로세스를 만들어 드리고 싶었습니다. 테스트를 하다가 개발 시간이 적어질 팀원과 저를 위한 것도 있었고요.
사실 가장 이상적으로 좋아보이는건 Jenkins 였습니다. Kubernetes 같은것을 통해 어느 때나 오케스트레이션을 하면서 테스트 서버를 눌려주면 4명이 테스트를 시도 때도 없이 할 수 있었습니다. 그렇지만 저희는 서버를 유지할 돈이 없었죠. 테스트를 그렇게 많이 할 것 같지도 않았습니다.
그리고 찾은 것은 Travis CI 였습니다. 오픈소스에서는 무료고, Github와 연동하는 방법은 버튼하나 누르는 것이 끝입니다. 브랜치가 다르다면 동시 빌드도 되는 것 같았습니다. 사용법도 간단해서 yml 파일에 스크립트를 추가한다면 바로 테스트를 진행 할 수 있었습니다.
Bookus! 의 배포 환경은 Kubernetes 입니다.
이벤트를 개최하면 티켓 구매를 하기전에 Warm up을 해서 트래픽을 견뎌낼 준비를 해야하는데 일반적인 Cloud 환경에선 구현이 어려워 보였습니다. 그리고 전 클라우드 플랫폼에 종속되는 느낌을 싫어했습니다.
처음에는 Kubernetes는 너무 어렵다고 느껴서 여러 인스턴스를 만들고 그걸 Swarm Cluster에 넣어버려야겠다 생각했습니다. Swarm은 Docker Compose 만으로 설정이 가능해서 도커에 익숙하다면 금방 사용할 수 있고, 각각 서비스에 대한 복제도 유연하게 가능했으며 자체적으로 Blue Green 배포와 Rollback도 지원했습니다! 하지만 Ncloud에서 직접적으로 제공하는 서비스가 아니라, Instance의 개수를 늘리는 것은 조금 힘이 들었죠.
그래서 무섭지만, Kubernetes를 써보기로 했습니다. 기본적인 컨테이너 관리의 개념은 동일했지만, 여러 단계들이 추상화되어있었습니다. 예를 들어, Swarm이 포트만 열어주면 되는 부분을 Kubernetes에서는 Service 계층을 통해서 통신을 하기도 하고, Pod 내에 Container가 여러개 들어갈 수도 있고, Deployment라고, 배포에 관한 설정을 해야 하는 부분도 있으며, Ingress 등의 여러 네트워크 계층도 있는 등 굉장히 추상화가 잘 되어있었죠. (그런만큼 힘들었고요)
적어도 Node를 늘리는 작업은 매우 간단한 점은 좋았습니다. NCP에서 쿠버를 기본적으로 세팅해주는 것도 좋았고요.
Repository 하나에서 백과 프론트를 한번에 개발하고 있었던 상황입니다.
CI 구성은 아래와 같이 해보았습니다.
최초에는 Git hooks를 이용해서 코드 스타일를 통합하고 lint 검사를 했습니다. 코드를 동일한 사람이 짠 것 처럼 통합시키기 위함이죠!
Github으로 코드를 Push 한 이휴에는 Git Flow 전략을 통해 코드가 통합되도록 했습니다. Master / Develop, 이슈를 통해 생성된 Feature - (n) 브랜치들이 있었고, PR과 Merge를 하면 팀원들에게 코드리뷰를 받아야만 병합되는 구조료 코드 통합을 하고있었습니다.
모든 PR과 Merge되는 코드는 Travis에서 테스트 했습니다.
또한 Develop에 Merge 되는 경우에는 Pre-release라는 이미지를 만들어서 테스트할 수 있도록 했고, Master로 코드가 머지될 경우에는 배포용 이미지를 빌드해서 Docker Hub에 올렸습니다.
만약 Travis 에서 테스트가 실패할 경우에는 Merge를 할 수 없도록 막아놓았습니다.
뽑힌 이미지를 어느정도 테스트를 하고 난 뒤에는 Kubernetes에서 이미지를 업데이트 했습니다. 배포주기는 3초 정도로 두어 무중단 배포가 가능하도록 했습니다!
부스트캠프에서는 NCP 를 사용할 수 있게 NBP에서 지원을 해줬습니다! 인당 30만원! 돈을 주면 써야죠!
Kubernetes Cluster 안에 Front와 Back, Reserve 서버를 띄워놓은 뒤 예약이 몰릴 것 같으면 Node를 증가시키고, 예약용 서버를 늘려서 트레픽을 받을 준비를 좀 더 쉽게 할 수 있도록 해놓았습니다.
대부분의 코드에는 테스트 코드가 존재했고, 그 테스트가 성공적으로 끝나야만 통합되어서 오류가 있는 코드가 통합되기 힘든 구조였습니다. (주니어의 입장에서 사실 테스트 코드의 안정성을 장담할 수는 없었지만요 ㅎㅎ..) 따라서 어느정도 신뢰가능한 코드만 올라와 있다고 믿을 수 있었습니다! 그리고 모두가 동일한 컨벤션이 지켜졌고요!
개발 속도가 어떻던 기능 통합만 된다면 정말 빠르게 명령어 한줄이면 가능했습니다. LoadBalancer에 Health Check 설정을 잘못했던 것 때문에 백엔드에 접속이 안되던 것 제외하고는 배포에 걸렸던 시간이 1분도 안되었습니다.
첫 배포 후, 접속했을 때 메인페이지가 뜨는 그 짜릿함은 잊을 수가 없어요.
아직 Kubernetes를 제대로 사용하지 못하겠다!
Docker Swarm에서 Kubernetes로 옮기면서, 제대로 활용하지는 못했던 점이 아쉬웠습니다. Swarm 의 단점인 Node 개수를 늘리는 것이 너무 번거로운 점을 완벽히 해결해 주었지만, Side Effect 가 너무 많이 발생했습니다. 예를 들면 Log 수집을 위해 DaemonSet을 띄워야 하는 것 같은데, Pod에 안붙어서 아직도 해결을 못하고 있습니다.. Helm 등의 부가적인 도구 사용도 아직 이해가 안되는 느낌이고요.. 또한 Yml 파일에 의존하다보니 '과연 인프라가 안정적일지' 에 대한 k8s의 코드 리뷰도 전무했습니다. 이 점이 너무 안타까웠습니다..
CI 과정에서 어디까지 해야할 지 모르겠다!
테스트 과정은 항상 15분 남짓이 소요되었습니다. 배포 과정까지 포함한다면 20분이 넘게 걸렸습니다. 배포가 얼마 안남은 시점에 테스트 결과를 봐야 하는 상황에선 20분이 넘는 시간이 무척이나 긴 시간처럼 느껴집니다. 시간을 줄이려면 몇가지 과정을 로컬에서 진행했어야 하는데 이것을 어디까지 로컬 환경에게 위임해야 할지 아직도 명확하지가 않습니다.
위의 두가지가 지금 가장 큰 아쉬움인데 이것은 나중에 공부를 더 하고, 프로젝트를 많이 진행해보면서 해결해봐야겠습니다.
배포랑 협업이 재미있는 경험은 처음이었습니다. 맨날 팀플하면 싸우고 난리치던 경험밖에 없던 저에겐 충격적일 만큼 재미있었습니다. 그리고 코드리뷰가 이렇게 생산적인 일인줄은 몰랐습니다.
아직 개발이 3주 남은 상태에서 4주차 CI/CD가 어느정도 안정되어 글을 써봤습니다. 개발하면서 달라진 점이 있다면 나중에 추가를 해봐야겠네요.
( '19.12.22 현재는 마무리를 하며 변경된 내용을 추가를 해놓은 상태입니다. 설마 환경이 Kubernetes로 바뀔지는 몰랐습니다...)
사실 테스트와 CI/CD라는 것을 부스트캠프에 와서 처음 알았습니다. 소프트웨어 엔지니어링에서 배웠던 에자일과 통합을 부스트캠프에서 경험했던 것은 정말 귀중한 경험이었습니다.
정말 정말 행복했던 것은 관심은 있었는데 제대로 사용하고 있는 느낌이 없던 Docker를 신나게 활용했던 것이네요. 그리고 Docker로는 뭔가 여러 컴퓨터에서 실행하는게 머릿속에 그려지질 않았는데, 이곳에 와서 Kubernetes와 Docker Swarm 과 같은 멋진 Orchestration 툴을 알고, 직접 사용해본게 너무 좋았습니다!
글에 코드가 들어가면 집중이 안되는 느낌이 있어서 따로 넣지는 않았습니다. 정말 만약에라도 저희 팀의 경험을 코드로써 살펴보고 싶으신 분들을 위해 아래에 링크를 남기겠습니다.
Bookus! Repository - 프로젝트 코드입니다.
Travis CI - Travis 링크입니다.
마지막으로 제가 하고싶은 것을 할 수 있는 기반을 마련해주신, @dobest27 @inthewalter @doong-jo 모두 감사합니다.
아키텍쳐에 고민해보았습니다 감사합니다.