“사용자는 느리다는데, 클러스터는 멀쩡해 보이고, Pod는 자꾸 생겼다가 사라지고… 도대체 어디서부터 봐야 하지?”
Kubernetes 환경에서 서비스 운영을 하다 보면 금방 이런 상황을 맞이하게 됩니다.
예전처럼 서버 몇 대에 SSH로 접속해 로그를 tail 치고, top 명령으로 상태를 보는 방식만으로는 더 이상 원인을 찾기 어렵습니다.
Pod는 언제든지 사라지고, 트래픽은 여러 서비스로 분산되고, 네트워크 hop도 많아졌기 때문입니다.
그래서 Monitoring이라는 개념이 Observability로 확장되었습니다.
단순히 “살아 있냐/죽었냐(Up/Down)”를 넘어서, 지금 시스템이 어떤 상태인지, 이상 징후가 어디에서 시작됐는지, 한 요청이 여러 마이크로서비스를 거치며 어디에서 느려졌는지까지 끝까지 추적할 수 있어야 합니다.
Kubernetes 모니터링/Observability는 보통 세 가지 축으로 이야기합니다.

| 축 | 답하려는 질문 | 데이터 형태 | 주요 사용처 |
|---|---|---|---|
| Metrics | “정상인가?” “얼마나?” | 숫자 시계열 | 대시보드, 알람, 용량/성능 트렌드 |
| Logs | “무슨 일이 있었나?” | 텍스트 이벤트 | 에러 분석, 디버깅, 감사 로그 |
| Traces | “요청이 어디로 흘러갔나?” “어디가 느린가?” | Span/Trace 구조 | 분산 호출 병목 파악, 아키텍처 이해 |
Gateway → Service A → Service B → DB를 지나갈 때의 전체 여정이 세 가지는 서로의 대체재가 아니라,
- Metrics: 탐지(Detection) – “문제가 있다”
- Traces: 위치 추적(Localization) – “어디가 느린가”
- Logs: 원인 분석(Diagnosis) – “왜 그런가”
이렇게 서로 다른 질문에 답하는 역할을 합니다.
실제 장애 상황에서는 보통 이렇게 흐릅니다.
Metrics로 “어? 이상하다”를 감지
→ Traces로 “어디가 느린지” 위치를 좁히고
→ Logs로 “그래서 정확히 왜 그런지”를 파고듦
이 관점을 머리에 두고, 이를 받치는 Observability 아키텍처를 봅니다.
Kubernetes Observability 스택은 보통 아래 4단계 파이프라인으로 정리할 수 있습니다.
/metrics 노출 (Prometheus용)간단한 그림으로 표현하면
Metrics / Logs / Traces vs 4단계
- Collect:
/metrics, stdout/stderr 로그, OTel SDK/Auto-instrumentation- Process: Prometheus/OTel Collector/Fluent Bit가 정제·샘플링
- Store: Prometheus/Thanos, Loki/Elastic, Jaeger/Tempo
- Visualize: Grafana/Kibana/Jaeger UI/Kiali에서 통합 탐색
뒤에서 나올 도구들을 4단계/3축에 매핑하면 대략 이렇게 볼 수 있습니다.
| 단계 \ 축 | Metrics | Logs | Traces |
|---|---|---|---|
| Collect | kube-state-metrics, node-exporter, OTel SDK | Promtail, Fluent Bit, Filebeat | OTel SDK/Auto-instrumentation, Envoy/Istio |
| Process | Prometheus, OTel Collector | Fluent Bit/Fluentd, OTel Collector | OTel Collector, (Istio Telemetry) |
| Store | Prometheus, Thanos/VictoriaMetrics | Loki, Elasticsearch | Jaeger, Tempo, ClickHouse |
| Visualize | Grafana | Grafana, Kibana | Jaeger UI, Grafana, Kiali |

