IT/모니터링

Loki structured metadata, 이거 모르면 라벨 카디널리티로 계속 운다

gfrog 2026. 6. 2. 06:11
반응형

라벨 vs structured metadata, 결정 기준

오늘 알게 된 건데, 아직 Loki에서 podtrace_id를 라벨로 박고 계신 분들 꽤 많더라. Loki 3.x부터는 structured metadata가 정식으로 들어왔는데 활용 안 하면 진짜 손해다. 라벨 카디널리티 폭증 없이 검색 가능한 메타데이터를 붙일 수 있는 기능이다.

Loki에서 라벨은 인덱스가 만들어지는 대상이라 카디널리티가 곧 비용이다. namespace, app 같은 저카디널리티 값만 라벨로 두고, trace_id, request_id, pod_name, thread_id 같은 고카디널리티 값은 structured metadata로 옮기는 게 정석이다. Grafana 공식 가이드도 "OpenTelemetry 데이터 ingest를 지원하기 위해 structured metadata를 설계했다"고 명시하고 있다.

문제는 이게 그냥 켜진다고 동작하는 게 아니다. limits_config.allow_structured_metadata: true 를 명시적으로 켜야 하고, 클라이언트(Promtail, Alloy, OTel Collector 등) 쪽에서도 metadata를 따로 보내줘야 한다.

설정 한 토막

Loki 쪽:

limits_config:
  allow_structured_metadata: true
  # 기본 1MB인 ingestion limit도 메타데이터 추가하면 빠르게 찰 수 있다
  per_stream_rate_limit: 5MB

Alloy(또는 Promtail) 쪽에서 Kubernetes pod 이름을 메타데이터로 보내는 예:

loki.process "default" {
  stage.structured_metadata {
    values = {
      pod         = "",
      container   = "",
      trace_id    = "",
    }
  }
  forward_to = [loki.write.default.receiver]
}

핵심은 pod를 라벨에서 빼고 structured_metadata로 보내는 것. 라벨에 그대로 두면 의미가 없다.

LogQL에서는 파이프로 필터링 가능:

{namespace="prod", app="api"} | pod="api-7d4f-xyz" | json

라벨로 박았을 때랑 쿼리 모양은 거의 동일한데, 인덱스 크기와 ingest 비용은 차이가 크다.

한 가지 함정

기존에 운영 중이던 Loki 환경에서 라벨을 metadata로 바꾸려고 했다가 흠칫한 부분. 공식 문서가 친절하게 적어두기를, 가장 쉬운 방법은 Loki를 멈추고 기존 로그 데이터를 다 지우고 처음부터 metadata로 보내는 것이라고 한다. 운영 중인 클러스터에서 이걸 하긴 좀 어렵다. 우리 팀에서는 새로운 테넌트를 만들어서 그쪽으로 점진적으로 옮기는 식으로 했다. 단순히 설정만 바꾸면 끝나는 작업이 아니라는 점 주의.

혹시 더 깔끔한 마이그레이션 방법 쓰시는 분 있으면 댓글로 알려주세요. 아직 우리도 검증 중이다.

반응형