학습일지/K-Digital Traing

[KDT] AIaaS 마스터클래스 3주차 - Prometheus & Grafana 모니터링 실습

tierr 2025. 4. 11. 17:25

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 &

 

포트포워딩을 통해 로컬에서 접속이 가능해짐:


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" 버튼으로 저장

CPU 사용량 패널

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 버튼 클릭)

Dashboard 메인 > 우측 상단 Settings 버튼

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

Settings 페이지 > Variables 탭

  • 다음과 같이 설정:
    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" 클릭

pod 변수 설정 내용

 

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

pod 변수 생성 완료
파드 선택 드롭다운

 

변수를 활용하기 위해 기존에 작성했던 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]))

pod 변수를 활용하기 위해 CPU 사용량 패널의 쿼리를 수정

 

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

CPU 사용량 패널 (쿼리 수정 후)

알람 설정 기능

Grafana에서 Slack, Discord, Email 등으로 경고알람을 받을 수 있다. 
실제로 적용을 해보진 않고 그냥 이런게 있다정도로만 살펴보고 넘어가겠다.

  1. 패널 편집 모드에서 "Alert" 탭 클릭 > "New alert rule" 버튼 클릭
    패널 편집 창 > Alert 탭 > New alert rule 버튼
  2. [2. Define Query and alert condition] 항목에서 알람 조건 설정이 가능하다. (예: CPU 사용량이 80% 이상일 때)
    어떤 조건에서 알람을 받을지 (Alert Rule) 설정
  3. [5.Configure notifications] 항목에서 알람을 통지할 채널의 설정이 가능하다. (사전에 Alertmanager 설정 필요)
    "view or create contact points" 버튼을 클릭해서 어떤 채널이 설정 가능한지 확인할 수 있다.

Alertmanager - Contact Point 설정

 

대시보드 자동 갱신 설정

데이터는 실시간으로 쌓이지만 대시보드는 실시간으로 변하지 않기 때문에 변화한 내용을 보기 위해서는 새로고침이 필요하다.

  1. 대시보드 메인 우측 상단에서 Refresh 버튼을 클릭해서 대시보드 새로고침 가능
  2. 혹은 자동으로 새로고침하는 간격을 설정할 수 있음 (예: 5s, 10s, 30s, 1m)

대시보드 자동 갱신 설정


5. 추가 팁 - 대시보드 템플릿 가져오기

하나하나 패널을 구성하지 않고, 기존에 만들어져있는 템플릿을 Import 해서 사용할 수도 있다.

  1. 우측 상단 메뉴에서 "+" 버튼 클릭 > 드롭다운 메뉴 "Import dashboard" 선택
    Grafana 우측 상단 메뉴
  2. grafana.com에서 유용한 대시보드 ID 입력 또는 JSON 파일 업로드
    • Kubernetes 모니터링: 315, 6417
    • 노드 모니터링: 1860
    • MySQL 모니터링: 7362

대시보드 ID를 입력하고 Import 하는 과정
Import 된 대시보드 (Kubernetes cluster monitoring)


본 후기는 [카카오엔터프라이즈x스나이퍼팩토리] 카카오클라우드로 배우는 AIaaS 마스터 클래스 (B-log) 리뷰로 작성 되었습니다.