본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

Loki 업그레이드

원문 보기 위키 갱신

Grafana Loki를 업그레이드할 때 알아 두어야 할 주요 변경 사항을 버전별로 정리한 페이지예요. 업그레이드를 계획하고 있다면 시작 전에 꼭 한 번 훑어보시길 권해요.

출처: Loki Documentation

본문

Grafana Loki는 최대한 하위 호환성을 지키려고 노력하고 있어서, 업그레이드는 대체로 위험도도 마찰도 낮은 편이에요.

하지만 Loki도 결국 소프트웨어고, 소프트웨어라는 건 쉽지 않은 법이죠. 그래서 가끔은 사용 편의성과 유지보수 편의성 사이에서 어쩔 수 없는 선택을 해야 할 때도 있어요.

업그레이드가 어려워질 것으로 예상되는 부분이 있다면 그 내용을 이 문서에 정리해 두고 있어요.

릴리스되는 버전이 많아질수록, 여러 버전을 한 번에 건너뛰고 이동할 때 예상치 못한 문제가 생길 가능성이 커져요. 가능하면 최신 상태를 유지하면서 한 단계씩 순차적으로 업그레이드하세요. 버전을 건너뛰고 싶다면 프로덕션을 업그레이드하기 전에 개발 환경에서 먼저 시도해 보세요.

설정 변경 사항 확인하기

도커를 사용한다면 아래와 같은 명령으로 두 버전의 Loki 사이에 어떤 설정 변경이 있는지 확인할 수 있어요:

export OLD_LOKI=2.9.4
export NEW_LOKI=3.0.0
export CONFIG_FILE=local-config.yaml
diff --color=always --side-by-side <(docker run --rm -t -v "${PWD}":/config grafana/loki:${OLD_LOKI} -config.file=/etc/loki/${CONFIG_FILE} -print-config-stderr 2>&1 | sed '/Starting Loki/q' | tr -d '\r') <(docker run --rm -t -v "${PWD}":/config grafana/loki:${NEW_LOKI} -config.file=/etc/loki/${CONFIG_FILE} -print-config-stderr 2>&1 | sed '/Starting Loki/q' | tr -d '\r') | less -R

tr -d '\r' 부분은 대부분의 사람에게는 필요 없을 거예요. WSL2가 윈도우 개행 문자를 몰래 섞어 넣는 일이 있었던 모양이라 들어 있답니다...

출력이 엄청나게 길 수 있어요. Loki를 실행할 때 쓰는 내부 설정 구조체 전체를 보여 주기 때문인데, 변경 사항만 보고 싶거나 다른 스타일의 출력을 원하면 diff 명령 옵션을 적절히 조절해서 써 보세요.

메인 / 미출시 버전

스트림 한도 위임이 테넌트별로 설정 가능해요

스트림 개수 한도를 ingest-limits 서비스에 위임하는 기능이 이제 테넌트별 한도로 바뀌었어요: limits_config.delegate_stream_limits_enabled (-limits.delegate-stream-limits-enabled). 이 설정은 Kafka로 Loki 수집(ingestion)을 운영할 때만 해당돼요.

인게스터 전체에 적용되던 ingester.delegate_stream_limits_enabled (-ingester.delegate-stream-limits-enabled) 설정은 여전히 동작하지만 지원 종료(deprecated) 예정이에요. 이 설정이 테넌트별 한도의 기본값을 제공하기 때문에, 기존 구성이라도 동작은 그대로 유지돼요.

선택 사항: OTLP 속성 확장 지연 처리

기본적으로 Loki는 구조화 메타데이터(structured metadata)로 구성된 OTLP 리소스 및 스코프 속성을 파싱하는 시점에 각 로그 엔트리에 복사해 넣어요.

이 확장을 뒤로 미루고 싶다면 distributor.otlp_config.defer_attribute_expansion를 true로 설정하세요 (-distributor.otlp.defer-attribute-expansion). 그러면 다운스트림 컴포넌트가 실제로 확장된 값을 필요로 할 때까지 디스트리뷰터 처리와 Kafka 쓰기 과정에서 해당 속성들이 공유된 상태로 유지되어, 반복 복사를 줄일 수 있어요. 이 옵션의 기본값은 false예요.

이 옵션을 켜면 Kafka 레코드 포맷도 함께 바뀌어요. 켜기 전에 Kafka에서 로그 레코드를 소비하는 배포된 모든 서비스(partition-ingester, dataobj-builder, logline-index-builder)가 Loki 4.0 이상으로 실행 중인지 확인하세요.

이 옵션을 다시 끄면 파싱 시점 확장으로 돌아가고, 새로운 Kafka 쓰기는 이전 포맷을 따르게 돼요. 옵션이 켜져 있던 동안 기록된 레코드가 Kafka에 남아 있는 동안에는, 소비자들이 Loki 4.0 이상을 유지해야 해요.

선택 사항: 인덱스 게이트웨이 클라이언트 요청 한도

인덱스 게이트웨이 클라이언트는 기본적으로 꺼져 있어 기존 요청 동작을 그대로 유지하는 실험적 한도 두 가지를 지원해요.

-tsdb.shipper.index-gateway-client.max-retries를 0 이상의 값으로 설정하면, 실패한 요청을 이후 몇 개의 인스턴스에 재시도할지 제한할 수 있어요. 기본값 -1은 GetShards 요청에 대해 최대 두 번의 재시도를 유지하고, 다른 요청은 후보 인스턴스 전체에 걸쳐 재시도하는 기존 동작을 그대로 둡니다. 0을 설정하면 재시도가 비활성화돼요. 0 이상의 값은 GetShards를 포함한 모든 요청에 적용되고, 각 후보 인스턴스는 최대 한 번만 시도돼요. 재시도 한도를 켜 두면, 인스턴스가 느리거나 접근 불가능한 상황에서 요청이 고루틴을 오래 붙잡고 있을 수 있는 시간을 제한할 수 있어요.

후보 인스턴스는 링(ring)이나 DNS가 알려 주는 정상(healthy) 인스턴스들이라서, 이미 하트비트에 실패한 인스턴스는 한도에 포함되지 않아요. -index-gateway.shard-size를 기본값 0으로 두면 요청이 인덱스 게이트웨이 전체 풀에서 대상을 고를 수 있어요.

-tsdb.shipper.index-gateway-client.max-in-flight-requests를 양수로 설정하면 진행 중(in-flight) 요청 개수를 제한할 수 있어요. 기본값 0은 이 한도를 끈 상태예요. 한도에 도달한 상태에서 들어온 요청은 HTTP 503 상태로 즉시 실패하고, query-frontend가 다시 시도하게 돼요. 이 한도는 클라이언트별로 적용돼요. Loki는 schema_config의 각 기간(period)마다 클라이언트를 하나씩 만들기 때문에, 프로세스 전체 한도는 이 값 × 클라이언트 수가 됩니다.

frontend.encoding 기본값이 protobuf로 변경

-frontend.encoding / frontend.encoding의 기본값이 json에서 protobuf로 바뀌었어요. 이 값은 query-frontend, query-scheduler, querier 사이의 내부 요청/응답 인코딩에만 영향을 줘요. 클라이언트를 향한 API는 그대로이고, 이 설정을 사용하는 영구 저장 상태도 없으니 데이터 마이그레이션은 필요 없어요.

스케줄러와 쿼리어는 두 인코딩을 모두 이미 받아들이기 때문에, 롤링 업그레이드 중에 프런트엔드 버전이 섞여 있어도 안전해요. 기존 동작을 유지하고 싶다면 frontend.encoding: json으로 명시적으로 설정하세요.

LogQL이 __error__와 __error_details__에 대한 숫자·시간·바이트·ip() 비교를 거부해요