Prometheus 스택은 “Kubernetes에서 지금 정상인가?”를 숫자로 대답해주는 기본 틀입니다.
인프라/클러스터/애플리케이션 상태를 한 번에 수집하고,
대시보드·알람의 기반이 되기 때문에 사실상 표준으로 자리 잡았습니다.
/metrics 엔드포인트를 Pull 방식으로 스크랩즉, Kubernetes 환경에서는
namespace, pod, container, service 라벨을 기반으로 쿼리 작성 가능이 조합으로,
- 인프라 상태(node-exporter)
- Kubernetes 오브젝트 상태(kube-state-metrics)
- 애플리케이션 커스텀 메트릭(/metrics) 를 한 번에 모을 수 있습니다.
실전에서 Prometheus를 쓸 때는 라벨 설계가 핵심입니다.
namespace, app, instance, env, pod, service 정도는모든 메트릭에 공통으로 들어가게 설계해두면 쿼리가 훨씬 단순해집니다.간단한 PromQL 예시를 보면 감이 더 옵니다.
# 네임스페이스별 p95 레이턴시
histogram_quantile(
0.95,
sum(rate(http_server_request_duration_seconds_bucket[5m]))
by (le, namespace)
)
# 서비스별 에러율 (5xx / 전체)
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
Grafana는 “여러 데이터소스를 묶는 관제실 모니터” 역할입니다.
Prometheus, Loki, Tempo, Elastic, ClickHouse 등 다양한 데이터소스를 한 화면에서 볼 수 있어
“Metrics 패널에서 → Logs/Traces로 점프”하는 흐름을 만들기 좋습니다.
왜 필요한가?
Prometheus는 로컬 디스크 기반이라 보관 기간을 너무 길게 가져가면 디스크 터지고,
여러 클러스터/Prometheus 인스턴스를 한 번에 조회하기도 어렵습니다.
운영에서 필요해지는 것은
그래서 Thanos / VictoriaMetrics 같은 솔루션이 Prometheus 앞뒤에 붙어
현실적인 운영 예시
- Prometheus: 최근 7~15일 (상세 데이터)
- Thanos/VictoriaMetrics: 그 이후 기간 전체를 조회 (롤업된 장기 데이터)
user_id, request_id, session_id 같은 값은 라벨로 넣지 않는 것이 원칙appname_subsystem_metricname_unitenv, namespace, app, instancehistogram_quantile 은 recording rule로 미리 계산해두는 패턴이 좋음
kubectl logs)만으로는 과거 기록 유지/검색이 힘듭니다.그래서 “클러스터 전체 로그를 한 곳에 모으고, 라벨로 검색할 수 있는 중앙 로그 스택”이 필요합니다.
/var/log/containers, /var/log/pods 등에서 컨테이너 로그를 읽음→ “어떤 Pod/서비스/네임스페이스에서 나온 로그인지” 메타데이터가 함께 전달됩니다.
장점
즉, Loki는 “Prometheus의 로그 버전” 느낌에 가깝습니다.
라벨을 잘 설계하면, 서비스/네임스페이스/Pod 기준으로 쉽게 Drilling Down 할 수 있습니다.
# prod 네임스페이스의 checkout 서비스 error 로그
{namespace="prod", app="checkout", level="error"}
# payment 서비스의 timeout 관련 로그 검색
{app="payment-service"} |= "timeout"
# 특정 trace_id에 해당하는 모든 로그 조회
{trace_id="abcd-1234-efgh-5678"}
이런 식으로 라벨 필터 + 텍스트 필터를 조합해 사용하는 게 일반적입니다.
최소한 이 정도 라벨은 공통으로 가져가면 운영이 편합니다.
namespace, app, pod, container, envlevel (info/warn/error)trace_id, span_id (Tracing과 연계하는 경우)이 라벨들이 잘 붙어 있으면,
같은 요청을 금방 처리할 수 있습니다.
일반적인 패턴
비즈니스/보안 요구에 따라
- 일반 애플리케이션 로그: 보통 7~30일
- 보안/감사 로그: 수개월~수년까지 별도 보관
로그 스택을 구축할 때는 “얼마나 모을지”뿐 아니라 “무엇을 어떻게 모을지”가 중요합니다.
DEBUG/INFO 로그를 무한정 찍으면 스토리지가 금방 터짐.DEBUG를 끄거나, 샘플링(예: 100건 중 1건) 도입.trace_id/span_id를 남겨두면Tracing은 “한 요청 단위의 스토리”를 보여주는 도구입니다.
“어디서부터 느려졌는지, 어느 hop에서 에러가 났는지”를 직관적으로 보여줍니다.

특징

Kiali는 “서비스 간 트래픽 지도를 그려주는 시각화 툴”입니다.
서비스 메쉬 관점에서 “어느 서비스가 병목인지” 빠르게 보기에 좋습니다.

Grafana와 연동 시, Metrics/Logs/Traces 간 점프가 매우 자연스러워
“한 화면에서 모든 Observability 데이터”를 보는 구성을 만들기 쉽습니다.
기존 구조
OpenTelemetry는 이런 문제를 해결하기 위해 등장한, 벤더 중립 Observability 표준입니다.

즉, 수집/전송 계층을 OpenTelemetry로 표준화하고,
백엔드는 필요에 따라 유연하게 교체/추가할 수 있습니다.
한 가지 예시 아키텍처

OpenTelemetry를 도입할 때, “전 서비스 한 번에 전환”은 현실적으로 어렵습니다.
보통은 아래처럼 단계적 도입을 많이 합니다.
이렇게 가면 리스크를 낮추면서 표준화를 할 수 있고, 도중에 백엔드를 바꿔야 해도 Collector 설정만 손보면 되기 때문에 유연합니다.

