CircleCI에서 GitHub Actions로 이전하며 배포 속도 개선하기
안녕하세요, 당근마켓 운영개발팀에서 인턴 서버 개발자로 일하고 있는 Wade(웨이드)예요. 이번에 당근마켓 어드민 툴 karrot-cs의 CI/CD 환경을 CircleCI에서 GitHub Actions로 이전하면서 배포 속도를 개선하는 작업을 진행했어요. 작업 과정에서 발생한 경험들을 공유해보려고 해요.
기존 방식
당근마켓에서 스팸 처리/신고/문의 등 운영적인 부분을 담당하고 있는 프로젝트인 karrot-cs는 GitHub Actions를 이용하여 캐나다(ca), 일본(jp) alpha 배포를, CircleCI를 이용하여 한국(kr) alpha 및 각국 production 배포를 진행하고 있었어요(당근마켓에서는 프로젝트 개발 및 배포 시 사용하는 테스트 서버를 alpha 서버, 운영 서버를 production 서버라고 불러요).
다만 Docker layer caching이 적용되지 않아 매번 이미지를 처음부터 새로 빌드하고 있었고, 이 때문에 배포 시간이 15분이 넘어가기도 하는 상태였어요.
또한, 코드를 관리하는 GitHub에서 CI를 함께 관리하는 것이 편리하기도 하고, 최근 GitHub Actions의 기능들이 많이 개선되고 있어, 사내에서 여러 프로젝트가 CircleCI보다는 GitHub Actions를 선택하고 있었어요.
그래서 이번 기회에 karrot-cs에도 GitHub Actions를 이용한 CI/CD를 적용하면서 동시에 Docker layer caching을 적용하여 배포 속도를 개선해보기로 했어요.
GitHub Actions로의 이전, Docker layer caching 적용
먼저, ca alpha에 사용되고 있는 GitHub Actions yml 파일을 살펴보았어요. 현재 ca alpha 배포는 15m 6s가 걸리는 상황이었어요. 그 이유는 GitHub Actions에서 workflow를 돌릴 때마다 새 머신에서 docker build로 이미지를 빌드하고 있기 때문에, layer caching이 일어나지 않고 매번 새로 빌드가 일어나기 때문이었어요.
먼저, Docker에서 제공하는 build-push-action을 사용하여 Docker layer caching을 적용하기로 했어요. build-push-action에서는 cache-from과 cache-to 파라미터를 통해 cache의 source와 destination을 설정할 수 있어요. karrot-cs에서는 별도의 추가 설정이 필요 없고, API를 통해 관리하기 편한 GitHub Actions Cache를 사용하여 caching을 적용하기로 했어요. 그리고 github-script를 이용해 최근 사용된 100개를 제외한 cache들을 비워주는 코드를 추가했어요.
Docker layer caching을 적용하니 빌드 시간이 약 8분 정도 줄어든 것을 확인할 수 있었어요. 하지만 여전히 빌드에 6분이 넘는 시간이 소요되고 있었어요. 배포시간을 더 개선할 부분이 있을지 Dockerfile을 살펴보았어요.
Rails assets precompile에 caching 적용
Docker는 명령어가 이전 빌드와 동일한지, 명령어를 실행하기 전 레이어가 이전 빌드와 동일한지, 그리고 ADD/COPY의 경우 외부 파일이 이전과 동일한지를 기준으로 layer caching을 적용해요.
karrot-cs Dockerfile의 경우, line 20의 ARG git_commit_id에서 캐시 미스가 났고, 그 이후 step들이 모두 재실행되고 있었어요. 그리고 rails assets:precompile에서 약 5분 정도가 소요되는 상황이었어요.
Rails asset precompile은 프로젝트에 포함된 css, js 등 여러 가지 asset들을 bundling하는 과정인데, 여러 파일을 처리하다 보니 일반적으로 레일즈 배포 과정에서 시간이 오래 걸리는 단계 중 하나예요. precompile에 사용되지 않는 코드만 수정한 경우, precompile step을 caching 하여 속도를 개선할 수 있어 보였어요.
캐시 미스가 나던 git_commit_id 설정 부분을 precompile 이후로 내리고, asset:precompile에 사용되는 소스 코드를 미리 ADD 하여 precompile을 실행한 후, line 35에서 전체 소스코드를 추가하는 방식으로 Dockerfile을 수정했어요.
precompile에 사용되지 않는 소스코드를 수정했다면, line 32의 precompile step까지 layer caching이 적용되고, precompile에 소요되던 시간을 줄일 수 있어요.
precompile step에 layer caching이 적용된 경우, 약 2분 정도까지 배포속도가 개선된 것을 확인할 수 있었어요. 작성된 yml을 kr, gb, jp 등 나머지 region(alpha & production)들에 적용해보았고, 정상적으로 배포되는 것을 확인했어요.
마치며
지금까지 당근마켓 어드민 툴 karrot-cs의 배포 이전 및 개선을 하면서 겪은 경험들을 공유해 보았어요. 제 인턴 마지막 태스크라 시간이 부족해 아직 개선할 수 있는 사항이 많지만(Clear Cache 코드라던가…), 간단한 yml, Dockerfile 수정으로 저희 팀의 생산성에 도움을 줄 수 있었던 재미있는 경험이었어요.
당근마켓 운영개발팀은 동네 이웃과 안심하고 거래할 수 있는 따뜻한 당근마켓을 만들기 위해 노력하는 팀이에요. 기술을 이용하여 스팸과 어뷰징을 줄이고, 당근마켓을 좀 더 신뢰할 수 있는 서비스로 만들기 위한 다양한 일들을 하고 있어요.