| __error__ > 0, | __error__ != 1s, | __error_details__ == 1MB, | __error__ = ip("1.2.3.4") 같은 쿼리는 이제 파싱에 실패해요. 이 두 레이블은 항상 문자열(또는 값이 없는 상태)을 담기 때문에, 숫자·시간(duration)·바이트·IP 비교로는 매치되는 결과가 있을 수 없거든요. 예전에는 이런 쿼리가 파싱까지는 성공한 뒤 조용히 결과 없이 끝나 버렸어요. 이 규칙은 | unwrap 이후에도 똑같이 적용돼요. 대신 문자열 비교를 사용하세요. 예를 들어 | __error__ != "" 또는 | __error__=""처럼요.

frontend.compress_responses 기본값이 true로 변경

frontend.compress_responses의 기본값이 true로 바뀌었어요. Loki 3.4.0의 버그가 이 값을 의도치 않게 false로 바꿔 놓았던 거예요. query-frontend가 HTTP 응답을 압축하지 않길 원한다면 frontend.compress_responses를 false로 명시적으로 설정하세요.

주요 변경(호환성 깨짐): LogQL variants() 쿼리 제거

실험적이었던 variants() LogQL 표현식은 더 이상 지원되지 않아요.

이 기능을 켜고 끄던 테넌트별 설정 enable_multi_variant_queries (-limits.enable-multi-variant-queries)는 제거됐어요. limits_config나 런타임 오버라이드 파일에 남아 있는 enable_multi_variant_queries: 키는 무시되기 때문에 업그레이드를 막지는 않지만, 가급적 지우는 게 좋아요. deprecated-config-checker 도구가 해당 항목을 표시해 줄 거예요. -limits.enable-multi-variant-queries 커맨드라인 플래그는 더 이상 존재하지 않고, 전달하면 Loki 시작이 실패해요.

선택 사항: 청크 조회 에러 전파

chunk_store_config.propagate_chunk_fetch_errors 설정을 켜면, 불완전한 쿼리 결과를 돌려주는 대신 청크 조회(fetch) 에러를 그대로 반환해요. 이 설정은 기본적으로 비활성화되어 있어요.

주요 변경(호환성 깨짐): row_shards 스키마 설정 제거

schema_config의 period_config에 있던 row_shards 설정이 제거됐어요. 이 설정은 레거시(TSDB 이전) 인덱스 타입을 위한 정적 쿼리 샤드 팩터를 지정하던 값이었어요. 현재 유일하게 지원되는 인덱스 타입인 TSDB는 인덱스 통계를 바탕으로 로그·메트릭 쿼리 샤딩을 동적으로 결정하고 row_shards는 무시하며, 시리즈 쿼리는 기존 기본 팩터인 16을 계속 사용해요. 스키마 설정은 엄격하게 파싱되기 때문에, 남아 있는 row_shards: 키가 있으면 이제 설정 로드가 실패해요. 모든 period_config에서 row_shards 설정을 제거하세요. deprecated-config-checker 도구가 해당 항목을 표시해 줍니다.

TSDB 스키마 v14

Loki에 실험적인 TSDB 스토리지 스키마 v14가 지원되기 시작했어요. v14는 v13과 같은 청크 포맷을 사용하고 TSDB 인덱스 포맷만 바뀌는데, 여기에는 청크별 수집(ingestion) 타임스탬프가 추가돼요. 이 타임스탬프는 수집 시점 보존(retention) 기능에서 사용돼요.

여전히 권장 스키마는 v13이에요. v14를 사용해 보고 싶다면 미래 날짜의 from과 schema: v14를 담은 새 period_config를 추가하세요. 기존 v13 기간에는 아무런 영향이 없어요.

v14 기간을 설정하기 전에, 모든 컴포넌트를 v14 인덱스 포맷을 읽을 수 있는 버전으로 먼저 업그레이드하세요. v14 데이터가 한 번 기록된 뒤에는 이전 바이너리가 v14 인덱스를 읽지 못하기 때문에, 롤백하려면 먼저 새로운 v14 쓰기를 멈춰야 해요.

TSDB head WAL 청크 레코드가 새 바이너리 포맷을 사용해요

인게스터는 TSDB head 쓰기 전용 로그(WAL)에 청크 레코드를 기록할 때, 각 청크의 수집 타임스탬프를 저장하는 새 포맷을 사용해요. TSDB 스키마 v14를 지원하기 위한 변경이에요. Loki가 여전히 이전 포맷을 읽을 수 있기 때문에 업그레이드 때는 별도로 해야 할 일이 없어요. 다만 업그레이드가 끝난 뒤에는 이전에 릴리스된 Loki 버전(3.7.x 이하)은 새 포맷을 읽지 못해요. WAL 리플레이가 error recovering head from TSDB WAL: unknown record type 오류로 실패하는데, Loki는 이를 WAL 손상으로 간주하지 않지만 인게스터 시작은 실패하게 돼요.

새 포맷이 기록된 상태에서 롤백하려면, 이전 바이너리를 시작하기 전에 WAL 데이터를 제거하세요:

  1. 각 인게스터를 정상적으로(gracefully) 종료하세요. 종료가 제대로 되면 청크가 플러시되고, 메모리의 head가 인덱스 파일로 만들어지며, head WAL이 잘려(truncate) 나가서 이전 바이너리는 비어 있는 WAL 디렉터리로 시작하게 돼요.
  2. 인게스터가 그 작업을 마치기 전에 크래시하거나 강제 종료됐다면, head WAL 디렉터리(storage_config.tsdb_shipper.active_index_directory의 wal 하위 디렉터리)를 삭제하세요.

WAL을 삭제하면, 인게스터가 마지막으로 head에서 인덱스를 만든 이후 플러시된 청크들의 인덱스 항목이 사라져요. 그 범위는 최대 한 인덱스 기간(index period)에 이를 수 있어요. 그 청크들은 오브젝트 스토리지에는 그대로 남아 있지만 인덱스가 더 이상 참조하지 않기 때문에, 해당 로그는 쿼리로 조회할 수 없게 돼요.

다른 레플리카들의 인덱스 항목은 같은 로그 데이터를 여전히 커버하고 있어요. 물론 모든 레플리카에서 WAL을 삭제하지 않는다면요.

주요 변경(호환성 깨짐): Thanos 스토리지 클라이언트가 기본으로 사용돼요

storage_config.use_thanos_objstore의 기본값이 false에서 true로 바뀌어서, 별도로 명시하지 않는 한 Thanos 기반 오브젝트 스토어 클라이언트가 기본으로 켜져요.

설정을 마이그레이션하는 방법은 Migrate to Thanos storage clients 문서를 참고하세요.

주요 변경(호환성 깨짐): Simple Scalable Deployment(SSD) 모드 완전 제거

Simple Scalable Deployment(SSD) 모드는 지원 종료되었고 Loki 4.0에서 제거됐어요. write, read, backend 타깃과 -legacy-read-mode 설정 옵션은 더 이상 사용할 수 없고, 사용하면 Loki 시작이 실패해요.

프로덕션에서 최상의 경험을 위해 Loki를 분산(distributed) 모드로 배포하기를 권해요. 배포를 분산 모드로 전환하는 방법은 Migrating from SSD to distributed 가이드를 참고하세요.

고가용성은 여전히 필요하지만 규모가 작은 배포라면, HA 모놀리식(HA Monolithic)으로 전환하는 방법도 있어요. 배포 복잡도가 줄어들거든요. 전환 방법은 Migrate from SSD to HA Monolithic 가이드를 참고하세요.

주요 변경(호환성 깨짐): Ruler가 시작할 때 remote-write WAL을 항상 초기화해요

