Theory
인프라
Loki 공식 문서 번역
시작하기
레이블 모범 사례

레이블 모범 사례

Grafana Loki는 활발하게 개발 중이며, 성능 향상을 위해 지속적으로 노력하고 있습니다. 하지만 다음은 Loki를 최상의 환경에서 사용하는 데 도움이 될 현재 가장 최신인 레이블 모범 사례입니다.

정적 레이블은 좋습니다

지역, 클러스터, 서버, 애플리케이션, 네임스페이스, 환경과 같은 항목에 레이블을 사용하십시오. 이러한 레이블은 주어진 시스템/앱에 대해 고정되어 있으며 제한된 값을 갖습니다. 정적 레이블을 사용하면 논리적인 의미에서 로그를 더 쉽게 쿼리할 수 있습니다(예: 특정 애플리케이션 및 특정 환경에 대한 모든 로그를 표시하거나 특정 호스트의 모든 앱에 대한 모든 로그를 표시).

동적 레이블은 신중하게 사용하십시오

레이블 값 조합이 너무 많으면 너무 많은 스트림이 생성됩니다. Loki에서 이에 대한 페널티는 큰 인덱스와 저장소의 작은 청크이며, 이는 실제로 성능을 저하시킬 수 있습니다.

이러한 문제를 피하려면 필요하다는 것을 알기 전까지는 레이블을 추가하지 마십시오! 필터 표현식(|= "text", |~ "regex", …)을 사용하고 해당 로그를 무차별 대입(brute force)하십시오. 작동하며 빠릅니다.

쿼리 시 로그 라인에서 레이블을 자주 파싱하고, 레이블의 카디널리티가 높으며, 해당 레이블을 추출하는 데 성능 비용이 많이 드는 경우, 클라이언트 측에서 레이블을 추출하여 로그 라인에 구조화된 메타데이터로 첨부하는 것을 고려하십시오.

초기부터 Promtail 파이프라인을 사용하여 level에 대한 레이블을 동적으로 설정했습니다. level="error"에 대한 로그만 표시하고 싶을 때 직관적으로 보였지만, {app="loki"} |= "level=error" 쿼리를 작성하는 것이 {app="loki",level="error"}만큼 많은 애플리케이션에서 빠른 것으로 입증되어 현재 이를 재평가하고 있습니다.

이것은 놀랍게 보일 수 있지만, 애플리케이션의 볼륨이 중간이거나 낮으면 해당 레이블로 인해 하나의 애플리케이션 로그가 최대 5개의 스트림으로 분할되어 5배의 청크가 저장됩니다. 그리고 청크를 로드하는 데는 오버헤드가 따릅니다. 이제 쿼리가 {app="loki",level!="debug"}라고 상상해보십시오. {app="loki"} != "level=debug"보다 훨씬 더 많은 청크를 로드해야 합니다.

위에서 필요할 때까지 레이블을 추가하지 말라고 언급했는데, 그렇다면 언제 레이블이 필요할까요? 조금 아래에 chunk_target_size에 대한 섹션이 있습니다. 이것을 1MB(합리적인 크기)로 설정하면 압축된 크기가 1MB인 청크를 자르려고 시도하며, 이는 압축되지 않은 로그 약 5MB(압축에 따라 최대 10MB)에 해당합니다. 로그가 max_chunk_age보다 짧은 시간에 5MB를 쓰거나 해당 시간 내에 많은 청크를 쓸 만큼 충분한 볼륨이 있는 경우 동적 레이블을 사용하여 별도의 스트림으로 분할하는 것을 고려할 수 있습니다.

피해야 할 것은 스트림이 유휴 상태이거나 가득 차기 전에 최대 수명에 도달하여 청크가 플러시되는 스트림으로 로그 파일을 분할하는 것입니다. Loki 1.4.0부터 청크가 플러시되는 이유를 이해하는 데 도움이 되는 메트릭이 있습니다: sum by (reason) (rate(loki_ingester_chunks_flushed_total{cluster="dev"}[1m])).

