블라인드 스터디 : 지표 모니터링 및 경보 시스템 설계
서버개발

블라인드 스터디 : 지표 모니터링 및 경보 시스템 설계

[5장] 지표 모니터링 및 경보 시스템

지표 모니터링 및 경보 시스템의 목적

지표 모니터링 및 경보 시스템은 인프라의 상태를 선명하게 볼 수 있고, 높은 가용성과 안정성을 달성하는데 중추적 역할을 한다

널리 쓰이는 서비스로는 DATADOG, Granfana, Prometheus, Munin, graphite 등이 있다

 

 

1단계 : 문제 이해 및 설계 범위 확정

지표 모니터링 및 경보 시스템의 범위는 회사마다 다르므로 상의하여 정확한 요구사항을 알아내는 것이 중요하다

인프라 지표에 맞춘 서비스일 수도, 에러 로그와 액세스 로그에 초점을 맞춘 시스템일 수도 있기 때문이다

 

고려할 사항으로는

- 시스템의 고객이 누구인가? (시스템 운영 지표 수집, CPU부하, 메모리 사용률, 디스크 사용량, TPS, RPS, 프로세스 개수 등)

- 시스템 인프라의 규모(일간 이용자 수, 서버 풀의 개수, 하드웨어 개수)

- 지표 데이터 유지 기간

- 장기 보관 시 절차(해상도 낮추기 : 1초마다 저장하던 정보를 60개 모아 1분마다의 정보로 치환 등)

- 경보 채널이 지원해야 하는 것(이메일, 전화, 페이지듀티, 웹훅(HTTP 프로토콜 엔드포인트))

- 에러 로그, 액세스 로그, 분산 시스템 추적 기능도 수집하여야 하는지?

 

 

요구사항 분석

기능 요구사항

대규모 인프라를 모니터링

- 일간 사용자 수 1억명

- 서버 풀 1,000개, 풀당 서버 수 100개, 서버당 100개의 운영 지표를 수집 시 지표의 수는 1,000만개나 된다

- 데이터 보관 기간은 1년, 그대로 일주일, 1분 단위로 한달, 1시간 단위로 1년

- 모니터링 지표(CPU 사용률, 요청 수, 메모리 사용량, 메시지 큐 내의 메시지 수)

 

비기능 요구사항

- 규모 확장성 : 시스템은 늘어나는 지표 수와 경보의 양에 맞게 확장 가능하여야 한다

- 낮은 응답 지연 : 대시보드와 경보를 신속하게 처리할 수 있도록 질의에 대한 낮은 응답 지연 보장

- 안정성 : 높은 안정성을 제공해 중요 경보를 놓치지 않아야 한다

- 유연성 : 기술은 계속 변화하므로, 신기술을 쉽게 통합할 수 있도록 파이프라인을 구축한 시스템이어야 한다

 

 

2단계 : 개략적 설계안 제시 및 동의 구하기

기본적 사항

- 여러 출처로부터 지표 데이터를 수집한다

- 지표 데이터를 지표 모니터링 시스템으로 전송한다

- 전송되어 오는 데이터를 정리하고 저장한다

- 밀려오는 데이터를 분석하고, 이상 징후를 감지하고, 경보를 발생 시킨다(다양한 채널로)

- 데이터를 차트나 그래프 등으로 제공한다

 

데이터 모델

값 집합에 타임스탬프가 붙은 시계열 데이터로 기록한다

 

ex) 

labels : host:1631,env:prod

timestamp : 1613707265

value : 0.29

 

데이터 접근 패턴

이 시스템에 대한 쓰기 부하는 막대하며 시점을 막론하고 많은 시계열 데이터가 기록된다

대부분은 쓰기 작업이며 읽기 부하는 일시적인으로 생겼다 사라지는 spiky한 작업이다

시각화와 경보 서비스는 데이터베이스에 대한 읽기 연산을 발생시켜 그래프나 경보를 확인하는 패턴에 따라 읽기 연산은 일시적으로 증가하거나 잠잠해진다

고로 쓰기 연산은 항상 비슷하게 많지만, 읽기 연산은 급증하였다가 사라진다는 것이다

 

일단 관계형 데이터베이스는 저장소로 적합하지 않다

시계열 데이터의 연산을 지속적으로 갱신하는 질의는 읽기 까다로우며 해당 질의에 대한 인덱스를 따로 지정해야 한다

또한 쓰기 연산이 지속적으로 발생할 때 좋은 성능을 보이지 않으며, 많은 튜닝을 필요로 하게 된다

 

NoSQL은 어떨까?

잘 알려진 카산드라와 빅테이블은 시계열 데이터 처리에 사용될 수 있다

하지만 이런 데이터베이스에 시계열 데이터를 효과적으로 저장하고 질의하기 위해서는 확장이 용이한 스키마를 사용해야 하고, 해당 NoSQL 데이터베이스의 내부 구조에 대한 지식이 필요하다

 