이제 ruler는 시작할 때 remote-write용 쓰기 전용 로그(WAL) 디렉터리를 삭제(초기화)하고, 각 테넌트를 새로운 빈 WAL로 시작해요. 이전 실행에서 남은 WAL 데이터는 더 이상 리플레이되지 않기 때문에, 재시작 전에 원격 스토리지로 아직 플러시되지 않은 샘플은 버려져요. 녹화 규칙(recording rules)은 시작 후에 다시 평가되고 다시 전송되기 때문에 대체로 안전해요.

그 결과로 다음 항목들이 제거됐어요:

  • -ruler.enable-wal-replay 플래그와 테넌트별 동일 설정인 ruler_enable_wal_replay(limits_config). ruler는 더 이상 WAL을 리플레이하지 않으므로 이 설정들은 아무런 효과가 없어요. 설정에서 제거하세요. deprecated-config-checker 도구가 표시해 줄 거예요.
  • 리플레이나 복구 활동만을 보고하던 ruler WAL 메트릭: loki_ruler_wal_corruptions_total, loki_ruler_wal_corruptions_repair_failed_total, loki_ruler_wal_corruptions_repair_succeeded_total, loki_ruler_wal_replay_duration. 이들을 참조하는 대시보드나 알럿은 정리하세요.

주요 변경(호환성 깨짐): 여러 지원 종료(deprecated) 설정 옵션 제거

  • 테넌트별 ruler remote write 설정들은 limits_config.ruler_remote_write_config로 통합되면서 제거됐어요:
    • limits_config.ruler_remote_write_url
    • limits_config.ruler_remote_write_timeout
    • limits_config.ruler_remote_write_headers
    • limits_config.ruler_remote_write_relabel_configs
    • limits_config.ruler_remote_write_queue_capacity
    • limits_config.ruler_remote_write_queue_min_shards
    • limits_config.ruler_remote_write_queue_max_shards
    • limits_config.ruler_remote_write_queue_max_samples_per_send
    • limits_config.ruler_remote_write_queue_batch_send_deadline
    • limits_config.ruler_remote_write_queue_min_backoff
    • limits_config.ruler_remote_write_queue_max_backoff
    • limits_config.ruler_remote_write_queue_retry_on_ratelimit
    • limits_config.ruler_remote_write_sigv4_config
  • 단일 remote-write client 설정(yaml 파일의 ruler.remote_write.client)은 clients 맵(ruler.remote_write.clients)으로 대체되어 제거됐어요. clients 맵은 id를 키로 삼아 하나 이상의 remote-write 클라이언트를 구성할 수 있게 해 줘요. 업그레이드할 때는 기존 client 설정을 원하는 키를 붙여 clients 아래로 옮기세요.
  • -limits.per-user-override-config(limits_config.per_tenant_override_config)과 -limits.per-user-override-period(limits_config.per_tenant_override_period) 설정은 각각 -runtime-config.file(runtime_config.file), -runtime-config.reload-period(runtime_config.period)로 대체되어 제거됐어요.
  • 테넌트별 설정 unordered_writes가 제거됐어요. 이제 Loki는 항상 순서 없는 쓰기(unordered writes)를 허용해요.
  • -store.index-cache-write 설정(yaml 파일의 chunk_store_config.write_dedupe_cache_config 블록)은 함께 제거된 레거시 스토리지 백엔드에서만 쓰이던 옵션이라 제거됐어요.
  • -store.index-cache-read 설정(yaml 파일의 storage_config.index_queries_cache_config 블록)은 함께 제거된 레거시 스토리지 백엔드(boltdb-shipper)에서만 쓰이던 옵션이라 제거됐어요.
  • -store.index-cache-validity 설정(yaml 파일의 storage_config.index_cache_validity 블록)은 제거된 -store.index-cache-read 설정과 함께 쓰이던 옵션이라 제거됐어요.
  • -store.cache-lookups-older-than 설정(yaml 파일의 chunk_store_config.cache_lookups_older_than)은 함께 제거된 레거시 스토리지 백엔드의 인덱스 항목을 캐시하는 데만 쓰이던 옵션이라 제거됐어요.
  • -store.disable-broad-index-queries 설정(yaml 파일의 storage_config.disable_broad_index_queries)은 함께 제거된 레거시 스토리지 백엔드에서만 쓰이던 옵션이라 제거됐어요.
  • chunks 블록(yaml 파일에서 schema_config의 period_config 아래 chunks:)은 함께 제거된 레거시 스토리지 백엔드의 청크 테이블만 설정하던 옵션이라 제거됐어요. TSDB는 청크를 오브젝트 스토리지에 직접 저장해요. 모든 period_config에서 chunks 블록을 제거하세요.
  • tags 설정(yaml 파일에서 schema_config의 period_config 아래 index 블록에 tags:)은 함께 제거된 레거시 스토리지 백엔드의 관리형(managed) 테이블에만 적용되던 옵션이라 제거됐어요. 모든 period_config에서 tags 설정을 제거하세요.

config.yaml 검증에는 deprecated-config-checker 도구를 활용하세요.

주요 변경(호환성 깨짐): 삭제(deletes)는 컴팩터에서 설정해요

-compactor.allow-deletes 설정 옵션이 제거됐어요. 대신 테넌트별 deletion_mode 옵션을 사용하세요. 이 옵션은 limits_config에서 설정하며 disabled, filter-only, filter-and-delete 중 하나를 고를 수 있어요. filter-only 또는 filter-and-delete로 설정하고 retention_enabled가 true로 되어 있으면, 로그 엔트리 삭제 API 엔드포인트를 사용할 수 있어요.

주요 변경(호환성 깨짐): 메트릭 이름 변경 및 제거

  • 지원 종료됐던 메트릭 loki_log_messages_total은 loki_internal_log_messages_total로 대체되어 제거됐어요.
  • 메트릭 loki_log_flushes는 loki_internal_log_messages_total과 이름을 맞추기 위해 loki_internal_log_flushes로 바뀌었어요.
  • loki_mutated_samples_total과 loki_mutated_bytes_total 메트릭의 두 번째 레이블이 truncated에서 tenant로 바뀌었어요. 이 레이블은 항상 테넌트 ID(불리언이 아님)를 담고 있었기 때문에, 새 이름이 실제 값을 더 정확히 나타내고 loki_discarded_samples_total / loki_discarded_bytes_total 메트릭의 tenant 레이블과도 일관성이 생겨요. 이 메트릭들을 truncated 레이블로 집계하던 대시보드나 알럿이 있다면 tenant를 쓰도록 수정하세요.

주요 변경(호환성 깨짐): jsonnet 라이브러리에서 TSDB 이외 스토어 지원 중단

지원 종료된 스토리지 백엔드가 제거되면서, Loki jsonnet 라이브러리도 이 변화를 반영해 정리됐어요. 영향을 받는 설정 플래그는 다음과 같아요:

  • $._config.using_shipper_store - 모든 사용처는 true를 기본값으로 가정해요
  • $._config.using_boltdb_shipper - 모든 사용처는 false를 기본값으로 가정해요
  • $._config.using_tsdb_shipper - 모든 사용처는 true를 기본값으로 가정해요

이 변경은 커맨드라인 인자와 Loki 설정 양쪽 모두에 반영될 수 있어요. 앞서 언급한 세 가지 설정 옵션 중 하나를 사용하거나 재정의(override)하고 있었다면, 해당 옵션을 제거하고 새 기본값으로 교체하세요.

주요 변경(호환성 깨짐): 지원 종료된 스토리지 백엔드 제거

Loki 3.0에서 레거시 스토리지 백엔드가 지원 종료되었고, 이번에 완전히 제거됐어요:

  • Google BigTable (청크와 인덱스용)
  • Apache Cassandra (청크와 인덱스용)
  • Amazon DynamoDB (인덱스용)
  • gRPC Store (청크와 인덱스용)
  • BoltDB (인덱스용)