모든 청크가 플러시될 때 가득 차는 것이 중요하지는 않지만, 많은 운영 측면을 개선할 것입니다. 따라서 현재 지침은 동적 레이블을 최대한 피하고 대신 필터 표현식을 선호하는 것입니다. 예를 들어, level 동적 레이블을 추가하지 말고 대신 |= "level=debug"를 사용하십시오.

다음은 Loki와 함께 동적 레이블을 사용하는 몇 가지 모범 사례입니다.

  • 레이블의 카디널리티가 낮도록 하십시오. 이상적으로는 수십 개의 값으로 제한됩니다.
  • HTTP 경로의 초기 세그먼트와 같이 오래 지속되는 값을 가진 레이블을 사용하십시오: /load, /save, /update.
    • 추적 ID 또는 주문 ID와 같은 임시 값을 레이블로 추출하지 마십시오. 값은 동적이 아닌 정적이어야 합니다.
  • 사용자가 쿼리에서 자주 사용할 레이블만 추가하십시오.
    • 아무도 실제로 이러한 레이블을 사용하지 않는 경우 인덱스 크기를 늘리고 로그 스트림을 조각내지 마십시오. 이는 성능을 저하시킵니다.

레이블 값은 항상 제한되어야 합니다

동적으로 레이블을 설정하는 경우 무한하거나 무한한 값을 가질 수 있는 레이블을 절대 사용하지 마십시오. 이는 항상 Loki에 큰 문제를 일으킬 것입니다.

값을 가능한 한 작은 집합으로 제한하십시오. Loki가 처리할 수 있는 것에 대한 완벽한 지침은 없지만, 동적 레이블의 경우 한 자릿수 또는 10개 정도의 값을 생각하십시오. 이는 정적 레이블의 경우 덜 중요합니다. 예를 들어, 환경에 1,000개의 호스트가 있는 경우 1,000개의 값을 가진 host 레이블을 사용하는 것은 괜찮습니다.

일반적으로 Loki의 단일 테넌트는 100,000개 미만의 활성 스트림과 24시간 동안 1백만 개 미만의 스트림을 유지하도록 노력해야 합니다. 이러한 값은 하루에 10TB 이상을 보내는 거대한 테넌트를 위한 것입니다. 테넌트가 10배 작다면 레이블도 10배 이상 적어야 합니다.

클라이언트가 적용하는 동적 레이블에 유의하십시오

Loki에는 Grafana Alloy, Promtail (systemd 저널 수집 및 TCP 기반 syslog 수집도 지원), Fluentd, Fluent Bit, Docker 플러그인 등 여러 클라이언트 옵션이 있습니다.

이들 각각에는 로그 스트림을 만들기 위해 어떤 레이블을 적용할지 구성하는 방법이 있습니다. 하지만 어떤 동적 레이블이 적용될 수 있는지 유의하십시오. Loki 시리즈 API를 사용하여 로그 스트림이 어떻게 생겼는지 파악하고 스트림과 카디널리티를 줄일 수 있는 방법이 있는지 확인하십시오. 시리즈 정보는 시리즈 API를 통해 쿼리하거나 logcli를 사용할 수 있습니다.

Loki 1.6.0 이상에서는 logcli series 명령에 높은 카디널리티 레이블을 디버깅하기 위한 --analyze-labels 플래그가 추가되었습니다.

Total Streams: 25017
Unique Labels: 8

Label Name      Unique Values   Found In Streams
requestId       24653           24979
logStream       1194            25016
logGroup        140             25016
accountId       13              25016
logger          1               25017
source          1               25016
transport       1               25017
format          1               25017

이 예에서 requestId 레이블은 24979개의 스트림에서 24653개의 다른 값을 가졌음을 알 수 있습니다. 이것은 나쁜 경우입니다!

이것은 레이블이 되어서는 안 되는 것의 완벽한 예입니다. requestId는 레이블에서 제거하고 대신 필터 표현식을 사용하여 특정 requestId에 대한 로그를 쿼리해야 합니다. 예를 들어, requestId가 로그 라인에서 key=value 쌍으로 발견되면 다음과 같은 쿼리를 작성할 수 있습니다: {logGroup="group1"} |= "requestId=32422355".

원본: https://grafana.com/docs/loki/latest/get-started/labels/bp-labels/ (opens in a new tab)