Prometheus & Grafana 모니터링 실습 가이드
1. 접속 방법 (포트포워딩)
Ingress 도메인 연결된 Grafana URL을 받았지만 매우 불안정하므로 포트포워딩으로 접속 설정해줬다.
# Prometheus 접속
kubectl port-forward svc/prometheus-server 9090:80 -n monitoring &
# Grafana 접속
kubectl port-forward svc/grafana 3000:80 -n monitoring &
포트포워딩을 통해 로컬에서 접속이 가능해짐:
- Prometheus: http://localhost:9090
- Grafana: http://localhost:3000
2. Prometheus 활용하기
Prometheus에 접속해서 PromQL 쿼리를 실행해보기:
2-1. 파드 정보 조회
# 네임스페이스의 모든 파드 정보 조회
# → 해당 네임스페이스에 존재하는 모든 Pod의 이름, 노드, IP, UID 등의 기본 정보 표시
kube_pod_info{namespace="본인네임스페이스명"}
# 특정 애플리케이션 파드만 조회 (예: 백엔드)
# → 해당 네임스페이스 내에서 app=backend 라벨이 붙은 Pod들만 필터링하여 정보 출력
kube_pod_info{namespace="본인네임스페이스명", app="backend"}
2-2. CPU 관련 쿼리
# 네임스페이스 내 파드별 CPU 사용량
# → 각 Pod이 최근 5분간 초당 얼마나 CPU를 사용했는지 보여줌
sum(rate(container_cpu_usage_seconds_total{namespace="본인네임스페이스명"}[5m])) by (pod)
# 특정 애플리케이션(예: 백엔드)의 CPU 사용량
# → container 이름이 "backend"인 컨테이너들의 CPU 사용량 총합
sum(rate(container_cpu_usage_seconds_total{namespace="본인네임스페이스명", container="backend"}[5m]))
# CPU 사용률 (요청 대비)
# → 실제 사용량 ÷ 요청량 × 100 = 사용률(%)을 계산
# → 요청 대비 얼마나 CPU를 쓰고 있는지 퍼센트로 확인 가능 (과소/과대 할당 분석)
sum(rate(container_cpu_usage_seconds_total{namespace="본인네임스페이스명"}[5m])) by (pod) /
sum(kube_pod_container_resource_requests_cpu_cores{namespace="본인네임스페이스명"}) by (pod)* 100
# 네임스페이스의 총 CPU 사용량
# → 해당 네임스페이스 전체 Pod가 사용하는 CPU의 초당 총합
sum(rate(container_cpu_usage_seconds_total{namespace="본인네임스페이스명"}[5m]))
| 쿼리 | 설명 |
| rate(metric[5m]) | 카운터 타입 메트릭의 초당 증가율 계산 (5분 간 평균) |
| sum(...) by (pod) | 각 Pod 단위로 그룹화해서 합산 |
| container_cpu_usage_seconds_total | 컨테이너가 사용한 CPU 시간(초), 누적값 |
| kube_pod_container_resource_requests_cpu_cores | 각 컨테이너가 요청한 CPU량 (core 단위, 정적 값) |
2-3. 메모리 관련 쿼리
💡 참고 팁) 단위 변환:
- Bytes → KB = / 1024
- Bytes → MB = / 1024 / 1024
# 파드별 메모리 사용량 (MB)
# → 각 파드가 사용하는 메모리(Working Set)를 MB 단위로 표시
# → Working Set: 실제로 "사용 중인" 메모리 (캐시 제외 X)
sum(container_memory_working_set_bytes{namespace="본인네임스페이스명"}) by (pod) / 1024 / 1024
# 특정 애플리케이션의 메모리 사용량 (GB)
# → container 이름이 "frontend"인 컨테이너 전체가 사용 중인 메모리의 총합을 GB로 변환
sum(container_memory_working_set_bytes{namespace="본인네임스페이스명", container="frontend"}) / 1024 / 1024 / 1024
# 메모리 사용률 (요청 대비)
# → (실제 사용량 ÷ 요청량) × 100 = 사용률(%)
# → 리소스 요청량보다 너무 많이 쓰고 있는지, 혹은 너무 적게 쓰고 있는지 확인 가능
sum(container_memory_working_set_bytes{namespace="본인네임스페이스명"}) by (pod) /
sum(kube_pod_container_resource_requests_memory_bytes{namespace="본인네임스페이스명"}) by (pod) * 100
# 최대 메모리 사용량 확인
# → 최근 30분간 파드들이 사용한 메모리 중 가장 높은 사용량 (피크 메모리)
max_over_time(container_memory_working_set_bytes{namespace="본인네임스페이스명"}[30m]) / 1024 / 1024
| 메트릭 이름 | 설명 |
| container_memory_working_set_bytes | 컨테이너가 실제 사용 중인 메모리 (캐시 포함) |
| kube_pod_container_resource_requests_memory_bytes | 컨테이너가 요청한 메모리량 (요청값 기준) |
2-4. 네트워크 관련 쿼리
# 네트워크 수신 트래픽 (KB/s)
# → 각 파드가 수신한 네트워크 바이트를 초당 계산 (5분 평균), KB 단위로 환산
sum(rate(container_network_receive_bytes_total{namespace="본인네임스페이스명"}[5m])) by (pod) / 1024
# 네트워크 송신 트래픽 (KB/s)
# → 각 파드가 송신한 네트워크 바이트를 초당 계산 (5분 평균), KB 단위로 환산
sum(rate(container_network_transmit_bytes_total{namespace="본인네임스페이스명"}[5m])) by (pod) / 1024
# 네트워크 총 트래픽 (MB/s)
# → 네임스페이스 전체의 수신 + 송신 트래픽을 합산, MB 단위로 환산
sum(
rate(container_network_receive_bytes_total{namespace="본인네임스페이스명"}[5m]) +
rate(container_network_transmit_bytes_total{namespace="본인네임스페이스명"}[5m])
) / 1024 / 1024
# 네트워크 에러 패킷
# → 파드별 네트워크 수신 중 발생한 에러 횟수의 초당 변화량
# → 네트워크 불안정 여부 점검 시 유용
sum(rate(container_network_receive_errors_total{namespace="본인네임스페이스명"}[5m])) by (pod)
| 메트릭 이름 | 설명 |
| container_network_receive_bytes_total | 컨테이너가 수신한 누적 바이트 수 |
| container_network_transmit_bytes_total | 컨테이너가 송신한 누적 바이트 수 |
| rate(metric[5m]) | 최근 5분간 초당 변화량 (단위: Bytes/s) |
| container_network_receive_errors_total | 수신 중 발생한 누적 에러 수 |
2-5. 애플리케이션 상태 관련 쿼리
💡 참고 팁) 실무 활용 예시:
- Running 파드 수
→ 서비스가 정상적으로 유지되고 있는지 확인 - 재시작 수
→ 불안정한 컨테이너 감지 (CrashLoop 등) - Pending 파드 수
→ 클러스터 자원 부족 여부 감지 - Ready 상태→ 실제 트래픽을 받을 수 있는 상태인지 판단 가능
# 실행 중인 파드 수
# → 현재 'Running' 상태인 파드의 총 개수 (정상적으로 동작 중인 파드 수 확인용)
sum(kube_pod_status_phase{namespace="본인네임스페이스명", phase="Running"})
# 파드 재시작 횟수
# → 파드 내 모든 컨테이너의 재시작 횟수를 파드별로 합산
# → 컨테이너가 자주 재시작된다면 에러 가능성 높음
sum(kube_pod_container_status_restarts_total{namespace="본인네임스페이스명"}) by (pod)
# Pending 상태의 파드 수
# → 스케줄링은 되었지만 아직 노드에 배치되지 못한 파드 수
# → 자원 부족, 네트워크 문제 등으로 파드가 대기 중일 수 있음
sum(kube_pod_status_phase{namespace="본인네임스페이스명", phase="Pending"})
# 컨테이너 상태 확인
# → 파드 내 컨테이너가 'Ready' 상태인지 여부 (값이 1이면 준비 완료)
# → 파드별 준비된 컨테이너 수를 합산해서 확인
sum(kube_pod_container_status_ready{namespace="본인네임스페이스명"}) by (pod)
| 메트릭 이름 | 설명 |
| kube_pod_status_phase | 파드의 상태 (Pending, Running, Succeeded 등) |
| kube_pod_container_status_restarts_total | 컨테이너 재시작 횟수 (누적) |
| kube_pod_container_status_ready | 컨테이너가 Ready 상태인지 여부 (1: 준비됨, 0: 준비되지 않음) |
2-6. HPA 관련 쿼리
# HPA 현재 레플리카 수
# → HPA가 현재 유지 중인 실제 파드 개수
kube_horizontalpodautoscaler_status_current_replicas{namespace="본인네임스페이스명"}
# HPA 목표 레플리카 수
# → HPA가 현재 상태를 기준으로 조정하려고 계산한 목표 파드 개수
kube_horizontalpodautoscaler_status_desired_replicas{namespace="본인네임스페이스명"}
# HPA 최소 레플리카 수
# → HPA 설정에서 정의한 최소 파드 개수 (절대 이 수보다 적게 줄어들지 않음)
kube_horizontalpodautoscaler_spec_min_replicas{namespace="본인네임스페이스명"}
# HPA 최대 레플리카 수
# → HPA 설정에서 정의한 최대 파드 개수 (절대 이 수보다 많이 늘어나지 않음)
kube_horizontalpodautoscaler_spec_max_replicas{namespace="본인네임스페이스명"}
💡 참고 팁) 실무에서 이 메트릭을 보는 이유 :
| 메트릭 이름 | 확인 목적 |
| current_replicas | 지금 몇 개의 파드가 돌고 있는가? |
| desired_replicas | 얼마나 늘려야/줄여야 한다고 판단했는가? |
| min/max_replicas | 설정 상 허용되는 범위는 어디까지인가? |
2-7. HTTP 요청 관련 쿼리 (백엔드에 Prometheus 메트릭이 노출된 경우)
# 특정 네임스페이스와 앱에 대한 HTTP 요청 수 (레이블 기준 조회)
# → 지정된 네임스페이스 내에서 app="backend" 라벨이 붙은 서비스의 전체 요청 수
http_requests_total{namespace="본인네임스페이스명", app="backend"}
# HTTP 요청 총 건수 (네임스페이스 필터링 후 전체 합산)
# → 지정된 네임스페이스에 있는 모든 서비스들의 HTTP 요청 총합 (누적 카운터)
sum(http_requests_total{namespace="본인네임스페이스명"})
# 특정 앱의 HTTP 요청 응답 시간 히스토그램 버킷 (측정용 기본 메트릭)
# → 응답 시간 분포 데이터를 담고 있는 히스토그램 버킷 (ms 기준)
# → 퍼센타일 계산에 사용되는 기본 메트릭
http_request_duration_ms_bucket{namespace="본인 네임스페이스", app="backend"}
# HTTP 요청 응답 시간의 95번째 백분위 (응답 시간 퍼센타일)
# → 최근 5분 동안의 요청 중, 95%가 이 시간 이하로 처리됨
# → SLA 기준으로 자주 사용하는 퍼센타일 지표 (지연/병목 감지용)
histogram_quantile(
0.95,
sum(rate(http_request_duration_ms_bucket{namespace="본인네임스페이스명"}[5m])) by (le)
)
# HTTP 응답 코드(status_code)별 요청 수 (5분간 초당 요청률)
# → 200, 404, 500 등 상태 코드별로 초당 몇 건의 요청이 발생했는지 확인
# → 오류 비율(4xx/5xx 비율)을 보기 위한 핵심 지표
sum(rate(http_requests_total{namespace="본인네임스페이스명"}[5m])) by (status_code)
# API 엔드포인트(path)별 요청 수 (5분간 초당 요청률)
# → 어떤 경로(API)로 요청이 많이 들어오는지 분석
# → 트래픽 분산, 인기 API 확인 등에 유용
sum(rate(http_requests_total{namespace="본인네임스페이스명"}[5m])) by (path)
💡 참고 팁) 실무에서 이 쿼리를 확인하는 이유 :
| 쿼리 | 확인 목적 |
| histogram_quantile(...) | 지연 시간 모니터링 |
| sum(rate(...) by (status_code)) | 에러율 분석 |
| sum(rate(...) by (path)) | 트래픽 많은 API 확인 |
| sum(rate(http_requests_total[5m])) | 전체 트래픽 변화 보기 |
3. Grafana 대시보드 구성하기
브라우저에서 http://localhost:3000 으로 접속합니다.
3-0. Grafana 로그인 및 Prometheus 데이터 소스 확인
- Username: admin
- Password: 아래 명령어로 확인
# Windows
kubectl get secret -n monitoring grafana -o jsonpath="{.data.admin-password}"
# ㄴ 이후 나오는 문자열을 따로 base64 디코딩해야함.
# Mac
# kubectl get secret -n monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode
- 왼쪽 메뉴에서 "Configuration(설정)" > "Data sources(데이터 소스)" 클릭
- Prometheus가 이미 추가되어 있는지 확인하고, 없으면 추가
3-1. 새 대시보드 만들기
- 왼쪽 메뉴에서 "Dashboards" > "+ New Dashboard" 클릭
- "+ Add visualization" 클릭
- 데이터 소스로 "Prometheus" 선택
- 다음 쿼리 입력:
# 특정 네임스페이스 안에서 '실행 중(Running)' 상태인 파드의 수
sum(kube_pod_status_phase{namespace="본인네임스페이스명", phase="Running"}) by (pod)
- "Run queries" 버튼 클릭하여 그래프 확인
- 패널 제목을 "실행 중인 파드"로 변경
- 우측 상단 "Apply" 버튼 클릭하여 패널 저장