스키마나 스토리지 설정에서 지원 종료되어 제거된 스토리지 백엔드를 참조하면 Loki 시작이 실패해요. 위에 나온 백엔드 중 하나라도 아직 사용 중이라면 절대 업그레이드해서는 안 돼요.

스키마를 발전시키는 방법에 대해서는 Storage schema 문서를 참고하세요.

스키마 설정의 마지막 항목이 데이터의 보존 기간보다 오래되었다면, 업그레이드할 때 schema_config.configs에서 오래된 항목을 안전하게 제거할 수 있어요.

레거시 백엔드가 제거되면서 table-manager 타깃과 table_manager 설정 블록도 더 이상 필요 없어져 함께 제거됐어요. config.yaml에 table_manager 설정 블록이 있다면 통째로 제거해도 안전해요.

디스트리뷰터의 비압축 바이트 최대 수신 한도

다음 Loki 릴리스에는 디스트리뷰터가 비압축 스트림 데이터의 최대 수신 크기를 제어할 수 있는 새 설정 옵션(예: -distibutor.max-recv-msg-size)이 도입돼요. 새 옵션의 기본값은 100MB로 설정돼요.

지원되는 클라이언트라면, 해당하는 경우 최대 전송 메시지 크기 설정 옵션도 확인해 보세요.

Ruler WAL 디렉터리가 이제 common.path_prefix를 따라요

