본문 바로가기
Observability/Prometheus & Grafana

Prometheus HA 구성2 (With 샤딩 + Thanos)

by wlsdn3004 2023. 5. 10.
728x90
반응형
Information Panel

샤딩이란?

샤딩(Sharding)은 대규모 데이터를 처리할 때 데이터를 분산하여 저장하는 데이터베이스 아키텍처 디자인 패턴이다. 이 패턴은 수평적 확장을 위한 방법 중 하나로, 데이터를 분할하고 각각의 작은 파티션(shard)에 저장함으로써 전체 시스템의 성능과 확장성을 향상시킨다.

 

본 글에서는 Promethes 샤딩과 Thanos를 구성하고 Tagers이 어떻게 분산되는지 확인하는 실습을 다룬다.

 

실습 구성을 간단히 표현하면 다음과 같다.

 

Prometheus를 설치하면 기본 샤드값은 1인데, 이 값을 2로 확장하면 아래와 같이 Prometheus configuration의 "scrape_configs.[ job_name].relabel_configs" 부분에 아래와 같은 값이 들어가게 된다.

## prometheus-0  
  - source_labels:
    - __address__
    target_label: __tmp_hash
    modulus: 2
    action: hashmod
  - source_labels:
    - __tmp_hash
    regex: 0
    action: keep
    
## prometheus-shard-1-0  
- source_labels:
    - __address__
    target_label: __tmp_hash
    modulus: 2
    action: hashmod
  - source_labels:
    - __tmp_hash
    regex: 1
    action: keep

위 내용에 의해 샤딩이 이루어지는데, 내용을 해석하자면 메트릭 데이터의 주소(__address__)를 md5(hashmod)으로 해싱하여 "__tmp_hash" 라벨로 매핑한 뒤 "modulus" 값(shard 개수 = 2)으로 나눈 나머지 값이 0이 나오면 prometheus-0 프로메테우스에, 1이면 prometheus-shard-1-0에 targets으로 생성되어 targets에 대한 메트릭을 스크랩해 간다. 이렇게 하면 "__address__"에 의해 메트릭 데이터가 분산되어 처리될 수 있다.

 

아래 python 코드를 사용하여 메트릭 데이터의 주소(__address__) 값을 md5으로 해싱하여 2로 나눈 나머지 값을 구할 수 있다.

import hashlib

ip = "{endpoind address}"
md5 = hashlib.md5()          ## md5 객체 생성
md5.update(ip.encode())      ## ip 문자열을 인코딩 후 md5 객체에 업데이트 하여 해싱
hash_hex = md5.hexdigest()   ## md5 객체에 있는 해싱된 값을 16진수 문자열로 반환
hash_int = int(hash_hex, 16) ## 16진수 문자열 해시값을 정수형으로 변환
hash_mod = hash_int % 2      ## modulus 2이므로 2로 나눈 나머지 계산
print(hash_mod)

 

 

전제 조건

- [Prometheus + Grafana 설치]

- [Prometheus HA 구성1 (with Thanos)]

 

 

실습


1. Prometheus 샤딩 설정


prometheus 샤딩을 위해 prometheus.values.yaml 파일을 수정한다.

## prometheus.values.yaml
prometheus:
  prometheusSpec:
#...  
    replicas: 2
    shards: 2

 

수정한 prometheus.values.yaml 파일로 Helm 업데이트한다.

$ helm upgrade prometheus -f prometheus.values.yaml prometheus-community/kube-prometheus-stack --namespace monitoring --set fullnameOverride=prometheus

 

설치된 prometheus의 샤드 파드를 확인할 수 있다.

$ kubectl get po -n monitoring
NAME                                             READY   STATUS    RESTARTS      AGE
#...
prometheus-prometheus-prometheus-0               3/3     Running   0             15h
prometheus-prometheus-prometheus-1               3/3     Running   0             15h
prometheus-prometheus-prometheus-shard-1-0       3/3     Running   0             13h
prometheus-prometheus-prometheus-shard-1-1       3/3     Running   0             13h

 

prometheus-0와 prometheus-shard-1-0 파드에 들어가 config.file의 값을 확인한다.

[prometheus-0]

$ kubectl exec -it -n monitoring prometheus-prometheus-prometheus-0 -- /bin/sh
$ cat /etc/prometheus/config_out/prometheus.env.yaml | grep -B1 -A7 "__address__"
  - source_labels:
    - __address__
    target_label: __tmp_hash
    modulus: 2
    action: hashmod
  - source_labels:
    - __tmp_hash
    regex: 0
    action: keep
#...

 

[prometheus-shard-1-0]

$ kubectl exec -it -n monitoring prometheus-prometheus-prometheus-shard-1-0 -- /bin/sh
$ cat /etc/prometheus/config_out/prometheus.env.yaml | grep -B1 -A7 "__address__"
  - source_labels:
    - __address__
    target_label: __tmp_hash
    modulus: 2
    action: hashmod
  - source_labels:
    - __tmp_hash
    regex: 1
    action: keep