3-2. CPU 사용량 패널 추가하기
- 우측 상단 "Add" 메뉴에서 "Visualization" 선택
- 데이터 소스로 "Prometheus" 선택
- 다음 쿼리 입력:
# 파드별 CPU 사용량 (초당)
# → 각 파드가 최근 5분 동안 사용한 CPU의 초당 평균 사용량을 계산
# → CPU 코어 단위로 측정되며, 1.0 = CPU 1개를 풀로 사용 중이라는 의미
sum(
rate(container_cpu_usage_seconds_total{namespace="본인네임스페이스명"}[5m])
) by (pod)
- 패널 제목을 "CPU 사용량 (파드별)"로 변경
- "Apply" 버튼으로 저장

3-3. 메모리 사용량 패널 추가하기
- 우측 상단 "Add" 메뉴에서 "Visualization" 선택
- 데이터 소스로 "Prometheus" 선택
- 다음 쿼리 입력:
# 파드별 메모리 사용량 (MB 단위)
# → 각 파드가 실제로 사용 중인 메모리(Working Set)를 MB로 환산하여 표시
# → Working Set은 캐시 등을 포함한 "현재 실제 사용 중인" 메모리 크기
sum(
container_memory_working_set_bytes{namespace="본인네임스페이스명"}
) by (pod) / 1024 / 1024
- Options" 탭에서 "Unit"을 "Bytes/IEC" > "mebibytes"로 변경
- 패널 제목을 "메모리 사용량 (MiB)"로 변경
- "Apply" 버튼으로 저장

