샤딩이란?
샤딩(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 HA 구성1 (with Thanos)]
실습 절차
1. Prometheus 샤딩 설정2. Thanos sidecar stores 엔드포인트 설정
3. Prometheus, Thanos 비교
4. 해시 함수 계산을 통해 분산된 Targets 분석하기
실습
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 정보가 다른 걸 확인할 수 있다.
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이었는데 위 값과 비교하면 맞는 결과인걸 확인할 수 있다.
'Observability > Prometheus & Grafana' 카테고리의 다른 글
Grafana Tempo란? 개념부터 설치까지 (0) | 2023.11.06 |
---|---|
Grafana Loki란? 개념부터 설치까지 (2) | 2023.11.01 |
Prometheus 란? (0) | 2023.05.10 |
Grafana + AWS CloudWatch를 이용한 AWS 모니터링 (0) | 2023.05.09 |
Grafana 대시보드 Variables 활용하기 (0) | 2023.05.04 |
댓글