Influx와 프로메테우스는 다량의 시계열 데이터를 저장하고 빠른 실시간 분석을 지원한다

두 제품 모두 메모리 캐시와 디스크 저장소를 함께 활용하며, 영속성 요건과 높은 성능 요구사항도 만족한다

시계열 데이터베이스는 레이블을 기준으로 집계하고 분석하는 기능을 제공하기 위해 레이블 별로 인덱스를 제공한다

그리고 각 레이블이 가질 수 있는 값의 가짓수가 낮아야 한다

 

3단계 : 상세 설계

몇 가지 핵심적 컴포넌트나 처리 흐름에 대한 상세 설계안을 제시할 수 있어야 한다

 

지표 수집

카운터나 CPU 사용량 같은 지표를 수집할 때는 때로 데이터가 소실되어도 아주 심각한 문제는 아니다 (신뢰성 보장X) 

지표를 보내는 클라이언트는 성공적으로 데이터가 전송되었는지 신경 쓰지 않아도 되니 이 점을 신경 쓰지 않고 설계한다

 

풀 vs 푸시 모델

풀 모델은 실행 중인 애플리케이션으로부터 지표 수집기가 주기적으로 지표 데이터를 가져온다

지표 수집기가 수집해야 할 서비스 목록에 대해 알아야 하며 지표 수집기 내부에 모든 서비스의 엔드포인트와 DNS/IP 정보를 두면 간단하나 서비스 확장/축소가 가능한 서비스에서 이용이 불가능하기 때문에 주키퍼와 같은 서비스 탐색 기술을 활용하여야 한다

각 서비스는 가용성 관련 정보를 서비스 탐색 서비스에 기록하고 변화가 생기면 지표 수집기에 통보한다

 

지표 수집기는 HTTP 엔드포인트에서 지표 데이터를 가져온다

이런 엔드 포인트를 수집기에 노출하기 위해 통상 서비스에 클라이언트 라이브버리를 설치한다

지표 수집기는 서비스 엔드 포인트 목록의 변화를 통지 받기 위해 변경 이벤트 알림 콜백을 서비스 탐색 컴포넌트에 등록하여 주기적으로 엔트포인트 목록을 다시 가져온다

 

수천 대 서버가 만들어 내는 지표 데이터를 수집하려면 지표 수집기 한 대로는 부족하며, 지표 수집기 서버 풀을 만들어야 데이터 규모를 감당할 수 있다

지표 수집기 서버를 여러 대 둘 때 여러 서버가 같은 출처에서 데이터를 중복으로 가져올 수 있는데, 이런 것을 방지하기 위한 중재 메커니즘이 필요하다

 

구현 메커니즘 중 하나로는 consistent hash ring을 사용하는 것이다

해시 링 구간마다 해당 구간에 속한 서버로부터 생산되는 지표의 수집을 담당하는 수집기 서버를 지정하여 특정 서버의 지표 데이터는 항상 하나의 수집 서버가 처리함을 보장할 수 있다

 

듣기만 하면 시스템 클러스터링처럼 보이기도 하지만, 같은 지표를 항상 고정된 시스템에서 항상 해결하는 것이 아니고 그림에서 볼 수 있듯이 해시 링 구조에서는 가장 지표를 발급하는 시스템으로부터 가까운 지표 수집기에서 지표를 수집한다

가장 가까운 값은 알고리즘마다 다를 수 있으며 시스템 추가에도 쉽게 대응할 수 있다

 

단점으로는 기본적으로 균등하게 분배되지 못하고 특정 시스템에 부하가 심하게 오는 Hotspot이 발생할 수 있다
중간에 있던 지표 처리기가 장애로 죽게되면 그 다음 지표 처리기에게 부하가 몰리게 된다

 

vnode를 이용해 각 물리적인 지표 처리기의 가상 시스템을 만들어 다른 해시값을 부여해 배치한다

이를 통해 단점을 극복하여 consistent hash ring의 단점을 해결한다

 

Consistent hashing (Hash ring)

Consistent hashing은 Hashing을 일관되게 유지하는 방법이다. 이게 뭐다 라고 설명하기 보단, 먼저 상황을 예시로 들어보자. 노드 3개에 데이터를 분산 저장하는 상황이 있다. 제일 쉬우면서 분산저장

binux.tistory.com

 

풀 모델은 HTTP 엔드포인트를 강제하여 언제든 쉽게 지표 데이터 디버깅이 가능하다

또한 WAS가 풀 요청에 응답하지 않으면 서버의 장애로 진단할 수 있기 때문에 쉽게 장애를 진단할 수 있다

일반적으로 TCP를 사용하며 지표 데이터를 가져올 WAS 목록이 이미 정의되어 있어 수집한 데이터를 믿을 수 있다

 