3-4. 네트워크 트래픽 패널 추가하기
- 우측 상단 "Add" 메뉴에서 "Visualization" 선택
- 데이터 소스로 "Prometheus" 선택
- 다음 쿼리 입력:
# 파드별 네트워크 수신 트래픽 (KB/s)
# → 각 파드가 최근 5분 동안 수신한 네트워크 바이트의 초당 평균값을 계산
# → 결과를 1024로 나눠서 KB(킬로바이트) 단위로 환산
sum(
rate(container_network_receive_bytes_total{namespace="본인네임스페이스명"}[5m])
) by (pod) / 1024
- "Add Query" 버튼 클릭하여 두 번째 쿼리 추가:
# 파드별 네트워크 송신 트래픽 (KB/s)
# → 각 파드가 최근 5분 동안 송신한 네트워크 바이트의 초당 평균값을 계산
# → 결과를 1024로 나눠서 KB(킬로바이트) 단위로 환산
sum(
rate(container_network_transmit_bytes_total{namespace="본인네임스페이스명"}[5m])
) by (pod) / 1024
- "Legend" 란의 형식을 "Custom"으로 선택 후 첫 번째 쿼리는 "수신(IN)", 두 번째 쿼리는 "송신(OUT)"으로 설정
- "Options" 탭에서 "Unit"을 "Data rate" > "kibibytes/sec"로 변경
- 패널 제목을 "네트워크 트래픽"으로 변경
- "Apply" 버튼으로 저장

