Grafana + Loki 실습 치트시트

📋 빠른 참조

환경 정보

Grafana: http://192.168.1.12
계정: admin / admin

Loki URL (Grafana 내부): http://loki.logging.svc.cluster.local:3100

테스트 네임스페이스: demo-app
- log-generator (2 pods)
- web-api (1 pod)

🔍 LogQL 쿼리 실습 (복사해서 사용하세요!)

기초 쿼리

1. 모든 로그 조회

{namespace=~".+"}

2. demo-app 네임스페이스 로그만

{namespace="demo-app"}

3. log-generator Pod 로그만

{namespace="demo-app", pod=~"log-generator.*"}

4. 특정 컨테이너 로그

{namespace="demo-app", container="logger"}

필터링 쿼리

5. ERROR 로그만 필터링

{namespace="demo-app"} |= "ERROR"

6. ERROR 또는 WARN 로그

{namespace="demo-app"} |~ "ERROR|WARN"

7. INFO 로그 제외

{namespace="demo-app"} != "INFO"

8. 대소문자 구분 없이 error 검색

{namespace="demo-app"} |~ "(?i)error"

집계 쿼리 (메트릭 생성)

9. 초당 로그 발생률

rate({namespace="demo-app"}[1m])

10. Pod별 로그 발생률

sum(rate({namespace="demo-app"}[1m])) by (pod)

11. 5분간 ERROR 로그 개수

sum(count_over_time({namespace="demo-app"} |= "ERROR" [5m]))

12. Pod별 ERROR 로그 비율

sum(rate({namespace="demo-app"} |= "ERROR" [5m])) by (pod)

13. 상위 10개 로그 발생 Pod

topk(10, sum(rate({namespace=~".+"}[5m])) by (pod))

고급 쿼리 (파싱 및 추출)

14. 로그 라인 파싱 (패턴 매칭)

{namespace="demo-app"}
| pattern `<_> <_> <level>: <message>`
| level = "ERROR"

15. Regex로 user_id 추출

{namespace="demo-app"}
| regexp "user_id=(?P<user_id>\\d+)"

16. 네임스페이스별 로그 볼륨 (바이트)

sum(bytes_over_time({namespace=~".+"}[5m])) by (namespace)

📊 Grafana Explore 실습 가이드

실습 1: 기본 로그 조회

  1. Grafana → Explore (🧭 아이콘)
  2. Data Source: Loki 선택
  3. 쿼리 입력:
    {namespace="demo-app"}
  4. Run Query 클릭
  5. 시간 범위 조정: Last 15 minutes → Last 5 minutes
  6. Live 모드 활성화: 우측 상단 “Live” 버튼

실습 2: 로그 레벨 필터링

  1. ERROR 로그만 조회:
    {namespace="demo-app"} |= "ERROR"
  2. Show logs 버튼 클릭 (Logs 시각화 확인)
  3. 로그 라인 클릭 → 상세 정보 확인
  4. Filter for value → 추가 필터 적용

실습 3: 메트릭 시각화

  1. 쿼리 입력:
    sum(rate({namespace="demo-app"}[1m])) by (pod)
  2. 시각화 변경: Logs → Time series
  3. 그래프에서 Pod별 로그 발생 추세 확인
  4. Legend 클릭 → 특정 Pod만 표시

실습 4: 에러율 모니터링

  1. Split 버튼 클릭 (쿼리 2개 비교)
  2. 왼쪽 쿼리:
    sum(rate({namespace="demo-app"}[1m]))
  3. 오른쪽 쿼리:
    sum(rate({namespace="demo-app"} |= "ERROR" [1m]))
  4. 두 그래프 비교하여 에러율 파악

📈 대시보드 생성 실습

대시보드 1: 실시간 로그 모니터링

  1. Create → Dashboard → Add new panel
  2. Data Source: Loki

Panel 1: 실시간 로그 스트림

