Journey to Observability — STAYGE LABS
이번 아티클에서는 옵저버빌리티(Observability)에 대해 이해하고 스테이지랩스에서는 어떻게 관찰 가능성을 확보하고 있는지 알아보도록 하겠습니다.
목차
- 관찰 가능성이란?
- 로그 Log
- 지표 Metric
- 추적 Trace
- 스테이지 관찰가능성 진단
관찰 가능성이란?
옵저버빌리티(Observability)를 번역 하면 관찰 가능성입니다. 관찰 가능성은 “서버 내부에서 외부로 보내는 신호를 통해서 얼마나 서버의 상태를 잘 추측 할수 있는지”를 의미 합니다. 서버에서 보내는 신호란 무엇인지 그림을 통해 알아 보겠습니다.
- 소중하고 가녀린 서버가 한대 있습니다.
- 서버는 어떠한 신호도 보내지 않습니다. 서버에 장애가 생겼는지 알 수도 없죠.
- 서버는 장애가 발생 했다는 경보 신호를 내보냅니다. 서버에 장애가 생겼다는 것을 알 수 있죠.
- 서버는 CPU 사용률의 지표를 신호로 보냅니다. CPU 사용률이 높아져서 서버 응답률이 낮아졌다는 것을 알 수 있습니다.
- 서버는 초당 API 호출 지표를 신호를 보냅니다. 평소 대비 10배의 트래픽이 몰려서 처리 가능양을 넘어 섰다는 것을 알 수 있습니다.
- 서버는 특정 API 의 실패 로그를 신호로 보냅니다. 로그인 기능에 트래픽이 몰린것을 알 수 있습니다.
우리는 서버가 외부로 보내는 신호의 종류가 많아 질수록 서버 내부의 가시성을 확보 할수 있었고, 이를 통해 서버의 상태를 추측 할수 있었습니다.
주요 신호들
신호란 인간이 기계의 상태를 추측 하기 위한 시스템의 출력이고, 달성하고자 하는 목표가 다릅니다. CNCF의 관찰 가능성 백서에서는 로그(log), 매트릭(Metric), 트레이스(Trace)를 관찰 가능성을 달성하기 위한 3가지 주요 신호로 제시합니다. 3개의 주요 신호 뿐 아니라 Profile, Dumps라는 신호도 있고, 기술이 발전하고 시스템 구조가 복잡해 짐에 따라 새로운 종류의 신호가 대두 될 수 있습니다. 이번 아티클에서는 매트릭, 로그, 트레이스 3가지 신호에 대해 다룰 예정입니다.
모든 신호는 수집하고 해석하는 방식이 다릅니다. 매트릭은 CPU 사용률, 에러 발생률 등의 시스템의 정보가 시간별로 집계(합산, 최대, 평균)된 신호입니다. 주로 1분 단위 혹은 1초 단위로 정보가 압축 되기 때문에 다른 신호들에 비하여 데이터의 양이 적은편이며, 늘어나는 데이터의 양이 예상 가능합니다.
로그는 시스템의 작업 내용이나 활동 상황을 시간의 흐름에 따라 텍스트 형태로 기록한 신호 입니다. 개발자가 디버그, 감사, 보안 등의 목적에 따라 남기게 됩니다. 로그를 상세하게 남기게 된다면, 오류 발생 시 오류가 발생한 근본적인 원인을 찾는데 도움이 됩니다. 하지만, 너무 상세하게 로그를 남기게 되면 로그 수집 및 처리에 큰 비용이 들어 갈 수 있습니다.
트레이스는 요청의 시작부터 끝날 때 까지 발생하는 모든 이벤트를 연관시켜서 하나의 흐름으로 이해 할수 있게 해주는 신호 입니다. “유저가 주문을 했다”, “주문 성공 푸시 알림을 보낸다” 라는 두가지 작업을 하는 시스템이 있다고 가정 했을 때 “A 유저가 주문을 했고 주문에 성공하여 푸시 알림을 보낸다.” 라고 두가지 이벤트를 한가지 이벤트로 이해 할때 활용 됩니다. 트레이스도 데이터의 양이 크기 때문에 샘플링을 통해 부분적인 데이터를 수집합니다.
우리의 시스템이 매트릭, 로그, 트레이스 신호를 외부로 보내고 있다면 관찰 가능성을 달성 했다고 할수 있을까요? 매트릭은 추이를 파악하는데 용이하지만, 정보가 집계 되었기 때문에 상세한 원인을 찾기에는 적합하지 않습니다. 로그는 상세한 원인을 찾는데 용이하지만, 분산된 시스템에서 로그를 연관 지어서 해석하는데는 부족합니다. 즉, 관찰 가능성을 달성 하기 위해서는 주요 신호 3개를 연관 지어 복합적으로 활용 하는 능력이 중요 합니다.
데이터 수집 및 분석 방법이 다른 신호들을 연관 지어 활용하는 방법 중 선행 되어야 하는 것은 바로 모니터링 도구를 단일화 시키는 것 입니다. 가장 쉽고 일반적인 방법은 Data Dog이나 New Reric 같은 Saas 서비스를 사용 하는 것 입니다. 하지만, $ 이게 비싸죠 🥵
로그 Log
스테이지랩스에서는 AWS CloudWatch, AWS X-ray 그리고 Sentry 를 관찰 가능성을 확보하기 위한 도구로 사용중입니다. AWS CloudWatch 는 AWS 서비스들에 최적화 되어 데이터를 수집하고 처리하여 분석에 필요한 검색이나 시각화 기능을 제공하는 통합 모니터링 도구입니다.
로그 검색
스테이지랩스는 비즈니스 로직을 처리하는 컴퓨팅 자원이 모두 AWS Lambda 로 구성 되어 있고, 200 개 이상의 Lambda 함수가 운영 되고 있습니다. AWS Lambda 는 console.log(), printf() 등의 시스템 출력 함수를 사용하여 로그를 출력하게 되면, 모든 로그가 자동적으로 CloudWatch Log 에 수집되고 Lambda 함수, 자원ID, 시간, 요청ID 별로 정리 되어 저장됩니다. 그리고 시간과 키워드를 입력하여 원하는 로그를 검색 할수도 있습니다.
또한, CloudWatch Logs Insights 를 사용 하면 여러개의 분산된 Lambda 함수에서 수집된 로그를, 원하는 로그 그룹은 선택하고 로그 분석에 필요한 쿼리를 실행 시켜서 통합된 로그 분석을 할 수도 있습니다.
로그 분석
CloudWatch Logs Insights 쿼리 언어를 사용 하면 아래 예시와 같이 분당 API 호출량을 측정하는 분석을 할 수 있습니다.
fields @message
// 로그 중 '[RES *] * *' 패턴의 * 을 idx, elapsed, res 로 정의
| parse @message '[RES *] * *' as idx, elapsed, res
// 200 코드인 호출만
| filter (statusCode >= 200)
// 1분 단위로 합산
| stats count(statusCode) by bin(1m) as interval
// 시간 단위로 정렬
| sort interval
이렇듯 로그 통찰력을 이용하면 “유저가 인증 이메일을 받고 인증코드를 입력하는데 걸리는 시간”과 같은 Ad Hoc 분석 할수도 있고, “응답 시간이 오래 걸리는 API & SQL“ 이나 “호출량이 많은 API & SQL” 과 같은 주기적인 분석도 할수 있습니다. 스테이지랩스에서는 주기적인 백엔드 성능에 대한 분석 결과를 Slack 으로 리포트 받는 기능을 만들어서 백엔드 성능을 매일 확인 하고 있습니다. (Made by Mario.)
지표 Metric
스테이지랩스에서는 RDS, Redis, Kafka 등의 거의 모든 Infrastructure 를 AWS 의 관리형 서비스로 운영 하고 있는데, AWS 에서는 관리형 서비스의 내부 상태를 알기 위한 웬만한 매트릭을 시간 순으로 자동 수집해 줍니다. 관계형 데이터 베이스인 AWS Aurora DB 에서 자동으로 수집되는 매트릭의 수는 무려 약 90개 정도가 됩니다. 그렇기 때문에 서비스에 장애가 발생한 시점에 장애가 발생한 원인을 매트릭을 통해 빠르게 유추 하기에는 충분하다고 할 수 있습니다.
자동 매트릭
다른 종류의 매트릭 정보를 하나의 그래프에 두어서 각 매트릭 간의 상관 관계를 파악 할수 있습니다. 아래 그래프를 예시로 본다면, 특정 시간에 RDS 의 CPU 사용량이 올라간 이유는 “같은 시간대에 API 서버의 CPU 사용량과 Lambda의 호출 횟수가 같이 올라간 것을 보아, 유저의 인입으로 인한 API 호출이 증가했고 처리를 위해 Lambda에서 RDS를 호출 했기 때문이다.” 로 각 매트릭의 상관 관계를 유추 할 수 있습니다.
여러가지의 매트릭 중에서 주요 매트릭을 대시보드로 구성하여 전반적인 시스템 상태의 가시성을 확보 할 수도 있습니다.
커스텀 매트릭
AWS CloudWatch에는 미리 자동으로 수집되는 매트릭 말고도 수집한 로그를 사용하여 유저 정의 매트릭도 생성 할수 있는데요. 로그에서 특정 키워드와 매칭하여 매트릭을 수집하는 지표 필터 기능과 쫌더 복잡한 규칙으로 매트릭을 수집하는 기여자 통찰력 기능(Contributor Insights) 을 사용 할수 있습니다.
저희는 지표 필터 기능을 사용해서 로그에 “RES”를 키워드를 필터로 정하여 매칭 1개당 API 호출 1회로 지정해 **“분당 API 호출량 매트릭”**을 수집하고 있습니다.
기여자 통찰력 기능을 사용해서 로그에서 Status가 399 보다 큰 API 호출을 매트릭으로 수집하여 현재 정상 응답 되고 있지 않는 API 를 확인 하고 있습니다.
매트릭 알람
미리 계측한 시간 순으로 집계된 신호 즉 매트릭이 모두 준비 되었다면 이제 매트릭의 임계 점에 대한 알람를 설정하여 시스템 대시보드를 보고 있지 않아도 서비스에 문제가 발생하거나 예상 되었을 때 개발자가 인지 할수 있게 해야 합니다.
스테이지랩스에서는 CloudWatch Alarm 과 Slack Bot 을 사용하여 시스템 알람를 구성 하였습니다. CPU 사용량, 사용 가능한 메모리 등의 원하는 매트릭을 선정하고 경고와 위험 단계의 임계치를 설정합니다. 그 후 “5분 동안 3개 이상이 임계 값을 넘었을 경우” 와 같은 알람의 민감도 조정 하면 CloudWatch Alarm 의 설정이 완료 됩니다.
여러가지 알람에서 경보가 발생하게 되면 AWS EventBridge(이벤트 버스, 메시지 큐)로 경보 이벤트가 모이게 됩니다. 람다는 EventBridge 에 모인 경보 이벤트를 Slack 으로 보내서 개발자에 알립니다.
팁: 너무 많은 알람이 온다면 상당한 피로가 되거나 어느 순간 알람 메시지를 안보게 됩니다. 알람의 효율을 높이기 위해서는 알람을 운영하면서 임계값과 민감도를 조정 하거나 복합 경보를 사용 하는 방법이 있습니다.
추적 Trace
스테이지랩스는 Error Tracking 도구로 Sentry 를 사용합니다. API 기능이나 비동기 처리 Worker 기능에서 Status 500 Code 의 에러가 발생하면 Slack 채널로 알람을 받고 있습니다. 이 때 CloudWatch Logs 로 바로 이동 할수 있는 링크를 만들어 센트리 알림에 추가하여 에러 발생 알림과 로그를 연결 하고 있습니다.
에러 메시지와 로그를 연결하여 에러 발생에 대한 신속하게 대응 할수 있게 되었지만, 분산 환경에서 이벤트 추적에는 어려움이 있었습니다. 그리하여 분산 환경에서 이벤트를 추적할 수 있고 분산 환경의 추적 맵을 시각화 된 형태로 제공하는 도구인 AWS X-Ray 를 도입하게 되었습니다. 아직 도입 초반 단계라 고도화 및 개선 해야할 부분이 많지만 분산환경에서의 분산 추적 문제를 해결 해줄 좋은 도구로 기대 되어 집니다.
스테이지 관찰가능성 진단
과연 우리는 관찰 가능성을 당성 했다고 할 수 있을 까요? 현재 스테이지랩스의 관찰 가능성에 부족한 점은 무엇인지 알아보겠습니다.
X-Ray 고도화
현재 X-Ray 의 도입은 매우 기초적인 단계입니다. DB와 API 의 처리 시간 정도만 기록되고 있습니다. 그리고 Kafka 와 같이 비동기적으로 분산 처리 되는 이벤트에 대한 추적 맵은 제공 되지 않고 있죠. 우리는 아래 항목들이 필요합니다.
- Redis, Memcached, Kafka 등 다른 인프라의 작업 추적
- 코드 레이어 간의 작업 추적
- Trace ID 를 심어 분산 처리 추적 고도화
- X-Ray 분석 도구 연구
Log 기록 고도화
로그를 분석하기 위해서는 로그의 일관성이 있어야 합니다. 현재 우리의 규칙은 INFO, ERROR, WARNING, DEBUG 정도의 단순한 규칙만 있습니다.
- JSON 형식으로 로그 구조화
- Trace ID를 기록하여 분산 환경의 로그 연결
- Log와 Trace 의 연결성 확보
스테이지랩스의 관찰 가능성을 진단하면 다음과 같습니다. 우리 개발 조직은 관찰 가능성을 위한 주요 신호 3가지인 매트릭, 로그, 트레이스를 수집하고 분석 할수 있는 도구를 모두 갖추게 되었습니다. 하지만, Trace 도구인 X-Ray에 대한 개선점들이 많이 있고 Log 와 Trace 를 연결 시켜야 하는 도전이 남아 있습니다.
부족한 점을 개선 및 고도화 하면 다음 아티클로 찾아오겠습니다~!
reference
https://github.com/cncf/tag-observability/blob/main/whitepaper.md