최근에 새로운 프로덕트에 백엔드 포지션으로 붙게 되면서 기존 프로덕트의 세팅을 해야 하는 일이 있었다. datadog를 통해서 로그 세팅부터 트레이스 세팅까지 완성을 해두었고, 로그 포맷을 조금 수정하고 있던 도중에 문득 관측성의 세 가지 축이란 키워드가 떠올랐다.
원래는 손이 많이 가던 프로덕트는 아니었으나, 나를 포함한 다른 개발자들이 프로덕트에 붙기도 하였고, 앞으로 다양한 서비스를 쌓아올릴 예정이라 정비를 할 필요가 있었다. 간단한 프론트엔드쪽 리펙토링과 함께 백엔드에서는 로그 시스템을 손보고 있었다. 백엔드 시스템의 Observability를 챙겨주는 과정에서 로그라는 것은 정확히 어떻게 찍는 건지. 그런 것들을 실무적으로 고민해 본 적이 없었다. 그래서 그런 것들을 찾아보는 과정에서 이 관측성을 위한 지표들을 정리해 봐야겠다는 생각이 들었다.
대시보드를 세팅하는 과정에서 기존에 grafana를 썼을 때에는 일반적으로 대시보드 템플릿을 그냥 import 해서 쓰는 경우가 많았는데, 직접 커스텀해서 대시보드를 만드는 과정에서 관측성의 세가지 축에 대한 개념을 제대로 확인해 보고 정리해보고자 한다. 이번 포스팅에서는 세 가지 지표에 대해서 "어떤 것인지" 자세히 알 수 있도록 할 예정이다. 어떻게 각 지표를 구축하는지, 어떻게 세세하게 작업할 수 있는지는 나도 좀 더 공부하여 다음 포스팅으로 남겨보고자 한다.
본론
관측성의 세가지 축(Three pillars of Observability)
관측성의 세가지 축에서 말하는 세 가지는 각각 매트릭(metrics), 로그(logs), 트레이스(traces)를 말한다. AWS 및 IBM 등 다양한 공식 문서에서 이 세 가지의 지표의 중요성을 꾸준히 말한다. 이에 대해 가장 자세하게 써져 있는 문서다고 생각되는 엘라스틱의 문서를 첨부한다. 아래에서 매트릭, 로그, 트레이스에 대해서 살펴볼 수 있다.
- [Elastic] 옵저버블리티의 3가지 핵심 요소 : https://www.elastic.co/blog/3-pillars-of-observability
The 3 pillars of observability: Unified logs, metrics, and traces
Learn the three pillars of observability and understand telemetry signals for better decision-making, improved performance, and enhanced customer experiences....
www.elastic.co
해당 페이지를 요약하면, 매트릭은 하드웨어, 애플리케이션 소프트웨어 그리고 웹사이트 등 다양한 소스에서 수집된 원시 수치 데이터로, 알려진 데이터를 측정한다. 리소스 사용량과 같은 정보를 제공한다. 로그는 특정 이벤트와 관련된 타임스탬프가 지정된 항목으로 구성된 인프라, 애플리케이션, 네트워크 및 시스템의 정형 및 비정형 데이터이다. 마지막으로 트레이스는 사용자가 애플리케이션 또는 서비스를 사용하는 동안 수행하는 작업을 기록하여 사용자의 관점에서 애플리케이션을 보여주는 신호이다. 트래픽의 시작점과 끝점을 볼 수 있도록 도와주는 역할을 한다.
이론적인 내용은 이정도로, 예시를 들어가며 자세하게 살펴보자. 이 포스팅에서는 우리가 일반적으로 쓰는 툴, Grafana, AWS, Datadog, ELK 등의 다양한 플랫폼을 통해서 예시를 들기 때문에, 해당 플랫폼이 뭔지 어느 정도는 알고 있으면 좋다.
매트릭(Metrics)
메트릭은 앞서 말했듯이, 시스템 상태를 시간에 따라 숫자 시계열로 본 것을 의미한다. 시계열이라는 개념이 가장 중요하다. 시간에 따라서 하드웨어나 소프트웨어의 상태는 변한다. 우리의 컴퓨터도 마찬가지다. Mac을 쓰고 있는데, 현재 컴퓨터의 CPU나 Memory의 사용량을 볼 수 있는 아이콘을 상단바에 위치시켜 두었는데, 다음과 같이 표시해 준다.
매트릭은 "주로" 이러한 CPU나 Memory의 사용량을 시계열로 측정하고자 할 때 쓰인다. 이 외에도 네트워크의 입출력 등도 확인할 수 있다. 각각의 지표는 CPU_utilization, Memory_utilization, network_io 등의 이름으로 매초, 매분 숫자를 남기며, 이러한 데이터를 수집해서 시각화하면 특정 지표에 대한 시계열 데이터를 볼 수 있다.
CPU와 Memory를 많이 쓰고 있다면 무슨 일이 일어날까
필자는 iStat Menus라는 툴을 통해서 CPU와 Memory 그리고 SSD(disk)를 모니터링할 수 있도록 설정해 두었다. 운영체제를 공부했다면 잘 알겠지만, CPU와 Memory는 아주 밀접한 관련이 있으며, 잘 관리를 해주어야 한다. CPU는 부족하면 느려지고, MEMORY는 부족하면 죽는다(OOM)가 법칙이다.
CPU의 사용량(이는 흔히 CPU Uilization이라고 부름)이 만약에 100%를 찍게 되면 대기열 폭증하게 된다. 요청이 들어오지만 그것을 처리할 능력이 없기 때문에 스레드나 요청이 밀리면서 타임아웃과 에러가 증가하고, 심하면 서버가 다운되기도 한다.
Memory는 어떨까? 운영 체제의 개념이지만, 스왑 영역과 페이지 폴트 등의 이슈로 느려지기 시작하고, 메모리는 CPU와 다르게 100%가 되면 매우 위험하다. A 프로그램과 B 프로그램을 동작하고 있다고 치자. 각각은 프로세스가 되어 메모리에 적재되는데, 이때 메모리가 꽉 찼다면 B 프로그램에서의 작업이 메모리에 액세스 할 때, 다른 부분을 건드릴 위험이 있다. 치명적인 사고를 칠 수 있는 일이기 때문에 OS 레벨의 OOM(Out-of-Memory) Killer가 메모리의 다른 부분에 액세스 하는 대참사를 막기 위해서 프로세스(혹은 컨테이너)를 SIGKILL로 종료시킨다.
이러한 개념은 굉장히 중요한데, K8s 등의 클러스터링 툴을 사용하게 되면 가끔씩 Pod 자체가 뜨지 않는 경우가 있다. OOM 등의 문제도 자주 마주칠 수 있기 때문에 주의를 기울여서 CPU와 Memory를 관리해 주자.
메트릭 모니터링
AWS에서 일반적으로, 어떤 컴퓨팅 서비스를 띄우는 경우에는 모두 이런 식으로 메트릭을 볼 수 있도록 해준다. 특히 EC2나 Fargate 같은 서비스를 띄울 때, 메모리나 CPU 등을 할당해서 띄우게 될 텐데, 이런 식으로 지표를 확인할 수 있도록 해준다. cloudwatch에서는 모든 AWS 서비스의 메트릭이 모이기 때문에 이러한 메트릭 수집을 알아서 해준다!
여기서 호기심이 있거나, 온프레미즈에서 어떤 식으로 메트릭 수집을 직접 해줄 수 있는지 궁금할 수 있는 사람들을 위해서 예전의 포스팅을 첨부한다.
- 프로메테우스와 그라파나로 레디스 서버 모니터링 : https://marsboy.tistory.com/42
prometheus와 grafana로 redis 서버 모니터링
저번 포스팅에서는 node-exporter를 통해서 리눅스 시스템을 모니터링하는 방법을 알아봤다. 이번에는 심층적으로 redis를 모니터링해 보자.본론먼저 소스 코드의 예제는 아래와 같다. 궁금하면 직
marsboy.tistory.com
요약하면, 시계열 데이터를 시각화하기 위해서는 그라파나라는 대시보드 툴에서 시계열 데이터를 data sources로 설정해야 한다. 그런 시계열 데이터를 수집해 주는 툴이 바로 프로메테우스(premetheus)이다.
그렇다면, 프로메테우스가 수집하는 시계열 데이터는 누가 어떻게 만드는 걸까? 위와 같이 redis-exporter라는 컨테이너를 띄우면, redis를 모니터링하여 정보들을 계속 내뿜는다(export). 실제로 redis-exporter는 9121 포트에 redis에 대한 정보를 계속 매초 내뿜고 있으며, 프로메테우스의 설정에 해당 9121 포트를 지정하면, 주기적으로 확인하여 레디스에 대한 메트릭을 수집한다.
이제 이렇게 프로메테우스가 수집하고 있는 정보를 그라파나에게 물려주면, 그라파나는 해당 정보를 확인할 수 있게 된다.
다음으로는 로그에 대해서 살펴보자.
로그(logs)
로그는 간단하게 말하면 사건의 세부 기록이다. 타임스탬프, 레벨, 메시지, 필드 등을 말한다. 로그는 메트릭과 트레이스와 다르게 꽤 친근한 느낌이 든다. 자바스크립트 기반으로 개발을 하다 보면 정보를 확인하기 위해 코드 곳곳에 console.log를 찍곤 할 것이다. 그런 식으로 정보를 남기는 것을 로깅(logging)이라고 한다.
로그에 대해서는 상세한 설명이 없어도 딱히 이해가 어렵진 않을 것이다. 아마 세 가지 지표 중에서 가장 먼저 접하게 되는 지표이기도 하고, 꽤 많이 경험적으로 로그를 남겨보았을 것이기 때문이다. 간단하게 로그를 어떻게 활용할 수 있는지 정리하고 넘어가려고 한다.
로그의 활용
로그는 그렇다면 어떻게 활용할 수 있을까? 디버깅에도 사용할 수 있기는 하지만, 옵서버블리티를 위해서 로그는 주로 모든 액세스 기록에 남기는 용도로 사용한다.
어떤 부분에 남길 수 있을까? 가장 먼저, 서버에 들어오는 모든 HTTP Request에 대해서 남길 수 있다. HTTP Request는 다양한 정보를 가지고 있다. 어떤 에이전트인지? 어떤 IP인지? 등등이다. 그런 것들을 잘 남겨놓는다면 IP를 통해서 국가별로 어떤 국가에서 접근을 많이 하는지, 어떤 에이전트에서 가장 많이 접근을 하는지 등을 알 수 있다.
그 외에 시간대에 맞춰 수행하는 작업과 같이 crontab이 수행되면 정상적으로 처리됐다는 메시지를 남길 수도 있고, 특정 도메인(예를 들면 users)에 접근하는 경우 꼭 로그를 남겨야 한다는 룰이 있다면, 해당 도메인에 접근할 때 로그를 남길 수도 있을 것이다.
해당 그래프는 서버의 Latency에 대한 정보를 시각화한 것이다. 이는 로그 데이터를 통해서 파악할 수 있다. HTTP Request의 응답 시간을 @responseTime으로 받아볼 수 있는데, 이러한 response time을 모아서 레이턴시가 얼마나 되는지 측정이 가능하다.
이와 같이 로그 또한 옵서버블리티를 위해서 사용할 수 있으며, 세세한 로그 시스템을 구축하는 것이 중요하다. 다음으로는 트레이스에 대해서 살펴보자.
트레이스 (Traces)
트레이스는 하나의 요청이 시스템을 통과하는 전체 여정이다. 사용자가 /orders를 호출했다고 치면, 프론트 -> API -> DB/캐시 -> 외부 결제 API -> 메시지 큐 같은 모든 구간의 시간과 인과관계를 한눈에 보여준다. 화면에서는 보통 워터풀 형태로 시각화된다.
먼저, 트레이스는 이렇게 여정을 정리하고 있는 내용이기 때문에 하나의 여정은 스팬(Span)이라고 부른다. 트레이스에 대해서 자세히 알아보기 전에 용어를 정리해 보면 다음과 같다.
- Trace: 요청 단위의 전체 실행 흐름. 고유한 trace_id로 식별.
- Span: Trace를 이루는 작업 단위. "컨트롤러 처리", "DB 쿼리", "외부 HTTP 호출" 같은 한 구간
- Root Span: 가장 바깥(시작) 스팬. 보통 "HTTP POST /orders"처럼 사용자 시나리오를 대표하는 이름을 쓴다.
- Span Kind: 스팬의 역할. SERVER(수신), CLIENT(외부호출), INTERNAL(내부 로직)
스팬에 들어가는 정보는 Anatomy라고 부르며, 이름, 시작/종료 시작(duration), 속성(attributes), 이벤트(event), 상태(status: OK/ERROR), 관계(부모-자식/링크) 등이 있다.
이러한 트레이스를 통해서 알 수 있는 정보들은 "느리다"는 증상을 어느 구간이 얼마큼 느린지 바로 확인할 수 있는 병목 구간이다. 또한 에러난 스팬에서 상태/이벤트/속성으로 단서를 확인해서 원인 맥락을 확보할 수 있다.
앞서, 스팬의 정보에 부모-자식 관계가 아나토미(anatomy)로 들어가 있다고 했는데, 그 관계를 이렇게 트리 구조로 시각화해서 볼 수 있다. 워터폴 구조로 볼 수 있으며, 스팬의 길이에 다라서 어느 정도의 ms가 소요됐는지 확인할 수 있다. 트레이스는 이렇게 하나의 요청에 대한 전체적인 경로를 제공하여, 특정 지점에서 병목이 생기는 것을 손쉽게 파악할 수 있다.
마지막으로 트레이스를 살펴보았는데, 앞서 이야기한 다른 지표인 메트릭, 로그와 함께 트레이스까지 제대로 확인할 수 있다면 높은 수준의 옵서버블리티를 지킬 수 있다. 우리 서비스가 어떤 상태인지? 뭔가를 배포했는데, 일단 표면적으로는 문제가 없는 것 같지만 지표는 그대로 모두 드러난다. 따라서 이러한 지표를 보면서 어떤 문제 상황인지 자세하게 맥을 짚을 수 있게 된다.
마치며
포스팅 내내 세 가지 지표를 계속 이야기했는데, 이러한 세가지 지표의 표준이 있다. CNCF에서 오픈 소스로 관리하고 있는 OpenTelemetry라는 것인데, 줄여서 OTel이라고 부른다.
OTel(OpenTelemetry)는 벤더 중립 표준으로, 애플리케이션이 세 가지 신호(Traces, Metrics, Logs)를 같은 방식으로 계측 -> 수집 -> 전송하게 해주는 API/SDK + Collector + 프로토콜(OTLP) 묶음이다.
따라서, 우리가 사용하는 datadog나 AWS 같은 툴은 손쉽게 지표를 받아올 수 있도록 해주는데, 그러한 것들이 다 이 OTel의 표준을 지켜서 써드파티를 개발한 것이다. 이 부분은 참고차로 알아두면 좋을 것 같다.
정말 마지막으로, 민감 정보를 저장할 때에는 마스킹하거나 삭제해야 한다! PII 등의 데이터가 노출되지 않도록 조심하자..
참고
- [AWS] 옵서버블리티 : https://docs.aws.amazon.com/whitepapers/latest/aws-caf-operations-perspective/observability.html?utm_source=chatgpt.com
- [Grafana] 옵서버블리티의 다음 관계 : https://grafana.com/blog/2019/10/21/whats-next-for-observability/
- [OpenTelemetry] 오픈텔레메트리란 무엇입니까 : https://opentelemetry.io/docs/what-is-opentelemetry/
- [HoneyComb] 트레이스 탐험하기 : https://docs.honeycomb.io/investigate/analyze/explore-traces/
감사합니다.
'DevOps > monitoring' 카테고리의 다른 글
Metabase(메타베이스)를 사용한 데이터 시각화 플랫폼 (0) | 2025.03.23 |
---|---|
prometheus와 grafana로 redis 서버 모니터링 (0) | 2024.07.16 |
promethous와 grafana로 linux 시스템 모니터링 (2) | 2024.07.14 |
Prometheus란? (1) | 2024.07.14 |