3-5. 대시보드 저장
- 우측 상단 디스크 아이콘(Save dashboard) 클릭
- 대시보드 이름 입력 (예: "3-Tier 애플리케이션 모니터링") 후, "Save" 클릭해서 최종적으로 저장

4. 대시보드 심화
변수(Variable) 를 사용해서 pod 필터링 기능 만들어보기
- 대시보드 설정 열기 (우측 상단 Settings 버튼 클릭)

- "Variables" 선택 > "Add variable" 클릭

- 다음과 같이 설정:
Variable Type: Query
Name: pod
Label: 파드 선택
Data source: Prometheus
Query Type: Classic Query
Classic Query : label_values(kube_pod_info{namespace="본인네임스페이스명"}, pod)
Selection options: "Multi-value" 활성화
"Run Query" 클릭

변수가 추가된 것을 확인 후, 대시보드로 돌아가서 상단을 확인해보면 "파드 선택" 드롭다운이 생겼다.


변수를 활용하기 위해 기존에 작성했던 CPU 사용량 패널의 쿼리를 수정해보겠다.
기존에는 이 패널이 모든 파드의 CPU 사용량을 표시했지만, 드롭다운에서 선택한 파드의 CPU 사용량을 표시하게 될 것이다.
# Before - 모든 pod의 pod별 cpu 사용량을 표시
# sum(rate(container_cpu_usage_seconds_total{namespace="본인네임스페이스명"}[5m])) by (pod)
# After - 필터링한 pod의 cpu 사용량만을 표시
sum(rate(container_cpu_usage_seconds_total{namespace="본인네임스페이스명", pod=~"$pod"}[5m]))

