숨고 서비스 컨테이너화
안녕하세요. 숨고 Platform Chapter의 DevOps Engineer Ted 입니다.
숨고를 이루고 있는 대부분의 서비스는 MSA로 구성되어 퍼블릭 클라우드인 AWS를 통해 운영하고 있습니다. 그 중 일부 레거시 서비스는 AWS Elastic Beanstalk을 통해 운영되고 있었습니다. 이 레거시 서비스를 컨테이너 환경의 AWS Elastic Kubernetes Service(EKS)로 무중단 마이그레이션한 경험을 공유하고자 합니다.
레거시 서비스에 대한 고찰
기존에 사용하던 AWS Elastic Beanstalk는 구성이 간편하고 롤링 업데이트와 배포를 이용하여 안정적으로 배포를 할 수 있다는 장점이 있습니다. 또, 트래픽 급증으로 인해서 컴퓨팅 자원의 임계치가 도달하는 경우 오토 스케일 설정을 통해서 유연하게 확장할 수 있는 기능이 있어 숨고 뿐만 아니라 많은 기업에서 사용하고 있니다.
하지만 배포 시에 오랜 시간이 소요되기 때문에 만약 장애가 발생하게 된다면 롤백에도 오랜 시간이 걸리는 것이 큰 단점입니다. 상용 서비스의 경우 장애가 길어지면 사용자에게 좋지 않은 경험을 제공하게 되면서 자연스럽게 사용자의 리텐션과 매출에도 부정적인 영향을 주기 때문에 대단히 치명적인 단점이라고 볼 수 있습니다.
이러한 AWS Elastic Beanstalk의 단점을 극복하고자 기존 레거시 서비스를 컨테이너화해 숨고의 메인 서비스들이 운영되고 있는 AWS EKS로 마이그레이션을 진행하기로 결정하였습니다.
컨테이너화 장점
먼저 레거시 서비스의 컨테이너화가 가져다주는 장점은 무엇이 있을지에 대해 고민해보았습니다. 저희 챕터에서 예상한 장점은 다음과 같습니다.
- 배포와 롤백 시간 단축
- 설정 변경의 단순화
- 환경 복제의 단순화
- 로컬에서 사용 가능
개발한 소스를 빠르게 빌드하고 배포할 수 있으며 필요 시 언제든 설정을 복제하고 환경을 생성할 수 있고, 리모트 환경에서 추적하기 어려운 부분을 로컬에서 즉시 테스트하거나 디버깅 할 수 있을 것으로 예상했습니다. 대부분의 장점은 시간의 단축과 프로세스의 단순화에 초점이 맞춰져 있습니다. 이를 통해서 사용자에게 더 좋은 기능들을 빠르게 제공할 수 있다는 것으로 요약할 수 있습니다.
숨고는 제품 개발에 Agile 방법론을 채택하고 있어 제품을 빠르게 출시할 수 있다는 것은 숨고의 개발 환경에 부합하는 중요한 조건이기 때문에 컨테이너화에서 오는 이점이 크다고 판단했습니다.
대상 선정
앞서 말씀드렸듯이 숨고 서비스의 일부는 AWS Elastic Beanstalk에서 서비스되고 있었습니다. 처음에는 이 서비스들 중에 마이그레이션을 했을때 가장 효과가 큰 서비스부터 마이그레이션 하는 것을 검토했습니다.
하지만 마이그레이션에 대한 경험을 쌓는 것이 필요한 상황이었고, 효과가 큰 서비스일수록 마이그레이션 도중 장애가 발생했을 때 오히려 서비스 전체에 부정적인 영향을 크게 줄 수 있을 수 있다고 판단했습니다. 때문에 이번에는 비교적 숨고 전체 서비스에 영향이 적은 서비스부터 마이그레이션을 진행하는 것을 계획하고 최종적으로 세 개 서비스를 마이그레이션 대상으로 최종 선정했습니다.
- 1차 : Private Soomgo Web - 알림 발송 서비스
- 2차 : Frontend - 프론트엔드 서비스
- 3차 : Soomgo Force 2 - 숨고 백오피스 서비스
진행 과정
이번 프로젝트는 크게 컨테이너화, 무중단 배포, 모니터링의 세 단계로 진행되었습니다. 컨테이너화 단계에서는 큰 어려움은 없었지만 기존 서비스에 영향이 가지 않도록 무중단으로 배포를 하는 것이 중요하기 때문에 가장 많은 고민을 한 단계입니다. 마지막으로 기존 프로세스 대비 조금 더 다양한 항목을 면밀하게 체크하는 형태로 모니터링을 진행했습니다. 프로젝트의 흐름을 단계로 구분하자면 아래와 같습니다.
- 기존 서비스 분석
- 컨테이너화
- CI/CD 파이프라인 변경
- 테스트
- 배포
- 모니터링
레거시 서비스 분석
컨테이너 이미지를 만들기 위해서는 Dockerfile 작성이 필요한데, 이를 위해서 최소 다음의 세 가지 정보가 필요합니다. 이 정보들을 파악하기 위해 기존 서비스에 대한 분석을 진행했습니다.
- 베이스 이미지
- 서비스에 필요한 바이너리 파일들
- 기동 커맨드
기존 서비스들은 AWS Elastic Beanstalk 에서 제공하는 구성 파일(.ebextensions)을 이용하여 서비스 생성을 자동화하고 있었는데, 이 파일들의 정보를 이용하여 위에서 필요한 정보를 모두 얻을 수 있었습니다.
컨테이너 이미지 생성
컨테이너 이미지를 만드는 과정에서 컨테이너 이미지의 경량화라는 이슈가 발생했습니다. 컨테이너 이미지의 크기가 배포, 롤백, 스케일 아웃, 로컬에서 디버깅을 위한 다운로드 등 여러 가지 비용(Not only price)과 직결되기 때문에 시간의 단축과 프로세스의 단순화라는 마이그레이션의 본래 목적을 생각하면 이미지 전체 파일 사이즈를 경량화 하는 것은 중요한 과제였습니다.
경량의 컨테이너를 만들기 위해서는 가벼운 베이스 이미지를 선택하거나, 기동에 필요한 바이너리 파일들을 최소화해야 했습니다.
경량의 베이스 이미지
대표적으로 컨테이너 이미지를 만들때 사용하는 Alpine
은 용량이 3MB가 채 되지 않아 이미지 경량화라는 저희 목적에는 가장 부합하는 이미지였습니다. 하지만 저희 서비스가 주로 Debian
으로 이루어져있고, 용량도 약 30MB 내외로 크지 않기 때문에 이번 프로젝트에서는 Debian
을 베이스 이미지로 사용했습니다.
기동에 필요한 최소한의 바이너리 파일들
베이스 이미지를 기반으로 OS 패키지와 서비스 바이너리도 선별했는데, 마찬가지로 경량화에 초점을 맞추었습니다.
OS에서 제공하는 패키지 인스톨러를 이용해서 다양한 패키지들을 설치할 수 있는데, 서비스 기동에 꼭 필요한 패키지만 설치하도록 하였습니다. 디버깅 하거나 트래픽 확인 시 유용한 curl
, vim
, nslookup
, netstat
등 커맨드들은 런타임에서 문제 발생 시 위급한 경우에 설치해서 사용하는 것으로 결정했습니다.
그 외에 서비스에 필요한 바이너리는 해당 서비스를 개발하는 챕터와의 논의를 거쳐 최소한의 바이너리만을 선별할 수 있었습니다.
CI/CD 파이프라인 변경
기존에는 AWS Elastic Beanstalk 구성 기능을 이용하여 .ebextensions
를 작성하였고, eb CLI를 이용하여 서비스를 배포했습니다. 하지만 새로운 환경에서는 마이그레이션하는 서비스들이 Kubernetes pod으로 동작할 수 있도록 파이프라인을 구성해야 합니다. 또한 이전 포스팅에서 볼 수 있듯이 숨고의 대부분의 서비스는 GitOps로 CI/CD가 구성되어 있어 Kubernetes 매니페스트와 ArgoCD Application 작성도 필요합니다. 다만 이미 helm templates 기반으로 구조가 잘 잡혀있기 때문에, values만 잘 작성해서 ArgoCD Application을 생성하기만 한다면 서비스를 위한 준비는 거의 마친 상태라고 볼 수 있습니다.
레거시 CI/CD 파이프라인과 컨테이너화 이후의 CI/CD 파이프라인은 아래와 같이 비교해서 볼 수 있습니다.
레거시 CI/CD 파이프라인
컨테이너화 CI/CD 파이프라인
통합 테스트
숨고 서비스는 기능 개발 후 스테이징 환경에 지속적으로 통합한 뒤 QA Chapter에서 통합 테스트를 진행하고 있습니다. 이와 마찬가지로 인프라에 대한 변경이 있을 때도 통합 테스트가 반드시 필요하고 실제로 운영 환경에 적용하기 전 스테이징 환경에 배포하여 통합 테스트를 받았습니다.
위에서 언급한 운영 환경에 배포를 위한 배포 시나리오를 스테이징 환경에서 그대로 재현하였고 배포 과정에서 문제가 없었는지 QA Chapter와 함께 꼼꼼하게 모니터링을 진행했습니다.
이러한 테스트와 모니터링은 이번 프로젝트에서 뿐만 아니라 숨고의 다른 개발 과정에서도 매우 중요한 과정입니다. 숨고의 테스트 환경은 실제 운영 환경에 배포할 때와 준하는 수준으로 이루어져 있어 효과적으로 이슈를 발견하고 예방할 수 있도록 되어 있습니다. 운영 환경에서는 예상치도 못한 문제가 항상 발생하기 때문에 선배포와 테스트, 모니터링을 꼼꼼하게 함으로써 미리 문제를 발견하고 대비책도 세울 수 있다고 생각합니다.
배포
배포 전략에는 많이 알려진 것처럼 롤링 배포, 블루-그린 배포, 카나리 배포 등 여러가지 전략이 있지만 이번에 저는 Route 53 가중치 기반 라우팅을 이용한 수동 카나리 배포 전략의 일종을 사용했습니다. 기본적인 시나리오는 다음과 같습니다.
- 신규 서비스 배포
- 기존 서비스와 신규 서비스가 공존할 수 있도록 트래픽 로드 밸런싱
- 기존 서비스와 신규 서비스 모두 모니터링 및 정상 상태 확인
- 기존 서비스 제거
- 신규 서비스 모니터링 및 정상 상태 확인
이 전략은 Route 53 가중치 기반 라우팅을 이용하여 기존 서비스와 신규 서비스의 트래픽 유입을 비율로 조정할 수 있고, 신규 서비스에 문제가 생기는 경우에는 가중치를 다시 조정하여 장애를 최소화 할 수 있다는 장점이 있습니다.
위의 시나리오를 Route 53을 사용한 라우팅에 적용해서 다음과 같은 순서로 마이그레이션을 진행했습니다.
- 기존 서비스 구조
- 신규 서비스 배포 및 Route 53 가중치 적용, 로드 밸런서 연결
- Route 53 가중치 비율 조정
- 기존 서비스 제거 후 신규 환경으로의 완전한 마이그레이션
모니터링
성공적으로 배포를 완료하였다고 판단되면 레거시 서비스를 운영할 때와 비교해서 안정적으로 서비스가 운영되고 있는지를 지켜보는 모니터링이 필요합니다. 숨고는 모든 서비스에 대해 항상 모니터링을 진행하고 있지만 이번에 마이그레이션 과정을 거친 서비스는 1~2주일 정도 심도있는 모니터링을 진행하였습니다.
숨고에서는 New Relic이라는 통합 모니터링 서비스를 이용하고 있습니다. New Relic에 이미 Kubernetes 에 대한 대시보드 및 Alert 설정이 되어 있었기 때문에 컨테이너화된 서비스에 대한 몇 가지 추가적인 Alert를 설정하는 방법으로 모니터링을 진행했습니다.
다행히 모니터링 기간에 서비스에 큰 문제가 발생하지 않았고, 모니터링 이후 실제 서비스 운영에서도 이슈가 발생하지 않아 성공적으로 프로젝트를 마무리할 수 있었습니다.
효과
서비스 컨테이너화 프로젝트를 통해 서비스가 얼마나 개선되었는지 수치로 나타내자면 다음과 같습니다.
- 배포 시간 : 약 80% 감소 (5분 → 1분)
- 환경 복제 시간 : 약 75% 감소 (2시간 → 30분)
- 오토 스케일 시간 : 서비스 별 70 ~ 85% 감소(2분 ~ 5분 → 15초 ~ 1분 30초)
- 응답 시간 : 약 50% 감소
- 비용 : 평균 50% 감소
수치를 보면 서비스 배포, 롤백 시간의 감소와 복제화 및 트래픽 대응에 대응하는 속도가 대폭 감소한 것을 확인할 수 있었습니다. 컨테이너화를 함으로써 숨고 서비스에 대한 품질을 높이는 데 큰 기여를 할 수 있고, 숨고를 이용하는 사용자에게는 더욱 안정적인 서비스를 제공할 수 있을 것으로 예상하고 있습니다.
또한 EKS의 오토 스케일링 기능을 통해 AWS의 인스턴스를 효율적으로 사용하게 되면서 인프라 유지 비용이 평균적으로 약 50% 감소했습니다. 서비스 운영 비용 감소를 통해 숨고가 더욱 집중할 수 있는 곳에 비용을 투자할 수 있게 되었다는 점에서 이번 프로젝트가 더욱 의미를 가질 수 있었습니다.
이번 프로젝트가 마무리되고 난 이후에 기존 레거시 서비스를 운영할 때보다 컨테이너화된 서비스를 통해서 다음과 같은 장점을 확인할 수 있었습니다.
- 개발한 기능을 빠르게 서비스에 통합
- 테스트가 필요한 환경을 빠르게 제공
- 급증한 트래픽에 안정적으로 대응
- 비용(Price) 감소로 숨고 인프라 운영 비용 절약
- 짧은 응답 시간으로 사용자에게 쾌적한 환경 제공
회고
이번 프로젝트를 진행하는 과정에서 더 큰 효과를 위해 기존에 계획했던 것 이상의 많은 것들을 고민했고, 그만큼 욕심도 많이 났었던 것이 사실입니다. 하지만 이번에 마이그레이션하지 못한 레거시 서비스들을 우선 모두 EKS로 전환하는 것을 가까운 목표로 삼고, 이번에 미처 하지 못한 고도화는 다음 번의 새로운 도전을 위한 미션으로 남겨두고자 합니다.
숨고에 DevOps Engineer로 입사하고 나서 저의 첫 임무로 컨테이너화를 진행하는 업무로 본격적으로 업무를 시작을 했습니다. 또한 추가로 여러 레거시 서비스에 대한 컨테이너화를 진행을 하면서 쉽지 않은 미션이었지만 그 효과가 크다고 생각하기 때문에 더욱 성취감이 컸습니다.
Tech Team 뿐만 아니라 숨고 프로덕트 전체에 기여하면서, “숨고 서비스의 엔트로피를 낮추고 안정성을 높인다”라는 Platform Chapter의 목표에도 잘 맞는 프로젝트였다는 점에 더 큰 보람을 느낍니다. 이번 서비스 컨테이너화 프로젝트가 수치로 보여지는 단기적인 성과를 넘어 시간이 지날 수록 서비스의 운영과정에서 더욱 큰 빛을 발휘할 것이라고 확신합니다.
또한 프로젝트 진행하면서 여러모로 도움주신 Tech Team 멤버들과 프로젝트 이후에도 많은 응원과 피드백을 해주신 숨고 멤버 분들께도 컨테이너화 하는 데 도움을 주신 숨고 멤버분들께 모두 감사드립니다.
- #aws
- #container
- #devops
- #kubernetes
- #development
Ted Jeong
Soomgo DevOps Engineer