일반적으로 kubernetes 클러스터 pod의 Metric을 모니터링하기 위해 Prometheus를 구축을 하게된다.
운영되는 서비스와 범위가 확장됨에 따라 Prometheus가 모니터링할 대상의 갯수도 증가하게 되는데, 이에 따라 Prometheus에 가해지는 부하가 증가하게 될 것이다.
이러한 Prometheus의 몇 가지 한계점은 아래와 같이 정리될 수 있다.
문제점 | 내용 |
확장성 제한 | 기본적으로 Prometheus는 단일 서버 구성을 전제로 설계되어있어 수평적 확장에 어려움이 존재한다. |
SPoF(Single Point of Failure) 문제 | Prometheus를 단일 서버로 운영하게 되는 경우, 해당 노드에 장애가 발생하면 Metric 수집이 불가해 모니터링이 불가능하다. |
HA(High Availability) 미지원 | 앞서 말한대로 Prometheus는 단일 서버 구성을 전제로 하기에 완벽한 HA 솔루션을 제공하지 않는다. |
데이터 보관 문제 | Prometheus는 2시간 까지는 메모리에 데이터를 저장하고, 이후 데이터는 disk에 저장한다. 장기 데이터의 저장에 최적화되어있지 않다. |
위와 같이 대부분 Prometheus의 확장에 대한 문제점이 발생한다.
이러한 한계점을 극복하기 위해 여러가지 설계방법이 제시되었고, 그 중 하나가 샤딩이다.
Sharding(샤딩)
스크래핑할 타깃 목록을 2개 이상의 Prometheus 서버를 이용해 분할 수집하는 방법
데이터베이스에서는 사용되는 샤딩과 같은 개념이다. DB의 성능과 확장성을 높이기 위해 샤딩을 사용해 데이터를 저장하는데, Prometheus 아키텍처에서도 샤딩을 사용해 구성할 수 있다.
샤딩 방식에는 크게 수직, 수평 샤딩이 존재한다.
수직 샤딩
스크래핑할 데이터를 수집할 메트릭, 라벨을 기준으로 분할하는 것으로, 각 Prometheus 서버가 특정 유형의 메트릭이나 특정 라벨을 가진 메트릭을 수집하도록 구성하는 것이다.
장점
특정 데이터 유형에 최적화된 설정과 쿼리 성능을 얻을 수 있다.
특정 메트릭에 대한 관리가 용이하다.
단점
일부 샤드로 부하가 집중될 수 있다. (특정 샤드가 더 많은 데이터를 처리하게 되어 부하가 비대칭적으로 분포)
→ [Hot-spot key 문제]
특정 샤드에 장애가 발생하면 해당 메트릭에 대한 모니터링이 불가하다.
수평 샤딩
데이터를 양적으로 분할하는 방법으로, 동일한 메트릭 데이터의 스크래핑 작업을 여러 샤드에 걸쳐 분산시키는 방법이다.
장점
각 샤드가 처리하는 데이터의 양이 줄어듦으로 개별 샤드에 대한 요구 성능치가 낮아진다.
대규모 환경에서 수직 샤딩보다 유연한 확장이 가능
단점
여러 샤드의 데이터를 집계하고 쿼리할때 오버헤드가 발생할 수 있다.
샤드 간의 데이터 일관성 유지에 어려움
Prometheus Federation
이러한 Prometheus의 문제점을 해결하기 위해 고안된 구조로, 2개 이상의 Prometheus 서버를 하위로 두고, 이들의 상위에 위치한 Prometheus 서버를 두는 트리식 계층 구조이다.
하위 레벨의 서버는 스크래핑 작업을, 상위에 있는 서버는 하위 레벨 서버에 쿼리
Federation 구조를 통해 서비스 인프라의 종합적인 모니터링을 수행할 수 있다.
또한, 수많은 노드가 존재하는 환경으로 확장할 수 있다는 점도 존재한다.
하지만 Federation 구조도 여전히 불완전하다는 점이 존재한다.
- 중앙서버 과부화 : 각 하위 서버에서 가져오는 데이터들이 상위 서버에 부담을 준다.
- SPoF : 중앙서버(상위)에 장애가 발생하면 전체 데이터 수집에 문제가 발생한다.
- 복잡한 집계로직 : Prometheus 서버 간의 계층이 생기게 되어 데이터를 집계하기 복잡해진다.
- 네트워크 대역폭/지연 문제 : 하위 Prometheus서버에서 상위 서버로 데이터를 전송하는 과정이 생기므로 네트워크 대역폭 이슈나 지연이 발생할 수 있음
중앙 Prometheus 서버가 핵심이 되기에, 중앙 서버가 다운되거나 성능에 따른 병목 등이 발생할 우려가 존재한다.
그리고 샤딩과 마찬가지로 시스템 구성과 유지보수의 어려움이 존재하기에 선택이 꺼려질 수 있다.
이러한 문제점과 복잡한 구조 설계 등의 해결 방안으로 Thanos가 등장하게 된다.
Thanos
Prometheus 서버를 확장하고 HA를 보장하며 장기적인 데이터 저장소 연동 기능을 제공
Thanos Sidecar를 Prometheus 서버에 붙어서 로그를 장기 데이터 저장소로 전송한다. (Shipping)
Prometheus는 기본적으로 클러스터링을 위해 만들어진 것이 아니고, 자체 로컬 스토리지(TSDB)의 한계로 장기 데이터를 보관하기에 적합하지 않다.
Thanos는 객체 스토리지를 저장소로 사용하기에 Prometheus의 장기 데이터 저장 이슈를 완화시킬 수 있다.
AWS S3, Azure Blob Storage와 같은 CSP 스토리지 서비스 뿐만 아니라 Minio와 같은 S3 기반 오픈소스 솔루션을 사용할 수도 있다.
Thanos 구성요소
Thanos의 컴포넌트는 크게 4가지로 나누어 볼 수 있다.
- Store : 객체 스토리지 버킷에 저장된 장기 데이터를 쿼리, Querier와 통합해 장기 데이터를 쿼리하도록 지원
- Querier : Prometheus HTTP API를 구현해, PromQL을 Thanos 클러스터의 데이터를 쿼리
- Compact : 객체 스토리지에 저장된 블록 데이터를 압축하고 정리, 최적화
- Ruler : 정의된 룰에 따라 메트릭 데이터를 평가 및 알람 생성
이러한 Thanos를 도입함을 통해 여러 Prometheus 서버에 쿼리로 글로벌 뷰를 확인할 수 있으며, 객체 스토리지를 사용해 장기 데이터를 저장할 수 있다는 장점이 존재한다.
Sidecar VS Receiver
Thanos는 Prometheus와 통합을 2가지 방식으로 수행할 수 있다.
Sidecar
사이드카 방식은 Thanos를 Prometheus 인스턴스에 붙여서 배포하는 방식이다.
쿠버네티스의 사이드카 패턴과 동일하게 Prometheus 파드에 Thanos sidecar를 묶어버리는 것이다.
Thanos Querier가 Thanos Store와 Thanos sidecar로 쿼리를 수행하면,
- 사이드카는 Prometheus에 원격 읽기 API를 통해 블록 생성 이전의 데이터를 조회하고
- Thanos Store는 블록 생성 이후의 객체 스토리지에 있는 데이터를 조회하는 구조이다.
사이드카는 Prometheus 서버의 로컬 데이터를 읽고, 데이터가 쌓여서 블록이 생성되면 객체 스토리지로 블록을 전송하는 역할을 담당한다.
이러한 사이드카 방식은 비교적 소규모 환경과 빠른 데이터 접근이 필요한 환경에 유리하다.
다만, 사이드카 방식은 Prometheus 서버(파드)에 종속적이고, 별도의 배포가 필요하다는 점이 존재한다.
Receiver
리시버 방식은 사이드카 방식과는 다르게 리시버 자체를 데몬 형식으로 배포한다.
또한, Prometheus는 원격 쓰기 API를 통해 리시버에 직접 데이터를 전송하며, 데이터를 받은 Receiver는 블록을 객체 저장소에 저장한다.
Thanos Querier가 쿼리하면, Receiver는 즉시 수집된 데이터를 제공하고, 장기 데이터는 Store를 통해 객체 스토리지의 데이터를 제공하는 구조이다.
즉, 리시버는 데이터를 수신하고, 객체 스토리지에 저장하는 역할을 수행한다.
이러한 리시버 방식은 중앙화된 데이터 수집이나 멀티 테넌트 등의 환경에 유리하다.