푸시 모델은 지표를 만드는 시스템(웹 서버, 데이터베이스, 등)에서 직접 지표를 수집기에 전송하는 모델로, 모니터링 대상 서버에 통상 수집 에이전트 소프트웨어를 설치한다

해당 장비에서 실행되는 서비스가 생산하는 지표 데이터를 받아 모은 다음 주기적으로 수집기에 전달한다

 

데이터 집계를 통해 수집기에 보내는 데이터의 양을 조절할 수 있으며, 데이터 전송 트래픽 양이 커져 일시적으로 전송이 실패한다면 내부의 소규모 버퍼를 이용해 일시적으로 보관한 다음 추후 재전송할 수 있다

하지만 시스템이 scale-out이 가능해 동적으로 추가하거나 삭제된다면 해당 데이터는 소실될 수 있다

 

이런 일을 막기 위해서 지표 수집기도 scale-out이 가능하도록 설계해야하며 로드밸런서를 두어야 한다

 

푸시 모델의 장점은 지표 수집기가 scale-out 확장 클러스터 형태로 구성되었다면 어디서 오든 지표 수집이 가능하다

하지만 지표를 받지 못할 때 네트워크 장애인지 서버 장애인지 원인을 알기 어렵다

 

 

지표 전송 파이프라인의 규모 확장

지표 수집기에서 바로 시계열 데이터베이스로 정보를 저장하게 되면 데이터 베이스 장애 시 데이터 손실이 발생할 가능성이 있다지표 수집기는 지표 데이터를 카프카와 같은 큐 시스템을 이용해 전송하면 Storm, Flink, Spark와 같은 소비자(스트림 처리 서비스)가 해당 데이터를 받아 시계열 데이터 베이스에 저장한다 

 

이렇게 하면 생기는 장점은- 카프카는 안정적이고 규모 확장성이 뛰어난 분산 메시지 플랫폼이다- 데이터 수집 컴포넌트와 처리 컴포넌트 사이의 결합도를 낮춘다- 데이터 베이스에 장애가 생겨도 데이터가 소실되지 않고 카프카에 보관된다

 

이전 글에서 본 것처럼 카프카의 파티션 메커니즘을 사용하면 시스템의 규모를 확장할 수 있다

지표 이름에 따라 어떤 파티션에 배치할지 결정하고 소비자는 지표 이름에 따라 쉽게 집계할 수 있다

태그/레이블에 따라 지표 데이터를 더욱 세분화한 파티션으로 나누고, 중요 지표가 먼저 처리될 수 있도록 지표를 분류하고 우선순위를 지정한다

 

데이터 집계 시점

여러 지점에서 데이터를 집계할 수 있다

수집 에이전트(클라이언트 측), 데이터 수집 파이프라인(저장소 기록 전), 질의 시점(저장소 기록 후)에 대해서 알아보자

 

수집 에어전트가 집계를 하게되면 클라이언트에 복잡한 집계 로직을 지원하기 어려워 단순한 지표를 해상도가 낮게 수집하는 정도가 가능하다

 

데이터 수집 파이프라인에서 집계를 하면 저장소에 저장되기 전에 집계하기 위해 스트림 프로세싱 엔진이 필요하다

데이터베이스는 계산 결과만 기록하므로 실제로 기록되는 양은 줄어들지만, 늦게 도착하는 지표 데이터의 처리가 어렵고 원본 데이터를 보관하지 않기 때문에 정밀도나 유연성 측면에서 손해를 보게 된다

 

스트림 프로세싱 엔진은 실시간으로 발생한 데이터를 즉각적으로 처리하여 활용하는 방식의 엔진으로
실시간 빅데이터 처리, 데이터 스트리밍이라고 표현하기도 한다

대표적으로 아파치 플링크가 있는데, 실시간 처리 말고도 배치 처리(일정량 기록 후 일괄 처리), 이벤트 처리 등도 지원한다

 

질의 시에 집계를 하면 데이터를 그대로 보관한 다음 질의할 때 필요한 시간 구간에 맞게 집계한다

데이터 손실 문제는 없으나 질의 처리시 전체 데이터 세트에 집계 결과를 계산해야 하므로 속도가 느리다

 

 

질의 서비스

질의 서버 클러스터 형태로 구현되며, 시각화 또는 경보 시스템(저장된 데이터를 조회하여 사용자에게 보여주는 플랫폼)에서 접수된 요청을 시계열 데이터베이스를 통해 처리하는 역할을 담당한다

질의 전담 서비스를 두면 클라이언트와 시계열 데이터베이스 사이의 결합도를 낮출 수 있다(데이터 베이스 제품 교체 용이)

 

캐시 계층

질의 결과를 저장할 캐시 서버를 도입해 질의 부하를 낮춰 질의 서비스의 성능을 올릴 수 있다

