컨퍼런스 영상 : 토스ㅣSLASH 22 - 어떻게 안정적인 서비스를 빠르게, 자주 출시할 것인가?
* 해당 블로그의 모든 내용과 사진은 위 영상을 참고하여 작성하였습니다.
좋은 코드
좋은 코드의 가치는 개발자가 작성한 코드가 서비스에 배포되어 사용자에 의해 이용될 때 가치가 발현됩니다.
사용하지 않는 코드는 아무리 잘 작성한 코드라 하더라도 기술적인 관점에서 보면 바이트 덩어리일 뿐입니다.
따라서 코드 작성단계에서부터 서비스 배포 및 운영까지의 제품전달 파이프라인 전체가 잘 구성되는 것이 중요합니다.
다음은 제품이 전달되는 과정입니다.
이제 토스페이먼츠가 안정적인 서비스를 빠르게 자주 출시하기 위해 어떤 노력을 하는지 알아보겠습니다.
프로젝트 셋업 및 개발
토스페이먼츠는 Spring 과 Kotlin을 이용하고 있습니다. MSA 구조로 시스템을 구성하다보면 프로젝트 구성할 일이 많은데 마땅한 가이드라인이 없으면 계속 물어보기 마련입니다. 또한 이런 가이드라인이 문서화되있으면 읽는 사람입장에서 많은 부담으로 다가올 것입니다.
그래서 토스메이먼츠는 항상 최신상태로 유지되는 Boilerplate Project를 구성해서 운영하고 있습니다. 이 Boilerplate Project는 기본적인 요소가 모두 정의되어있어 사용해야할 DB 정보만 설정해주면 바로 비지니스에 필요한 로직을 작성해야합니다.
또한 로깅이나 모니터링과 같이 모든 서비스가 필수적으로 챙겨야하는 기능을 Common Library로 제공합니다. 해당 Common Library는 라이브러리를 사용하는 프로젝트와의 의존성을 최소화하는 방향으로 구현되고있습니다.
그 이유는 프로젝트와 라이브러리가 강결합되어있다면 유지보수가 힘들어지기 때문입니다.
Boilerplate Project 기반의 표준화된 프로젝트 구성과 모듈화된 라이브러리 덕분에 전사프로젝트를 대상으로 공통된 기능의 적용이 용이한편입니다. 전사프로젝트를 대상으로 변경사항을 추가하거나 라이브러리 버전을 올리는 PR에도 문제가 있는 경우가 거의 없습니다 (log4j 보안 취약점 대응이 쉬웠습니다.)
CI / CD
사내 환경에 맞게 CI / CD 환경을 구성하는 것은 복잡하고 어려운일일수 있습니다.
이러한 문제는 샘플 YAML 파일을 기반으로 프로젝트명, 도메인, 메모리 할당량 등의 최소 수정을 통해 CI / CD 환경의 구성이 가능하도록 하여 해결하고있습니다.
최근에는 Github Actions를 많이 사용하는데 Workflow를 YAML로 정의할 수 있다는 점과 YAML 파일을 Git Repository에 포함만 시켜주면 되는 사용방법 덕분에 Boilerplate Project에 포함만 해준다면 큰 노력없이 전사시스템에 반영하는 것이 가능하기 때문입니다.
또한 변경이 잦은 Application Layer와 변경이 자주 발생하지 않는 라이브러리 부분을 구분해서 빌드할 수 있게 해주는 Spring Boot Layerd Jar, 그리고 Docker Multi Stage Build를 통해 Docker Image 경량화 및 캐시 효과를 높이고 있으며, 빌드 병렬화 등의 기능을 통해 더 빠른 빌드 속도를 보여주는 Docker BuildKit을 사용하고 있습니다.
토스페이먼츠는 클라우드를 활용하고 있기 때문에 동적으로 컴퓨팅 자원을 조정하는 것이 가능한데, 시간 대 별로 빌드서버의 수를 조절하여 관리하고 있습니다.
배포
토스 페이먼츠의 거의 모든 프로젝트는 Kubernetes에 배포되고 있으며, Istio에 의해 트래픽이 제어되고 있습니다.
Istio를 이용하면 비율단위의 트래픽 조절이 가능한데요. 왼쪽 케이스와 같이 1% 단위로 신규버전에 적용하는 것을 가능하게하여, 혹여나 Staging 환경에서 발견하지 못한 문제가 Production 환경에서 발생하더라도 빠른 롤백이 가능해 영향범위를 최소화하는것이 가능합니다.
운영
운영단계에서는 우리의 시스템이 기대한 대로 잘 동작하는지 문제가 있지않은지 문제가 있다면 알림을 수신해 빠르게 복구 할 수 있는지 등이 중요합니다.
이러한 문제를 해결하는 데이터 유형 및 기능은 크게 Metric, Log, Trace, Alerting 으로 나뉠 수 있습니다.
Metric
Metric은 시스템의 상태를 주기적으로 측정하여 숫자화한 데이터 앱입니다.
서버가 정상적인 상황인지 확인하기 위해 10초 단위로 측정하고 있는 CPU 사용률 정보나 메모리 사용률 정보등입니다.
Metric이 수집된 상태로 저장만 되어 있다면 의미가 없기 때문에, 이를 시각화하고 문제가 있다면 알려주는 것이 중요합니다. 토스페이먼츠는 시각화 기능을 제공하고, 다양한 데이터 스토리지를 지원하는 Grafana를 통해 여러 데이터소스에 저장된 정보를 조회하고 알림이 생성될 수 있도록 구성하고 있습니다.
Log
로그는 어떤 처리나 이벤트가 발생할 때마다 생성되어 기록되는 히스토리 데이터입니다.
로그에는 상당히 많은 다양한 로그가 있는데요.
그 중 Application Log와 Access Log를 어떻게 다루고 있는지 소개합니다.
Application Log는 Application이 어떻게 동작했는지 기록하는 로그입니다.
개발자가 필요하다 싶은 문맥에 관련 문맥정보와 함께 로그를 남기게 되는데, 비 정형적이고 양도 많은 편입니다.
그래서 보관비용이 많지만 문제분석에 매우 중요한 단서가 되고, 로그가 있다면 로그가 남아있지 않을 때 대비 원인을 파악하는데 소요되는 시간이 극단적으로 줄어들기에 찾기 쉬운 형태로 오래 보관하는 것이 중요합니다.
하지만 시간이 지날 수록 잘 찾지않는 데이터를 보관하기위해 많은 비용을 투자하는 것은 아까운일입니다. 생성된지 수십일 정도의 로그만 저장하고 있는 Elastic Search의 클러스터 규모가 작년에 100TB를 넘고 로그의 양이 점점 증가하는 추세이기에 대처가 필요한데요. 이를 위해 Storage Tiering 즉, 오래된 로그일 수록 고사양 장비에 저장된 데이터가 저사양 장비로 이동하도록 구성하여 운영함으로써 로그 저장비용을 줄이고 있습니다.
Access Log는 Nginx, Apache Http Server, Tomcat 등의 웹서버 뿐아니라 로드밸런서, CDN, S3등 웹 서비스 제공에 필요한 기능들은 Access Log를 제공합니다. Access Log는 서버가 하나의 요청을 처리할 때마다 한줄로 기록하는 형태의 로그로 서비스 트래픽에 대한 이해와 네트워크 문제 식별등에 중요한 역할을 합니다.
하지만 Access Log에 요청관련 정보가 부족해서 문제가 해결하는데 어려움을 겪는 경우가 많습니다. 특히 여러대의 서버가 협업하는 경우에 API 스펙만 보고는 어떤 기능을 수행하는지 한번에 알 수 없습니다. 이는 Access Log를 봤을 떄, 서버에 맞는 식별자가 없다면 문제원인을 파악하기 어려워지는 문제가 있습니다. 따라서 토스 페이먼츠는 어떤 API가 요청을 처리했는지, 요청에 관한 서비스는 무엇인지, 요청을 처리한 Kubernetes 클러스터 및 데이터센터 정보 등 특정 요청에 문맥을 이해할 수 있는 다양한 정보를 Access Log에 포함 시키고있습니다.
Trace
해당 이미지는 넷플릭스의 아키텍처를 소개할 때 보여준 사진입니다. 이렇게 복잡하게 구성이 되있다면 문제가 발생했을 때, 더욱 문제의 원인을 찾기 어려울 것입니다.
Trace는 분산시스템 간의 호출 정보 및 문제 발생 여부등을 쉽게 알 수 있게 해주는 도구입니다.
Alerting
알림은 알림 수신자의 Action이 필요한 상황에서 보내지는 것이 일반적이기 때문에, 담당자가 알림을 수신했을 때 관련 정보를 함께 전달하는 것이 중요합니다. 또한 문제가 되는 부분의 로그를 특정할 수 있는경우 해당 로그뷰어의 링크를 포함시켜 알림을 받은 담당자로 하여금 빠른 상황파악을 제공합니다.
'Conference' 카테고리의 다른 글
[Conference] JVM warm up (0) | 2023.05.22 |
---|---|
[Conference] 지속 성장 가능한 코드를 만들어가는 방법 (0) | 2023.05.10 |
[Conference] 레거시 개편 (1) | 2023.05.04 |