수정후에, 해당 패널이 "파드 선택" 드롭다운에서 선택한 파드의 CPU 사용량만을 표시하도록 바뀌었다.

알람 설정 기능
Grafana에서 Slack, Discord, Email 등으로 경고알람을 받을 수 있다.
실제로 적용을 해보진 않고 그냥 이런게 있다정도로만 살펴보고 넘어가겠다.
- 패널 편집 모드에서 "Alert" 탭 클릭 > "New alert rule" 버튼 클릭

패널 편집 창 > Alert 탭 > New alert rule 버튼 - [2. Define Query and alert condition] 항목에서 알람 조건 설정이 가능하다. (예: CPU 사용량이 80% 이상일 때)

어떤 조건에서 알람을 받을지 (Alert Rule) 설정 - [5.Configure notifications] 항목에서 알람을 통지할 채널의 설정이 가능하다. (사전에 Alertmanager 설정 필요)
"view or create contact points" 버튼을 클릭해서 어떤 채널이 설정 가능한지 확인할 수 있다.

대시보드 자동 갱신 설정
데이터는 실시간으로 쌓이지만 대시보드는 실시간으로 변하지 않기 때문에 변화한 내용을 보기 위해서는 새로고침이 필요하다.
- 대시보드 메인 우측 상단에서 Refresh 버튼을 클릭해서 대시보드 새로고침 가능
- 혹은 자동으로 새로고침하는 간격을 설정할 수 있음 (예: 5s, 10s, 30s, 1m)

5. 추가 팁 - 대시보드 템플릿 가져오기
하나하나 패널을 구성하지 않고, 기존에 만들어져있는 템플릿을 Import 해서 사용할 수도 있다.
- 우측 상단 메뉴에서 "+" 버튼 클릭 > 드롭다운 메뉴 "Import dashboard" 선택

Grafana 우측 상단 메뉴 - grafana.com에서 유용한 대시보드 ID 입력 또는 JSON 파일 업로드
- Kubernetes 모니터링: 315, 6417
- 노드 모니터링: 1860
- MySQL 모니터링: 7362


본 후기는 [카카오엔터프라이즈x스나이퍼팩토리] 카카오클라우드로 배우는 AIaaS 마스터 클래스 (B-log) 리뷰로 작성 되었습니다.
'학습일지 > K-Digital Traing' 카테고리의 다른 글
| [KDT] AIaaS 마스터클래스 4주차 - 리눅스에 대해 (0) | 2025.04.18 |
|---|---|
| [KDT] AIaaS 마스터클래스 4주차 - Database와 ERD 작성 과제 (0) | 2025.04.17 |
| [KDT] AIaaS 마스터클래스 3주차 - 클라우드 어플리케이션 배포 실습 (0) | 2025.04.10 |
| [KDT] AIaaS 마스터클래스 3주차 - 쿠버네티스 실습 (0) | 2025.04.09 |
| [KDT] AIaaS 마스터클래스 2주차 - 3 Tier Application 배포 실습 (0) | 2025.04.04 |