상용 시각화 및 경보 시스템은 대부분 시계열 데이터베이스와 연동 처리하는 강력한 플러그인이 있기 때문에 이 점도 고려해야 할 사항이다

 

시계열 데이터베이스 질의어

지표 모니터링 시스템들은 SQL이 아닌 독자 질의어를 제공한다

SQL은 질의하기가 까다롭기 때문에 자체적으로 제공한다

 

from(db:"telegraf") |> range(start:-1h) |> filter(fn: (r) => r._measurement == "foo") |> exponentialMovingAverage(size:-10s)

 

 

저장소 계층

지표 모니터링 시스템에 저장할 데이터의 양은 막대하기 때문에 몇 가지 사항에 대해 고려해야 한다

 

데이터 인코딩 및 압축

데이터를 인코딩하고 압축하면 크기를 상당히 줄일 수 있다

데이터를 완전한 형태로 저장하는 대신 기준값과의 차이를 저장하여 적은 비트 수로 차이에 대해 나타낼 수 있다

 

{ 123456789, 123456790, 123456799 } -> 기준값 123456789, { 123456789, 1, 10 }

 

다운 샘플링

데이터의 해상도를 낮춰 저장소 요구량을 줄이는 기법이다

요구된 데이터 보관 기간이 1년이지만, 낡은 데이터는 해상도를 줄여도 되는지 여부를 파악해야 한다

이러한 시스템은 대부분의 데이터가 최신 데이터만 이용되기 때문에 오래된 데이터부터 다운 샘플링을 진행한다

 

다운 샘플링을 하는 동안 해당 데이터에 대한 요청이 올 수 있기 때문에 

일정 시간이 지난 데이터는 기존 데이터를 다운 샘플링된 것처럼 보이도록 인터페이스를 구성해 캐시에 등록한 뒤, 타 쓰레드에서 다운 샘플링을 하는 동안 요청을 대신 처리하고 완료 후 캐시 데이터를 교환하는 작업을 진행한다

혹은 요청 큐를 통해 다운 샘플링이 진행된 후 다운 샘플링 된 데이터에 접근하도록 제어할 수 있다

 

냉동 저장소

잘 사용되지 않는 비활성 상태 데이터를 보관하는 것으로, 일반 저장소에 비해 훨씬 비용이 낮다

 

 

경보 시스템

경보를 처리하는 흐름은 다음과 같다

 

1. 경보 규칙 설정 파일을 가져와 캐시 서버에 저장하고, 경보 규칙을 디스크 파일 상태로 보관한다 

2. 경보 관리자가 경보 설정 내역을 캐시에서 가져온다

3. 설정된 규칙에 근거하여 지정된 시간마다 질의 서비스를 호출해 질의 결과가 임계값(threshold)을 위반하면 경보 이벤트를 발생시킨다

그 외의 경보 관리자의 역할
- 경보 필터링, 병합, 중복 제거 : 짧은 시간 동안 같은 인스턴스에서 발생한 경보는 병합할 수 있다
90% 이상 디스크 사용량이 초과했다고 여러 이벤트에서 발생했어도 같은 인스턴스의 내용이라면 1개의 경보로 줄이는 것
- 접근 제어 : 사람의 실수로 빚어지는 장애를 막고 시스템의 보안을 유지하기 위해 경보 관리 작업은 반드시 특정한 개인만이 수행할 수 있도록 제한한ㄷ
- 재시도 : 경보 관리자는 경보 상태를 확인하고 알림이 최소 한 번은 전달됨을 보장한다

4. 경보 저장소는 카산드라 같은 키-값 저장소이다. 모든 경보의 상태가 여기 보관된다. 알림이 적어도 한 번 이상 전달될 수 있도록 보장하기 위해서 사용된다

5. 경보 이벤트를 카프카에 전달한다

6. 경보 소비자는 카프카에서 경보 이벤트를 읽는다

7. 경보 소비자는 카프카에서 읽은 경보 이벤트를 처리하여 이메일, 단문 메시지, 페이지듀티, HTTP 서비스 엔드포인트 등의 다양한 채널로 알림을 전송한다

 

 

시각화 시스템

시각화 시스템은 데이터 계층 위에서 만들어진다

지표 대시보드에는 지표를 다양한 시간 범위로 표시하고, 경보 대시보드에는 다양한 경보의 상태를 표시한다

서버가 처리하고 있는 요청의 수, 메모리, CPU 사용률, 페이지 로드 시간, 트래픽 양, 로그인 현황 등의 지표를 표시한다

 

회사에서 Granfana Dashboard를 통해 요청이 오래걸려 Slow packet으로 잡힌 패킷들에 대해 원인을 분석하고 개선해본 경험이 있어 시각화 시스템의 유무는 중요하다고 생각한다