잘 설계된 지표 모니터링 및 경보 시스템은 인프라의 상태를 선명하게 볼 수 있도록 하여 높은 가용성과 안정성을 달성하는 데 중추적 역할을 한다.
1단계: 문제 이해 및 설계 범위 확정
개략적 요구사항 및 가정
- 대규모 인프라를 모니터링 해야 함
- 일단 능동 사용자 수 1억 명
- 서버 풀 1000개, 풀당 서버 수 100개, 서버당 100개의 운영 지표를 수집한다고 치면 모니터링 해야 하는 지표의 수는 천만 개 수준
- 데이터 보관 기간은 1년
- 수집한 그대로 데이터를 보관하는 기간은 일주일. 그 뒤에는 1분 단위 데이터로 변환한 후에 30일간 보관. 그 뒤에는 1시간 단위 데이터로 변환한 뒤에 1년간 보관.
- 모니터링할 지표
- CPU 사용률
- 요청 수
- 메모리 사용량
- 메시지 큐 내의 메시지 수
비기능 요구사항
- 규모 확장성: 시스템은 늘어나는 지표 수와 경보의 양에 맞게 확장될 수 있어야 한다.
- 낮은 응답 지연: 대시보드(dashboard)와 경보(alert)를 신속하게 처리할 수 있도록, 질의(query)에 대한 낮은 응답 지연을 보장해야 한다.
- 안정성: 높은 안정성을 제공하여 중요 경보를 놓치지 않도록 해야 한다.
- 유연성: 기술을 계속 변화하므로, 미래의 신기술을 쉽게 통합할 수 있도록 유연하게 변경 가능한 파이프라인을 이용해 구축한 시스템이어야 한다.
고려하지 않아도 되는 요구사항
- 로그 모니터링(log monitoring)
- 분산 시스템 추적(distributed system tracing)
2단계: 개략적 설계안 제시 및 동의 구하기
기본적 사항
- 데이터 수집(data collection): 여러 출처로부터 지표 데이터를 수집한다.
- 데이터 전송(data trasmissione): 지표 데이터를 지표 모니터링 시스템으로 전송한다.
- 데이터 저장소(data storage): 전송되어 오는 데이터를 정리하고 저장한다.
- 경보(alerting): 밀려오는 데이터를 분석하고, 이상 징후를 감지하고, 경보를 발생시킨다. 이 시스템은 다양한 통신 채널로 경보를 발송할 수 있어야 한다.
- 시각화(visualization): 데이터를 차트나 그래프 등으로 제공한다. 엔지니어는 데이터를 시각적으로 보여주면 패턴, 추이, 문제점을 더 쉽게 파악한다.
데이터 모델
지표 데이터는 통상 시계열(time series) 데이터로 기록한다. 값 집합에 타임스탬프가 붙은 형태로 기록한다는 뜻이다.
시계열 각각에는 고유한 이름이 붙고, 선택적으로 레이블(label)을 붙이기도 한다.
데이터 접근 패턴
쓰기 부하
막대하다.
시점을 막론하고 많은 시계열 데이터가 기록될 수 있다. 매일 천만 개 운영 지표가 기록된다. 상당수의 지표는 발생 빈도도 높다. 따라서 이 시스템으로 오는 트래픽은 단연 쓰기가 압도적이다.
읽기 부하
일시적으로 치솟았다 사라지는(spiky) 편이라고 봐야 한다.
시각화와 경보 서비스는 데이터베이스에 대한 읽기 연산을 발생시킨다. 따라서 그래프나 경보를 확인하는 패턴에 따라 읽기 연산은 일시적으로 증가하였다가 잠잠해질 수 있다.
=> 이 시스템은 언제나 많은 양의 쓰기 연산 부하를 감당해야 하지만, 읽기 연산의 부하는 잠시 급증하였다가 곧 사라진다.
데이터 저장소 시스템
데이터 저장소 시스템은 본 설계안의 핵심이다.
지표 모니터링 및 경보 시스템을 위한 저장소 시스템을 직접 설계하거나, MySQL 같은 범용의 저장소 시스템을 사용하는 선택지 가운데 어떤 것도 추천하지 않는다.
범용 데이터베이스
이론적으로는 시계열 데이터를 처리할 수 있지만 이 설계안이 감당하려는 부하 규모에 맞추려면 전문가 수준의 튜닝(tuning)이 필요하다.
특히 관계형 데이터베이스는 시계열 데이터를 대상으로 통상적으로 수행하는 연산에 최적화되어 있지 않다.
NoSQL
시계열 데이터를 효율적으로 처리할 수 있다고 알려진 NoSQL 데이터베이스들이 시장에 나와 있다. e.g. 카산드라(cassandra)나 빅테이블(bigtable)
하지만 이런 데이터베이스에 시계열 데이터를 효과적으로 저장하고 질의하기 위해서는 확장이 용이한 스키마를 설계해야 하는데, 그러려면 해당 NoSQL 데이터베이스의 내부 구조에 대한 해박한 지식이 필요하다. 기업에 필요한 규모를 지원하는 시계열 데이터베이스가 시장에 나와 있는 만큼 범용 NoSQL 데이터베이스를 사용하는 방안은 그다지 매력적이지 않다.
시계열 데이터베이스
같은 양의 시계열 데이터를 더 적은 서버에 보관할 수 있도록 잘 최적화된 저장소 시스템은 시장에 많다. 이들 상당수는 시계열 데이터 분석에 적합하며 SQL보다 사용하기 쉬운 질의 인터페이스도 갖추고 있다. 데이터 보관 기간을 설정하거나 데이터 집계(aggregation) 기능을 제공하기도 한다.
- OpenTSDB: 분산 시계열 데이터베이스지만 하둡(Hadoop)과 HBase에 기반하고 있어서 하둡/HBase 클러스터를 구성하고 운영해야 하므로 복잡하다.
- MetricsDB: X(구 트위터)에서 사용한다.
- 타임스트림(Timestream): 아마존에서 출시하였다.
DB-engins에서 조사한 결과에 따르면 시장에서 가장 인기 있는 시계열 데이터베이스 두 가지는 InfluxDB 그리고 프로메테우스(Promethues)이다. 다량의 시계열 데이터를 저장하고 빠른 실시간 분석을 지원하는 것이 특징이다. 두 제품 모두 메모리 캐시와 디스크 저장소를 함께 사용한다. 영속성(durability) 요건과 높은 성능 요구사항도 잘 만족한다. 8CPU 코어와 32GB 램을 갖춘 InfluxDB 서버 한 대로 초당 250,000회의 쓰기 연산 처리가 가능하다.
좋은 시계열 데이터베이스는 막대한 양의 시계열 데이터를 레이블(또는 태그(tag)) 기준으로 집계하고 분석하는 기능을 제공한다. 예를 들어 InfluxDB는 레이블 기반의 신속한 데이터 질의를 지원하기 위해 레이블별로 인덱스를 구축한다. 레이블을 이용할 때 데이터베이스 과부하를 피하는 지침도 제공한다. 핵심은 각 레이블이 가질 수 있는 값의 가짓수(cardinality)가 낮아야 한다는 것이다. 이 기능은 데이터 시각화에 특히 중요하며, 범용 데이터베이스로 구축하기는 매우 까다롭다.
개략적 설계안
- 지표 출처(metrics source): 지표 데이터가 만들어지는 곳으로 애플리케이션 서버, SQL 데이터베이스, 메시지 큐 등 어떤 것이든 가능하다.
- 지표 수집기(metrics collector): 지표 데이터를 수집하고 시계열 데이터에 기록하는 역할을 한다.
- 시계열 데이터베이스(time-series database): 지표 데이터를 시계열 데이터 형태로 보관하는 역할을 한다.
- 질의 서비스(query service): 지표 데이터를 시계열 데이터 형태로 보관하는 저장소다. 다량의 시계열 데이터를 분석하고 요약하는 데 적합하도록 설계된 질의 인터페이스를 제공한다.
- 경보 시스템(alerting system): 경보를 받아야 하는 다양한 대상으로 경보 알림을 전송하는 역할을 하는 시스템이다.
- 시각화 시스템(visualization system): 지표를 다양한 형태의 그래프/차트로 시각화하는 기능을 제공하는 시스템이다.
3단계: 상세 설계
지표 수집
카운터(counter)나 CPU 사용량 같은 지표를 수집할 때는 때로 데이터가 소실되어도 아주 심각한 문제는 아니다. 지표를 보내는 클라이언트는 성공적으로 데이터가 전송되었는지 신경 쓰지 않아도 상관없다.
풀 vs 푸시 모델
풀 모델
지표 수집기가 실행 중인 애플리케이션에서 주기적으로 지표 데이터를 가져오는 모델
푸시 모델
지표 출처에 해당하는 서버(웹 서버나 데이터베이스 서버)가 직접 지표를 수집기에 전송하는 모델
풀 모델 | 푸시 모델 | |
손쉬운 디버깅 | 애플리케이션 서버에 /metrics 엔드포인트를 두도록 강제하므로 필요하다면 언제든 지표 데이터를 볼 수 있다. ✔️ | |
상태 진단(health check) | 애플리케이션 서버가 풀 요청에 응답하지 않으면 바로 해당 서버에 장애가 발생한 것으로 진단할 수 있다. ✔️ | 지표 수집기가 지표를 받지 못하면 네트워크 장애가 원인인지 서버 장애가 원인인지 알 기 어렵다. |
생존 기간이 짧은 프로세스 | 생명 주기가 짧은 일괄 작업 프로세스의 경우 수집기가 미쳐 지표를 끌어가기도 전에 종료될 수 있다. ✔️ | |
방화벽 등의 복잡한 네트워크 | 수집기 서버가 지표 데이터를 제대로 끌어갈 수 있도록 모든 /metrics 엔드포인트에 접근 가능하도록 구성되어야 한다. | 지표 수집기가 로드밸런서 및 자동 규모 확장 클러스터 형태로 구성되었다면 어디서 오는 지표라도 수집 가능하다. ✔️ |
성능 | 일반적으로 TCP를 사용한다. | 보통 UDP를 사용한다. ✔️ 푸시 모델의 지표 전송 지연이 더 낮다는 뜻이다. |
데이터 신빙성 | 지표 데이터를 가져올 애플리케이션 서버의 목록이 이미 정의된 상태이므로 해당 서버에서 수집한 데이터는 믿을 수 있다. ✔️ | 아무나 지표 수집기에 데이터를 보낼 수 있다. 지표 전송을 허용할 서버의 목록을 수집기 측에 유지하거나 인증(authentication)을 강제하여 문제를 해결할 수 있다. |
유명한 사례
- 풀 모델: 프로메테우스
- 푸시 모델: 아마존 클라우드와치(CloudWatch), 그래파이트(Graphite)
풀 모델과 푸시 모델 가운데 무엇이 나은지는 논쟁을 불러일으키는 질문이지만 정답은 없다.
지표 전송 파이프라인의 규모 확장
지표 수집기는 서버 클러스터 형태이며 엄청난 양의 데이터를 받아 처리해야 한다.
이 클러스터는 자동으로 규모 확장이 가능하도록 설정하여 언제나 데이터 처리에 충분한 수집기 서버가 존재하도록 해야 한다.
하지만 시계열 데이터베이스에 장애가 생기면 데이터 손실이 발생할 가능성이 있다. 큐를 두면 그런 문제를 해소할 수 있다.
지표 수집기는 지표 데이터를 카프카와 같은 큐 시스템에 전송한다.
그러면 스트림 처리 서비스(e.g. 아파치 스톰(Storm), 플링크(Flink), 스파크(Spark))가 해당 데이터를 받아 시계열 데이터베이스에 저장한다.
장점
- 카프카는 고도로 안정적이고 규모 확장성이 뛰어난 분산 메시지 플랫폼이다.
- 데이터 수집 컴포넌트와 처리 컴포넌트 사이의 결합도를 낮춘다.
- 데이터베이스에 장애가 생겨도 데이터는 소실되지 않는다. 카프카에 보관해 두면 되기 때문이다.
데이터 집계 지점
수집 에이전트가 집계하는 방안
클라이언트에 설치된 수집 에이전트는 복잡한 집계 로직은 지원하기 어렵다.
데이터 수집 파이프라인에서 집계하는 방안
데이터를 저장소에 기록하기 전에 집계할 수 있으려면 보통 플링크 같은 스트림 프로세싱 엔진이 필요하다.
데이터베이스에는 계산 결과만 기록하므로, 실제로 기록되는 양은 엄청나게 줄어들 것이다.
하지만 이 방안은 늦게 도착하는 지표 데이터의 처리가 어렵고, 원본 데이터를 보관하지 않기 때문에 정밀도나 유연성 측면에서 손해를 보게 된다는 문제가 있다.
질의 시에 집계하는 방안
데이터를 날것 그대로 보관한 다음 질의할 때 필요한 시간 구간에 맞게 집계한다.
데이터 손실 문제는 없으나 질의를 처리하는 순간에 전체 데이터세트를 대상으로 집계 결과를 계산해야 하므로 속도는 느릴 것이다.
질의 서비스
질의 서비스는 질의 서비스 클러스터 형태로 구현되며, 시각화 또는 경보 시스템에서 접수된 요청을 시계열 데이터베이스를 통해 처리하는 역할을 담당한다.
이런 질의 처리 전담 서비스를 두면 클라이언트(시각화 또는 경보 시스템)와 시계열 데이터베이스 사이의 결합도를 낮출 수 있다.
캐시 계층
질의 결과를 저장할 캐시 서버를 도입하면 시계열 데이터베이스에 대한 질의 부하를 낮추고 질의 서비스의 성능을 높일 수 있다.
질의 서비스를 두면 곤란한 경우
대부분의 상용 시각화 및 경보 시스템은 시장에서 널리 사용되는 시계열 데이터베이스와의 연동을 처리하는 강력한 플러그인을 이미 갖추고 있는 경우가 많다.
시계열 데이터베이스 질의어
시계열 데이터는 SQL로는 질의하기가 까다롭기 때문에 널리 사용되는 지표 모니터링 시스템들은 SQL이 아닌 독자 질의어를 제공한다.
지수 이동 평균(exponential moving average) 계산식을 SQL로 작성하면 다음과 같이 복잡해진다.
select id,
temp,
avg(temp) over (partition by group_nr order by time_read)
as rolling_avg
from (
select id,
temp,
time_read,
interval_group,
id - row_number () over (partition by interval_group order by time_read) as group_nr
from (
select id,
time_read,
"epoch"::timestamp + "900 seconds"::interval * (extract(epoch from time_read)::int4 / 900 as interval_group,
temp
from readings
) t1
) t2
order by time_read;
플럭스(Flux)로 작성하면 다음과 같이 간단해진다.
from(db:"telegraf")
|> range(start:-1h)
|> filter(fn: (r) => r._measurement == "foo")
|> exponentialMovingAverage(size:-10s)
저장소 계층
시계열 데이터베이스는 신중하게 선택할 것
페이스북에서 내놓은 연구 논문에 따르면 운영 데이터 저장소에 대한 질의 85%는 지난 26시간 내에 수집된 데이터를 대상으로 한다. 이 사실을 잘 활용하는 시계열 데이터베이스를 고르면 성능 측면에서 큰 이득을 볼 수 있다.
저장 용량 최적화
데이터 인코딩 및 압축
데이터를 인코딩하고 압축하면 크기를 상당히 줄일 수 있다.
다운샘플링
데이터의 해상도를 낮춰 저장소 요구량을 줄이는 기법이다.
냉동 저장소
잘 사용되지 않는 비활성 상태 데이터를 보관하는 곳이다.
냉동 저장에 드는 비용은 일반 저장소에 비해 훨씬 저렴하다.
경보 시스템
- 설정 파일을 가져와 캐시 서버에 보관한다.
- 경보 관리자(alert manager)는 경보 설정 내역을 캐시에서 가져온다.
- 설정된 규칙에 근거하여 경보 관리자는 지정된 시간마다 질의 서비스(query service)를 호출한다. 그리고 질의 결과가 설정된 임계값(threshold)을 위반하면 경보 이벤트를 생성한다.
- 경보 필터링, 병합(merge), 중복 제거(dedupe)
- 접근 제어(access control)
- 재시도(retry)
- 경보 저장소는 키-값 저장소(like 카산드라)다. 모든 경보의 상태(비활성화, 응답 대기, 경보 발령, 문제 해결 등)가 여기 보관된다. 알림이 적어도 한 번 이상 전달되도록 보장하는 구실을 한다.
- 경보 이벤트를 카프카에 전달한다.
- 경보 소비자는 카프카에서 경보 이벤트를 읽는다.
- 경보 소비자는 카프카에서 읽은 경보 이벤트를 처리하여 이메일, 단문 메시지, 페이저 듀티(PagerDuty), HTTP 서비스 엔드포인트 등의 다양한 채널로 알림을 전송한다.
만들 것인가 구매할 것인가
기업이 필요로 하는 규모를 바로 지원 가능한 경보 시스템은 시장에 많다.
대부분이 유명 시계열 데이터베이스와 통합되어 있고, 다양한 알림 채널을 지원한다.
시각화 시스템
지표 대시보드(dashboard)에는 지표를 다양한 시간 범위로 표시하고, 경보 대시보드에는 다양한 경보의 상태를 표시한다.
품질 좋은 시각화 시스템은 구현하기 어렵다. => 상용품을 구입해서 쓰자. e.g. 그라파나(Grafana)
4단계: 마무리
- 지표 데이터 수집 모델: 풀 모델 vs 푸시 모델
- 카프카를 활용한 규모 확장 방안
- 최적 시계열 데이터베이스의 선정
- 다운샘플링을 통한 데이터 크기 절감
- 경보/시각화 시스템: 구현 vs 구입