Title: Demo App Logs
Query: {namespace="demo-app"}
Visualization: Logs
Options:
  - Show time: ✅
  - Wrap lines: ✅
  - Dedupe: None

Panel 2: 로그 발생률 (시계열)

Title: Log Rate by Pod
Query: sum(rate({namespace="demo-app"}[1m])) by (pod)
Visualization: Time series
Legend: {{pod}}

Panel 3: ERROR 로그 카운트

Title: Error Count (5min)
Query: sum(count_over_time({namespace="demo-app"} |= "ERROR" [5m]))
Visualization: Stat
Color mode: Value
Graph mode: None

Panel 4: 로그 레벨 분포

Title: Log Level Distribution
Query:
  # TODO(human) - 여기에 로그 레벨별 카운트 쿼리 작성
Visualization: Pie chart
  1. Save Dashboard (💾 아이콘)
    • Name: “Demo App Monitoring”
    • Folder: General

대시보드 2: 변수(Variables) 활용

  1. Dashboard Settings (⚙️) → Variables → Add variable
  2. 변수 설정:
    Name: namespace
    Type: Query
    Data source: Loki
    Query: label_values(namespace)
    
  3. Save
  4. 패널 쿼리 수정:
    {namespace="$namespace"}
  5. 대시보드 상단에서 네임스페이스 선택 가능!

🧪 추가 실습 과제

과제 1: 커스텀 로그 생성

# VM에서 실행
vagrant ssh cp-k8s-1.30.4
 
# 커스텀 로그 생성 Pod
kubectl run custom-logger --image=busybox --restart=Never -- sh -c '
while true; do
  echo "$(date) - Custom log: Transaction ID $(($RANDOM % 10000))";
  sleep 1;
done'
 
# Grafana에서 확인
{pod="custom-logger"}

과제 2: 에러 시뮬레이션

# 집중적인 에러 로그 생성
kubectl run error-bomb --image=busybox --restart=Never -- sh -c '
for i in $(seq 1 100); do
  echo "CRITICAL ERROR: System failure at component-$((i % 5))";
  sleep 0.5;
done'
 
# Grafana 쿼리
{pod="error-bomb"} |= "CRITICAL"
count_over_time({pod="error-bomb"} |= "CRITICAL" [1m])

과제 3: 멀티 Pod 로그 집계

# 3개의 앱 배포
for i in {1..3}; do
  kubectl run app-$i --image=busybox --restart=Never -- sh -c "
  while true; do
    echo 'App-$i: Processing order #$((RANDOM % 1000))';
    sleep 2;
  done"
done
 
# 전체 조회
{pod=~"app-.*"}
 
# 집계
sum(rate({pod=~"app-.*"}[1m])) by (pod)

🎯 실전 시나리오

시나리오 1: 장애 탐지

상황: 특정 시간대에 ERROR가 급증했다는 알림 수신

해결 단계:

  1. Explore에서 시간 범위를 해당 시간대로 설정
  2. 쿼리:
    {namespace="demo-app"} |= "ERROR"
  3. 에러 메시지 패턴 분석
  4. Pod별 에러 분포 확인:
    sum(count_over_time({namespace="demo-app"} |= "ERROR" [5m])) by (pod)

시나리오 2: 성능 분석

상황: API 응답 시간이 느리다는 보고

해결 단계:

  1. 응답 시간 관련 로그 검색:
    {namespace="demo-app"} |~ "response time|timeout"
  2. 느린 요청 필터링:
    {namespace="demo-app"} |~ "response time: [5-9]\\d{2}ms|response time: \\d{4,}ms"

시나리오 3: 보안 이벤트 추적

상황: 인증 실패 로그 모니터링 필요

해결 단계:

  1. 인증 관련 로그:
    {namespace=~".+"} |~ "(?i)auth|login|unauthorized|forbidden"
  2. 실패 횟수 카운트:
    sum(count_over_time({namespace=~".+"} |~ "(?i)failed|unauthorized" [5m])) by (namespace)

