제품의 첫 메이저 버전을 릴리즈하고, 팀의 내실을 다질 시간을 얻었다. 팀에서 부족하다고 느꼈던 것은 바로 CI/CD 파이프라인이 없다는 점과 명확한 브랜치 정책이 수립되어있지 않았다는 점이었다.
팀에 처음 합류했을 때, 개발에 대한 코드 적용의 프로세스를 질문했던 것이 기억에 남는다. 당시에 너무 바쁜 나머지 브랜치 하나에 바로바로 기능 추가와 QA 도커 이미지 테스트가 이루어지고 있었는데, 다만 모든 것이 자동화가 되어있지 않아 손으로 하나하나 도커 이미지 업로드하고 테스트하고 있었다.
자동화할 부분이 많았고, 한번만 CI/CD 파이프라인을 구축하여 자동화만 해놓는다면 팀의 개발 경험이 많이 개선될 것이라 생각하였다. CI/CD 파이프라인 구축 경험도 없던 터라 팀장님께 CI/CD 파이프라인을 구축하고 싶다 어필하여 해당 구축을 맡아 진행하게 되었다.
팀에서 사용하고 있는 Git은 Gitlab이었고, Jenkins는 그나마 사용은 해본 CI/CD 툴이었기에 선택하였다. 그리고 사내 메신저로 Mattermost를 사용하고 있어, 알림을 Mattermost로 날리는 것까지가 기본 골자였다.
CI/CD 툴 결정을 빠르게 하였는데, Gitlab 배포나 다른 CI/CD툴을 사용하지 않고 Jenkins를 사용을 결정한 것은 익숙한 것을 사용하는 것이 구축 시간을 단축하고 후에 장애 대응에도 도움이 될 것이라는 판단이었다.
Jenkinsfile을 직접 작성한 경험은 없지만 전 팀에서 Jenkinsfile을 작성하던 팀원에게 이것저것 듣기도 했고 물어볼 수도 있기 때문이었다.
CI/CD 파이프라인 기본 설계를 아래와 같이 했다.
도커 레지스트리에 이미지 등록까지가 공통 파이프라인 설계로 잡았다. 이후 이 도커 레지스트리에서 이미지를 받아서 서버를 실행시키는 것을 다양하게 진행된다.
QA 서버에는 Jenkins가 직접 ssh docker command를 날려 도커 레지스트리에 있는 이미지를 받아 실행시킨다.
메인 제품 서버는 K8S환경이며 kubectl을 이용하여 도커 레지스트리에 있는 이미지를 받아 새로운 이미지로 pod들을 생성한다.
도커 레지스트리에 등록까지만 하면 해당 이미지를 받아서 다양한 환경에서 제 입맛에 맞게 실행할 수 있다. 이 점에서 새삼 도커라는 것의 편리함에 감탄하게 되었다.
CI/CD 파이프라인 구축 작업을 하면서 일정한 빌드 환경을 제공하기 하려면 어떻게 해야할까 고민하다 jdk 바이너리 파일서버도 따로 구축하기도 하고 어떻게 하면 쉘 스크립트 내에서 exit code를 다루어야할지 고민하다 타협하기도하는 많은 경험을 할 수 있는 구축 과정이었다.
특히 docker engine과 k8s를 REST API로 컨트롤 한다는 것은 인상 깊었다. docker client 명령어만 사용했지 내부적으로 docker client와 engine이 어떻게 통신하는지에 대해서는 들여다볼 생각을 못했었는데, 지금까지 궁금해하지 않은 것을 반성하게 되었다.