우아한테크코스에서 진행하는 프로젝트, 201 서비스를 본격적으로 출시하는 단계가 됐다.
서비스를 개발하며 팀 내 코드 리뷰를 필수로 진행하였고, QA를 거치며 예외 상황에 대비했다. 하지만 실제 유저가 존재하는 환경에서는 예상치 못한 문제가 발생할 수 있다. 그렇기 때문에 몇가지 지표에 대해서 모니터링을 하고자 하였다.
모니터링 툴을 선택하고 적용하며 가졌던 고민들을 두 편에 나눠서 작성할 예정이다.
이번 편에서는 모니터링을 하는 이유, 지표를 선택하는 기준, CloudWatch 선택의 이유에 대해서 알아본다.
결론부터 말하자면, 오류 발생 원인을 빠르게 찾아내기 위해서다.
모니터링 과정은 간단하게 다음과 같다.
즉, 확인하고자 하는 데이터를 지표로 심고, 해당 지표의 상태 변화를 확인하며 애플리케이션의 상태를 진단하는 것이다.
이러한 모니터링의 필요성을 알아보기 위해, 특정 상황을 상상해보자. EC2 서버에서 스프링 서버를 실행하고 있다고 가정한다.
어느 날, 우리 서비스의 ‘TODO 완료 인증’ 기능이 동작하지 않게 됐다는 제보를 받게 됐다. 이 기능이 동작하지 않는다면 사용자에게 나쁜 경험을 제공하게 될 수도 있다!
재빨리 컴퓨터를 키고, 원인을 파악하기 위해 에러 로그를 확인해 보지만 도저히 원인을 확인할 수가 없다. 결국에는 TODO 완료 인증 기능과 관련된 모든 부분을 점검해 본다..
생각만 해도 답답해진다.
이때 만약 모니터링을 하고 있었다면 어땠을까? CPU 사용량, 메모리 사용량, 디스크 사용량에 대한 지표를 모니터링하고 있었다고 가정하자.
문제 상황을 제보받은 뒤, 에러 로그를 확인한다. 하지만 에러 로그에서 원인을 파악할 수 없게 되자, 모니터링하고 있던 지표를 확인한다.
지표를 확인하던 중, 디스크 사용량에 문제가 발생한 것을 확인하게 된다. 디스크 사용량이 임계 값에 도달하여 더 이상 사용자가 전송하는 이미지 파일을 저장할 수 없게 된 것이다. (TODO 완료 인증 기능은 사용자가 이미지를 업로드한다고 가정)
디스크 여유 공간을 만들었더니 TODO 완료 인증 기능이 다시 정상적으로 동작하는 것을 확인했다.
여기서 핵심은 모니터링을 통해 문제 발생 범위를 좁혔다는 것이다.
모니터링을 하지 않았다면, 모든 범위를 대상으로 문제의 원인을 찾아야 했다.
하지만 모니터링을 하면 기존에 심어 놓았던 지표를 통해 문제가 발생한 부분을 빠르게 확인할 수 있었다.
문제 발생 시점에 원인을 빠르게 파악할 수 있다는 이유 뿐 아니라, 경보(Alarm)를 통해 특정 지표를 기준으로 알람 이벤트를 발생할 수 있다.
이는 문제가 실제로 발생하기 전에 미리 조치를 취할 수 있도록 한다.
위에서 봤듯이 문제 발생 범위를 좁히기 위해서는, 문제가 발생할 여지가 있는 데이터를 주시해야 한다.
즉, 의미 있는 데이터를 모니터링 해야 한다는 것이다. 예를 들어 디스크에서 읽기/쓰기 작업이 일어나지 않는 서비스라면 굳이 디스크의 사용량 또는 I/O 성능을 확인할 필요가 없다.
물론 의미 없는 값도 ‘혹시혹시혹시나 나중에 문제 발생할 수 있으니 모니터링 하고 있어야지’ 생각할 수도 있다. 당연히 다양한 지표를 모니터링 할수록 안정성이 높아질 수도 있다.
하지만 첫 번째 문제는 돈이다. AWS에서 제공하는 모니터링 서비스 CloudWatch의 경우, 모니터링하고 있는 지표 수에 따라 요금이 청구된다. 돈까지 내면서 의미 없는 값을 모니터링 하는 것은 굳이…라고 생각한다
개인적인 생각으로는 많은 지표를 수집할수록, 해당하는 데이터를 보내주는 애플리케이션에 부하가 올 것이라고 생각한다.
지표 수집 주기가 너무 짧으면 애플리케이션 성능에 부하가 올 수도 있다는 내용을 들었는데, 이와 비슷한 맥락이지 않을까 싶다.
팀 내에서 어떤 지표를 수집할지 상의한 결과, 필요에 따라 다음 데이터들을 모니터링 하기로 했다.
현재는 이정도의 모니터링 계획을 가지고 있지만, 서버 및 사용자의 규모 그리고 새롭게 추가되는 기능 등에 따라 새로운 지표를 모니터링 하게 될 수도 있다.
모니터링 툴을 선택하기 위해 조사한 결과, 세상에는 정말 다양한 모니터링 툴이 존재한다는 것을 알 수 있었다.
그 많은 툴 중에서 어떤 것이 우리에게 최선의 선택지인지 판단하는 것은 정말 어려운 일이었다.
일단은 레퍼런스를 쉽게 찾을 수 있는 프로메테우스와 그라파나를 사용하는 방향으로 생각했지만, 문제점을 한 가지 발견했다.
프로메테우스에서 수집하는 CPU 사용량은 실제값과 차이가 있다.
문제의 원인은 서버가 EC2, 즉, 가상 서버 상에서 존재하다는 것이었다. 가상 서버는 물리 서버의 자원을 가져다 쓰는 CPU 구조를 가진다. 이러한 구조에서 정확한 CPU 사용량을 알기 위해서는 가상화 컨텍스트를 알고 있어야 한다.
다시 프로메테우스로 돌아가면, 프로메테우스는 Spring Boot Actuator를 통해 지표를 수집한다. 하지만 Actuator는 가상화 컨텍스트에 대해 알지 못하기 때문에 가상 서버에서 실제로 자원을 어떻게 할당받고, 얼마나 사용하고 있는지 정확히 알 수 없는 것이다.
즉, 정확한 CPU 사용량을 알기 위해서는 프로메테우스가 아닌 방식을 사용해야 한다.
(더욱 자세한 원리를 알고 싶다면 Stolen CPU, vCPU 라는 키워드로 공부하면 될 것 같다)
결국 가상 서버의 CPU 사용량을 정확하게 알 수 있는 CloudWatch를 모니터링 툴로 사용하기로 결정했다. CloudWatch는 AWS에서 제공하는 모니터링 서비스로, 이 서비스를 선택한 이유는 다음과 같다.
CloudWatch 요금
vCpu 관련