common.path_prefix가 설정되어 있다면 이제 기본 -ruler.wal.dir(ruler-wal) 경로가 이 접두어를 반영해 만들어져요. Loki가 이미 경로 계산 방식을 바꿔 둔 다른 기본값들(-ruler.rule-path, -ingester.wal-dir, -compactor.working-directory, -bloom.shipper.working-directory)과 같은 동작이에요. 이전에는 ruler WAL이 cwd 기준의 ruler-wal에 그대로 머물렀고, rootfs가 읽기 전용인 컨테이너에서는 mkdir이 실패했었어요 (#7377).

common.path_prefix를 설정했지만 -ruler.wal.dir을 명시적으로 설정하지 않은 배포에서는, 업그레이드 후 ruler가 <path_prefix>/ruler-wal에 새 WAL 디렉터리를 만들어요. 기존의 cwd 기준 ruler-wal 디렉터리는 마이그레이션되지 않고, 그곳에 버퍼링됐지만 remote-write로 아직 전송되지 않은 녹화 규칙 샘플은 첫 재시작 때 사라져요.

기존 위치를 그대로 유지하고 싶다면, 업그레이드 전에 설정에서 -ruler.wal.dir을 예전 경로(예: ruler-wal 또는 그 절대 경로)로 명시적으로 지정하세요. 이미 -ruler.wal.dir을 명시적으로 설정해 둔 배포라면 영향이 없어요.

Helm 차트 업그레이드

{{< admonition type="note" >}} Grafana-community/helm-charts 저장소로 옮겨 오면서 차트 버전 번호 체계가 바뀌었어요. 메이저 버전 업데이트는 차트에 주요 변경(breaking change)이 있다는 신호예요. 자세한 내용은 README를 참고하세요. {{< /admonition >}}

Loki 저장소 헬름 차트에서 커뮤니티 헬름 차트로 마이그레이션

기존에 Loki 저장소에서 호스팅하던 헬름 차트(차트 버전 6.x)를 사용하다가 Grafana Community 헬름 차트(차트 버전 18.x)로 업그레이드하는 경우, 전용 마이그레이션 가이드를 참고하세요: Upgrade to the Community Helm chart.

헬름 차트 6.50.0 - 사이드카 이미지에서 전역 레지스트리 존중

사이드카 컨테이너에 프라이빗 레지스트리 접두어(sidecar.image.repository)를 붙여 쓰고 있었다면, 이제 그럴 필요가 없어졌어요. 헬름 차트 6.46.1부터 전역 레지스트리(global registry)가 사용되기 때문에 이 방식은 지원 종료됐어요. 대신 global.imageRegistry를 사용하거나, 더 세밀한 제어가 필요하면 sidecar.image.registry를 사용하세요.

헬름 차트 6.50.0 - 사이드카 이미지에서도 이미지 다이제스트(digest) 이름 규칙 통일

헬름 차트에서 쓰이는 대부분의 이미지에는 이미지를 특정 해시로 고정(pin)할 수 있는 .digest가 제공돼요. 사이드카 이미지만 이 규칙에서 벗어나 .tag를 사용하고 있었죠. 헬름 차트 6.46.1부터 .tag는 지원 종료되었고 .digest를 사용해야 해요.

헬름 차트 6.46.0 - 기본 서비스어카운트 이름 변경

{{< admonition type="warning" >}} 헬름 차트 6.46.0에는 **주요 변경(breaking change)**이 있어요. 기본 서비스어카운트 이름을 사용해 AWS EKS Pod Identity, IAM Roles for Service Accounts(IRSA), GCP Workload Identity, Azure Workload Identity 같은 외부 아이덴티티를 바인딩하는 사용자에게 영향을 줘요. {{< /admonition >}}

헬름 차트 6.46.0(#19590)부터, serviceAccount.create가 true이고 serviceAccount.name이 설정되지 않은 경우 기본 서비스어카운트 이름이 차트 name이 아니라 차트의 fullname 템플릿에서 파생돼요. 예를 들면:

배포 6.46.0 이전 기본 서비스어카운트 이름 6.46.0 이상의 기본 서비스어카운트 이름
Grafana Enterprise Logs (GEL) enterprise-logs <release-name>-enterprise-logs
오픈소스 Loki loki <release-name>-loki

EKS Pod Identity나 IRSA를 통한 AWS IAM 역할 같은 외부 아이덴티티가 이전 서비스어카운트 이름에 바인딩되어 있었다면, 업그레이드 후 해당 아이덴티티에 대한 접근 권한을 잃게 돼요. 오브젝트 스토리지 백엔드의 경우 Loki 컴포넌트가 더 이상 버킷을 읽거나 쓰지 못해 일반적으로 장애(outage)로 이어져요.

권장 조치:

기존 동작을 유지하고 이름 변경을 피하려면 values.yaml에서 서비스어카운트 이름을 명시적으로 지정하세요:

serviceAccount:
  name: enterprise-logs   # 오픈소스 배포라면 "loki"를 사용하세요

serviceAccount.name을 명시적으로 지정하는 방식은 상위 버전 호환이 되어 6.46.0 이전과 이후 차트 버전 모두에서 동작해요. 그래서 서비스어카운트 이름을 헬름 릴리스 이름과 무관하게 유지하고 싶다면 앞으로도 이 방식을 권해요.

이미 업그레이드를 마쳤고 파드가 클라우드 프로바이더 IAM 접근 권한을 잃었다면 두 가지 선택지가 있어요:

  • serviceAccount.name을 이전 기본값(예: enterprise-logs)으로 설정하고 helm upgrade를 다시 실행하세요. 기존에 바인딩됐던 외부 아이덴티티가 다시 동작하기 시작해요.
  • 외부 아이덴티티 바인딩(예: EKS Pod Identity 연결 또는 IRSA 신뢰 정책)을 새 서비스어카운트 이름을 참조하도록 업데이트하세요.

헬름 차트 6.34.0 - Zone-aware 인게스터 주요 변경

{{< admonition type="warning" >}} 헬름 차트 6.34.0에는 zone-aware 인게스터 복제를 사용 중인 사용자에게 영향을 주는 **주요 변경(breaking change)**이 있어요. {{< /admonition >}}

zone-aware 인게스터(ingester.zoneAwareReplication.enabled: true)를 사용 중이라면, 헬름 차트 6.34.0으로 업그레이드하기 전에 StatefulSet을 수동으로 삭제해야 해요. zone-aware 인게스터 StatefulSet의 serviceName 필드 수정이 원인인데, 이 필드는 쿠버네티스에서 변경 불가(immutable)한 필드거든요.

자세한 업그레이드 절차는 여기서 확인하세요: Helm Chart 6.x Upgrade Guide - Zone-aware Ingester Breaking Change

핵심 포인트:

  • ingester.zoneAwareReplication.enabled: true로 설정된 배포에만 영향이 있어요
  • --cascade=orphan 옵션을 붙여 StatefulSet을 수동으로 삭제해야 해요
  • 데이터 손실 없음 - PersistentVolumeClaim과 데이터는 그대로 보존돼요
  • 새 StatefulSet은 올바른 서비스 참조로 생성돼요

3.6.0

Loki 3.6.0

AWS SDK v2로 업그레이드

Loki는 S3 오브젝트 스토리지 설정과 통신에 공식 AWS SDK를 사용해요. SDK 버전 1은 2025년 1월 31일에 지원이 종료되어 버전 2로 교체되어야 했어요. 사용자가 접하는 Loki 설정은 바뀌지 않았지만, 오브젝트 스토어 클라이언트의 내부 동작은 바뀌었어요. 물론 Loki 기능 자체에는 영향이 없어요.

변경 사항으로 인해 영향을 받을 수 있는지 자세히 알아보려면 v2의 전체 릴리스 노트 https://github.com/aws/aws-sdk-go-v2/releases/tag/release-2025-01-15를 참고하세요.

3.5.0

Loki 3.5.8

도커 이미지에서 BusyBox 셸 제거

Loki 버전 3.5.8부터 공식 Loki 도커 이미지에서 busybox 유틸리티가 제거됐어요. 즉, 기본적으로 /bin/sh 같은 셸 유틸리티를 컨테이너 안에서 더 이상 사용할 수 없다는 뜻이에요.

영향

  • 이제는 Loki 컨테이너에 exec로 접속해 셸을 쓸 수 없어요. kubectl exec -it podname -- sh나 docker exec -it containername sh 같은 명령은 이미지에 /bin/sh가 없어서 실패해요.
  • BusyBox가 제공하던 흔한 유틸리티(ls, cat, ps 등)도 컨테이너 안에서 쓸 수 없어요.

왜 BusyBox를 제거했나요?

BusyBox 제거는 아래 CVE들을 해결하기 위한 조치예요:

  • CVE-2023-42364
  • CVE-2023-42365
  • CVE-2023-42363
  • CVE-2023-42366
  • CVE-2025-46394
  • CVE-2024-58251

이제 실행 중인 Loki 컨테이너는 어떻게 점검하나요?

Loki 컨테이너를 디버그하거나 점검해야 한다면:

  1. 임시(ephemeral) 컨테이너 사용: 쿠버네티스에서는 (클러스터가 지원한다면) 실행 중인 파드에 셸을 가진 임시 컨테이너를 붙여 디버깅할 수 있어요.
    • 예시:
      kubectl debug -it <pod-name> --image=busybox --target=<container-name>
      
  2. 셸로 접속하는 대신 파일을 복사: 로그나 설정 파일을 꺼내거나 넣으려면 kubectl cp나 docker cp를 사용하세요.
  3. 자체 파생 이미지에 셸 유틸리티 포함: 운영 절차상 셸이 꼭 필요하다면 Loki 기반으로 커스텀 도커 이미지를 빌드해 BusyBox나 다른 셸을 추가할 수 있어요 (프로덕션에서는 권장하지 않아요).
    • Dockerfile 예시 조각:
      FROM grafana/loki:3.5.8
      USER root
      RUN apk add --no-cache busybox
      USER 10001
      

3.4.0

Loki 3.4.0

새 오브젝트 스토리지 클라이언트

Loki 3.4.0 릴리스에는 Thanos Object Storage Client Go 모듈 기반의 새 오브젝트 스토리지 클라이언트가 도입됐어요. 옵트인(opt-in) 기능이에요. 이후 릴리스에서는 스토리지 설정의 기본 방식이 되고 기존 스토리지 클라이언트는 지원 종료될 예정이에요.

새 스토리지 설정은 기존 포맷과 다르게 구성돼요. 지원되는 스토리지 프로바이더와 각 설정 옵션의 전체 목록은 Thanos storage configuration reference에서 확인할 수 있어요.

문서에는 Thanos 기반 스토리지 클라이언트 사용을 위한 마이그레이션 가이드와 설정 예시도 추가되어 있어요.

3.3.0

Loki 3.3.0

실험적 블룸 필터(Bloom Filters)

Loki 3.3.0에서 블룸 블록 포맷이 바뀌어서, 이전에 만들어진 블록은 새 포맷과 호환되지 않아요. 업그레이드 전에 오브젝트 스토어에 있는 기존 블룸 블록을 모두 지우기를 권해요. 블룸 블록과 메타는 설정된 오브젝트 스토리지의 bloom 경로 안에 저장돼요. 블룸 블록을 모두 없애려면 오브젝트 스토리지의 bloom 경로 안의 오브젝트를 모두 삭제하면 돼요.

3.2.0

Loki 3.2.0

HTTP API

인스턴트(instant) 쿼리 API 엔드포인트 /api/v1/query는 이제 query 파라미터에 로그 셀렉터 쿼리가 담겨 들어오면, 일관성 없는 결과를 돌려주는 대신 HTTP 상태 400(Bad Request)을 반환해요. 대신 범위(range) 쿼리 엔드포인트인 /api/v1/query_range(Grafana Explore의 Range 타입)를 사용하세요.

설정

Loki의 -ruler.alertmanager-use-v2 기본값이 false에서 true로 바뀌었어요. Alertmanager APIv1은 Alertmanager 0.16.0에서 지원 종료되었고 0.27.0에서 제거됐어요.

실험적 블룸 필터(Bloom Filters)

{{< admonition type="note" >}} 실험적 기능은 빠르게 바뀌거나 제거될 수 있어서, 마이너 버전 사이에서도 주요 변경(breaking change)이 생길 수 있어요. 또한 일반 기능의 지원 종료(deprecation) 라이프사이클을 따르지 않아요. {{< /admonition >}}

쿼리 가속을 위한 블룸 필터 블록을 만들던 블룸 컴팩터(bloom compactor) 컴포넌트가 제거되고, bloom planner와 bloom builder라는 두 개의 새 컴포넌트로 대체됐어요. 자세한 내용은 Query Acceleration with Blooms 문서를 참고하세요.

이번 변경으로 제거된 테넌트별 설정의 CLI 인자(및 YAML 상응 항목)는 다음과 같아요:

  • -bloom-compactor.enable-compaction
  • -bloom-compactor.shard-size
  • -bloom-compactor.shard-size
  • -bloom-compactor.shard-size

이번 변경으로 다른 접두어로 옮겨진 테넌트별 설정의 CLI 인자는 다음과 같아요:

  • -bloom-compactor.max-page-size → -bloom-builder.max-page-size로 변경
  • -bloom-compactor.max-block-size → -bloom-builder.max-block-size로 변경
  • -bloom-compactor.ngram-length → -bloom-builder.ngram-length로 변경
  • -bloom-compactor.ngram-skip → -bloom-builder.ngram-skip로 변경
  • -bloom-compactor.false-positive-rate → -bloom-builder.false-positive-rate로 변경
  • -bloom-compactor.block-encoding → -bloom-builder.block-encoding로 변경

limits_config 블록의 YAML 상응 항목들은 이름이 그대로 유지돼요.

-bloom-compactor. 접두어를 사용하는 그 외 모든 CLI 인자(및 YAML 상응 항목)는 제거됐어요.

3.0.0

{{< admonition type="note" >}} Loki 3.0으로의 업그레이드에 대해 궁금한 점이 있다면 커뮤니티 Slack의 #loki-3 채널로 와 주세요.

또는 이 GitHub 이슈에 코멘트를 남겨 주세요. {{< /admonition >}}

{{< admonition type="tip" >}} 아직 TSDB로 마이그레이션하지 않았다면, Loki 3.0으로 업그레이드하기 전에 먼저 진행하세요. {{< /admonition >}}

Loki 3.0은 메이저 버전 상승이고 여러 가지 주요 변경(breaking changes)이 함께 온다.

대부분의 사용자가 마주칠 것으로 예상되는 주요 항목은 아래와 같아요:

기존 설정이 Loki 3.0에서 동작하는지 확인해 보고 싶다면:

  1. 컴퓨터의 빈 디렉터리에서 설정을 loki-config.yaml이라는 파일로 복사하세요.
  2. 그 디렉터리에서 아래 명령을 실행하세요:
docker run --rm -t -v "${PWD}":/config grafana/loki:3.0.0 -config.file=/config/loki-config.yaml -verify-config=true

{{< admonition type="note" >}} 새 schema_config 항목을 추가하면 검증 오류가 추가로 발생할 수 있어요. {{< /admonition >}}

{{< admonition type="tip" >}} common 설정 섹션에 path_prefix를 구성하면 설정을 많이 아낄 수 있어요. Common Config Docs를 참고하세요. {{< /admonition >}}

헬름 차트는 상당히 큰 변화를 겪었고 별도의 업그레이드 가이드가 있어요: Upgrading to Helm 6.x.

Loki 3.0.0

{{< admonition type="caution" >}} Loki 2.x에서 3.0으로 소프트웨어를 업그레이드하기 전에, Migrate to TSDB 절차를 먼저 따르세요. {{< /admonition >}}

Structured Metadata, Open Telemetry, 스키마와 인덱스

Loki 3.0의 대표 기능은 OpenTelemetry Protocol(OTLP) 네이티브 지원이에요. 이것은 Loki의 Structured Metadata라는 새 기능 덕분에 가능해졌는데, 레이블이나 로그 라인에는 속하지 않는 메타데이터를 담아 두는 공간이에요. OTel 리소스와 속성은 인덱스에도 로그 라인에도 속하지 않는 데이터의 좋은 예시죠.

Structured Metadata는 Loki 3.0에서 기본으로 켜져 있어요. 다만 현재 사용 중인 스키마가 tsdb 인덱스 타입과 v13 스토리지 스키마를 모두 사용하고 있어야 해요. 둘 중 하나라도 아니라면 두 가지 선택지가 있어요:

  • 3.0으로 업데이트하기 전에 인덱스 버전과 스키마 버전을 먼저 업그레이드하세요. schema config upgrade를 참고하세요.
  • Structured Metadata(그리고 그에 따라 OTLP 지원)를 끈 상태로 3.0으로 업그레이드한 뒤 스키마 마이그레이션을 진행할 수도 있어요. 이렇게 하려면 limits_config 섹션에 allow_structured_metadata: false를 설정하거나 커맨드라인 인자 -validation.allow-structured-metadata=false를 사용하세요.

service_name 레이블

Loki 3.0은 기본으로 수집되는 모든 로그에 service_name 레이블을 자동으로 할당해요. 서비스 이름은 OpenTelemetry 시맨틱 컨벤션이 요구하는 항목이고, Grafana Labs도 향후 사용자 인터페이스와 쿼리 경험에 이를 반영하고 있어요.

Loki는 아래 목록을 순서대로 확인하면서 service_name 레이블을 만들려고 시도해요:

  • service_name
  • service
  • app
  • application
  • name
  • app_kubernetes_io_name
  • container
  • container_name
  • component
  • workload
  • job

목록에서 매치되는 레이블을 찾지 못하면 unknown_service 값이 적용돼요.

limits_config 블록의 discover_service_name에 레이블 목록을 넣어 이 목록을 바꿀 수 있어요.

{{< admonition type="note" >}} 이미 service_label을 사용하고 있다면 Loki가 새로 할당하지 않아요. {{< /admonition >}}

discover_service_name에 빈 값을 주면 이 기능을 끌 수 있어요.

shipper 설정에서 shared_store와 shared_store_key_prefix 제거

TSDB와 BoltDB shipper의 공유 스토어(shared store)를 설정하던 다음 CLI 플래그와 상응하는 YAML 설정이 제거됐어요:

  • -boltdb.shipper.shared-store
  • -tsdb.shipper.shared-store

앞으로는 period_config의 object_store 설정으로 인덱스 스토어를 구성해요. 이로써 주어진 기간(period)의 청크와 인덱스 파일은 반드시 같은 스토리지 버킷에 함께 있게 강제돼요.

스토리지 설정을 단순하게 만들고 잘못 설정할 가능성을 줄이려는 취지에서 공유 스토어 설정을 제거하고 있어요.

{{< admonition type="warning" >}} 이 변경으로 Loki는 더 이상 주어진 기간의 청크와 인덱스를 서로 다른 스토리지 버킷에 나눠 저장할 수 없어요. -boltdb.shipper.shared-store 또는 -tsdb.shipper.shared-store를 period_config의 object_store와 다른 값으로 설정해 청크와 인덱스를 다른 버킷에 저장해 온 구성에는 주요 변경(breaking change)이에요. {{< /admonition >}}

  • -boltdb.shipper.shared-store, -tsdb.shipper.shared-store 또는 상응하는 YAML 설정을 아직 사용하지 않았다면, 업그레이드 때 추가로 할 일은 없어요.
  • -boltdb.shipper.shared-store 또는 그 YAML 설정을 사용해 왔다면:
    • 인덱스 타입이 boltdb-shipper인 모든 기간에서 그 값이 object_store와 일치한다면, 제거된 설정 옵션 사용을 지우는 일 외에는 추가 변경이 필요 없어요.
    • 값이 일치하지 않는다면, -boltdb.shipper.shared-store가 object_store와 다른 기간의 인덱스에는 접근할 수 없게 돼요.
      • 이 인덱스들을 쿼리 가능하게 만들려면, 인덱스 테이블을 object_store에 설정된 스토어로 옮기거나 복사해야 해요.
  • -tsdb.shipper.shared-store 또는 그 YAML 설정을 사용해 왔다면:
    • 인덱스 타입이 tsdb인 모든 기간에서 그 값이 object_store와 일치한다면, 제거된 설정 옵션 사용을 지우는 일 외에는 추가 변경이 필요 없어요.
    • 값이 일치하지 않는다면, -tsdb.shipper.shared-store가 object_store와 다른 기간의 인덱스에는 접근할 수 없게 돼요.
      • 이 인덱스들을 쿼리 가능하게 만들려면, 인덱스 테이블을 object_store에 설정된 스토어로 옮기거나 복사해야 해요.

TSDB와 BoltDB shipper의 경로 접두어를 설정하던 다음 CLI 플래그와 상응하는 YAML 설정이 제거됐어요:

  • -boltdb.shipper.shared-store.key-prefix
  • -tsdb.shipper.shared-store.key-prefix

인덱스 저장 경로 접두어는 이제 period_config의 index 키 아래 path_prefix를 설정해 구성할 수 있어요. 이제 사용자는 새 기간 설정을 추가하는 방식으로 경로 접두어를 바꿀 수 있게 됐죠.

period_config:
  index:
    path_prefix: "index/"
    period: 24h

{{< admonition type="note" >}} path_prefix는 TSDB와 BoltDB 인덱스에만 적용돼요. 이 설정은 레거시 인덱스에는 아무런 영향이 없어요. {{< /admonition >}}

path_prefix의 기본값은 index/로, 제거된 설정들의 기본값과 같아요.

  • -boltdb.shipper.shared-store.key-prefix, -tsdb.shipper.shared-store.key-prefix 또는 상응하는 YAML 설정을 아직 사용하지 않았다면 할 일이 없어요.
  • -boltdb.shipper.shared-store.key-prefix 또는 그 YAML 설정을 index/ 이외의 값으로 사용해 왔다면, boltdb-shipper를 인덱스로 쓰는 기존 모든 기간 설정의 path_prefix가 이전에 설정했던 값으로 되어 있는지 확인하세요.
  • -tsdb.shipper.shared-store.key-prefix 또는 그 YAML 설정을 index/ 이외의 값으로 사용해 왔다면, tsdb를 인덱스로 쓰는 기존 모든 기간 설정의 path_prefix가 이전에 설정했던 값으로 되어 있는지 확인하세요.

compactor 설정에서 shared_store와 shared_store_key_prefix 제거

compactor의 공유 스토어와 경로 접두어를 설정하던 다음 CLI 플래그와 상응하는 YAML 설정이 제거됐어요:

  • -boltdb.shipper.compactor.shared-store
  • -boltdb.shipper.compactor.shared-store.key-prefix

앞으로 compactor는 인덱스 타입이 tsdb 또는 boltdb-shipper인 기간 설정(period configs)에 구성된 모든 오브젝트 스토어에서 컴팩션과 보존(retention) 작업을 수행해요.

delete_request_store는 명시적으로 설정해야 해요

보존(retention) 기능을 켠 경우 -compactor.delete-request-store 또는 그 YAML 설정을 명시적으로 구성해야 해요. 삭제 요청(delete request)을 저장하는 데 필요한 설정이거든요. 삭제 요청이 저장되는 경로 접두어는 -compactor.delete-request-store.key-prefix로 결정되며 기본값은 index/예요.

설정 async_cache_write_back_concurrency와 async_cache_write_back_buffer_size 제거

이 설정들은 cache-config의 Background 설정과 중복되는 항목들이었어요.

async_cache_write_back_concurrency는 writeback_goroutines로 설정할 수 있어요. async_cache_write_back_buffer_size는 writeback_buffer로 설정할 수 있어요.

게다가 Background 설정에는 writeback_size_limit도 있어서, 오브젝트 개수가 아니라 writeback 오브젝트에 사용할 메모리의 최대치를 정할 수도 있어요.

레거시 인게스터 셧다운 핸들러 제거

이미 지원 종료되었던 /ingester/flush_shutdown 핸들러가 제거되고 /ingester/shutdown?flush=true로 대체됐어요.

인게스터 설정 max_transfer_retries 제거

max_transfer_retries 설정(-ingester.max-transfer-retries)은 Write Ahead Log(WAL)로 대체되며 제거됐어요. 이 설정은 롤링 재시작 중 오래된 인게스터가 셧다운될 때, 청크를 새 인게스터로 전송(transfer)할 수 있게 허용하던 기능이었어요. 이 설정의 대안은 다음과 같아요:

  • A. (권장) WAL을 켜고, 새 인게스터가 WAL을 리플레이하도록 맡기세요.
    • 원한다면 flush_on_shutdown(-ingester.flush-on-shutdown)을 켜서 셧다운 시 장기 스토리지로 플러시되게 할 수도 있어요.
  • B. 셧다운할 때 인게스터의 /shutdown?flush=true 엔드포인트를 통해 수동으로 플러시하세요.

런타임 오버라이드 설정 파일의 default 섹션 제거

이 기능은 2.9에서 도입되었고 아마 널리 쓰이지는 않았을 거예요. 런타임 설정 파일로 Loki를 실행하면서 2.9에서 추가된 새 default 블록을 채워 사용하고 있었다면 이 변경의 영향을 받아요.

default 블록은 제거되었고, 대신 표준 Loki 설정에 operational_config라는 최상위 설정이 새로 생겼어요. 여기에서 런타임 설정의 기본값을 지정할 수 있어요.

설정 use_boltdb_shipper_as_backup 제거

use_boltdb_shipper_as_backup 설정(-tsdb.shipper.use-boltdb-shipper-as-backup)은 TSDB 스토리지 개발 과정에서 남겨진 잔재였어요. TSDB가 아직 고도로 실험적이던 시기에 TSDB와 BoltDB 양쪽에 모두 쓸 수 있게 하던 기능이었죠. 이제 TSDB는 안정적이고 권장되는 인덱스 타입이 되었기 때문에, 이 설정은 무의미해져서 제거됐어요. 이전 기본값인 false가 적용돼요.

지원 종료된 설정 옵션들 제거

  1. 이미 지원 종료되었던 store.max-look-back-period CLI 플래그와 상응하는 YAML 설정이 제거됐어요. 대신 querier.max-query-lookback 설정을 사용하세요.
  2. 이미 지원 종료되었던 -querier.engine.timeout CLI 플래그와 상응하는 YAML 설정이 제거됐어요.
  3. querier YAML 섹션의 query_timeout도 제거됐어요. 이제 querier 아래에 query_timeout을 설정하는 대신 Limits Config에서 설정하세요.
  4. s3.sse-encryption이 제거됐어요. 이제 AWS가 모든 버킷의 암호화 기본값을 SSE-S3로 사용해요. SSE 유형 지정은 sse.type을 사용하세요.
  5. ruler.wal-cleaer.period가 제거됐어요. 대신 ruler.wal-cleaner.period를 사용하세요.
  6. experimental.ruler.enable-api가 제거됐어요. 대신 ruler.enable-api를 사용하세요.
  7. query_range YAML 섹션에서 split_queries_by_interval이 제거됐어요. 대신 Limits Config에서 설정할 수 있어요.
  8. frontend.forward-headers-list CLI 플래그와 상응하는 YAML 설정이 제거됐어요.
  9. frontend.cache-split-interval CLI 플래그가 제거됐어요. 결과 캐싱 구간(interval)은 이제 querier.split-queries-by-interval이 결정해요.
  10. querier.worker-parallelism CLI 플래그와 상응하는 YAML 설정이 제거됐어요. 이미 있는 querier.max-concurrent에 별도의 가치를 더하지 않기 때문이에요. querier가 처리하는 최대 동시 요청 수를 제한하려면 querier.max-concurrent를 설정하기를 권해요.
  11. ruler.evaluation-delay-duration CLI 플래그와 상응하는 YAML 설정이 제거됐어요.
  12. validation.enforce-metric-name CLI 플래그와 상응하는 YAML 설정이 제거됐어요.
  13. boltdb.shipper.compactor.deletion-mode CLI 플래그와 상응하는 YAML 설정이 제거됐어요. 대신 compactor.deletion-mode CLI 플래그나 Limits Config의 deletion_mode YAML 설정을 사용하세요.
  14. boltdb.shipper.compactor. 접두어를 사용하는 compactor CLI 플래그들이 제거됐어요. 대신 compactor. 접두어를 쓰는 CLI 플래그를 사용하세요.

디스트리뷰터 메트릭 변경

loki_distributor_ingester_append_failures_total 메트릭이 제거되고 loki_distributor_ingester_append_timeouts_total로 대체됐어요. 새 메트릭은 인게스터에 문제가 있다는 신호를 더 명확히 드러내 주기 때문에, 고신뢰(high-signal) 알럿팅에 활용할 수 있어요.

3.0의 기본 설정값 변경

{{< responsive-table >}}

설정 새 기본값 이전 기본값 비고
compactor.delete-max-interval 24h 0 삭제 요청을 delete_max_interval을 넘지 않는 구간으로 나눠요
distributor.max-line-size 256KB 0 -
ingester.sync-period 1h 0 주어진 스트림의 청크 컷(chunk cut)이 복제 세트의 인게스터들 사이에서 동기화되도록 해요. 청크 중복 제거에 도움이 돼요.
ingester.sync-min-utilization 0.1 0 -
frontend.max-querier-bytes-read 150GB 0 -
frontend.max-cache-freshness 10m 1m -
frontend.max-stats-cache-freshness 10m 0 -
frontend.embedded-cache.max-size-mb 100MB 1GB 임베디드 결과 캐시 크기의 기본값이 이제 100MB예요
memcached.batchsize 4 1024 -
memcached.parallelism 5 100 -
querier.compress-http-responses true false 요청이 gzip 인코딩을 허용하면 응답을 압축해요
querier.max-concurrent 4 10 querier에 더 많은 CPU 자원이 있다면 이 값을 올려 보는 것도 좋아요. 너무 높게 잡으면 메모리 부족(OOM) 오류를 만날 수 있다는 점은 유의하세요.
querier.split-queries-by-interval 1h 30m -
querier.tsdb-max-query-parallelism 128 512 -
query-scheduler.max-outstanding-requests-per-tenant 32000 100 -
validation.max-label-names-per-series 15 30 -
legacy-read-mode false true 지원 종료 예정. 다음 마이너 릴리스에서 제거될 거예요.

{{< /responsive-table >}}

자동 스트림 샤딩이 기본으로 켜져요

자동 스트림 샤딩(automatic stream sharding)은 대용량 스트림의 쓰기 부하를 인게스터들 사이에 골고루 분산시켜 핫스팟(hot-spotting)을 피하게 도와줘요. 자세한 내용은 operations page를 확인하세요.

더 많은 결과 캐싱이 기본으로 켜져요

TSDB 인덱스 타입은 'stats'와 'volume' 쿼리의 결과 캐싱을 지원하는데, 이제 기본으로 켜져 있어요.

'label'과 'series' 요청도 이제 캐시할 수 있고, 역시 기본으로 켜져 있어요.

이 모든 것들은 query_range 설정 섹션에 구성되는 results_cache에 캐시돼요. 기본적으로는 메모리 캐시가 사용돼요.

쓰기 중복 제거(write dedupe) 캐시는 지원 종료

쓰기 중복 제거 캐시는 새로운 단일 스토어 인덱스(TSDB와 boltdb-shipper)에서는 필요하지 않기 때문에 지원 종료됐어요. 레거시 인덱스 타입을 사용 중이라면 Loki 4.0을 쓰려면 TSDB로 마이그레이션해야 해요.

임베디드 캐시 메트릭 변경

  • 다음 임베디드 캐시 메트릭들이 제거됐어요. 대신 loki_cache_fetched_keys, loki_cache_hits, loki_cache_request_duration_seconds를 사용하세요. 이들은 설정된 캐시(embeddedcache, memcached, redis)로 나가는 요청을 계측(instrument)하는 메트릭이에요.

    • querier_cache_added_total
    • querier_cache_gets_total
    • querier_cache_misses_total
  • 다음 임베디드 캐시 메트릭들은 이름이 바뀌었어요:

    • querier_cache_added_new_total → loki_embeddedcache_added_new_total
    • querier_cache_evicted_total → loki_embeddedcache_evicted_total
    • querier_cache_entries → loki_embeddedcache_entries
    • querier_cache_memory_bytes → loki_embeddedcache_memory_bytes
  • 이미 지원 종료되었던 메트릭 querier_cache_stale_gets_total은 이번에 제거됐어요.

메트릭 네임스페이스

일부 Loki 메트릭은 cortex_ 접두어로 시작했어요. 이번 릴리스에서 loki_로 시작하도록 바뀌어요. cortex_를 유지하고 싶다면 metrics_namespace를 기본값 loki에서 cortex로 바꾸세요. 아래 메트릭들이 변경 대상이에요:

  • cortex_distributor_ingester_clients
  • cortex_dns_failures_total
  • cortex_dns_lookups_total
  • cortex_dns_provider_results
  • cortex_frontend_query_range_duration_seconds_bucket
  • cortex_frontend_query_range_duration_seconds_count
  • cortex_frontend_query_range_duration_seconds_sum
  • cortex_ingester_flush_queue_length
  • cortex_kv_request_duration_seconds_bucket
  • cortex_kv_request_duration_seconds_count
  • cortex_kv_request_duration_seconds_sum
  • cortex_member_consul_heartbeats_total
  • cortex_prometheus_last_evaluation_samples
  • cortex_prometheus_notifications_alertmanagers_discovered
  • cortex_prometheus_notifications_dropped_total
  • cortex_prometheus_notifications_errors_total
  • cortex_prometheus_notifications_latency_seconds
  • cortex_prometheus_notifications_latency_seconds_count
  • cortex_prometheus_notifications_latency_seconds_sum
  • cortex_prometheus_notifications_queue_capacity
  • cortex_prometheus_notifications_queue_length
  • cortex_prometheus_notifications_sent_total
  • cortex_prometheus_rule_evaluation_duration_seconds
  • cortex_prometheus_rule_evaluation_duration_seconds_count
  • cortex_prometheus_rule_evaluation_duration_seconds_sum
  • cortex_prometheus_rule_evaluation_failures_total
  • cortex_prometheus_rule_evaluations_total
  • cortex_prometheus_rule_group_duration_seconds
  • cortex_prometheus_rule_group_duration_seconds_count
  • cortex_prometheus_rule_group_duration_seconds_sum
  • cortex_prometheus_rule_group_interval_seconds
  • cortex_prometheus_rule_group_iterations_missed_total
  • cortex_prometheus_rule_group_iterations_total
  • cortex_prometheus_rule_group_last_duration_seconds
  • cortex_prometheus_rule_group_last_evaluation_timestamp_seconds
  • cortex_prometheus_rule_group_rules
  • cortex_query_frontend_connected_schedulers
  • cortex_query_frontend_queries_in_progress
  • cortex_query_frontend_retries_bucket
  • cortex_query_frontend_retries_count
  • cortex_query_frontend_retries_sum
  • cortex_query_scheduler_connected_frontend_clients
  • cortex_query_scheduler_connected_querier_clients
  • cortex_query_scheduler_inflight_requests
  • cortex_query_scheduler_inflight_requests_count
  • cortex_query_scheduler_inflight_requests_sum
  • cortex_query_scheduler_queue_duration_seconds_bucket
  • cortex_query_scheduler_queue_duration_seconds_count
  • cortex_query_scheduler_queue_duration_seconds_sum
  • cortex_query_scheduler_queue_length
  • cortex_query_scheduler_running
  • cortex_ring_member_heartbeats_total
  • cortex_ring_member_tokens_owned
  • cortex_ring_member_tokens_to_own
  • cortex_ring_members
  • cortex_ring_oldest_member_timestamp
  • cortex_ring_tokens_total
  • cortex_ruler_client_request_duration_seconds_bucket
  • cortex_ruler_client_request_duration_seconds_count
  • cortex_ruler_client_request_duration_seconds_sum
  • cortex_ruler_clients
  • cortex_ruler_config_last_reload_successful
  • cortex_ruler_config_last_reload_successful_seconds
  • cortex_ruler_config_updates_total
  • cortex_ruler_managers_total
  • cortex_ruler_ring_check_errors_total
  • cortex_ruler_sync_rules_total

metrics_namespace 설정은 이미 지원 종료 상태예요. 다음 마이너 릴리스에서 제거되고, 그때부터 기본 접두어는 loki가 될 거예요.

LogCLI

원격 스키마를 가져오는 스토어

이전에는 LogCLI가 -remote-schema를 true로 설정하면 -boltdb.shipper.shared-store에 설정된 스토어에서 원격 스키마를 가져왔어요. 원격 스키마를 가져올 스토어를 지정하는 대안으로 새 CLI 플래그 -schema-store가 도입됐어요.

더 읽을거리

Loki 2.x 버전 중 하나에서 업그레이드하려면 Upgrade Loki 2.x versions를 참고하세요.

Loki 1.x 버전 중 하나에서 업그레이드하려면 Upgrade Loki 1.x versions를 참고하세요.