이번 글에서는 대규모 쿠버네티스 환경에서 모니터링 시스템의 성능을 극대화하는 전략에 대해 알아보겠습니다. 클러스터가 커지고 워크로드가 복잡해질수록 모니터링 시스템 자체의 성능과 확장성이 중요한 과제가 됩니다. 이 글에서는 Prometheus와 Grafana를 포함한 모니터링 스택의 성능을 최적화하고, 대규모 환경에서도 안정적으로 운영하기 위한 고급 설정 방법을 살펴보겠습니다.
📌 고성능 모니터링의 필요성과 도전 과제
대규모 쿠버네티스 환경에서 모니터링 시스템이 직면하는 문제와 이를 해결하기 위한 접근 방식을 알아보겠습니다.
✅ 모니터링 시스템의 성능 병목 현상
모니터링 시스템이 확장됨에 따라 발생하는 주요 병목 지점과 그 원인에 대해 살펴보겠습니다.
- 샘플 수집 부하
- 대규모 클러스터의 수천 개 엔드포인트
- 짧은 스크래핑 간격의 영향
- 타겟 응답 지연 시간의 누적 효과
- 스토리지 성능
- TSDB 쓰기 압력
- 블록 컴팩션 오버헤드
- 디스크 I/O 병목
- 쿼리 성능
- 복잡한 PromQL 쿼리의 실행 비용
- 대시보드 렌더링 지연
- 고카디널리티 메트릭의 영향
# 모니터링 시스템의 주요 성능 지표 예시
# 이 Prometheus Recording Rules는 모니터링 시스템 자체의 핵심 성능 지표를 계산합니다.
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: PrometheusRule # PrometheusRule 리소스 종류 정의
metadata:
name: monitoring-performance-metrics # 규칙 이름
namespace: monitoring # 리소스가 생성될 네임스페이스
spec:
groups:
- name: monitoring-performance # 규칙 그룹 이름
interval: 1m # 규칙 평가 주기 (1분마다 평가)
rules:
# 스크래핑 성능 지표 - 얼마나 효율적으로 메트릭을 수집하는지 측정
- record: monitoring:scrape_duration:avg5m # 생성될 새 메트릭 이름
expr: avg by (job) (rate(prometheus_target_interval_length_seconds_sum[5m]) / rate(prometheus_target_interval_length_seconds_count[5m]))
# 설명: 각 작업(job)별 평균 스크래핑 시간 계산. 값이 높을수록 스크래핑 성능 문제 의심
- record: monitoring:scrape_samples:sum5m # 메트릭 이름
expr: sum(rate(prometheus_tsdb_head_samples_appended_total[5m]))
# 설명: 초당 수집되는 총 샘플 수 - 모니터링 시스템 부하를 직접적으로 나타냄
# 스토리지 성능 지표 - 데이터베이스 성능 측정
- record: monitoring:storage_writes:avg5m # 메트릭 이름
expr: rate(prometheus_tsdb_head_chunks_created_total[5m])
# 설명: 초당 생성되는 청크 수 - 스토리지 쓰기 부하 지표
- record: monitoring:compaction_duration:avg5m # 메트릭 이름
expr: avg_over_time(prometheus_tsdb_compaction_duration_seconds_bucket{le="300"}[1h])
# 설명: 컴팩션 작업의 평균 지속 시간 - 값이 증가하면 스토리지 성능 저하 가능성
# 쿼리 성능 지표 - 사용자 쿼리 응답성 측정
- record: monitoring:query_duration:avg5m # 메트릭 이름
expr: avg by (handler) (rate(prometheus_engine_query_duration_seconds_sum[5m]) / rate(prometheus_engine_query_duration_seconds_count[5m]))
# 설명: 각 API 핸들러별 평균 쿼리 실행 시간 - 쿼리 성능 문제 감지에 중요
- record: monitoring:query_timeouts:rate5m # 메트릭 이름
expr: sum(rate(prometheus_engine_queries_total{result="timeout"}[5m])) / sum(rate(prometheus_engine_queries_total[5m]))
# 설명: 쿼리 타임아웃 비율 - 심각한 성능 문제 지표 (값이 0보다 크면 문제)
✅ 성능 측정 및 벤치마킹
모니터링 시스템의 성능을 정확히 측정하고 개선 목표를 설정하는 방법입니다.
- 핵심 성능 지표
- 초당 샘플 수집률 (samples/s)
- 스크래핑 간격 준수율
- 쿼리 지연 시간 분포
- 디스크 I/O 및 CPU 사용량
- 부하 테스트 방법론
- 점진적 타겟 증가 테스트
- 쿼리 복잡성 스케일링
- 카디널리티 증가 시뮬레이션
- 장기 안정성 테스트
- 성능 분석 도구
- pprof 프로파일링
- 분산 트레이싱 통합
- 리소스 사용량 모니터링
# Prometheus 성능 벤치마킹을 위한 ConfigMap 예시
# 이 설정은 Prometheus 성능 테스트를 위한 k6 부하 테스트 스크립트를 정의합니다.
apiVersion: v1 # Kubernetes API 버전
kind: ConfigMap # ConfigMap 리소스 종류 정의
metadata:
name: prometheus-benchmark # ConfigMap 이름
namespace: monitoring # 네임스페이스
data:
k6-load-test.js: | # 설정 파일 키 (k6 부하 테스트 스크립트)
import http from 'k6/http'; // k6 HTTP 모듈 가져오기
import { check, sleep } from 'k6'; // k6 유틸리티 함수 가져오기
// 테스트 설정 - 다양한 부하 시나리오 정의
export const options = {
stages: [
{ duration: '5m', target: 10 }, // 5분 동안 점진적으로 10명의 동시 사용자로 증가
{ duration: '10m', target: 50 }, // 10분 동안 50명으로 점진적 증가 (부하 상승)
{ duration: '5m', target: 100 }, // 5분 동안 100명으로 증가 (최대 부하)
{ duration: '10m', target: 100 }, // 10분 동안 100명 유지 (지속 부하 테스트)
{ duration: '5m', target: 0 }, // 5분 동안 0명으로 감소 (점진적 종료)
],
thresholds: {
http_req_duration: ['p(95)<500'], // 성능 목표: 95%의 요청이 500ms 미만이어야 함
http_req_failed: ['rate<0.01'], // 성능 목표: 1% 미만의 실패율 허용
},
};
// 테스트할 PromQL 쿼리 목록 - 다양한 복잡도의 쿼리
const queries = [
// 간단한 쿼리 (빠른 실행) - 기본적인 시스템 상태 확인
'up', // 모든 타겟의 가용성 체크 (매우 가벼운 쿼리)
'sum(rate(node_cpu_seconds_total{mode="idle"}[5m]))', // 전체 유휴 CPU (중간 쿼리)
// 중간 복잡도 쿼리 - 네임스페이스별 집계
'sum by (pod) (rate(container_cpu_usage_seconds_total{namespace="default"}[5m]))',
// 설명: default 네임스페이스의 모든 파드별 CPU 사용량 (여러 시계열 집계)
// 복잡한 쿼리 (고 부하) - 조인 및 다중 집계 사용
'sum by (pod_name) (rate(container_cpu_usage_seconds_total{namespace=~".+"}[5m])) / on (pod_name) group_left sum by (pod_name) (kube_pod_container_resource_limits{resource="cpu"})',
// 설명: 모든 네임스페이스의 파드별 CPU 사용량 대비 할당량 비율 (조인 연산 포함)
// 시계열 포인트가 많은 쿼리 - 매우 넓은 시간 범위 사용
'rate(node_cpu_seconds_total[1h])'
// 설명: 1시간 기준 CPU 사용률 - 많은 데이터 포인트 처리 필요
];
// HTTP 요청 실행 - 가상 사용자의 행동 시뮬레이션
export default function () {
// 쿼리 목록에서 랜덤하게 하나 선택 (실제 사용 패턴 시뮬레이션)
const query = queries[Math.floor(Math.random() * queries.length)];
// Prometheus API에 쿼리 실행 - HTTP GET 요청
const response = http.get(`http://prometheus-server:9090/api/v1/query?query=${encodeURIComponent(query)}`);
// 응답 확인 - 성공 여부 검증
check(response, {
'status is 200': (r) => r.status === 200, // HTTP 상태 코드 확인
'query successful': (r) => r.json().status === 'success', // Prometheus API 응답 상태 확인
});
// 다음 가상 사용자 요청 전에 잠시 대기 (실제 사용자 행동 시뮬레이션)
sleep(Math.random() * 3 + 1); // 1-4초 사이 무작위 대기 (자연스러운 사용자 패턴)
}
▶️ 성능 병목 분석 사례: 한 대규모 e커머스 기업은 블랙 프라이데이 시즌 전에 모니터링 시스템 부하 테스트를 실시했습니다. 기존 설정으로는 초당 200,000개 샘플에서 스크래핑 지연이 발생했고, 복잡한 대시보드에서 30초 이상의 로딩 시간이 관찰되었습니다. 시스템 프로파일링 결과, Prometheus의 TSDB 쓰기 작업이 CPU 바운드되어 있고, 복잡한 집계 쿼리에서 과도한 메모리 사용이 발견되었습니다. 이러한 병목 현상을 해결하기 위해 샤딩 아키텍처를 도입하고 쿼리 최적화를 진행한 결과, 초당 500,000개 샘플까지 성능을 확장하고 대시보드 로딩 시간을 5초 이내로 단축할 수 있었습니다.
📌 Prometheus 성능 최적화 전략
Prometheus 서버의 성능을 향상시키기 위한 구체적인 설정과 아키텍처 최적화 방법을 살펴보겠습니다.
✅ 메모리 및 CPU 최적화
Prometheus의 리소스 사용량을 효율적으로 관리하는 방법입니다.
- 메모리 관리 설정
- 시계열 제한 조정
- 샘플 보존 기간 최적화
- 힙 크기 및 GC 설정
- CPU 성능 튜닝
- 쿼리 병렬화 설정
- 스크래핑 동시성 조정
- 컴팩션 일정 최적화
- 리소스 할당 전략
- 워크로드 특성에 맞는
- QoS 클래스 선택
- 자동 스케일링 구성
# Prometheus의 성능 최적화 설정 예시
# 이 설정은 대규모 클러스터를 위한 Prometheus 리소스 관리 방법을 보여줍니다.
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: Prometheus # Prometheus 커스텀 리소스 타입
metadata:
name: prometheus-high-performance # Prometheus 인스턴스 이름
namespace: monitoring # 배포될 네임스페이스
spec:
replicas: 2 # 고가용성 및 부하 분산을 위한 복제본 수
# 2개 이상의 복제본으로 가용성 확보 및 쿼리 부하 분산
# 메모리 관리 최적화 - 리소스 요청 및 제한 설정
resources:
requests:
memory: 16Gi # 충분한 메모리 요청 - 시계열 데이터와 인덱스 저장용
# 메모리가 부족하면 OOM 킬러에 의해 종료될 위험
cpu: 4 # 멀티코어 활용을 위한 CPU 요청
# 쿼리 실행과 TSDB 작업을 병렬화하기 위해 필요
limits:
memory: 24Gi # OOM 방지를 위한 적절한 메모리 상한
# 요청보다 여유있게 설정하여 부하 급증 대응
cpu: 8 # 버스트 성능을 위한 CPU 상한
# 병렬 쿼리 처리와 컴팩션 작업 동시 수행 지원
# 성능 관련 플래그 설정 - Prometheus 실행 매개변수
additionalArgs:
# 쿼리 성능 최적화
- name: "query.max-samples"
value: "100000000" # 쿼리당 최대 샘플 수 증가 (기본값: 50,000,000)
# 대규모 클러스터의 복잡한 쿼리 처리를 위해 확장
# 동시성 관리
- name: "query.max-concurrency"
value: "20" # 병렬 쿼리 수 증가 (기본값: 10)
# 다수의 동시 사용자/대시보드 지원
# 스크래핑 최적화
- name: "scrape.adjust-timestamps"
value: "false" # 타임스탬프 조정 비활성화로 CPU 절약
# 정확한 시간 동기화가 보장된 환경에서 안전하게 비활성화 가능
# TSDB 성능 조정
- name: "storage.tsdb.min-block-duration"
value: "2h" # 작은 블록 생성 빈도 감소로 압축 오버헤드 감소
# 블록 크기를 2시간으로 설정하여 컴팩션 작업 최적화
# 메모리 사용량 최적화
- name: "storage.remote.read-sample-limit"
value: "50000000" # 원격 읽기 샘플 제한 증가
# 원격 저장소에서 큰 데이터셋 쿼리 지원
# 워크로드 특성 최적화 - Pod 배치 및 메타데이터 설정
podMetadata:
annotations:
prometheus.io/scrape: "false" # 자체 스크래핑 방지
# 다른 Prometheus가 이 인스턴스를 모니터링하도록 설정
# Pod 배치 최적화 - 여러 노드에 분산 배치
affinity:
podAntiAffinity: # 여러 Prometheus 복제본을 다른 노드에 배치
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100 # 높은 가중치로 설정 (강한 선호도)
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- prometheus # prometheus 라벨을 가진 Pod 간 분리
topologyKey: kubernetes.io/hostname # 노드 레벨에서 분리
# 단일 노드 장애에 대한 복원력 확보
# 스토리지 설정 - 고성능 영구 스토리지 구성
storage:
volumeClaimTemplate:
spec:
storageClassName: fast-ssd # 고성능 스토리지 클래스 사용
# SSD 기반 스토리지로 I/O 병목 해소
resources:
requests:
storage: 500Gi # 충분한 스토리지 용량 확보
# 데이터 증가 및 컴팩션 작업을 위한 여유 공간
# WAL(Write-Ahead Log) 최적화
walCompression: true # WAL 압축으로 I/O 감소
# 디스크 I/O 및 네트워크 대역폭 절약
✅ 스크래핑 최적화
효율적인 메트릭 수집을 위한 스크래핑 설정 최적화 방법입니다.
- 스크래핑 간격 차등화
- 중요도 기반 간격 전략
- 변화율에 따른 조정
- 부하 분산을 위한 지터(jitter) 적용
- 서비스 디스커버리 효율화
- 레이블 기반 필터링
- 릴레이션 구성 최적화
- 불필요한 메타데이터 제한
- 분산 스크래핑 아키텍처
- 스크래핑 책임 분할
- 지역별 계층화
- 푸시 게이트웨이 활용
# 효율적인 스크래핑 설정 예시
# 이 구성은 대규모 클러스터에서 스크래핑 성능을 최적화합니다.
apiVersion: v1 # Kubernetes API 버전
kind: ConfigMap # ConfigMap 리소스 정의
metadata:
name: prometheus-scrape-config # ConfigMap 이름
namespace: monitoring # 배포될 네임스페이스
data:
prometheus.yml: | # Prometheus 설정 파일
global:
scrape_interval: 30s # 기본 스크래핑 간격 (낮은 빈도로 기본 설정)
# 대부분의 메트릭에 대해 30초마다 수집 (부하 감소)
scrape_timeout: 15s # 스크래핑 타임아웃 (제한적인 값으로 설정)
# 15초 후 응답 없는 타겟은 타임아웃 처리
evaluation_interval: 30s # 규칙 평가 간격
# 알림 및 기록 규칙 30초마다 평가
scrape_configs:
# 중요 시스템 메트릭 - 높은 빈도로 수집
- job_name: 'kubernetes-critical' # 작업 이름 (메트릭에 job 레이블로 추가됨)
scrape_interval: 15s # 중요 메트릭 빈도 높임 (15초마다 수집)
# 중요 시스템 메트릭은 더 자주 수집하여 신속한 문제 감지
scrape_timeout: 10s # 타임아웃 설정 (빠른 실패 처리)
kubernetes_sd_configs: # 쿠버네티스 서비스 디스커버리 설정
- role: pod # Pod 대상 자동 발견
relabel_configs: # 레이블 재작성 규칙 (타겟 필터링)
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep # 특정 조건을 만족하는 타겟만 유지
regex: true # prometheus.io/scrape=true 주석이 있는 Pod만 스크래핑
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_priority]
regex: high # 우선순위가 high로 설정된 Pod만 선택
action: keep # 조건에 맞는 타겟만 유지
# 시간 분산을 위한 지터(offset) 적용 - 스크래핑 부하 분산
- source_labels: [__meta_kubernetes_pod_name]
regex: (.*) # Pod 이름 캡처
target_label: __tmp_hash # 임시 레이블에 저장
replacement: '${1}' # Pod 이름 그대로 사용
action: replace # 레이블 값 대체
- source_labels: [__tmp_hash]
regex: (.*) # 임시 해시 값 캡처
target_label: __tmp_offset # 오프셋 임시 레이블
replacement: '{{ mod (hash .Value) 15 }}s' # pod 이름 기반 0-14초 지터
# 해시 함수로 분산된 오프셋 생성
action: replace # 레이블 값 대체
- source_labels: [__tmp_offset]
regex: (.+) # 임시 오프셋 값 캡처
target_label: __scrape_interval_offset # 실제 스크래핑 오프셋으로 설정
replacement: '${1}' # 계산된 오프셋 사용
action: replace # 레이블 값 대체
# 임시 레이블 제거 - 최종 메트릭에서 불필요한 레이블 정리
- regex: __tmp_.* # __tmp_로 시작하는 모든 레이블
action: labeldrop # 해당 레이블 삭제
# 일반 메트릭 - 중간 빈도로 수집
- job_name: 'kubernetes-standard' # 일반 메트릭 작업 이름
scrape_interval: 30s # 일반 메트릭 기본 간격 (30초)
# 대부분의 애플리케이션 메트릭에 적합한 간격
kubernetes_sd_configs: # 쿠버네티스 서비스 디스커버리
- role: pod # Pod 타겟 자동 발견
relabel_configs: # 레이블 재작성 규칙
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep # 조건에 맞는 타겟만 유지
regex: true # prometheus.io/scrape=true 주석이 있는 Pod만
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_priority]
regex: standard # 우선순위가 standard로 설정된 Pod만
action: keep # 조건에 맞는 타겟만 유지
# 마찬가지로 지터 적용 (생략됨)
# 저빈도 메트릭 - 변화가 적은 메트릭들
- job_name: 'kubernetes-slow' # 저빈도 메트릭 작업 이름
scrape_interval: 120s # 저빈도 메트릭은 2분마다 수집
# 천천히 변하는 메트릭에 적합 (리소스 절약)
kubernetes_sd_configs: # 쿠버네티스 서비스 디스커버리
- role: pod # Pod 타겟 자동 발견
relabel_configs: # 레이블 재작성 규칙
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep # 조건에 맞는 타겟만 유지
regex: true # prometheus.io/scrape=true 주석이 있는 Pod만
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_priority]
regex: low # 우선순위가 low로 설정된 Pod만
action: keep # 조건에 맞는 타겟만 유지
# 메타데이터 레이블 최적화 (모든 작업에 공통 적용)
metric_relabel_configs: # 메트릭 레이블 재작성 규칙 (메트릭 수집 후 적용)
# 불필요한 높은 카디널리티 레이블 제거
- regex: 'id|uuid|pod_name|container_id' # 고카디널리티 레이블 패턴
action: labeldrop # 해당 레이블 삭제 (카디널리티 감소)
# 이러한 레이블은 고유 값이 많아 스토리지 소비가 큼
# 특정 메트릭 필터링
- source_labels: [__name__] # 메트릭 이름 기준
regex: 'go_.*|process_.*' # 내부 런타임 메트릭 제외
# 애플리케이션 내부 상태 메트릭은 대개 불필요
action: drop # 해당 메트릭 완전히 제외 (저장소 사용량 감소)
✅ 쿼리 및 규칙 최적화
PromQL 쿼리와 alerting/recording
PromQL 쿼리와 alerting/recording 규칙의 성능을 향상시키는 방법입니다.
- 효율적인 PromQL 패턴
- 쿼리 최적화 기법
- 카디널리티 제한 전략
- 시간 범위 제한
- Recording Rules 활용
- 사전 계산된 뷰 생성
- 집계 레벨 계층화
- 규칙 평가 간격 최적화
- 쿼리 캐싱 및 제한
- 결과 캐싱 설정
- 타임아웃 및 최대 샘플 제한
- 쿼리 페더레이션 최적화
# 쿼리 및 알림 규칙 최적화 예시
# 이 설정은 효율적인 PromQL 쿼리와 규칙 평가를 위한 구성입니다.
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: PrometheusRule # PrometheusRule 커스텀 리소스 타입
metadata:
name: optimized-recording-rules # 규칙 세트 이름
namespace: monitoring # 네임스페이스
spec:
groups:
# 기본 집계 규칙 - 낮은 빈도로 실행되며 기본 집계 수행
- name: cpu-aggregation # 규칙 그룹 이름 (CPU 관련 집계)
interval: 1m # 1분마다 실행 (기본 빈도)
# 자주 사용되는 기본 집계는 더 자주 계산
rules:
# 노드별 CPU 사용률 계산 - 기본 메트릭을 1분 단위로 집계
- record: node:cpu_utilization:avg1m # 생성될 새 메트릭 이름
expr: 1 - avg by (node) (rate(node_cpu_seconds_total{mode="idle"}[1m]))
# CPU 사용률 계산: 1 - 유휴 CPU 비율
# node별로 평균을 계산하여 각 노드의 전체 CPU 사용률 제공
# 네임스페이스별 CPU 사용률 집계
- record: namespace:cpu_usage:avg1m # 메트릭 이름
expr: sum by (namespace) (rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[1m]))
# 컨테이너 CPU 사용량을 네임스페이스별로 합산
# 빈 컨테이너와 POD 인프라 컨테이너는 제외
# 2차 집계 규칙 - 1차 집계 데이터를 기반으로 더 높은 레벨의 집계 수행
- name: advanced-aggregation # 고급 집계 그룹
interval: 5m # 5분마다 실행 (낮은 빈도)
# 상위 레벨 집계는 덜 자주 계산해도 충분
rules:
# 클러스터 전체 CPU 사용률 - 이미 집계된 데이터 활용
- record: cluster:cpu_utilization:avg5m # 클러스터 전체 CPU 사용률
expr: avg(node:cpu_utilization:avg1m)
# 모든 노드의 CPU 사용률을 평균하여 클러스터 전체 사용률 계산
# 이미 집계된 메트릭을 사용하여 계산 비용 절감
# 네임스페이스별 CPU 사용률 5분 평균
- record: namespace:cpu_usage:avg5m # 메트릭 이름
expr: avg_over_time(namespace:cpu_usage:avg1m[5m])
# 1분 집계 값의 5분 평균을 계산
# 단기 스파이크를 평탄화하여 더 안정적인 지표 제공
# 클러스터 상위 5개 CPU 사용 네임스페이스 (최적화된 쿼리)
- record: cluster:top5_cpu_namespace:avg5m # 상위 5개 네임스페이스
expr: bottomk(5, namespace:cpu_usage:avg5m)
# CPU 사용량이 많은 상위 5개 네임스페이스만 선택
# 대시보드에서 자주 요청되는 데이터를 미리 계산하여 성능 향상
# 고급 성능 지표 - 복잡한 계산을 미리 수행하여 대시보드 성능 향상
- name: performance-metrics # 성능 지표 그룹
interval: 10m # 10분마다 실행 (매우 낮은 빈도)
# 복잡한 계산은 부하가 크므로 빈도 낮춤
rules:
# 리소스 효율성 지표 (미리 계산된 비율)
- record: namespace:cpu_efficiency_ratio:avg10m # 효율성 비율
expr: >
sum by (namespace) (rate(container_cpu_usage_seconds_total[10m])) /
sum by (namespace) (kube_pod_container_resource_requests{resource="cpu"})
# CPU 사용량과 요청량의 비율을 계산하여 리소스 효율성 측정
# 복잡한 나눗셈 연산을 미리 계산하여 대시보드 쿼리 성능 향상
# 포드 레플리카 안정성 지표
- record: deployment:stability_ratio:avg1h # 안정성 비율
expr: >
min_over_time(kube_deployment_status_replicas_available[1h]) /
max_over_time(kube_deployment_status_replicas_desired[1h])
# 1시간 동안의 최소 가용 레플리카를 최대 원하는 레플리카로 나눔
# 이 비율이 1에 가까울수록 디플로이먼트가 안정적임을 의미
---
# Prometheus 쿼리 성능 설정
apiVersion: v1 # Kubernetes API 버전
kind: ConfigMap # ConfigMap 리소스 타입
metadata:
name: prometheus-query-optimization # ConfigMap 이름
namespace: monitoring # 네임스페이스
data:
query-optimization.yaml: | # 설정 파일
# 쿼리 성능 최적화 설정
query:
# 결과 캐싱 설정
lookback-delta: 5m # 룩백 델타 (기본값: 5m)
# 인스턴트 쿼리가 현재 시간에서 얼마나 뒤를 볼지 설정
max-samples: 50000000 # 쿼리당 최대 샘플 수
# 너무 큰 쿼리로 인한 OOM 방지
timeout: 2m # 쿼리 타임아웃
# 오래 실행되는 쿼리로 인한 리소스 고갈 방지
# 쿼리 실행 설정
max-concurrency: 20 # 동시 쿼리 수 (기본값: 10)
# 여러 대시보드/사용자 지원을 위해 증가
# 쿼리 성능 최적화 기능
enable-auto-govs: true # 자동 메모리 관리
# 쿼리 실행 중 메모리 사용량 자동 조절
▶️ 쿼리 최적화 사례: 금융 서비스 회사는 실시간 트랜잭션 모니터링 대시보드의 느린 로딩 시간 문제에 직면했습니다. 원인 분석 결과, 대시보드에서 사용하는 복잡한 PromQL 쿼리가 매번 수백만 개의 시계열을 처리하고 있었습니다. 이를 해결하기 위해 3단계 접근 방식을 채택했습니다: 1) 1분 및 5분 단위로 데이터를 미리 집계하는 recording rule 구현, 2) 카디널리티가 높은 레이블(고유 트랜잭션 ID 등)을 필터링하는 메트릭 재레이블링 규칙 추가, 3) 대시보드 패널의 쿼리를 미리 계산된 집계 메트릭을 사용하도록 재작성. 이러한 최적화 후 대시보드 로딩 시간이 45초에서 2초로 단축되었습니다.
📌 대규모 환경을 위한 분산 아키텍처
대규모 쿠버네티스 환경에서 모니터링 시스템의 확장성을 확보하기 위한 아키텍처 설계 방법을 알아보겠습니다.
✅ Prometheus 샤딩 및 페더레이션
Prometheus 인스턴스를 분할하여 부하를 분산시키는 방법입니다.
- 기능적 샤딩
- 메트릭 타입별 분리
- 네임스페이스별 인스턴스
- 알림/저장/쿼리 분리
- 계층적 페더레이션
- 레벨별 책임 분담
- 집계 데이터 상향 전파
- 쿼리 부하 분산
- Thanos 기반 글로벌 뷰
- 쿼리 레이어 통합
- 글로벌 룰 평가
- 장기 저장소 통합
# Prometheus 샤딩 및 페더레이션 설정 예시
# 이 구성은 기능별로 샤딩된 Prometheus 인스턴스를 보여줍니다.
# 1. 네임스페이스별 샤딩 - 애플리케이션 메트릭 전용 Prometheus
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: Prometheus # Prometheus 커스텀 리소스 타입
metadata:
name: prometheus-apps # 애플리케이션 전용 Prometheus 이름
namespace: monitoring # 네임스페이스
spec:
replicas: 2 # 고가용성을 위한 복제본 수
# 2개의 복제본으로 장애 대응 및 부하 분산
version: v2.35.0 # Prometheus 버전
serviceAccountName: prometheus # 사용할 서비스 계정 (권한 관련)
# 애플리케이션 메트릭만 수집 - 특정 네임스페이스만 모니터링
serviceMonitorNamespaceSelector: # 서비스 모니터 선택 기준 (네임스페이스)
matchExpressions:
- key: monitoring-type # 네임스페이스의 monitoring-type 레이블 확인
operator: In
values: ["application"] # "application" 값을 가진 네임스페이스만 선택
# 이를 통해 앱 메트릭만 포함하도록 제한
# 스토리지 최적화 (짧은 보존 기간)
retention: 24h # 데이터를 24시간만 보관
# 애플리케이션 메트릭은 단기 분석용으로만 사용
# 자원 제한 - 애플리케이션 메트릭에 맞게 최적화
resources:
requests:
memory: 8Gi # 메모리 요청량
cpu: 2 # CPU 요청량
limits:
memory: 12Gi # 메모리 상한
cpu: 4 # CPU 상한
# 애플리케이션 특화 설정
additionalArgs:
- name: "query.max-samples" # 쿼리당 최대 샘플 수 설정
value: "50000000" # 5천만 샘플로 제한 (애플리케이션 쿼리 크기에 맞춤)
---
# 2. 인프라 메트릭 전용 Prometheus
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: Prometheus # Prometheus 커스텀 리소스 타입
metadata:
name: prometheus-infra # 인프라 전용 Prometheus 이름
namespace: monitoring # 네임스페이스
spec:
replicas: 2 # 고가용성을 위한 복제본 수
version: v2.35.0 # Prometheus 버전
serviceAccountName: prometheus # 사용할 서비스 계정
# 인프라 메트릭만 수집 - 특정 레이블을 가진 ServiceMonitor만 선택
serviceMonitorSelector: # ServiceMonitor 선택 기준
matchExpressions:
- key: prometheus # ServiceMonitor의 prometheus 레이블 확인
operator: In
values: ["infra"] # "infra" 값을 가진 ServiceMonitor만 선택
# 이를 통해 노드, 클러스터 컴포넌트 등의 메트릭만 수집
# 더 긴 보존 기간 - 인프라 메트릭은 더 오래 보관
retention: 7d # 데이터를 7일간 보관
# 인프라 트렌드 분석에 유용
# 더 많은 자원 할당 - 인프라 메트릭은 일반적으로 더 많은 자원 필요
resources:
requests:
memory: 16Gi # 더 많은 메모리 요청
cpu: 4 # 더 많은 CPU 요청
limits:
memory: 24Gi # 더 높은 메모리 상한
cpu: 8 # 더 높은 CPU 상한
# 인프라 특화 설정
additionalArgs:
- name: "storage.tsdb.wal-compression" # WAL 압축 활성화
value: "true" # 디스크 I/O 감소를 위한 압축 설정
---
# 3. 상위 레벨 페더레이션 Prometheus - 다른 Prometheus에서 데이터 수집
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: Prometheus # Prometheus 커스텀 리소스 타입
metadata:
name: prometheus-federated # 페더레이션 Prometheus 이름
namespace: monitoring # 네임스페이스
spec:
replicas: 2 # 고가용성을 위한 복제본 수
version: v2.35.0 # Prometheus 버전
serviceAccountName: prometheus # 사용할 서비스 계정
# 더 긴 데이터 보존 (집계 데이터용)
retention: 30d # 데이터를 30일간 보관
# 집계된 메트릭은 더 오래 보관하여 장기 트렌드 분석
# 페더레이션 스크래핑 설정 - 하위 Prometheus에서 데이터 수집
additionalScrapeConfigs: # 추가 스크래핑 설정
name: federated-scrape # 설정 이름
key: federated-scrape.yaml # Secret에서 가져올 키
---
# 페더레이션 스크래핑 설정을 위한 Secret
apiVersion: v1 # Kubernetes API 버전
kind: Secret # Secret 리소스 타입
metadata:
name: federated-scrape # Secret 이름
namespace: monitoring # 네임스페이스
type: Opaque # Secret 타입
stringData: # 문자열 데이터
federated-scrape.yaml: | # 스크래핑 설정 파일
- job_name: 'federate-apps' # 앱 Prometheus 페더레이션 작업
scrape_interval: 15s # 스크래핑 간격
honor_labels: true # 원본 레이블 유지 (충돌 방지)
metrics_path: '/federate' # 페더레이션 엔드포인트
params:
'match[]': # 수집할 메트릭 필터링
- '{job=~".+"}:.*_sum' # 모든 _sum 시리즈 (카운터 합계)
- '{job=~".+"}:.*_count' # 모든 _count 시리즈 (카운터 개수)
- '{job=~".+"}:.*_bucket' # 모든 _bucket 시리즈 (히스토그램)
- 'job:.*' # job: 접두사가 있는 모든 집계 메트릭
static_configs:
- targets:
- 'prometheus-apps.monitoring.svc:9090' # 앱 Prometheus 서비스 주소
- job_name: 'federate-infra' # 인프라 Prometheus 페더레이션 작업
scrape_interval: 15s # 스크래핑 간격
honor_labels: true # 원본 레이블 유지
metrics_path: '/federate' # 페더레이션 엔드포인트
params:
'match[]': # 수집할 메트릭 필터링
- '{job=~"node.*|kube.*"}' # 노드 및 쿠버네티스 관련 메트릭만
- 'cluster:.*' # 인프라 수준 집계 메트릭
static_configs:
- targets:
- 'prometheus-infra.monitoring.svc:9090' # 인프라 Prometheus 서비스 주소
✅ Thanos 기반 확장 아키텍처
Thanos를 활용한 대규모 분산 모니터링 아키텍처 구현 방법입니다.
- Thanos 컴포넌트 구성
- Sidecar 통합
- Query 및 Store 분리
- Compactor 최적화
- 멀티 클러스터 통합
- 글로벌 쿼리 뷰
- 크로스 클러스터 알림
- 중앙 집중식 대시보드
- 고가용성 설계
- 장애 도메인 분리
- 데이터 중복성 확보
- 무중단 업그레이드 전략
# 1. Thanos Sidecar가 통합된 Prometheus
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: Prometheus # Prometheus 커스텀 리소스 타입
metadata:
name: prometheus-thanos # Prometheus 인스턴스 이름
namespace: monitoring # 네임스페이스
spec:
replicas: 2 # 고가용성을 위한 복제본 수
version: v2.35.0 # Prometheus 버전
# 메모리 최적화 설정
resources:
requests:
memory: 16Gi # 메모리 요청량 - 시계열 데이터와 인덱스 저장용
cpu: 4 # CPU 요청량 - 쿼리 및 스크래핑 병렬 처리용
limits:
memory: 24Gi # 메모리 상한 - 버스트 수요 대응
cpu: 8 # CPU 상한 - 부하 급증 시 처리 능력 확보
# 단기 보존 설정 - 로컬에는 짧게 보관하고 객체 스토리지에 장기 보관
retention: 24h # 24시간만 로컬 보관 - 최신 데이터는 로컬에 유지
retentionSize: 10GB # 최대 10GB까지만 보관 - 디스크 사용량 제한
# Thanos Sidecar 설정 - Prometheus와 Thanos 통합
thanos: # Thanos 사이드카 설정 섹션
image: quay.io/thanos/thanos:v0.26.0 # Thanos 이미지 및 버전
version: v0.26.0 # Thanos 버전 명시
objectStorageConfig: # 객체 스토리지 설정 - 장기 저장용
name: thanos-objstore-config # 객체 스토리지 설정을 담은 Secret 이름
key: objstore.yaml # Secret 내 설정 파일 키
# Thanos 사이드카 추가 설정
resources: # 사이드카 리소스 설정
requests:
memory: 2Gi # 메모리 요청량 - 블록 메타데이터 처리용
cpu: 500m # CPU 요청량 - 데이터 전송 처리용
limits:
memory: 4Gi # 메모리 상한 - 대용량 블록 처리 대비
cpu: 1 # CPU 상한 - 병렬 업로드 처리용
# Tracing 설정 (성능 모니터링용)
tracing: # 분산 트레이싱 설정 - 내부 성능 분석용
config: # 트레이싱 설정
type: JAEGER # Jaeger 트레이싱 사용
config: | # Jaeger 설정 세부사항
service_name: thanos-sidecar # 서비스 이름 식별자
sampler_type: const # 상수 비율 샘플링
sampler_param: 1 # 100% 트레이싱 (프로덕션에서는 낮출 수 있음)
endpoint: http://jaeger-collector:14268/api/traces # 트레이싱 엔드포인트
# 스토리지 설정 - SSD 기반 고성능 스토리지
storage:
volumeClaimTemplate:
spec:
storageClassName: fast-ssd # 고성능 SSD 스토리지 클래스 - I/O 성능 최적화
resources:
requests:
storage: 100Gi # 100GB 스토리지 요청 - 단기 데이터와 WAL용
---
# 2. Thanos Query - 여러 Prometheus 데이터 통합 조회
apiVersion: apps/v1 # Kubernetes API 버전
kind: Deployment # Deployment 리소스 타입
metadata:
name: thanos-query # Thanos Query 이름
namespace: monitoring # 네임스페이스
spec:
replicas: 3 # 3개 복제본으로 고가용성 및 부하 분산
selector:
matchLabels:
app: thanos-query # Pod 선택자
template:
metadata:
labels:
app: thanos-query # Pod 레이블
spec:
containers:
- name: thanos-query # 컨테이너 이름
image: quay.io/thanos/thanos:v0.26.0 # Thanos 이미지
args:
- "query" # Query 컴포넌트로 실행 - 통합 쿼리 인터페이스
- "--log.level=info" # 로그 레벨 설정
- "--query.replica-label=replica" # 복제본 구분을 위한 레이블 - 중복 데이터 제거용
# 여러 데이터 소스 지정 - 여러 클러스터/Prometheus 인스턴스 연결
- "--store=dnssrv+_grpc._tcp.thanos-store.monitoring.svc" # Store Gateway - DNS 서비스 디스커버리
- "--store=dnssrv+_grpc._tcp.thanos-sidecar.monitoring.svc" # 로컬 Sidecar 연결
- "--store=dnssrv+_grpc._tcp.thanos-receive.monitoring.svc" # Receive 컴포넌트 연결
- "--store=thanos-sidecar-cluster-b.example.com:10901" # 원격 클러스터 Sidecar 직접 연결
# 고급 쿼리 최적화 설정
- "--query.timeout=5m" # 쿼리 타임아웃 설정 - 장기 실행 쿼리 제한
- "--query.max-concurrent=20" # 동시 쿼리 수 제한 - 리소스 보호
- "--query.auto-downsampling" # 자동 다운샘플링 활성화 - 장기 쿼리 최적화
# 긴 시간 범위 쿼리에 대해 다운샘플링된 데이터 사용
# 메모리 사용량 최적화
- "--query.max-samples=100000000" # 쿼리당 최대 샘플 수 - OOM 방지
# 캐싱 설정
- "--query.cache-results" # 쿼리 결과 캐싱 활성화 - 반복 쿼리 성능 향상
# 분산 트레이싱 설정
- "--tracing.config-file=/etc/thanos/tracing.yaml" # 트레이싱 설정 파일
# 리소스 설정
resources:
requests:
memory: 4Gi # 메모리 요청량 - 쿼리 처리 및 캐싱용
cpu: 2 # CPU 요청량 - 병렬 쿼리 처리용
limits:
memory: 8Gi # 메모리 상한 - 대용량 쿼리 처리 대비
cpu: 4 # CPU 상한 - 부하 급증 대응용
ports:
- name: http # HTTP 포트 (UI 및 API)
containerPort: 10902 # Thanos Query HTTP 포트
- name: grpc # gRPC 포트 (컴포넌트 간 통신)
containerPort: 10901 # Thanos 내부 통신 포트
volumeMounts:
- name: thanos-config # 설정 파일 볼륨
mountPath: /etc/thanos # 마운트 경로
volumes:
- name: thanos-config # Thanos 설정 볼륨
configMap:
name: thanos-config # 설정이 저장된 ConfigMap
---
# 3. Thanos Store Gateway - 장기 저장된 메트릭 접근용
apiVersion: apps/v1 # Kubernetes API 버전
kind: StatefulSet # StatefulSet 리소스 타입 (상태 유지 필요)
metadata:
name: thanos-store # Thanos Store Gateway 이름
namespace: monitoring # 네임스페이스
spec:
replicas: 3 # 고가용성 및 부하 분산을 위한 복제본 수
selector:
matchLabels:
app: thanos-store # Pod 선택자
serviceName: thanos-store # Headless 서비스 이름 - 개별 Pod 직접 접근용
template:
metadata:
labels:
app: thanos-store # Pod 레이블
spec:
containers:
- name: thanos-store # 컨테이너 이름
image: quay.io/thanos/thanos:v0.26.0 # Thanos 이미지
args:
- "store" # Store Gateway 컴포넌트로 실행 - 객체 스토리지 액세스
- "--log.level=info" # 로그 레벨
- "--data-dir=/var/thanos/store" # 로컬 캐시 디렉토리 - 블록 메타데이터 저장
- "--objstore.config-file=/etc/thanos/objstore.yaml" # 객체 스토리지 설정
# 성능 최적화 설정
- "--index-cache-size=10GB" # 인덱스 캐시 크기 - 메모리 내 캐싱으로 쿼리 가속
- "--chunk-pool-size=8GB" # 청크 풀 크기 - 메모리 내 데이터 청크 캐싱
- "--store.grpc.series-sample-limit=50000000" # 시리즈당 최대 샘플 수 - 쿼리 제한
- "--store.grpc.series-max-concurrency=20" # 병렬 시리즈 처리 수 - 동시성 제어
# 블록 메타데이터 동기화 설정
- "--sync-block-duration=5m" # 블록 메타데이터 동기화 주기 - 새 데이터 발견 빈도
- "--min-time=0000-01-01T00:00:00Z" # 가장 오래된 데이터 시작점 - 전체 범위 포함
- "--max-time=9999-12-31T23:59:59Z" # 가장 최근 데이터 종료점 - 미래 데이터 포함
resources:
requests:
memory: 8Gi # 메모리 요청량 - 인덱스 및 청크 캐싱용
cpu: 2 # CPU 요청량 - 쿼리 및 객체 스토리지 통신용
limits:
memory: 16Gi # 메모리 상한 - 대용량 인덱스 처리 대비
cpu: 4 # CPU 상한 - 병렬 처리 최대화
ports:
- name: http # HTTP 포트 (메트릭 및 디버깅)
containerPort: 10902 # HTTP 포트 번호
- name: grpc # gRPC 포트 (내부 통신)
containerPort: 10901 # gRPC 포트 번호
volumeMounts:
- name: data # 캐시 데이터 볼륨 - 블록 메타데이터 저장
mountPath: /var/thanos/store # 마운트 경로
- name: thanos-objstore-config # 객체 스토리지 설정 볼륨
mountPath: /etc/thanos # 마운트 경로
volumes:
- name: thanos-objstore-config # 객체 스토리지 설정 볼륨
secret:
secretName: thanos-objstore-config # Secret 이름
volumeClaimTemplates: # 영구 볼륨 클레임 템플릿
- metadata:
name: data # 볼륨 이름
spec:
storageClassName: standard # 스토리지 클래스
resources:
requests:
storage: 200Gi # 스토리지 요청량 - 블록 메타데이터 캐시용
✅ 자동화된 장애 복구 및 고가용성
모니터링 시스템의 장애 대응 및 자동 복구 전략입니다.
- 자가 치유 아키텍처
- 장애 감지 메커니즘
- 자동 재시작 및 복구
- 데이터 일관성 검증
- 다중 가용성 영역 설계
- 지역 분산 배포
- 데이터 복제 전략
- 장애 도메인 격리
- 무중단 업그레이드 및 확장
- 롤링 업데이트 전략
- 블루/그린 배포
- 동적 설정 리로드
# 자동화된 장애 복구 및 고가용성 설정 예시
# 이 설정은 모니터링 스택의 고가용성과 자동 복구 메커니즘을 구현합니다.
# 1. Prometheus 고가용성 구성 (PodDisruptionBudget 설정)
apiVersion: policy/v1 # Kubernetes API 버전
kind: PodDisruptionBudget # PDB 리소스 타입 - 무중단 운영 지원
metadata:
name: prometheus-pdb # PDB 이름
namespace: monitoring # 네임스페이스
spec:
minAvailable: 1 # 최소 1개 인스턴스 항상 유지
# 업그레이드 중에도 서비스 유지
selector:
matchLabels:
app: prometheus # Prometheus Pod 선택
---
# 2. Thanos 컴포넌트 안티-어피니티 설정 (예: Thanos Query)
apiVersion: apps/v1 # Kubernetes API 버전
kind: Deployment # Deployment 리소스 타입
metadata:
name: thanos-query-ha # 고가용성 Thanos Query 이름
namespace: monitoring # 네임스페이스
spec:
replicas: 3 # 3개 복제본으로 고가용성 확보
selector:
matchLabels:
app: thanos-query # Pod 선택자
template:
metadata:
labels:
app: thanos-query # Pod 레이블
spec:
# 노드 안티-어피니티 설정 - 다른 노드에 분산 배치
affinity:
podAntiAffinity: # Pod 안티-어피니티 (분산 배치)
requiredDuringSchedulingIgnoredDuringExecution: # 강제 분산 (필수)
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- thanos-query # thanos-query 라벨을 가진 Pod
topologyKey: kubernetes.io/hostname # 노드 레벨 분리
# 같은 노드에 복제본 배치 방지
# 가용성 영역 분산 설정
nodeAffinity: # 노드 어피니티 (영역 분산)
preferredDuringSchedulingIgnoredDuringExecution: # 선호도 설정 (권장)
- weight: 100 # 높은 가중치 (강한 선호도)
preference:
matchExpressions:
- key: topology.kubernetes.io/zone # 가용성 영역 레이블
operator: Exists # 영역 정보가 있는 노드 선호
# 리소스 설정
containers:
- name: thanos-query # 컨테이너 이름
image: quay.io/thanos/thanos:v0.26.0 # Thanos 이미지
args:
- "query" # Query 컴포넌트로 실행
- "--log.level=info" # 로그 레벨
# 고가용성 관련 설정
- "--query.replica-label=replica" # 복제본 구분용 레이블
- "--store=dnssrv+_grpc._tcp.thanos-store.monitoring.svc" # DNS SRV 기반 서비스 디스커버리
# 자동으로 모든 Store 인스턴스 발견
# 내결함성 설정
- "--query.partial-response" # 부분 응답 허용 - 일부 Store 실패해도 결과 반환
- "--query.timeout=2m" # 타임아웃 설정 - 응답 지연 제한
- "--endpoint=0.0.0.0:10902" # 모든 인터페이스 바인딩
# 상태 점검 설정
livenessProbe: # 활성 프로브 - 컨테이너 정상 작동 확인
httpGet:
path: /-/healthy # 상태 확인 엔드포인트
port: 10902 # HTTP 포트
initialDelaySeconds: 30 # 시작 후 대기 시간
periodSeconds: 15 # 점검 주기
readinessProbe: # 준비 프로브 - 트래픽 처리 가능 여부 확인
httpGet:
path: /-/ready # 준비 확인 엔드포인트
port: 10902 # HTTP 포트
initialDelaySeconds: 15 # 시작 후 대기 시간
periodSeconds: 5 # 점검 주기
---
# 3. 동적 설정 자동화 (HA Proxy 예시)
apiVersion: v1 # Kubernetes API 버전
kind: ConfigMap # ConfigMap 리소스 타입
metadata:
name: haproxy-dynamic-config # ConfigMap 이름
namespace: monitoring # 네임스페이스
data:
haproxy.cfg: | # HAProxy 설정 파일
global
maxconn 4096 # 최대 연결 수
log stdout format raw local0 info # 로깅 설정
defaults
log global
mode http # HTTP 모드
option httplog
timeout connect 5s # 연결 타임아웃
timeout client 30s # 클라이언트 타임아웃
timeout server 30s # 서버 타임아웃
# 프론트엔드 설정
frontend prometheus_frontend
bind *:9090 # 9090 포트 바인딩
default_backend prometheus_backend # 기본 백엔드 지정
# 백엔드 설정 - 자동 서비스 디스커버리
backend prometheus_backend
mode http
balance roundrobin # 라운드 로빈 부하 분산
option httpchk GET /api/v1/status/config # 상태 확인 경로
http-check expect status 200 # 200 응답 기대
default-server inter 5s fall 3 rise 2 # 상태 확인 간격 및 임계값
# 자동 업데이트되는 서버 목록 (외부 스크립트로 관리)
server-template prometheus 3 prometheus-operated._grpc._tcp.monitoring.svc.cluster.local:9090 check
# 템플릿으로 3개의 서버 자동 설정
---
# 4. 자동 백업 및 복구 CronJob
apiVersion: batch/v1 # Kubernetes API 버전
kind: CronJob # CronJob 리소스 타입 - 정기적 작업 실행
metadata:
name: prometheus-backup # 백업 작업 이름
namespace: monitoring # 네임스페이스
spec:
schedule: "0 1 * * *" # 매일 1시에 실행 (cron 표현식)
concurrencyPolicy: Forbid # 중복 실행 방지
successfulJobsHistoryLimit: 3 # 성공 작업 기록 보존 수
failedJobsHistoryLimit: 1 # 실패 작업 기록 보존 수
jobTemplate:
spec:
template:
spec:
containers:
- name: prometheus-backup # 백업 컨테이너
image: alpine:3.16 # 경량 베이스 이미지
command:
- /bin/sh
- -c
- |
# Prometheus API를 통한 규칙 및 설정 백업
apk add --no-cache curl jq # 필요한 도구 설치
# 백업 디렉토리 생성
BACKUP_DIR="/backups/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
# 알림 규칙 백업
curl -s http://prometheus-operated:9090/api/v1/rules | jq . > $BACKUP_DIR/rules.json
# 현재 설정 백업
curl -s http://prometheus-operated:9090/api/v1/status/config | jq . > $BACKUP_DIR/config.json
# 대상 상태 백업
curl -s http://prometheus-operated:9090/api/v1/targets | jq . > $BACKUP_DIR/targets.json
# 객체 스토리지에 백업 복사
mc cp -r $BACKUP_DIR backup/prometheus-backups/
echo "Backup completed successfully at $(date)"
volumeMounts:
- name: backup-volume # 백업 볼륨
mountPath: /backups # 마운트 경로
restartPolicy: OnFailure # 실패 시 재시작 정책
volumes:
- name: backup-volume # 백업 볼륨
persistentVolumeClaim:
claimName: prometheus-backup-pvc # 백업용 PVC
✅ 모니터링 시스템 상태 모니터링
모니터링 시스템 자체의 상태를 추적하고 문제를 조기에 발견하는 전략입니다.
- 메타 모니터링 설정
- 모니터링 시스템 자체 메트릭
- 별도 인스턴스로 모니터링
- 독립적인 알림 채널
- 시스템 건강 대시보드
- 핵심 성능 지표 추적
- 상태 이력 및 추세 분석
- 이상 감지 및 예측
- 자가 테스트 메커니즘
- 합성 메트릭 및 알림
- 주기적 진단 검사
- 부하 테스트 자동화
# 모니터링 시스템 상태 모니터링 설정 예시
# 이 설정은 Prometheus와 Thanos 자체를 모니터링하는 독립적인 메타-모니터링 시스템을 구현합니다.
# 1. 메타 모니터링용 Prometheus 인스턴스
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: Prometheus # Prometheus 커스텀 리소스 타입
metadata:
name: meta-monitoring # 메타 모니터링 Prometheus 이름
namespace: monitoring # 네임스페이스
spec:
replicas: 2 # 고가용성을 위한 복제본 수
version: v2.35.0 # Prometheus 버전
# 독립 스토리지 설정 - 기본 모니터링과 분리
retention: 7d # 7일 데이터 보존
# 메타 모니터링용 리소스 설정 - 더 작게 설정
resources:
requests:
memory: 4Gi # 메모리 요청량 - 더 적은 메트릭 처리
cpu: 1 # CPU 요청량 - 단순 모니터링 작업
limits:
memory: 8Gi # 메모리 상한
cpu: 2 # CPU 상한
# 메인 모니터링 시스템 타겟 설정
serviceMonitorSelector: # ServiceMonitor 선택기
matchLabels:
monitoring-type: meta # meta 타입 ServiceMonitor만 선택
# 독립 알림매니저 설정
alerting:
alertmanagers: # 알림매니저 설정
- namespace: monitoring
name: alertmanager-meta # 메타 모니터링 전용 알림매니저
port: web
# 독립 스토리지 설정
storage:
volumeClaimTemplate:
spec:
storageClassName: standard # 일반 스토리지 클래스 사용
resources:
requests:
storage: 50Gi # 50GB 스토리지 요청
---
# 2. 모니터링 시스템 타겟을 위한 ServiceMonitor
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: ServiceMonitor # ServiceMonitor 커스텀 리소스 타입
metadata:
name: monitoring-system # ServiceMonitor 이름
namespace: monitoring # 네임스페이스
labels:
monitoring-type: meta # 메타 모니터링 레이블 - 메타 Prometheus에서 선택됨
spec:
selector:
matchExpressions: # 서비스 선택 표현식
- key: app # app 레이블 기준
operator: In # 포함 조건
values: # 모니터링 시스템 컴포넌트들
- prometheus
- thanos-query
- thanos-store
- thanos-compact
- alertmanager
- grafana
namespaceSelector: # 네임스페이스 선택기
matchNames:
- monitoring # 모니터링 네임스페이스만 선택
endpoints:
- port: web # 모니터링 엔드포인트 포트 (표준)
interval: 15s # 높은 빈도로 스크래핑 (빠른 이상 감지)
path: /metrics # 메트릭 경로
# 추가 엔드포인트 - Thanos 컴포넌트용
- port: http # Thanos 컴포넌트의 HTTP 포트
interval: 15s # 15초마다 스크래핑
path: /metrics # 메트릭 경로
relabelings: # 레이블 재작성 규칙
- sourceLabels: [__meta_kubernetes_pod_label_app] # Pod app 레이블 기준
regex: thanos.* # thanos로 시작하는 레이블만 선택
action: keep # 조건에 맞는 타겟만 유지
---
# 3. 메타 모니터링용 알림 규칙
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: PrometheusRule # PrometheusRule 커스텀 리소스 타입
metadata:
name: monitoring-system-alerts # 모니터링 시스템용 알림 규칙 이름
namespace: monitoring # 네임스페이스
labels:
monitoring-type: meta # 메타 모니터링 유형 레이블 - 메타 Prometheus에서 선택됨
spec:
groups:
# Prometheus 상태 알림 그룹
- name: prometheus-health # 알림 그룹 이름 - Prometheus 상태 관련
interval: 30s # 평가 간격 - 빠른 감지를 위해 짧게 설정
rules:
# Prometheus 인스턴스 다운 알림
- alert: PrometheusDown # 알림 이름
expr: up{job="prometheus"} == 0 # Prometheus 가용성 검사 - 0은 다운 상태
for: 1m # 1분 동안 지속되면 알림 발생 - 일시적 문제 필터링
labels:
severity: critical # 심각도: 위험 수준 - 즉시 대응 필요
component: prometheus # 컴포넌트: Prometheus - 문제 영역 식별
annotations:
summary: "Prometheus 인스턴스 다운" # 알림 요약
description: "{{ $labels.instance }} 인스턴스가 {{ $value }}분 동안 다운되었습니다." # 상세 설명
runbook_url: "https://example.com/runbooks/prometheus-down" # 조치 가이드 URL
# Prometheus 고부하 알림
- alert: PrometheusHighLoad # 알림 이름
expr: rate(prometheus_tsdb_head_samples_appended_total[5m]) > 100000 # 초당 10만 샘플 초과 시
for: 10m # 10분 동안 지속되면 알림 발생 - 일시적 부하 필터링
labels:
severity: warning # 심각도: 경고 수준 - 주의 필요하나 즉시 대응은 아님
component: prometheus # 컴포넌트: Prometheus
annotations:
summary: "Prometheus 고부하 상태" # 알림 요약
description: "{{ $labels.instance }}의 수집 부하가 {{ $value | humanize }} samples/s로 높습니다." # 상세 설명
# Prometheus 스크래핑 실패율 알림
- alert: PrometheusHighScrapeFailureRate # 알림 이름
expr: sum(rate(prometheus_target_scrapes_sample_scrape_failures_total[5m])) / sum(rate(prometheus_target_scrapes_sample_duration_seconds_count[5m])) > 0.1 # 10% 초과 실패율
for: 10m # 10분 동안 지속되면 알림 발생
labels:
severity: warning # 심각도: 경고 수준
component: prometheus # 컴포넌트: Prometheus
annotations:
summary: "스크래핑 실패율 높음" # 알림 요약
description: "{{ $labels.instance }}의 타겟 스크래핑 실패율이 {{ $value | humanizePercentage }}입니다." # 상세 설명
# Thanos 컴포넌트 상태 알림 그룹
- name: thanos-health # Thanos 상태 알림 그룹
interval: 1m # 1분마다 평가 - 신속한 문제 감지
rules:
# Thanos Query 다운 알림
- alert: ThanosQueryDown # 알림 이름
expr: up{app="thanos-query"} == 0 # Thanos Query 가용성 검사
for: 5m # 5분 동안 지속되면 알림 발생
labels:
severity: critical # 심각도: 위험 수준
component: thanos # 컴포넌트: Thanos
annotations:
summary: "Thanos Query 다운" # 알림 요약
description: "{{ $labels.instance }} Thanos Query 인스턴스가 {{ $value }}분 동안 다운되었습니다." # 상세 설명
# Thanos Store 상태 알림
- alert: ThanosStoreGrpcErrorRate # 알림 이름
expr: sum by (instance) (rate(grpc_server_handled_total{grpc_code=~"Unknown|ResourceExhausted|Internal|Unavailable|DataLoss|DeadlineExceeded", app="thanos-store"}[5m])) / sum by (instance) (rate(grpc_server_handled_total{app="thanos-store"}[5m])) > 0.05 # gRPC 에러율 5% 초과
for: 5m # 5분 동안 지속되면 알림 발생
labels:
severity: warning # 심각도: 경고 수준
component: thanos # 컴포넌트: Thanos
annotations:
summary: "Thanos Store gRPC 에러율 높음" # 알림 요약
description: "{{ $labels.instance }}의 gRPC 에러율이 {{ $value | humanizePercentage }}로 높습니다." # 상세 설명
4. 자가 진단 테스트 CronJob 설정
apiVersion: batch/v1 # Kubernetes API 버전
kind: CronJob # CronJob 리소스 타입
metadata:
name: monitoring-self-test # 자가 진단 작업 이름
namespace: monitoring # 네임스페이스
spec:
schedule: "*/15 * * * *" # 15분마다 실행 (cron 표현식)
concurrencyPolicy: Forbid # 중복 실행 방지
successfulJobsHistoryLimit: 3 # 성공 작업 기록 보존 수
failedJobsHistoryLimit: 3 # 실패 작업 기록 보존 수
jobTemplate:
spec:
template:
spec:
containers:
- name: monitoring-test # 테스트 컨테이너
image: curlimages/curl:7.86.0 # curl 이미지
command:
- /bin/sh
- -c
- |
# 기본 변수 설정
PROMETHEUS_URL="http://prometheus-operated:9090"
THANOS_URL="http://thanos-query:10902"
FAILED=0
# 결과 출력 함수
log_test() {
echo "$(date) - $1: $2"
}
# Prometheus 상태 API 테스트
PROM_STATUS=$(curl -s -o /dev/null -w "%{http_code}" $PROMETHEUS_URL/-/ready)
if [ "$PROM_STATUS" == "200" ]; then
log_test "Prometheus 준비 상태" "정상 (200)"
else
log_test "Prometheus 준비 상태" "실패 ($PROM_STATUS)"
FAILED=1
fi
# Prometheus 쿼리 API 테스트 - 간단한 쿼리 실행
QUERY_RESULT=$(curl -s -G --data-urlencode 'query=up' $PROMETHEUS_URL/api/v1/query | grep -c "success")
if [ "$QUERY_RESULT" -gt 0 ]; then
log_test "Prometheus 쿼리 API" "정상"
else
log_test "Prometheus 쿼리 API" "실패"
FAILED=1
fi
# Thanos Query 상태 테스트
THANOS_STATUS=$(curl -s -o /dev/null -w "%{http_code}" $THANOS_URL/-/ready)
if [ "$THANOS_STATUS" == "200" ]; then
log_test "Thanos Query 준비 상태" "정상 (200)"
else
log_test "Thanos Query 준비 상태" "실패 ($THANOS_STATUS)"
FAILED=1
fi
# 테스트 메트릭 생성 - Pushgateway로 전송하여 모니터링 시스템 테스트
echo 'monitoring_self_test{test="heartbeat"} 1' | curl -s --data-binary @- http://prometheus-pushgateway:9091/metrics/job/monitoring_test
# 테스트 결과 종합
if [ "$FAILED" -eq 0 ]; then
echo "== 모니터링 시스템 자가 진단 완료: 모든 검사 통과 =="
exit 0
else
echo "== 모니터링 시스템 자가 진단 완료: 일부 검사 실패 =="
exit 1
fi
restartPolicy: OnFailure # 실패 시 재시작 정책
5. 장기 성능 추세 분석을 위한 Recording Rules
apiVersion: monitoring.coreos.com/v1 # Prometheus Operator CRD API 버전
kind: PrometheusRule # PrometheusRule 커스텀 리소스 타입
metadata:
name: monitoring-system-performance # 성능 기록 규칙 이름
namespace: monitoring # 네임스페이스
labels:
monitoring-type: meta # 메타 모니터링 유형 레이블
spec:
groups:
# 모니터링 시스템 성능 지표 기록 그룹
- name: monitoring-performance-records # 규칙 그룹 이름
interval: 5m # 5분마다 평가 - 장기 추세 분석용
rules:
# Prometheus 메모리 사용량 추세
- record: monitoring:prometheus_memory:avg5m # 생성될 메트릭 이름
expr: avg by (pod) (container_memory_usage_bytes{container="prometheus", namespace="monitoring"})
# 각 Prometheus Pod별 평균 메모리 사용량 기록
# Prometheus CPU 사용량 추세
- record: monitoring:prometheus_cpu:avg5m
expr: avg by (pod) (rate(container_cpu_usage_seconds_total{container="prometheus", namespace="monitoring"}[5m]))
# 각 Prometheus Pod별 5분 평균 CPU 사용량 기록
# 스크래핑 성능 지표
- record: monitoring:scrape_duration:avg5m
expr: avg by (job) (scrape_duration_seconds)
# 작업별 평균 스크래핑 시간 기록
# 스크래핑 샘플 수 추세
- record: monitoring:scrape_samples:sum5m
expr: sum by (job) (scrape_samples_post_metric_relabeling)
# 작업별 수집된 총 샘플 수 기록
# Thanos Query 성능 지표
- record: monitoring:thanos_query_api_requests:rate5m
expr: sum by (handler) (rate(http_requests_total{job="thanos-query"}[5m]))
# Thanos Query API 엔드포인트별 요청 비율 기록
# Thanos Store 디스크 사용량
- record: monitoring:thanos_store_disk_usage:avg5m
expr: avg by (pod) (container_fs_usage_bytes{container="thanos-store", namespace="monitoring"})
# Thanos Store의 디스크 사용량 기록
📌 Summary
대규모 쿠버네티스 환경에서 효과적인 고성능 모니터링 시스템을 구축하는 것은 여러 도전 과제를 수반합니다. 이 글에서는 다음과 같은 주요 측면을 다루었습니다:
- 성능 병목 이해와 측정: 모니터링 시스템의 주요 병목 현상(샘플 수집, 스토리지, 쿼리)을 식별하고 이를 측정하기 위한 도구와 방법론을 살펴보았습니다.
- Prometheus 성능 최적화: 메모리 및 CPU 자원 관리, 스크래핑 설정 최적화, 효율적인 쿼리 및 규칙 설계 방법을 구체적인 설정 예제와 함께 알아보았습니다.
- 분산 아키텍처 설계: 대규모 환경을 위한 Prometheus 샤딩 및 페더레이션 전략, Thanos 기반 글로벌 쿼리 통합, 다단계 스토리지 아키텍처를 실제 구현 예제와 함께 살펴보았습니다.
- 자동화 및 자가 관리: 모니터링 시스템의 자동 튜닝, 장애 복구, 자가 진단 메커니즘을 구현하는 방법과 모니터링 시스템 자체의 상태를 모니터링하는 방법에 대해 알아보았습니다.
고성능 모니터링 설정의 핵심은 단순히 도구를 설치하는 것이 아니라, 워크로드와 환경에 맞는 최적화된 아키텍처를 설계하고 지속적으로 개선해 나가는 과정입니다. 규모가 커질수록 모니터링 자체의 자원 소비도 증가하므로, 효율적인 설계와 관리가 더욱 중요해집니다. 이 글에서 소개한 기법들을 활용하여 클러스터 규모에 상관없이 안정적이고 성능이 뛰어난 모니터링 시스템을 구축하는 데 도움이 되길 바랍니다.
'Observability > Prometheus' 카테고리의 다른 글
EP18 [Part 6: 고급 모니터링 전략] 보안 및 성능 최적화 (0) | 2025.03.25 |
---|---|
EP16 [Part 6: 고급 모니터링 전략] 메트릭 보존 정책 (0) | 2025.03.25 |
EP15 [Part 5: 애플리케이션 레벨 모니터링] 웹 애플리케이션 모니터링 (Airflow 등) (0) | 2025.03.25 |
EP14 [Part 5: 애플리케이션 레벨 모니터링] 데이터베이스 모니터링 (MySQL, PostgreSQL) (0) | 2025.03.24 |
EP13 [Part 5: 애플리케이션 레벨 모니터링] 다양한 애플리케이션 익스포터 소개 (0) | 2025.03.24 |