#...

 

prometheus-0은 __address__를 해싱하여 2로 나눈 나머지 값이 0인 엔드포인트 Targets만 선택하고,

prometheus-shard-1-0는  __address__를 해싱하여 2로 나눈 나머지 값이 1인 엔드포인트 Targets만 선택하도록 설정된 걸 확인할 수 있다.

 

2. Thanos sidecar stores 엔드포인트 설정


Prometheus서버와 샤딩 된 서버 전부 엔드포인트로 등록해야 하기 때문에 headless 서비스에 연결되어 있는 Thanos sidecar 컨테이너를 지정하기 위한 {pod-name}.{subdomain}:10901 형태로 Thanos thanos-vaules.yaml 파일을 수정한다.

## thanos-vaules.yaml
query:
  enabled: true
  stores:
  - prometheus-prometheus-prometheus-shard-1-0.prometheus-operated:10901
  - prometheus-prometheus-prometheus-0.prometheus-operated:10901
  - prometheus-prometheus-prometheus-1.prometheus-operated:10901
  - prometheus-prometheus-prometheus-shard-1-1.prometheus-operated:10901
  replicaLabel: [prometheus_replica]

 

변경된 thanos-vaules.yaml파일을 이용하여 helm upgrade를 진행한다.

$ helm upgrade -n monitoring thanos -f thanos-vaules.yaml bitnami/thanos

 

thanos-query-frontend로 Thanos 대시보드에 들어가면 아래와 같이 Sidecar Endpoint 4개가 설정된 것을 확인할 수 있다.

 

3. Prometheus, Thanos 비교


Prometheus와 Thanos의 상태를 비교하기 위해 각각 Prometheus의 대시보드로 확인한다.

 

먼저 prometheus-prometheus-prometheus-0, prometheus-prometheus-prometheus-shard-1-0 파드의 대시보드를 확인해 보면 Targets 정보가 다른 걸 확인할 수 있다.

prometheus-prometheus-prometheus-0
prometheus-prometheus-prometheus-shard-1-0

 

Thanos 대시보드를 확인해 보면 위 두 개의 Targets값을 더한 값이 나온다.

즉 샤딩 계산방식을 이용하여 두 개의 Prometheus에 분산되어 저장되는 걸 알 수 있다.

 

아래는 prometheus-prometheus-prometheus-0 프로메테우스에서 스크랩한 인스턴스 정보이다.

 

아래는 prometheus-prometheus-prometheus-shard-1-0 프로메테우스에서 스크랩한 인스턴스 정보이다.

 

Grafana에서 Thanos data source를 사용하여 쿼리 하면 위 4개 정보값이 합쳐져서 4개의 인스턴스 정보가 나오는 걸 확인할 수 있다.

 

4. 해시 함수 계산을 통해 분산된 Targets 분석하기


위에서 prometheus-0 프로메테우스에는 3개의 노드 정보가, prometheus-shard-1-0 프로메테우스에는 1개의 노드 정보가 수집되었었다. 왜 저렇게 분산되었는지 직접 해시 함수를 계산하여 이해해 보자.

 

prometheus-0 에는 node-exporter로 수집되는 Endpoint 3개가 있다.

 

prometheus-shard-1-0 에는 node-exporter로 수집되는 Endpoint 1개가 있다.

 

위 Endpoint 주소를 이용하여 아래 python 코드를 실행하고 결과를 확인해 보자.

## hash.py
# -*- coding: utf-8 -*-

import hashlib

## __address__ 값을 넣어준다.
ip_list = ["192.168.6.106:9100", "192.168.6.144:9100", "192.168.7.233:9100", "192.168.8.8:9100"]


for ip in ip_list:
    md5 = hashlib.md5()
    md5.update(ip.encode())
    hash_hex = md5.hexdigest()
    hash_int = int(hash_hex, 16)
    hash_mod = hash_int % 2

    print("IP 주소: {}".format(ip))
    print("해시 결과: {}".format(hash_mod))
    print("")

 

결과는 다음과 같다.

IP 주소: 192.168.6.106:9100
해시 결과: 0

IP 주소: 192.168.6.144:9100
해시 결과: 0

IP 주소: 192.168.7.233:9100
해시 결과: 0

IP 주소: 192.168.8.8:9100
해시 결과: 1

 

1. Prometheus 샤딩 설정 과정에서 Prometheus 샤드값 2로 설정 후 변경된 프로메테우스 configuration에서 regex 값이 Prometheus-0은 0, prometheus-shard-1-0은 1이었는데 위 값과 비교하면 맞는 결과인걸 확인할 수 있다.

 

 

반응형

댓글