🛠️ kubectl 명령어 치트시트

Pod 관리

# 모든 Pod 확인
kubectl get pods -A
 
# demo-app Pod 확인
kubectl get pods -n demo-app
 
# 특정 Pod 로그 보기
kubectl logs -n demo-app <pod-name>
 
# 모든 log-generator Pod 로그
kubectl logs -n demo-app -l app=log-generator
 
# Pod 삭제
kubectl delete pod <pod-name> -n demo-app

Loki/Promtail 관리

# Loki 상태 확인
kubectl get pods -n logging
 
# Loki 로그 확인
kubectl logs -n logging -l app=loki
 
# Promtail 로그 확인 (특정 노드)
kubectl logs -n logging <promtail-pod-name>
 
# Loki API 직접 호출
kubectl exec -n logging -it deploy/loki -- wget -O- http://localhost:3100/ready
kubectl exec -n logging -it deploy/loki -- wget -O- http://localhost:3100/metrics

디버깅

# Loki 서비스 확인
kubectl get svc -n logging loki
 
# DNS 확인
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup loki.logging.svc.cluster.local
 
# Loki 연결 테스트
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- curl http://loki.logging.svc.cluster.local:3100/ready

📚 LogQL 문법 요약

Stream Selector (로그 스트림 선택)

{label="value"}              # 정확히 일치
{label=~"regex"}             # 정규표현식 일치
{label!="value"}             # 일치하지 않음
{label!~"regex"}             # 정규표현식 불일치
{label1="value1", label2="value2"}  # AND 조건

Line Filter (로그 라인 필터)

|= "string"                  # 포함
!= "string"                  # 미포함
|~ "regex"                   # 정규표현식 일치
!~ "regex"                   # 정규표현식 불일치

Parser (로그 파싱)

| json                       # JSON 파싱
| logfmt                     # logfmt 파싱
| pattern `<pattern>`        # 패턴 매칭
| regexp `regex`             # 정규표현식 파싱

Aggregation (집계)

rate({label="value"}[1m])                    # 변화율
count_over_time({label="value"}[5m])         # 개수
bytes_over_time({label="value"}[5m])         # 바이트 합계
sum(rate({label="value"}[1m])) by (label)    # 그룹별 합계
avg(rate({label="value"}[1m])) by (label)    # 그룹별 평균
max(rate({label="value"}[1m])) by (label)    # 그룹별 최대값
topk(10, sum(...) by (label))                # 상위 10개

✅ 학습 체크리스트

기초

  • Grafana 접속 및 Loki 데이터소스 연결
  • Explore에서 기본 로그 조회
  • 시간 범위 조정 및 Live 모드 사용
  • 로그 라인 필터링 (|=, |~)
  • 네임스페이스별 로그 조회

중급

  • LogQL 메트릭 쿼리 작성 (rate, count_over_time)
  • Pod별 로그 집계
  • 대시보드 생성 (최소 3개 패널)
  • 시각화 타입 변경 (Logs, Time series, Stat)
  • 테스트 로그 생성 및 확인

고급

  • 변수(Variables)를 사용한 동적 대시보드
  • 복잡한 정규표현식 필터링
  • 로그 파싱 및 레이블 추출
  • 멀티 쿼리 대시보드 구성
  • 알림 설정 (선택)

🚀 다음 단계

  1. Alert 설정: Grafana에서 로그 기반 알림 구성
  2. Prometheus 통합: 메트릭 + 로그 통합 대시보드
  3. Tempo 추가: 분산 트레이싱 연동
  4. S3 스토리지: Loki 장기 보관 설정
  5. Helm 차트: 프로덕션급 Loki 스택 배포

작성일: 2025-12-17 환경: Kubernetes 1.30.4, Loki 2.9.3, Grafana 10.x