왜 여전히 많이 쓰이는가?
장점
단점
요즘 K8s Observability에서는
“전체 스택”이라기보다, “로그 특화 스토어”로 사용하는 경우가 많습니다.
ELK를 “로그만”이 아니라 메트릭까지 포함한 관제로 쓰고 싶다면 보통
Filebeat (로그), Heartbeat(가용성 체크) 등과 함께 조합해서 “Beat → Elasticsearch → Kibana” 파이프라인을 구성즉, ELK 진영에서 Metrics까지 보려면
분산 트레이싱/성능 분석까지 ELK 안에서 해결하려면 Elastic APM을 붙입니다.
구조를 정리하면
Logs -> Filebeat/Logstash -> Elasticsearch -> Kibana(Logs)
Metrics -> Metricbeat -> Elasticsearch -> Kibana(Metrics)
Traces -> Elastic APM Agent -> APM Server -> Elasticsearch -> Kibana(APM)
즉, ELK를 “진짜 Observability 스택”으로 쓰려면
Filebeat + Metricbeat + Elastic APM까지 포함한 구성이 되고,
그만큼 클러스터/스토리지 운영 복잡도와 비용도 함께 올라가는 구조입니다.
포지션
구조

장점
단점/고려사항
“전체 Observability를 하나의 제품/화면에서 보고 싶고,
OpenTelemetry 기반으로 가고 싶다”면 충분히 고려할 수 있는 옵션입니다.
Prometheus+Loki+Tempo 조합, ELK, SigNoz를 간단히 비교하면
| 스택 | 강점 | 약점 | 적합한 케이스 |
|---|---|---|---|
| Prom+Loki+Tempo | K8s 친화, 모듈형, Grafana 연동, 확장성 | 설계/운영 난이도, 처음 셋업 손이 많이 감 | 인프라/플랫폼 팀이 있고 커스터마이징 중시 |
| ELK(+APM) | 텍스트 검색/로그 분석 최강, 에코시스템 풍부 | 리소스/운영 비용 높음, K8s 친화성은 상대적으로 약함 | 로그/검색 위주, 이미 ELK 도입된 조직 |
| SigNoz | OTel-native, All-in-one UI, ClickHouse | 자체 운영 필요, 모듈형 대비 유연성 제한 | 소규모 팀, All-in-one 선호, OTel 도입 초기 |
지금까지 내용을 표로 정리하면
| 축 | 단기 보관 (운영/장애 대응) | 장기 보관 (분석/컴플라이언스) | 대표 솔루션/패턴 |
|---|---|---|---|
| Metrics | Prometheus TSDB (7~15일) | Thanos / VictoriaMetrics + Object Storage | S3/MinIO, GCS 등 |
| Logs | Loki / Elasticsearch (7~30일) | Object Storage tier, ES ILM, Loki chunk 장기 보관 | S3/MinIO, Cold Storage |
| Traces | Jaeger/Tempo (샘플링된 단기 Trace) | Tempo + Object Storage, Jaeger + ES/Cassandra 등 | OTLP + OTel Collector 기반 |
현실적인 포인트
간단한 예시
상황: /checkout API가 특정 시간대에 유난히 느려졌다는 제보
- Metrics (Prometheus + Grafana)
checkout-service의 p95 latency 그래프에서 특정 시간대 스파이크 확인- 같은 시점의 CPU, DB 쿼리 수, 다른 서비스 의존성도 함께 확인
- Traces (Jaeger/Tempo + Kiali/OTel UI)
- 해당 시간대 Trace를 조회
checkout → payment → DB호출 체인 중
DB 호출 구간에서 지연이 집중되어 있는 것을 확인- Logs (Loki/ELK)
- 같은 시점
payment-service로그를 조회- DB 인덱스 미사용 쿼리, 타임아웃, 설정 변경 등의 단서를 로그에서 발견
이런 식으로 Metrics → Traces → Logs 순으로 내려가며
- “문제가 있다”
- “어디가 느린가”
- “왜 그런가”
를 연결하는 것이 Observability의 핵심 흐름입니다.
OpenTelemetry를 도입하면
형태로 위 시나리오를 표준화된 파이프라인으로 구현할 수 있습니다.
현실적인 선택지를 몇 가지 패턴으로 정리해보면
“Kubernetes + OSS로 Observability 환경을 꾸리고 싶다”
- Metrics: Prometheus + Alertmanager + Grafana
- Logs: Loki + Promtail
- Traces: Jaeger 또는 Tempo
- 수집 표준화: OpenTelemetry Collector(선택)
“로그 볼륨이 크고 텍스트 검색/분석이 중요하다”
- Metrics: Prometheus + Grafana
- Logs: ELK (Elastic + Logstash/Beats + Kibana) 또는 Loki+ELK 혼합
- Traces: Jaeger/Tempo, 필요하다면 OTel 기반 추가
“한 제품/한 UI로 M/L/T를 보고 싶다 + OTel 기반”
- 수집/전송: OpenTelemetry SDK + OTel Collector
- 백엔드/뷰어: SigNoz 혹은 상용 APM (Datadog, New Relic 등)
- Kubernetes/비-Kubernetes 환경 통합에 유리
어떤 패턴을 택할지는, 대략 이런 질문에 답해보면 윤곽이 잡힙니다.