Loki 운영 문제 해결하기
이 문서는 설정 문제, 스토리지 백엔드 장애, 클러스터 통신 실패, 서비스 컴포넌트 오류처럼 Loki를 운영하다가 만나는 오류들을 Troubleshooting하는 방법을 안내해요. 별도 문서에서 다루는 수집(쓰기 경로)·쿼리(읽기 경로) 오류와는 다른 범위예요.
본문
이 가이드는 설정 문제, 스토리지 백엔드 장애, 클러스터 통신 실패, 서비스 컴포넌트 오류처럼 Loki 운영 중에 발생하는 오류를 Troubleshooting하는 데 도움을 줘요. 여기서 다루는 오류는 별도의 문제 해결 주제에서 다루는 수집(쓰기 경로) 오류와 쿼리(읽기 경로) 오류와는 구분돼요.
시작하기 전에 다음 항목을 준비했는지 확인하세요:
- Loki 로그와 메트릭에 접근할 수 있어야 해요
- Loki 설정을 조회하고 수정할 수 있는 권한이 있어야 해요
- 배포 토폴로지(단일 바이너리/모놀리식, simple scalable, 마이크로서비스/분산)를 이해하고 있어야 해요
설정 오류
설정 오류는 Loki가 시작할 때나 런타임 설정을 로드할 때 발생해요. 이런 오류가 있으면 Loki가 제대로 시작하지 못하거나 동작하지 않아요.
오류: Multiple config errors found
오류 메시지:
MULTIPLE CONFIG ERRORS FOUND, PLEASE READ CAREFULLY
<list of configuration errors>
원인:
시작 과정에서 여러 개의 설정 검증 오류가 한꺼번에 발견됐어요. Loki는 첫 번째 오류에서 바로 멈추지 않고 모든 설정 오류를 모아서 보여줘요.
해결 방법:
-
나열된 모든 오류를 꼼꼼히 확인하세요. 각 오류 메시지가 특정 설정 문제를 설명해 줘요.
-
설정 파일에 문법 오류나 잘못된 값이 없는지 확인하세요.
-
적용하기 전에 설정을 검증하세요:
loki -config.file=/path/to/config.yaml -verify-config
속성:
- 적용 위치: Loki 시작
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Too many storage configs
오류 메시지:
too many storage configs provided in the common config, please only define one storage backend
원인:
common 설정 섹션에 여러 스토리지 백엔드가 함께 설정돼 있어요. Loki는 common 설정에 스토리지 백엔드를 하나만 둘 것을 요구해요.
해결 방법:
-
common 설정에서는 스토리지 백엔드를 하나만 사용하세요:
common: storage: # Choose only ONE of the following: s3: endpoint: s3.amazonaws.com bucketnames: loki-data # OR gcs: bucket_name: loki-data # OR azure: container_name: loki-data -
여러 스토리지 백엔드가 필요하다면, common 설정 대신 각 섹션에 명시적으로 설정하세요.
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Persist tokens path prefix required
오류 메시지:
if persist_tokens is true, path_prefix MUST be defined
원인:
어떤 ring에서 persist_tokens 옵션이 켜져 있는데 path_prefix가 지정되지 않았어요. Loki는 토큰 파일을 저장할 경로가 필요해요.
해결 방법:
-
경로 접두사를 지정하세요:
common: path_prefix: /var/loki persist_tokens: true ingester: lifecycler: ring: kvstore: store: memberlist tokens_file_path: /var/loki/tokens -
토큰 영속화가 필요 없다면 persist_tokens를 끄세요:
common: persist_tokens: false
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Conflicting gRPC client configs
오류 메시지:
both `grpc_client_config` and (`query_frontend_grpc_client` or `query_scheduler_grpc_client`) are set at the same time. Please use only `query_frontend_grpc_client` and `query_scheduler_grpc_client`
원인:
더 이상 권장되지 않는 grpc_client_config와 새로운 전용 gRPC 클라이언트 설정이 동시에 지정돼 있어요. 이 둘은 함께 쓸 수 없어요.
해결 방법:
-
폐기된 설정을 제거하고 전용 gRPC 클라이언트 설정을 사용하세요:
# Remove this: # grpc_client_config: ... # Use these instead: query_frontend_grpc_client: max_recv_msg_size: 104857600 query_scheduler_grpc_client: max_recv_msg_size: 104857600
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Schema v13 required for structured metadata
오류 메시지:
CONFIG ERROR: schema v13 is required to store Structured Metadata and use native OTLP ingestion, your schema version is <version>. Set `allow_structured_metadata: false` in the `limits_config` section or set the command line argument `-validation.allow-structured-metadata=false` and restart Loki. Then proceed to update to schema v13 or newer before re-enabling this config, search for 'Storage Schema' in the docs for the schema update procedure
원인:
structured metadata가 활성화돼 있는데 현재 스키마 버전이 v13보다 낮아요. structured metadata를 쓰려면 스키마 v13 이상이 필요해요.
해결 방법:
-
structured metadata를 임시로 끄세요:
limits_config: allow_structured_metadata: false -
스키마 설정을 v13 이상으로 업데이트하세요:
schema_config: configs: - from: "2024-04-01" store: tsdb object_store: s3 schema: v13 index: prefix: index_ period: 24h -
스키마 마이그레이션이 끝나면 structured metadata를 다시 켜세요.
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: TSDB index type required for structured metadata
오류 메시지:
CONFIG ERROR: `tsdb` index type is required to store Structured Metadata and use native OTLP ingestion, your index type is `<type>` (defined in the `store` parameter of the schema_config). Set `allow_structured_metadata: false` in the `limits_config` section or set the command line argument `-validation.allow-structured-metadata=false` and restart Loki. Then proceed to update the schema to use index type `tsdb` before re-enabling this config, search for 'Storage Schema' in the docs for the schema update procedure
원인:
structured metadata가 활성화돼 있는데 현재 인덱스 타입이 TSDB가 아니에요. structured metadata에는 TSDB 인덱스 타입이 필요해요.
해결 방법:
-
structured metadata를 임시로 끄고 TSDB 인덱스 타입으로 마이그레이션하세요:
limits_config: allow_structured_metadata: false schema_config: configs: - from: "2024-01-01" store: tsdb object_store: s3 schema: v13 -
TSDB로 마이그레이션한 뒤 structured metadata를 다시 켜세요.
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: TSDB directories not configured
오류 메시지:
CONFIG ERROR: `tsdb` index type is configured in at least one schema period, however, `storage_config`, `tsdb_shipper`, `active_index_directory` is not set, please set this directly or set `path_prefix:` in the `common:` section
또는:
CONFIG ERROR: `tsdb` index type is configured in at least one schema period, however, `storage_config`, `tsdb_shipper`, `cache_location` is not set, please set this directly or set `path_prefix:` in the `common:` section
원인:
스키마에 TSDB 인덱스 타입이 설정돼 있는데, 인덱스 파일에 필요한 로컬 디렉터리가 지정되지 않았어요.
해결 방법:
-
common 경로 접두사를 지정하세요 (가장 간단한 방법이에요):
common: path_prefix: /var/loki -
또는 디렉터리를 명시적으로 설정하세요:
storage_config: tsdb_shipper: active_index_directory: /var/loki/tsdb-index cache_location: /var/loki/tsdb-cache
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Compactor working directory empty
오류 메시지:
CONFIG ERROR: `compactor:` `working_directory:` is empty, please set a valid directory or set `path_prefix:` in the `common:` section
원인:
compactor가 인덱스 압축(compaction)에 쓸 작업 디렉터리를 필요로 하는데, 설정된 디렉터리가 없어요.
해결 방법:
-
common 경로 접두사를 지정하세요:
common: path_prefix: /var/loki -
또는 compactor 작업 디렉터리를 명시적으로 지정하세요:
compactor: working_directory: /var/loki/compactor
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Unrecognized index or store type
오류 메시지:
unrecognized `store` (index) type `<type>`, choose one of: <supported_types>
또는:
unrecognized `object_store` type `<type>`, which also does not match any named_stores. Choose one of: <supported_types>. Or choose a named_store
원인:
스키마 설정에서 Loki가 인식하지 못하는 인덱스 타입이나 오브젝트 스토어 타입을 참조하고 있어요.
해결 방법:
-
지원되는 인덱스 타입을 사용하세요:
tsdb -
지원되는 오브젝트 스토어 타입을 사용하세요:
s3,gcs,azure,swift,filesystem,bos -
또는 설정에 정의된 유효한 named store를 참조하세요:
storage_config: named_stores: aws: my-store: endpoint: s3.amazonaws.com bucketnames: my-bucket schema_config: configs: - from: 2024-01-01 store: tsdb object_store: my-store # References the named store
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Overrides exporter requires runtime configuration
오류 메시지:
overrides-exporter has been enabled, but no runtime configuration file was configured
원인:
overrides-exporter 대상이 활성화됐는데 런타임 설정 파일이 제공되지 않았어요. overrides-exporter는 테넌트별 limit 오버라이드를 메트릭으로 노출하려면 런타임 설정이 필요해요.
해결 방법:
-
런타임 설정 파일을 지정하세요:
runtime_config: file: /etc/loki/runtime-config.yaml -
필요 없다면 대상 목록에서 제거해서 overrides-exporter를 비활성화하세요.
속성:
- 적용 위치: 모듈 초기화
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Invalid override for tenant
오류 메시지:
invalid override for tenant <tenant>: <details>
원인:
런타임 설정 파일에 특정 테넌트에 대한 잘못된 오버라이드가 들어 있어요. 해당 오버라이드가 검증을 통과하지 못했어요.
해결 방법:
- 지정된 테넌트 항목을 기준으로 런타임 설정 파일을 검토하세요.
- limits 설정 스키마를 기준으로 오버라이드 값을 검증하세요.
- 음수 duration, 잘못된 label matcher, 범위를 벗어난 설정 같은 잘못된 값을 고치세요.
속성:
- 적용 위치: 런타임 설정 로더
- 재시도 가능 여부: 아니요 (런타임 설정을 고쳐야 해요)
- HTTP 상태: N/A (런타임 설정 리로드 실패)
- 테넌트별 설정: 예
오류: Retention period too short
오류 메시지:
retention period must be >= 24h was <duration>
원인:
스트림 단위 retention 규칙이 최소 허용치인 24시간보다 짧은 보존 기간을 지정하고 있어요.
해결 방법:
-
보존 기간을 최소 24시간 이상으로 설정하세요:
limits_config: retention_stream: - selector: '{namespace="dev"}' priority: 1 period: 24h # Must be >= 24h
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 예
오류: Invalid query store max look back period
오류 메시지:
it is an error to specify a non zero `query_store_max_look_back_period` value when using any object store other than `filesystem`
원인:
filesystem이 아닌 다른 스토리지 백엔드를 쓰는데 query_store_max_look_back_period가 0이 아닌 값으로 설정돼 있어요. 이 설정은 로컬 파일시스템 스토리지에만 적용돼요.
해결 방법:
-
오브젝트 스토리지를 사용 중이라면 이 설정을 제거하세요:
# Remove or set to 0: query_store_max_look_back_period: 0 -
로컬 개발 환경에서 이 설정이 필요하다면 filesystem 스토리지를 사용하세요.
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
인증 및 테넌트 오류
인증 및 테넌트 오류는 요청에 필수 테넌트 식별 정보가 빠졌거나 테넌트 ID가 잘못됐을 때 발생해요. 멀티 테넌트 모드에서는 모든 요청에 유효한 테넌트 ID가 포함돼야 해요.
오류: No org ID
오류 메시지:
no org id
원인:
필수 X-Scope-OrgID 헤더 없이 Loki에 요청이 들어왔어요. 멀티 테넌트 모드에서는 모든 요청이 테넌트를 식별해야 해요.
해결 방법:
-
요청에
X-Scope-OrgID헤더를 추가하세요:curl -H "X-Scope-OrgID: my-tenant" http://loki:3100/loki/api/v1/push ... -
Grafana에서는 Loki 데이터 소스 설정의 "HTTP Headers"에서 테넌트 ID를 설정하세요.
-
Alloy에서는
loki.write컴포넌트에 테넌트 ID를 지정하세요:loki.write "default" { endpoint { url = "http://loki:3100/loki/api/v1/push" tenant_id = "my-tenant" } } -
단일 테넌트 배포라면 멀티 테넌시를 비활성화하세요:
auth_enabled: false
속성:
- 적용 위치: 인증 미들웨어
- 재시도 가능 여부: 예 (테넌트 ID를 넣으면)
- HTTP 상태: 401 Unauthorized
- 테넌트별 설정: 아니요
오류: Multiple org IDs present
오류 메시지:
multiple org IDs present
원인:
요청에 서로 다른 여러 테넌트 ID가 담겨 있지만, 이 작업에는 테넌트가 하나만 허용돼요. 요청이 여러 프록시를 거치면서 각 프록시가 테넌트 ID를 주입할 때 이런 일이 생길 수 있어요.
해결 방법:
-
X-Scope-OrgID헤더에 테넌트 ID가 하나만 설정돼 있는지 확인하세요. -
테넌트 ID 주입이 충돌하는 프록시 설정을 점검하세요.
-
교차 테넌트 쿼리는 지원되는 위치에서만 파이프로 구분된 테넌트 ID를 사용하세요:
curl -H "X-Scope-OrgID: tenant1|tenant2" http://loki:3100/loki/api/v1/query ...
속성:
- 적용 위치: 테넌트 리졸버
- 재시도 가능 여부: 예 (올바른 테넌트 ID를 넣으면)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Tenant ID too long
오류 메시지:
tenant ID is too long: max 150 characters
원인:
테넌트 ID가 최대 허용 길이인 150자를 초과했어요.
해결 방법:
- 더 짧은 테넌트 ID를 사용하세요 (최대 150자).
속성:
- 적용 위치: 테넌트 검증
- 재시도 가능 여부: 예 (유효한 테넌트 ID를 넣으면)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Unsafe tenant ID
오류 메시지:
tenant ID is '.' or '..'
원인:
테넌트 ID가 . 또는 ..로 설정돼 있어요. 이 값들은 파일시스템 경로 구성 요소로 예약돼 있어서 경로 탐색(path traversal) 문제를 일으킬 수 있어요.
해결 방법:
.이나..가 아닌 다른 테넌트 ID를 선택하세요.
속성:
- 적용 위치: 테넌트 검증
- 재시도 가능 여부: 예 (유효한 테넌트 ID를 넣으면)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Tenant ID contains unsupported character
오류 메시지:
tenant ID '<id>' contains unsupported character '<char>'
원인:
테넌트 ID에 허용되지 않는 문자가 포함돼 있어요. 테넌트 ID는 영숫자, 하이픈, 언더스코어, 마침표로만 구성돼야 해요.
해결 방법:
- 테넌트 ID에는 지원되는 문자만 사용하세요: 영문자, 숫자, 하이픈(
-), 언더스코어(_), 마침표(.).
속성:
- 적용 위치: 테넌트 검증
- 재시도 가능 여부: 예 (유효한 테넌트 ID를 넣으면)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Deletion not available for tenant
오류 메시지:
deletion is not available for this tenant
원인:
어떤 테넌트에 삭제 요청이 제출됐지만 삭제 API 엔드포인트에 접근할 수 없어요. 이런 일은 compactor 설정에서 retention_enabled가 false(기본값)일 때, 또는 해당 테넌트의 deletion_mode 오버라이드가 명시적으로 disabled로 설정됐을 때 발생해요.
해결 방법:
-
삭제 API 엔드포인트의 게이트 역할을 하는 compactor에서 retention을 켜세요:
compactor: retention_enabled: true -
필요하다면 런타임 설정에서 해당 테넌트의 deletion 모드를 오버라이드하세요:
overrides: my-tenant: deletion_mode: filter-and-delete # Or "filter-only"유효한 deletion 모드:
disabled- 삭제가 허용되지 않아요filter-only- 삭제 요청과 일치하는 라인이 쿼리 시점에 필터링되지만 실제로는 삭제되지 않아요filter-and-delete- 라인이 쿼리 시점에 필터링되고 compaction 중에 물리적으로 삭제돼요 (기본값)
-
compactor가 retention을 위해 제대로 설정돼 있는지 확인하세요:
compactor: retention_enabled: true delete_request_store: s3
속성:
- 적용 위치: Compactor 삭제 핸들러
- 재시도 가능 여부: 아니요 (설정을 바꿔야 해요)
- HTTP 상태: 403 Forbidden
- 테넌트별 설정: 예
스토리지 백엔드 오류
스토리지 백엔드 오류는 Loki가 오브젝트 스토리지(Amazon S3, Google Cloud Services, Microsoft Azure, Swift, filesystem)와 통신하거나 제대로 설정하지 못할 때 발생해요.
오류: Unsupported storage backend
오류 메시지:
unsupported storage backend
원인:
지정된 스토리지 백엔드 타입이 인식되지 않아요. 보통 스토리지 타입 설정에 오타가 있을 때 발생해요.
해결 방법:
-
유효한 스토리지 백엔드 타입을 사용하세요:
s3- Amazon S3 또는 S3 호환 스토리지gcs- Google Cloud Storage (구글 클라우드 스토리지)azure- Azure Blob Storage (애저 블롭 스토리지)swift- OpenStack Swiftfilesystem- 로컬 파일시스템bos- Baidu Object Storage (바이두 오브젝트 스토리지)
storage_config: tsdb_shipper: shared_store: s3 # Must be one of the valid types
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Invalid characters in storage prefix
오류 메시지:
storage prefix contains invalid characters, it may only contain digits, English alphabet letters and dashes
원인:
스토리지 경로 접두사에 허용되지 않는 문자가 포함돼 있어요. 영숫자와 대시만 사용할 수 있어요.
해결 방법:
-
스토리지 접두사에 유효한 문자만 사용하세요:
storage_config: # Invalid: prefix_with_underscore_or/special chars # Valid: my-loki-data or lokilogs123 aws: s3: s3://my-bucket/my-loki-data
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Unsupported S3 SSE type
오류 메시지:
unsupported S3 SSE type
원인:
S3 서버 사이드 암호화(SSE) 타입이 지원되지 않아요. Loki는 특정 SSE 타입만 지원해요.
해결 방법:
-
지원되는 SSE 타입을 사용하세요:
storage_config: aws: sse: type: SSE-S3 # Or SSE-KMS지원되는 타입:
SSE-S3- Amazon S3가 관리하는 키를 사용하는 서버 사이드 암호화SSE-KMS- AWS KMS가 관리하는 키를 사용하는 서버 사이드 암호화
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Invalid S3 SSE encryption context
오류 메시지:
invalid S3 SSE encryption context
원인:
SSE-KMS 암호화 컨텍스트가 잘못된 형태라서 유효한 JSON으로 파싱할 수 없어요.
해결 방법:
-
암호화 컨텍스트에 유효한 JSON을 제공하세요:
storage_config: aws: sse: type: SSE-KMS kms_key_id: alias/my-key kms_encryption_context: '{"key": "value"}' # Valid JSON
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Invalid S3 endpoint prefix
오류 메시지:
the endpoint must not prefixed with the bucket name
원인:
S3 엔드포인트에 버킷 이름이 접두사로 잘못 포함돼 있어요. 이러면 path-style과 virtual-hosted-style URL 사이에 문제가 생길 수 있어요.
해결 방법:
-
엔드포인트에서 버킷 이름을 제거하고 별도로 설정하세요:
storage_config: aws: # Incorrect: # endpoint: my-bucket.s3.amazonaws.com # Correct: endpoint: s3.amazonaws.com bucketnames: my-bucket
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Invalid STS endpoint
오류 메시지:
sts-endpoint must be a valid url
원인:
AWS STS(Security Token Service) 엔드포인트 URL이 잘못된 형식이거나 유효하지 않아요.
해결 방법:
-
STS 엔드포인트에 유효한 URL을 제공하세요:
storage_config: aws: sts_endpoint: https://sts.us-east-1.amazonaws.com
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Azure connection string malformed
오류 메시지:
connection string is either blank or malformed. The expected connection string should contain key value pairs separated by semicolons. For example 'DefaultEndpointsProtocol=https;AccountName=<accountName>;AccountKey=<accountKey>;EndpointSuffix=core.windows.net'
원인:
Azure 스토리지 연결 문자열이 없거나 기대하는 형식을 따르지 않아요.
해결 방법:
-
유효한 연결 문자열 형식을 사용하세요:
storage_config: azure: # Use account credentials: account_name: myaccount account_key: mykey # Or connection string: connection_string: "DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=mykey;EndpointSuffix=core.windows.net" -
Azure Portal의 Storage Account > Access Keys에서 연결 문자열을 확인하세요.
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Unrecognized named storage config
오류 메시지:
unrecognized named storage config <name>
특정 백엔드라면:
unrecognized named s3 storage config <name>
unrecognized named gcs storage config <name>
unrecognized named azure storage config <name>
unrecognized named filesystem storage config <name>
unrecognized named swift storage config <name>
인식되지 않는 스토어 타입이라면:
unrecognized named storage type: <storeType>
원인:
스키마 설정에서 참조하는 named storage 설정이 named stores 설정에 존재하지 않아요.
해결 방법:
-
설정에 named store를 정의하세요:
storage_config: named_stores: aws: my-s3-store: # This name must match the reference endpoint: s3.amazonaws.com bucketnames: my-bucket schema_config: configs: - from: 2024-01-01 store: tsdb object_store: my-s3-store # References the named store above -
정의와 참조 양쪽에서 스토어 이름 철자를 확인하세요.
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
캐시 오류
캐시 오류는 Loki가 캐시 백엔드(Memcached, Redis)에 연결하거나 통신하지 못할 때 발생해요.
오류: Redis client setup failed
오류 메시지:
redis client setup failed: <details>
원인:
Loki가 Redis 서버와의 연결을 맺지 못해요. 흔한 원인은 다음과 같아요:
- 잘못된 Redis 엔드포인트
- 네트워크 연결 문제
- 인증 실패
- TLS 설정 문제
해결 방법:
-
Loki 호스트에서 Redis 연결을 확인하세요:
redis-cli -h <REDIS-HOST> -p <REDIS-PORT> ping -
Redis 엔드포인트 설정을 점검하세요:
chunk_store_config: chunk_cache_config: redis: endpoint: redis:6379 timeout: 500ms -
필요하다면 인증을 설정하세요:
chunk_store_config: chunk_cache_config: redis: endpoint: redis:6379 password: ${REDIS_PASSWORD}
속성:
- 적용 위치: 캐시 클라이언트 초기화
- 재시도 가능 여부: 예 (설정을 바로잡으면)
- HTTP 상태: N/A (시작 실패 또는 성능 저하)
- 테넌트별 설정: 아니요
오류: Could not lookup Redis host
오류 메시지:
could not lookup host: <hostname>
원인:
Redis 호스트 이름의 DNS 조회가 실패했어요.
해결 방법:
-
DNS 조회를 확인하세요:
nslookup redis-host -
DNS를 쓸 수 없다면 IP 주소를 사용하세요:
chunk_store_config: chunk_cache_config: redis: endpoint: 10.0.0.100:6379 -
DNS 설정과 네트워크 설정을 점검하세요.
속성:
- 적용 위치: DNS 조회
- 재시도 가능 여부: 예
- HTTP 상태: N/A
- 테넌트별 설정: 아니요
오류: Unexpected Redis PING response
오류 메시지:
redis: Unexpected PING response "<response>"
원인:
Redis 서버가 PING 명령에 예상 밖의 응답을 돌려줬어요. 다음 가능성이 있어요:
- 해당 엔드포인트가 Redis 서버가 아니에요
- 프록시나 로드 밸런서가 방해하고 있어요
- Redis가 오류 상태에 있어요
해결 방법:
-
해당 엔드포인트가 실제 Redis 서버인지 확인하세요.
-
Redis 상태를 확인하세요:
redis-cli -h <HOST> -p <PORT> INFO -
Redis 앞에 로드 밸런서를 두고 있다면 프록시 설정을 검토하세요.
속성:
- 적용 위치: Redis 헬스 체크
- 재시도 가능 여부: 예
- HTTP 상태: N/A
- 테넌트별 설정: 아니요
오류: Multiple cache systems not supported
오류 메시지:
use of multiple cache storage systems is not supported
원인:
같은 캐시 타입에 Memcached와 Redis 캐시 백엔드가 둘 다 설정돼 있어요. 캐시 타입마다 캐싱 백엔드는 하나만 지원돼요.
해결 방법:
-
캐시 타입마다 캐시 백엔드를 하나만 선택하세요:
chunk_store_config: chunk_cache_config: # Use either memcached OR redis, not both redis: endpoint: redis:6379 memcached: {} # Remove this
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: No cache configured
오류 메시지:
no cache configured
원인:
query frontend에 결과 캐시가 필요한데 캐시 설정이 제공되지 않았어요.
해결 방법:
-
캐시 백엔드를 설정하세요:
query_range: results_cache: cache: memcached: expiration: 1h memcached_client: addresses: memcached:11211 -
필요 없다면 결과 캐싱을 비활성화하세요:
query_range: cache_results: false
속성:
- 적용 위치: Query frontend 초기화
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Error loading cache generation numbers
오류 메시지:
msg="error loading cache generation numbers" err="unexpected status code: 403"
compactor HTTP 클라이언트에서는:
msg="error getting cache gen numbers from the store" err="unexpected status code: 403"
메트릭: loki_delete_cache_gen_load_failures_total
원인:
Loki는 로그 삭제 요청이 처리될 때 쿼리 캐시를 무효화하기 위해 캐시 세대 번호(cache generation numbers)를 사용해요. 캐시 세대 번호 로더는 이 번호들을 주기적으로 compactor에서 가져오는데, compactor가 HTTP 403을 돌려주면 해당 테넌트에 삭제 API가 활성화되지 않았다는 뜻이에요. 로더는 이 오류를 기록하고 loki_delete_cache_gen_load_failures_total 메트릭을 증가시켜요.
403이 아닌 다른 원인으로는 다음이 있어요:
- compactor에 접근할 수 없어요 (네트워크 또는 DNS 문제)
- compactor가 실행 중이 아니거나 준비되지 않았어요
- querier와 compactor 사이의 TLS 또는 인증 설정이 잘못됐어요
해결 방법:
-
삭제가 의도적으로 비활성화된 건 아닌지 확인하세요. 이 테넌트에서 로그 삭제를 쓰지 않는다면 이 오류는 무해하지만 시끄러워요. compactor의 캐시 세대 번호 엔드포인트로 GET 요청을 보내 확인할 수 있어요:
curl -s -H "X-Scope-OrgID: <tenant>" http://compactor:3100/loki/api/v1/cache/generation_numbers응답이
"deletion is not available for this tenant"라면 해당 테넌트에 삭제 API가 활성화되지 않은 거예요. -
로그 삭제가 필요하다면 해당 테넌트에 삭제를 활성화하세요:
overrides: <tenant>: deletion_mode: filter-and-delete -
오류에 403이 아닌 상태 코드나 연결 오류가 포함돼 있다면 compactor 연결을 점검하세요:
curl -s http://compactor:3100/ready -
캐시 세대 번호 로더를 사용하는 querier와 다른 컴포넌트가 compactor에 도달할 수 있도록 compactor 주소가 올바르게 설정돼 있는지 확인하세요:
compactor: compactor_address: http://compactor:3100
속성:
- 적용 위치: 캐시 세대 번호 로더 (
GenNumberLoader) - 재시도 가능 여부: 예 (로더가 5분마다 자동으로 재시도해요)
- HTTP 상태: N/A (백그라운드 프로세스, 요청 시점 오류가 아니에요)
- 테넌트별 설정: 예 (테넌트 오버라이드의
deletion_mode로 설정)
Ring 및 클러스터 통신 오류
Ring 오류는 Loki 컴포넌트들이 작업을 인스턴스들에 분산하는 데 쓰이는 해시 ring을 통해 제대로 통신하지 못할 때 발생해요. Ring은 Loki의 분산 동작에 필수적인 요소예요.
오류: Too many unhealthy instances in the ring
오류 메시지:
too many unhealthy instances in the ring
원인:
Ring에 비정상 인스턴스가 너무 많아서 복제 계수를 충족할 수 없어요. 예를 들어 복제 계수가 3이면 최소 3개의 정상 인스턴스가 사용 가능해야 해요.
해결 방법:
-
ring 멤버들의 상태를 확인하세요:
curl -s http://loki:3100/ring | jq '.shards[] | select(.state != "ACTIVE")' -
나쁜 상태에 멈춰 있는 비정상 인스턴스를 재시작하세요.
-
정상 멤버가 부족하다면 인스턴스를 스케일 업하세요.
-
비정상 인스턴스의 리소스 제약(CPU, 메모리, 디스크)을 확인하세요.
속성:
- 적용 위치: Ring 복제
- 재시도 가능 여부: 예 (인스턴스가 회복되면)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: Empty ring
오류 메시지:
empty ring
원인:
Ring에 등록된 인스턴스가 하나도 없어요. 보통 클러스터 초기 시작 중에 발생하는데, 예를 들어 ingester가 OOM 크래시를 일으키는 경우나 설정이 잘못된 경우에 생겨요.
해결 방법:
-
초기 시작 중에는 인스턴스들이 등록될 때까지 기다리세요.
-
ingester가 실행 중인지 확인하세요.
-
모든 인스턴스가 설정된 포트로 통신할 수 있는지 확인하세요.
-
모든 컴포넌트에서 ring 설정을 검증하세요. 특히 memberlist 설정이 중요해요:
ingester: lifecycler: ring: kvstore: store: memberlist replication_factor: 3 -
KV 스토어 상태를 확인하세요 (Consul, etcd, memberlist):
# For memberlist curl -s http://loki:3100/memberlist
속성:
- 적용 위치: Ring 연산
- 재시도 가능 여부: 예 (인스턴스가 등록되면)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: Instance not found in the ring
오류 메시지:
instance <id> not found in the ring
원인:
Ring에 있어야 할 특정 인스턴스가 등록되어 있지 않아요. 재시작 후 인스턴스가 아직 ring에 다시 합류하지 못했을 때 발생할 수 있어요.
해결 방법:
- 인스턴스가 ring에 다시 등록될 때까지 기다리세요.
- ring 합류 실패가 있는지 인스턴스 로그를 확인하세요.
- 해당 인스턴스에서 KV 스토어 연결을 검증하세요.
속성:
- 적용 위치: Ring 연산
- 재시도 가능 여부: 예 (인스턴스가 등록되면)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: Instance owns no tokens
오류 메시지:
this instance owns no tokens
원인:
인스턴스가 ring에는 합류했지만 아직 토큰을 하나도 확보하지 못했어요. 토큰이 없으면 인스턴스는 아무 작업도 받을 수 없어요. 다음 경우에 발생할 수 있어요:
- 인스턴스가 아직 시작 중이에요
- 토큰 클레임이 실패했어요
- KV 스토어 업데이트가 전파되지 않았어요
해결 방법:
-
시작 중에는 토큰 할당을 기다리세요.
-
인스턴스의 ring 상태를 확인하세요: 브라우저를 열고 http://localhost:3100/ring으로 이동하세요. Loki Ring Status 페이지가 보여야 해요.
또는
curl -s http://loki:3100/ring -
시작이 끝난 뒤에도 토큰이 할당되지 않는다면 인스턴스를 재시작하세요.
-
KV 스토어 연결과 상태를 확인하세요.
속성:
- 적용 위치: Lifecycler 준비 상태 검사
- 재시도 가능 여부: 예 (토큰이 할당되면)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: Error talking to the KV store
오류 메시지:
error talking to the KV store
원인:
인스턴스가 ring 상태에 사용되는 키-값 스토어와 통신하지 못해요. KV 스토어(Consul, etcd, memberlist)는 ring 조정에 필수예요.
해결 방법:
-
KV 스토어의 상태와 연결을 확인하세요:
# For Consul curl http://consul:8500/v1/status/leader # For etcd etcdctl endpoint health -
Loki 인스턴스들과 KV 스토어 사이의 네트워크 연결을 검증하세요.
-
KV 스토어 포트의 트래픽을 방화벽 규칙이 허용하는지 확인하세요.
-
memberlist라면 모든 인스턴스 사이에서 gossip 포트에 접근 가능한지 확인하세요:
memberlist: bind_port: 7946 join_members: - loki-memberlist:7946
속성:
- 적용 위치: Ring lifecycler
- 재시도 가능 여부: 예 (KV 스토어가 회복되면)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: No ring returned from the KV store
오류 메시지:
no ring returned from the KV store
원인:
KV 스토어가 응답했지만 비어 있거나 잘못된 ring 디스크립터를 돌려줬어요. KV 스토어가 최근에 초기화됐거나 데이터가 지워진 경우에 생길 수 있어요.
해결 방법:
- 첫 시작 중에는 ring 초기화를 기다리세요.
- KV 스토어 데이터가 실수로 지워지지 않았는지 확인하세요.
- KV 스토어가 초기화됐다면 ring에 다시 등록하도록 모든 ring 멤버를 재시작하세요.
속성:
- 적용 위치: Ring lifecycler
- 재시도 가능 여부: 예 (ring이 초기화되면)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: Failed to join memberlist cluster
오류 메시지:
failed to join memberlist cluster on startup
또는:
joining memberlist cluster failed
원인:
인스턴스가 memberlist gossip 클러스터에 합류하지 못했어요. 흔한 원인:
- 시드 노드에 도달할 수 없어요
- join 주소의 DNS 조회가 실패했어요
- 방화벽이 gossip 포트를 막고 있어요
- 기존 멤버가 모두 내려가 있어요
해결 방법:
-
join 멤버에 도달 가능한지 확인하세요:
# Test connectivity to seed nodes nc -zv loki-memberlist 7946 -
join 주소의 DNS 조회를 검증하세요:
nslookup loki-memberlist -
memberlist 설정을 점검하세요:
memberlist: bind_port: 7946 join_members: - loki-gossip-ring.loki.svc.cluster.local:7946 -
방화벽 규칙이 gossip 포트(기본값 7946)의 UDP와 TCP 트래픽을 허용하는지 확인하세요.
-
Kubernetes라면 memberlist용 headless service가 올바르게 설정돼 있는지 검증하세요.
속성:
- 적용 위치: Memberlist KV 클라이언트
- 재시도 가능 여부: 예 (백오프를 두고 자동 재시도)
- HTTP 상태: N/A (시작 실패 또는 성능 저하)
- 테넌트별 설정: 아니요
오류: Re-joining memberlist cluster failed
오류 메시지:
re-joining memberlist cluster failed
원인:
memberlist 클러스터에서 연결이 끊긴 후 인스턴스가 다시 합류하지 못했어요. 네트워크 파티션이나 긴 네트워크 문제 이후에 발생할 수 있어요.
해결 방법:
- 클러스터 멤버들 사이의 네트워크 연결을 확인하세요.
- 다른 클러스터 멤버들이 정상인지 검증하세요.
- 자동 재합류가 계속 실패하면 영향을 받은 인스턴스를 재시작하세요.
- 네트워크 안정성을 검토하세요. 잦은 재합류는 근본적인 네트워크 문제를 의미해요.
속성:
- 적용 위치: Memberlist KV 클라이언트
- 재시도 가능 여부: 예 (자동 재시도)
- HTTP 상태: N/A (성능 저하)
- 테넌트별 설정: 아니요
컴포넌트 준비 상태 오류
준비 상태 오류는 Loki 컴포넌트가 요청을 처리할 준비가 되지 않았을 때 발생해요. 이런 오류는 /ready 헬스 체크 엔드포인트가 돌려주며, 로드 밸런서가 준비되지 않은 인스턴스로 트래픽을 보내지 않도록 막아줘요.
오류: Application is stopping
오류 메시지:
Application is stopping
원인:
Loki가 종료 중이라 새 요청을 더 이상 받지 않아요. 우아한 종료(graceful shutdown) 과정에서는 정상적인 현상이에요.
해결 방법:
- 롤링 업데이트 중이라면 인스턴스가 재시작되길 기다리세요.
- 종료가 예상된 것인지 확인하세요 (유지보수, 스케일 다운).
- 종료가 예상 밖이라면 오케스트레이터 로그를 검토하세요 (Kubernetes, systemd).
속성:
- 적용 위치: Loki 준비 상태 핸들러
- 재시도 가능 여부: 예 (재시작 후)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: Some services are not running
오류 메시지:
Some services are not Running:
<state>: <count>
<state>: <count>
예를 들면:
Some services are not Running:
Starting: 1
Failed: 2
원인:
하나 이상의 Loki 내부 서비스가 시작에 실패했거나 예기치 않게 멈췄어요. 오류 메시지는 각 서비스 상태와 해당 상태의 서비스 개수를 나열해요.
해결 방법:
- 나열된 서비스의 오류가 있는지 Loki 로그를 확인하세요.
- 영향을 받은 서비스의 설정을 검증하세요.
- 리소스 가용성을 확인하세요 (메모리, 디스크, CPU).
- 서비스가 멈춰 있다면 인스턴스를 재시작하세요.
속성:
- 적용 위치: Loki 서비스 매니저
- 재시도 가능 여부: 예 (서비스가 회복되면)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: Ingester not ready
오류 메시지:
Ingester not ready: <details>
ingester 자신의 상태 검사가 실패하면 <details>에 ingester 상태가 담겨서 전체 메시지는 이렇게 돼요:
Ingester not ready: ingester not ready: <state>
여기서 <state>는 서비스 상태예요. 예를 들어 Starting, Stopping, Failed 같은 값이에요.
원인:
ingester가 쓰기를 받거나 읽기를 처리할 준비 상태가 아니에요. 상세 메시지가 구체적인 이유를 알려줘요. 예를 들면:
- ingester가 아직 시작 중이고 ring에 합류하는 중이에요 (
Starting) - lifecycler가 준비되지 않았어요 (lifecycler 오류 텍스트)
- ingester가 ring 합류 후 최소 준비 시간을 기다리고 있어요
해결 방법:
-
시작이 끝나길 기다리세요 - ingester가 ring에 합류하고 준비되려면 시간이 걸려요.
-
ring 멤버십을 확인하세요: 브라우저를 열고 http://localhost:3100/ring으로 이동하세요. Loki Ring Status 페이지가 보여야 해요.
또는
curl -s http://ingester:3100/ring -
시작 오류가 있는지 로그를 검토하세요.
-
시작이 너무 느리다면 최소 준비 시간을 조정하세요:
ingester: lifecycler: min_ready_duration: 15s
속성:
- 적용 위치: Ingester 준비 상태 검사
- 재시도 가능 여부: 예 (ingester가 준비되면)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: No queriers connected to query frontend
오류 메시지:
Query Frontend not ready: not ready: number of queriers connected to query-frontend is 0
원인:
query frontend에 연결된 querier 워커가 없어요. querier가 없으면 frontend는 어떤 쿼리도 처리할 수 없어요. 보통 다음 경우에 발생해요:
- querier가 아직 시작되지 않았어요
- querier가 frontend에 도달하지 못해요
- querier와 frontend 사이에 gRPC 연결 문제가 있어요
해결 방법:
-
querier가 실행 중이고 정상인지 확인하세요.
-
querier 설정이 올바른 frontend 주소를 가리키는지 검증하세요:
frontend_worker: frontend_address: query-frontend:9095 -
querier와 frontend 사이의 gRPC 연결을 확인하세요:
# Test gRPC port connectivity nc -zv query-frontend 9095 -
연결 오류가 있는지 querier 로그를 검토하세요.
속성:
- 적용 위치: Query frontend (v1) 준비 상태 검사
- 재시도 가능 여부: 예 (querier가 연결되면)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: No schedulers connected to frontend worker
오류 메시지:
Query Frontend not ready: not ready: number of schedulers this worker is connected to is 0
원인:
query frontend 워커가 어떤 query scheduler에도 활성 연결을 갖고 있지 않아요. 이러면 frontend가 쿼리를 디스패치할 수 없어요.
해결 방법:
-
query scheduler가 실행 중이고 정상인지 확인하세요.
-
scheduler 주소 설정을 검증하세요:
frontend_worker: scheduler_address: query-scheduler:9095 -
frontend와 scheduler 사이의 gRPC 연결을 확인하세요.
-
오류가 있는지 query scheduler 로그를 검토하세요.
속성:
- 적용 위치: Query frontend (v2) 준비 상태 검사
- 재시도 가능 여부: 예 (scheduler가 연결되면)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
gRPC 및 메시지 크기 오류
gRPC 오류는 컴포넌트 간 통신 중에 발생해요. Loki 컴포넌트들은 ring 조정, 쿼리 실행, 데이터 전송에 gRPC를 사용해요.
오류: Message size too large
오류 메시지:
message size too large than max (<size> vs <max>)
압축 해제된 본문이라면:
decompressed message size too large than max (<size> vs <max>)
원인:
distributor로 향하는 HTTP push 요청의 압축 본문 또는 압축 해제된 본문이 설정된 한도를 초과했어요.
기본 설정:
distributor.max_recv_msg_size: 100MB (압축된 요청 본문 한도)distributor.max_decompressed_size: 5000MB (압축 해제된 본문 한도, 기본값은max_recv_msg_size의 50배)
해결 방법:
-
distributor 수신 메시지 크기 한도를 늘리세요:
distributor: max_recv_msg_size: 209715200 # 200MB compressed max_decompressed_size: 10737418240 # 10GB decompressed -
로그 수집 클라이언트(Alloy 등)에서 push 배치 크기를 줄여서 개별 요청을 더 작게 보내세요.
-
클라이언트의 배치 크기나 flush 간격을 낮춰서 요청당 데이터 양을 줄이세요.
속성:
- 적용 위치: Distributor push 핸들러
- 재시도 가능 여부: 아니요 (요청을 줄이거나 한도를 늘려야 해요)
- HTTP 상태: 413 Request Entity Too Large (압축), 400 Bad Request (압축 해제)
- 테넌트별 설정: 아니요
오류: Response larger than max message size
오류 메시지:
response larger than the max message size (<size> vs <max>)
원인:
querier에서 frontend로 가는 쿼리 결과가 허용된 최대 gRPC 응답 크기를 초과했어요. 아주 큰 결과 집합을 돌려주는 쿼리에서 주로 발생해요.
기본 설정:
server.grpc_server_max_send_msg_size: 4MB (querier의 gRPC 서버 송신 한도)querier.query_frontend_grpc_client.max_recv_msg_size: 100MB (querier 워커의 gRPC 클라이언트 수신 한도)
해결 방법:
-
결과가 더 적게 나오도록 쿼리 범위를 줄이세요:
- 더 구체적인 label matcher를 추가하세요
- 시간 범위를 줄이세요
- entries limit을 낮추세요
-
필요하다면 gRPC 메시지 크기 한도를 늘리세요. 이 설정은 querier 노드에 적용하세요:
server: grpc_server_max_send_msg_size: 209715200 # 200MB querier: query_frontend_grpc_client: max_recv_msg_size: 209715200 # 200MB
속성:
- 적용 위치: Querier 워커
- 재시도 가능 여부: 아니요 (쿼리 범위나 한도를 바꿔야 해요)
- HTTP 상태: 413 Request Entity Too Large
- 테넌트별 설정: 아니요
오류: Compressed message size exceeds limit
오류 메시지:
compressed message size <size> exceeds limit <limit>
원인:
HTTP push 요청의 압축 본문이 distributor의 설정 한도를 초과했어요. 이 검사는 요청 본문을 전부 읽은 후에 실행되고, 압축된 전체 크기를 설정된 최댓값과 비교해요.
기본 설정:
distributor.max_recv_msg_size: 100MB
해결 방법:
-
로그 수집 클라이언트에서 배치 크기를 줄이세요.
-
큰 배치를 더 작고 자주 보내는 요청으로 분할하세요.
-
필요하다면 한도를 늘리세요:
distributor: max_recv_msg_size: 209715200 # 200MB
속성:
- 적용 위치: Distributor push 핸들러
- 재시도 가능 여부: 아니요 (요청을 줄여야 해요)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
TLS 및 인증서 오류
TLS 오류는 인증서 문제로 Loki나 그 클라이언트가 보안 연결을 맺지 못할 때 발생해요.
오류: TLS certificate loading failed
오류 메시지:
error loading ca cert: <path>
또는:
error loading client cert: <path>
또는:
error loading client key: <path>
또는:
failed to load TLS certificate <cert_path>,<key_path>
원인:
Loki가 지정된 경로에서 TLS 인증서를 로드하지 못해요. 흔한 원인:
- 설정된 경로에 인증서 파일이 존재하지 않아요
- 권한 문제로 파일을 읽을 수 없어요
- 인증서나 키 형식이 잘못됐어요
- 인증서와 키가 서로 맞지 않아요
해결 방법:
-
인증서 파일이 존재하고 읽을 수 있는지 검증하세요:
ls -la /path/to/cert.pem /path/to/key.pem /path/to/ca.pem -
파일 권한을 확인하세요 (Loki 프로세스가 읽을 수 있어야 해요).
-
인증서 형식을 검증하세요:
openssl x509 -in /path/to/cert.pem -noout -text openssl rsa -in /path/to/key.pem -check -
인증서와 키가 서로 맞는지 확인하세요:
openssl x509 -noout -modulus -in cert.pem | md5sum openssl rsa -noout -modulus -in key.pem | md5sum # Both should produce the same hash -
TLS 설정을 확인하세요:
server: http_tls_config: cert_file: /path/to/cert.pem key_file: /path/to/key.pem client_ca_file: /path/to/ca.pem grpc_tls_config: cert_file: /path/to/cert.pem key_file: /path/to/key.pem client_ca_file: /path/to/ca.pem
속성:
- 적용 위치: TLS 설정
- 재시도 가능 여부: 아니요 (인증서를 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: TLS configuration error
오류 메시지:
error generating http tls config: <details>
또는:
error generating grpc tls config: <details>
<details>에는 TLS version %q not recognized, cipher suite %q not recognized, unknown TLS version: <version> 같은 메시지가 포함될 수 있어요.
원인:
TLS 설정이 유효하지 않아요. 다음 경우에 발생할 수 있어요:
- 지원되지 않는 TLS 버전 문자열이 들어왔어요
- cipher suite 설정이 잘못됐어요
- client auth 타입이 인식되지 않아요
해결 방법:
-
호환성 문제가 있는지 TLS 설정을 검토하세요.
-
server블록의 최상위에tls_min_version을 지정해서 지원되는 TLS 버전을 사용하세요:server: tls_min_version: VersionTLS12유효한 값은
VersionTLS10,VersionTLS11,VersionTLS12,VersionTLS13이에요.max_version설정은 없고,tls_min_version이 유일한 버전 제약이에요. -
커스터마이즈했다면 cipher suite 설정을 확인하세요.
속성:
- 적용 위치: TLS 초기화
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
DNS 조회 오류
DNS 오류는 Loki가 서비스 디스커버리나 백엔드 연결을 위해 호스트 이름을 조회하지 못할 때 발생해요.
오류: DNS lookup timeout
오류 메시지:
msg="failed to resolve server addresses" err="... DNS lookup timeout: [<address>] ..."
원인:
Loki의 서비스 디스커버리나 백엔드 연결을 위한 주소를 조회하려다 DNS 조회가 5초 제한 시간을 초과했어요.
이 오류는 index gateway와 bloom gateway의 DNS 디스커버리 루프에서 발생해요.
DNS lookup timeout: [<address>] 문자열은 err 필드 안에 포함된 context cause예요. 전체 주소 목록은 Go 슬라이스 형식으로 표현돼요 (예: [dns+loki-index-gateway.loki.svc.cluster.local:9095]).
해결 방법:
-
DNS 서버 가용성과 설정을 확인하세요.
-
호스트 이름 조회를 검증하세요:
nslookup <hostname> dig <hostname> -
DNS가 불안정하다면 임시 방편으로 IP 주소를 사용하세요:
# Instead of dns+hostname:port memberlist: join_members: - 10.0.0.1:7946 - 10.0.0.2:7946 -
Kubernetes라면 CoreDNS가 정상이고 headless service가 올바르게 설정돼 있는지 확인하세요.
속성:
- 적용 위치: Index gateway 클라이언트, bloom gateway 클라이언트 DNS 디스커버리 루프
- 재시도 가능 여부: 예 (DNS가 회복될 수 있어요)
- HTTP 상태: N/A (연결 실패)
- 테넌트별 설정: 아니요
Scheduler 및 frontend 오류
이 오류들은 쿼리 스케줄링, frontend 워커, 큐 관리와 관련돼 있어요.
오류: Scheduler is not running
오류 메시지:
scheduler is not running
원인:
query scheduler 서비스가 실행 상태가 아니에요. 다음 경우에 발생할 수 있어요:
- scheduler가 시작 중이에요
- scheduler가 치명적인 오류를 만났어요
- scheduler가 종료 중이에요
해결 방법:
-
시작 오류나 크래시가 있는지 scheduler 로그를 확인하세요.
-
scheduler 상태를 검증하세요:
curl -s http://scheduler:3100/ready -
ring 기반 스케줄링을 사용한다면 scheduler ring 멤버십을 확인하세요:
curl -s http://scheduler:3100/ring | jq
속성:
- 적용 위치: Scheduler 서비스
- 재시도 가능 여부: 예 (scheduler가 준비되기를 기다리세요)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
오류: Too many outstanding requests
오류 메시지:
too many outstanding requests
원인:
쿼리 큐가 최대 용량에 도달했어요. 시스템이 쿼리로 과부하 상태라는 뜻이에요.
해결 방법:
-
쿼리를 더 빨리 처리하도록 querier를 스케일 아웃하세요:
querier: max_concurrent: 10 -
큐 용량을 늘리세요 (신중하게). 기본값은
32000이고, 시스템이 추가 부하를 감당할 수 있음을 확인한 경우에만 그 이상으로 늘리세요.tsdb_max_query_parallelism을 크게 잡으면 생성되는 서브쿼리 수가 많아지기 때문에 큐를 늘려야 하는 경우가 흔해요. 일반적으로 querier를 더 추가하고 이 설정은 그대로 두는 편이 좋아요.query_scheduler: max_outstanding_requests_per_tenant: 64000 -
클라이언트나 로드 밸런서 수준에서 쿼리에 rate limit을 적용하세요.
-
큐 대기 시간을 줄이도록 느린 쿼리를 최적화하세요.
속성:
- 적용 위치: Query scheduler/frontend
- 재시도 가능 여부: 예
- HTTP 상태: 429 Too Many Requests
- 테넌트별 설정: 아니요
오류: Querying is disabled
오류 메시지:
querying is disabled, please contact your Loki operator
원인:
쿼리 병렬도가 0으로 설정돼서 모든 쿼리가 사실상 비활성화됐어요. 보통 유지보수 중 의도적으로 이렇게 하는 거예요.
해결 방법:
-
인덱스 타입에 맞는 병렬도 설정을 확인하세요. TSDB 인덱스(현재 기본값)에서는
tsdb_max_query_parallelism이max_query_parallelism을 대체해요. 어느 값이든 0이면 이 오류가 발생해요. 둘 다 0보다 큰지 확인하세요:limits_config: max_query_parallelism: 32 # default; applies to non-TSDB schemas tsdb_max_query_parallelism: 128 # default; applies to TSDB schemas -
tsdb_max_query_parallelism을 수집 볼륨에 맞게 조정하세요. 프로덕션에서 흔한 값은 하루 수집되는 로그 볼륨에 비례해서 128–2048 범위예요:하루 수집 볼륨 일반적인 값 낮음–중간 128–256 높음 512 하루 수십 TB 1024–2048 -
이에 필요한 querier 용량을 고려하세요. 병렬도 단위 하나가 querier 워커 슬롯 하나를 소비해요. 기본값
querier.max_concurrent가4일 때 하나의 쿼리를 완전히 병렬화하는 데 필요한 querier 수는:queriers needed = tsdb_max_query_parallelism / max_concurrent예를 들어
tsdb_max_query_parallelism: 2048에max_concurrent: 4라면 하나의 쿼리를 완전히 병렬로 돌리는 데 512개의 querier가 필요해요. 여러 테넌트가 동시에 큰 쿼리를 돌리는 프로덕션 배포는 흔히 수천 개의 querier를 운영해요. -
이 설정을 바꿀 권한이 없다면 관리자에게 문의하세요.
속성:
- 적용 위치: Query frontend
- 재시도 가능 여부: 아니요 (설정을 바꿔야 해요)
- HTTP 상태: 429 Too Many Requests
- 테넌트별 설정: 예
오류: No frontend address
오류 메시지:
no frontend address
원인:
scheduler가 frontend로부터 요청을 받았지만 응답을 돌려보낼 frontend 주소가 제공되지 않았어요.
해결 방법:
-
주소가 설정돼 있는지 frontend 설정을 확인하세요:
frontend: address: query-frontend:9095 -
frontend와 scheduler 사이의 gRPC 연결을 검증하세요.
속성:
- 적용 위치: Scheduler
- 재시도 가능 여부: 아니요 (설정 문제)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Scheduler shutting down
오류 메시지:
scheduler is shutting down
원인:
frontend scheduler 워커가 scheduler가 종료 모드에 들어가서 새 요청을 받을 수 없음을 감지했어요.
해결 방법:
- 종료가 끝나고 scheduler가 재시작되길 기다리세요.
- 예상된 것인지 확인하세요 (롤링 업데이트, 유지보수).
- scheduler가 정상화된 뒤 요청을 재시도하세요.
속성:
- 적용 위치: Scheduler
- 재시도 가능 여부: 예 (scheduler 재시작 후)
- HTTP 상태: 503 Service Unavailable
- 테넌트별 설정: 아니요
Index gateway 오류
Index gateway 오류는 querier가 인덱스 조회를 위해 index gateway와 통신하지 못할 때 발생해요.
오류: Index gateway unhealthy in ring
오류 메시지:
index-gateway is unhealthy in the ring
원인:
index gateway 인스턴스가 ring에서 자신을 비정상으로 판단하고 쿼리 처리를 거부했어요. 이건 자기 점검이에요. 테넌트 요청을 처리하기 전에 게이트웨이는 자신이 정상 ring 멤버 집합에 포함돼 있는지 확인해요.
해결 방법:
-
index gateway 상태를 확인하세요:
curl -s http://index-gateway:3100/ready -
ring 상태를 확인하세요: 브라우저를 열고 http://localhost:3100/ring으로 이동하세요. Loki Ring Status 페이지가 보여야 해요.
또는
curl -s http://index-gateway:3100/ring -
게이트웨이가 정상 상태가 되지 못하게 하는 오류가 있는지 로그를 확인하세요.
-
비정상 상태에 멈춰 있다면 index gateway를 재시작하세요.
속성:
- 적용 위치: Index gateway ring
- 재시도 가능 여부: 예 (게이트웨이가 정상되기를 기다리세요)
- HTTP 상태: 500 Internal Server Error
- 테넌트별 설정: 아니요
오류: No index gateway instances found
오류 메시지:
no index gateway instances found for tenant <tenant>
원인:
해당 테넌트의 요청을 처리할 수 있는 index gateway 인스턴스가 ring에 없어요. 다음 가능성이 있어요:
- 모든 index gateway가 비정상이에요
- shuffle sharding이 이 테넌트를 제외했어요
- ring이 비어 있어요
해결 방법:
-
실행 중인 index gateway가 있는지 확인하세요:
curl -s http://index-gateway:3100/ring | jq '.shards | length' -
shuffle sharding을 사용한다면 ring 모드가 설정돼 있는지 검증하세요. index gateway는
ring모드로 실행되어야 하고 테넌트별 shard size가 설정되어야 해요:index_gateway: mode: ring limits_config: index_gateway_shard_size: 3 # default = 0 (use all instances) -
필요하다면 index gateway를 스케일 업하세요.
속성:
- 적용 위치: Index gateway 클라이언트
- 재시도 가능 여부: 예
- HTTP 상태: 500 Internal Server Error
- 테넌트별 설정: 예 (
limits_config의index_gateway_shard_size로 설정)
Compactor 및 retention 오류
Compactor 오류는 인덱스 compaction이나 retention 적용 중에 발생해요.
오류: No chunks found in table
오류 메시지:
no chunks found in table, please check if there are really no chunks and manually drop the table or see if there is a bug causing us to drop whole index table
원인:
compactor가 retention 처리 중에 비어 있는 인덱스 테이블을 발견했어요. 다음 가능성이 있어요:
- 테이블의 모든 청크가 만료됐어요
- 테이블이 한 번도 채워지지 않았어요
- 데이터 손상이 있어요
해결 방법:
-
테이블이 비어 있어야 하는 게 맞는지 검증하세요:
# Check if data exists for the time period logcli query '{job=~".+"}' --from="<table-start-time>" --to="<table-end-time>" --limit=1 -
테이블이 정당하게 비어 있다면 오브젝트 스토리지에서 수동으로 삭제하세요.
-
데이터가 있어야 한다면 잠재적인 데이터 손실을 조사하세요.
속성:
- 적용 위치: Compactor retention
- 재시도 가능 여부: 아니요 (수동 개입이 필요해요)
- HTTP 상태: N/A (백그라운드 프로세스)
- 테넌트별 설정: 아니요
오류: Delete request store not configured
오류 메시지:
compactor.delete-request-store should be configured when retention is enabled
원인:
retention이 활성화됐는데 삭제 요청을 추적할 스토어가 설정되지 않았어요.
해결 방법:
-
삭제 요청 스토어를 설정하세요:
compactor: retention_enabled: true delete_request_store: s3 -
필요 없다면 retention을 비활성화하세요:
compactor: retention_enabled: false
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Max compaction parallelism invalid
오류 메시지:
max compaction parallelism must be >= 1
원인:
compactor의 병렬도 설정이 0이나 음수로 되어 있어요.
해결 방법:
-
유효한 병렬도 값을 설정하세요:
compactor: max_compaction_parallelism: 1 # Must be >= 1
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Delete request not found
오류 메시지:
could not find delete request with given id
원인:
삭제 요청을 취소하려고 시도했지만 일치하는 요청이 존재하지 않아요.
해결 방법:
-
기존 삭제 요청을 나열해 보세요:
curl -s http://compactor:3100/loki/api/v1/delete | jq -
삭제 요청 ID가 올바른지 확인하세요.
-
요청이 이미 처리되고 제거됐는지 확인하세요.
속성:
- 적용 위치: Compactor API
- 재시도 가능 여부: 아니요
- HTTP 상태: 404 Not Found
- 테넌트별 설정: 아니요
오류: Retention is not enabled
오류 메시지:
Retention is not enabled
원인:
삭제 요청이 제출됐지만 compactor 설정에서 retention이 활성화되지 않았어요. 삭제 요청에는 retention이 활성화되어야 해요.
해결 방법:
-
compactor에서 retention을 활성화하세요:
compactor: retention_enabled: true delete_request_store: s3 -
설정을 바꾼 뒤 compactor를 재시작하세요.
속성:
- 적용 위치: Compactor 삭제 요청 핸들러
- 재시도 가능 여부: 아니요 (설정을 바꿔야 해요)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Invalid delete request time format
오류 메시지:
invalid start time: require unix seconds or RFC3339 format
또는:
invalid end time: require unix seconds or RFC3339 format
원인:
삭제 요청의 시작 또는 종료 시간이 유효한 형식이 아니에요.
해결 방법:
-
Unix 초 또는 RFC3339 형식을 사용하세요:
# Unix seconds curl -X POST http://compactor:3100/loki/api/v1/delete \ -H "X-Scope-OrgID: my-tenant" \ -d "query={app=\"foo\"}" \ -d "start=1704067200" \ -d "end=1704153600" # RFC3339 curl -X POST http://compactor:3100/loki/api/v1/delete \ -H "X-Scope-OrgID: my-tenant" \ -d "query={app=\"foo\"}" \ -d "start=2024-01-01T00:00:00Z" \ -d "end=2024-01-02T00:00:00Z"
속성:
- 적용 위치: Compactor 삭제 요청 핸들러
- 재시도 가능 여부: 아니요 (요청을 고쳐야 해요)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Delete request already processed
오류 메시지:
deletion of request which is in process or already processed is not allowed
원인:
이미 처리 중이거나 처리가 완료된 삭제 요청을 취소하려고 시도했어요.
해결 방법:
-
삭제 요청의 상태를 확인하세요:
curl -s http://compactor:3100/loki/api/v1/delete \ -H "X-Scope-OrgID: my-tenant" | jq -
추가 데이터를 삭제해야 한다면 새 삭제 요청을 제출하세요.
속성:
- 적용 위치: Compactor 삭제 요청 핸들러
- 재시도 가능 여부: 아니요
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Invalid max_interval for delete request
오류 메시지:
invalid max_interval: valid time units are 's', 'm', 'h'
또는:
max_interval can't be greater than <configured-limit>
또는:
max_interval can't be greater than the interval to be deleted (<duration>)
원인:
삭제 요청의 max_interval 파라미터가 잘못된 값을 갖고 있거나, 설정된 delete_max_interval 한도를 초과하거나, 삭제 요청 자체의 시간 범위를 초과해요.
해결 방법:
-
지원되는 단위(
s,m,h)를 사용해서 유효한 시간 형식을 사용하세요:curl -X POST http://compactor:3100/loki/api/v1/delete \ -H "X-Scope-OrgID: my-tenant" \ -d "query={app=\"foo\"}" \ -d "start=1704067200" \ -d "end=1704153600" \ -d "max_interval=1h"
속성:
- 적용 위치: Compactor 삭제 요청 핸들러
- 재시도 가능 여부: 아니요 (요청을 고쳐야 해요)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
Ruler 오류
Ruler 오류는 알림 규칙이나 기록 규칙을 평가할 때 발생해요.
오류: Invalid ruler evaluation config
오류 메시지:
invalid ruler evaluation config: <details>
원인:
ruler 평가 모드 설정이 잘못됐어요.
해결 방법:
-
유효한 평가 모드를 사용하세요:
ruler: evaluation: mode: local # Or "remote"
속성:
- 적용 위치: Ruler 모듈 초기화 (
initRuleEvaluator) - 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Ruler remote write config conflict
오류 메시지:
ruler remote write config: both 'client' and 'clients' options are defined; 'client' is deprecated, please only use 'clients'
원인:
ruler remote write에서 폐기된 client 옵션과 새로운 clients 옵션이 동시에 설정돼 있어요.
해결 방법:
-
폐기된 설정을 제거하고
clients를 사용하세요:ruler: remote_write: # Remove this: # client: {} # Use this instead: clients: primary: url: http://prometheus:9090/api/v1/write
속성:
- 적용 위치: Ruler 초기화 (
NewRuler) - 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Remote write enabled but no URL configured
오류 메시지:
remote-write enabled but no clients URL are configured
clients 맵에 여러 클라이언트가 설정돼 있고 그중 하나에 URL이 없다면:
remote-write enabled but client '<name>' URL for tenant <client-id> is not configured
원인:
ruler에 remote write가 활성화됐는데 대상 URL이 설정되지 않았어요. 첫 번째 변형은 clients 맵이 비어 있을 때 발생해요. 두 번째 변형은 clients 맵의 이름 붙은 항목에 url이 설정되지 않았을 때 발생하고, <client-id>는 테넌트 ID가 아니라 해당 항목의 맵 키예요.
해결 방법:
-
remote write URL을 설정하세요:
ruler: remote_write: enabled: true clients: primary: url: http://prometheus:9090/api/v1/write -
또는 remote write를 비활성화하세요:
ruler: remote_write: enabled: false
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Rule result is not a vector or scalar
오류 메시지:
rule result is not a vector or scalar
원인:
규칙 평가가 예상 밖의 결과 타입을 돌려줬어요. 기록 규칙과 알림 규칙은 모두 vector나 scalar 결과를 만들어야 해요. 로그 라인을 돌려주는(숫자 메트릭이 아닌) 일반 로그 스트림 표현식은 어느 규칙 타입에서든 이 오류를 유발해요.
해결 방법:
-
규칙 표현식이 vector나 scalar를 돌려주는지 확인하세요:
# Valid - returns vector: record: my_metric expr: sum(rate({job="app"}[5m] | json | level="error")) # Invalid - returns logs (triggers error for both recording and alerting rules): # record: my_metric # expr: '{job="app"}' -
로그 쿼리에서 숫자 결과를 만들어내도록 집계 함수를 사용하세요.
속성:
- 적용 위치: Ruler 평가
- 재시도 가능 여부: 아니요 (규칙을 고쳐야 해요)
- HTTP 상태: N/A (백그라운드 프로세스)
- 테넌트별 설정: 아니요
오류: Ruler WAL closed
오류 메시지:
WAL storage closed
원인:
ruler의 write-ahead log(WAL)가 닫힌 후에 그에 대한 연산이 시도됐어요. 보통 종료 과정에서 발생해요.
해결 방법:
- ruler가 재시작 중이라면 재시작되길 기다리세요.
- 예상 밖의 WAL 종료를 일으킨 오류가 있는지 ruler 로그를 확인하세요.
- WAL 연산에 필요한 디스크 여유 공간을 확인하세요.
속성:
- 적용 위치: Ruler WAL
- 재시도 가능 여부: 예 (ruler 재시작 후)
- HTTP 상태: N/A
- 테넌트별 설정: 아니요
Kafka 통합 오류
이 오류들은 Loki가 수집에 Kafka를 사용하도록 설정됐을 때 발생해요.
오류: Missing Kafka address
오류 메시지:
the Kafka address has not been configured
원인:
Kafka 수집이 활성화됐는데 Kafka 브로커 주소가 설정되지 않았어요.
해결 방법:
-
Kafka 주소를 설정하세요:
kafka_config: topic: loki-logs reader_config: address: kafka:9092 writer_config: address: kafka:9092
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Missing Kafka topic
오류 메시지:
the Kafka topic has not been configured
원인:
Kafka 수집이 활성화됐는데 토픽 이름이 설정되지 않았어요.
해결 방법:
-
Kafka 토픽을 설정하세요:
kafka_config: topic: loki-logs reader_config: address: kafka:9092 writer_config: address: kafka:9092
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Inconsistent SASL username and password
오류 메시지:
both sasl username and password must be set
원인:
SASL(Simple Authentication and Security Layer) 사용자 이름과 비밀번호 중 하나만 설정돼 있어요. 둘은 함께 설정해야 해요.
해결 방법:
-
사용자 이름과 비밀번호를 모두 설정하세요:
kafka_config: sasl_username: my-user sasl_password: ${KAFKA_PASSWORD} -
SASL 인증이 필요 없다면 둘 다 제거하세요.
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Kafka enabled in distributor but not in ingester
오류 메시지:
kafka is enabled in distributor but not in ingester
원인:
Kafka가 distributor에는 설정됐지만 ingester는 Kafka에서 읽도록 설정되지 않았어요. 둘은 함께 설정해야 해요.
해결 방법:
-
distributor와 ingester 둘 다 Kafka를 활성화하세요:
distributor: kafka_writes_enabled: true ingester: kafka_ingestion: enabled: true
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Invalid producer max record size bytes
오류 메시지:
the configured producer max record size bytes must be a value between 1048576 and 15983616
원인:
kafka_config.producer_max_record_size_bytes 값이 허용 범위를 벗어났어요.
해결 방법:
-
producer_max_record_size_bytes를 허용 범위 안으로 설정하세요:kafka_config: producer_max_record_size_bytes: 15983616 -
개발 환경에서 테스트하는 게 아니라면 이 값은 기본값으로 두는 걸 강력히 권장해요.
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Invalid producer max inflight requests per broker
오류 메시지:
the configured producer max inflight requests per broker must be greater than or equal to 1
원인:
kafka_config.producer_max_inflight_requests_per_broker 값이 1보다 작아요.
해결 방법:
-
producer_max_inflight_requests_per_broker를1이상으로 설정하세요:kafka_config: producer_max_inflight_requests_per_broker: 20
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Invalid producer linger
오류 메시지:
the configured producer linger must be greater than or equal to 0
원인:
kafka_config.producer_linger 값이 음수예요.
해결 방법:
-
producer_linger를0또는 양수 duration으로 설정하세요:kafka_config: producer_linger: 50ms
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Partition ring required for Kafka writes
오류 메시지:
partition ring is required for kafka writes
원인:
distributor.kafka_writes_enabled가 true인데 distributor가 partition ring 없이 시작됐어요. 보통 partition ring 키-값 스토어가 distributor와 ingester 간에 일관되게 설정되지 않았다는 뜻이에요.
해결 방법:
-
distributor와 ingester 양쪽에 partition ring 키-값 스토어를 설정하세요:
ingester: kafka_ingestion: enabled: true partition_ring: kvstore: store: memberlist -
Kafka 기반 수집에 참여하는 모든 컴포넌트(distributor, ingester, querier, ruler)가 동일한 키-값 스토어 설정을 사용하도록 확인하세요.
속성:
- 적용 위치: Distributor 시작
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Single entry size exceeds maximum
오류 메시지:
single entry size (%d) exceeds maximum allowed size (%d)
원인:
단일 로그 라인이 설정된 kafka_config.producer_max_record_size_bytes보다 커요. Loki는 큰 쓰기 요청을 여러 Kafka 레코드로 분할하지만, 단일 로그 라인은 여러 레코드에 걸쳐 분할할 수 없어요.
해결 방법:
-
Loki로 보내기 전에 소스에서 로그 라인 크기를 줄이세요.
-
limits_config.max_line_size(기본값: 256KB)로 최대 로그 라인 크기를 강제하세요. 이 한도를 초과하는 라인은 Kafka producer에 도달하기 전에 폐기돼요. 폐기 대신 넘치는 라인을 잘라내려면limits_config.max_line_size_truncate: true로 설정하세요:limits_config: max_line_size: 256KB max_line_size_truncate: true -
Kafka 클러스터가 더 큰 레코드를 지원한다면 허용 범위 안에서
producer_max_record_size_bytes를 늘리세요:kafka_config: producer_max_record_size_bytes: 15983616
속성:
- 적용 위치: Kafka 레코드 인코딩
- 재시도 가능 여부: 아니요
- HTTP 상태: 400 (Bad Request)
- 테넌트별 설정: 아니요 (
limits_config.max_line_size와limits_config.max_line_size_truncate는 테넌트별 설정 가능)
오류: Dataobj builder topic required
오류 메시지:
topic is required
원인:
컬럼형 스토리지에 사용되는 실험적 data object builder가 활성화됐는데 이를 위한 Kafka 토픽이 설정되지 않았어요.
해결 방법:
-
data object builder의 토픽을 설정하세요:
dataobj: builder: topic: loki-logs
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Ingest-limits configuration errors
오류 메시지:
num partitions must be greater than 0
consumer group must be set
topic must be set
원인:
선택 기능인 ingest-limits 서비스가 활성화됐는데(ingest_limits.enabled: true) 필요한 Kafka 설정 중 하나 이상이 빠졌거나 잘못됐어요.
해결 방법:
-
필요한 ingest-limits Kafka 설정을 모두 구성하세요:
ingest_limits: enabled: true num_partitions: 64 consumer_group: ingest-limits topic: loki-ingest-limits
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Ingest-limits readiness errors
오류 메시지:
waiting to be assigned some partitions
partitions are not ready
원인:
ingest-limits 서비스가 partition ring 합류를 아직 끝내지 못했거나, 할당된 파티션 중 하나 이상이 준비되지 않았어요. 보통 시작 중이나 롤링 재시작 동안의 일시적인 상태예요.
해결 방법:
- 서비스가 시작을 끝내길 기다리세요. partition ring이 안정되면 이 오류들은 저절로 사라져요.
- 오류가 계속되면 ingest-limits 서비스와 Kafka 브로커 사이의 연결을 확인하고, 설정된 partition ring 키-값 스토어에 접근 가능한지 확인하세요.
속성:
- 적용 위치: Ingest-limits 서비스 준비 상태 검사
- 재시도 가능 여부: 예 (시작 중 일시적)
- HTTP 상태: 503 (Service Unavailable)
- 테넌트별 설정: 아니요
오류: Generic Kafka protocol errors
오류 메시지:
unexpected response type
malformed response
원인:
Kafka 클라이언트가 브로커로부터 예상하지 못한 응답을 받았거나 파싱할 수 없었어요. 보통 Loki의 Kafka 클라이언트(franz-go)가 완전히 지원하지 않는 프로토콜 버전을 쓰는 Kafka(또는 Kafka 프로토콜 호환 브로커)를 가리키거나, 응답을 손상시킨 네트워크 문제를 가리켜요.
해결 방법:
- Kafka 브로커 버전을 Loki의 Kafka 클라이언트(franz-go)가 지원하는 버전과 비교해 보세요.
- Loki와 Kafka 브로커 사이에 패킷 손실이나 잘림이 있는지 네트워크 연결을 확인하세요.
속성:
- 적용 위치: Kafka 클라이언트 (오프셋 매니저)
- 재시도 가능 여부: 예
- HTTP 상태: N/A
- 테넌트별 설정: 아니요
Bloom gateway 오류
Bloom gateway 오류는 쿼리 가속을 위해 bloom filter를 사용할 때 발생해요.
오류: Invalid bloom gateway addresses
오류 메시지:
addresses requires a list of comma separated strings in DNS service discovery format with at least one item
원인:
bloom_gateway.client.addresses 설정 필드가 비어 있거나 설정되지 않았어요.
해결 방법:
-
유효한 주소를 설정하세요:
bloom_gateway: client: addresses: dns+bloom-gateway:9095유효한 형식:
dns+hostname:port- DNS 기반 디스커버리host1:port,host2:port- 정적 목록
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Request time range must span exactly one day
오류 메시지:
request time range must span exactly one day
원인:
bloom 블록이 구성되는 방식 때문에 bloom gateway 요청은 정확히 하루치 데이터에 대한 것이어야 해요.
해결 방법:
- 보통 bloom querier가 여러 날짜에 걸친 쿼리를 게이트웨이로 보내기 전에 하루 단위 요청으로 분할해서 자동으로 처리해요. 이 오류가 보인다면:
- querier가 제대로 설정돼 있는지 확인하세요
- 쿼리가 querier를 통해 라우팅되는지 확인하세요
속성:
- 적용 위치: Bloom gateway
- 재시도 가능 여부: 아니요
- HTTP 상태: 500 Internal Server Error
- 테넌트별 설정: 아니요
오류: From time must not be after through time
오류 메시지:
from time must not be after through time
원인:
bloom gateway가 시작 시간(from)이 종료 시간(through)보다 뒤인 요청을 받았어요.
해결 방법:
- 잘못된 형태의 요청이 bloom gateway에 도달했다는 뜻이에요. 요청을 보내는 클라이언트가
from≤through로 시간 범위를 올바르게 구성하는지 검증하세요.
속성:
- 적용 위치: Bloom gateway
- 재시도 가능 여부: 아니요
- HTTP 상태: 500 Internal Server Error
- 테넌트별 설정: 아니요
Write-ahead log(WAL) 오류
WAL 오류는 ingester가 자신의 write-ahead log를 제대로 관리하지 못할 때 발생해요.
오류: WAL is stopped
오류 메시지:
wal is stopped
원인:
WAL이 중지된 후에 그에 대한 연산이 시도됐어요. 보통 종료 과정이나 치명적인 오류 이후에 발생해요.
해결 방법:
- 오류가 있는지 ingester 상태와 로그를 확인하세요.
- 디스크 여유 공간을 확인하세요.
- 나쁜 상태에 있다면 ingester를 재시작하세요.
속성:
- 적용 위치: Ingester WAL
- 재시도 가능 여부: 예 (ingester 재시작 후)
- HTTP 상태: 500 Internal Server Error
- 테넌트별 설정: 아니요
오류: Invalid checkpoint duration
오류 메시지:
invalid checkpoint duration: <duration>
원인:
WAL checkpoint duration이 잘못된 값(아마 0이나 음수)으로 설정돼 있어요.
해결 방법:
-
유효한 checkpoint duration을 설정하세요:
ingester: wal: checkpoint_duration: 5m
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Invalid disk full threshold
{{< admonition type="note" >}}
disk_full_threshold 설정 옵션은 Loki 3.7에서 도입됐어요. 이 오류는 이전 릴리스에서는 발생하지 않아요.
{{< /admonition >}}
오류 메시지:
invalid disk full threshold: <value> (must be between 0 and 1)
원인:
WAL 디스크 가득 임계값이 유효 범위를 벗어난 값으로 설정돼 있어요. 유효한 값은 0과 1 사이(양 끝 포함)예요. 0은 스로틀링을 비활성화하고, 0보다 큰 값은 쓰기가 스로틀되는 디스크 용량 비율을 의미해요.
해결 방법:
-
유효한 임계값을 설정하세요:
ingester: wal: disk_full_threshold: 0.9 # 90%
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
Ingester 생명주기 오류
Ingester 생명주기 오류는 ingester 시작, 종료, 상태 전환 중에 발생해요.
오류: Ingester is shutting down
오류 메시지:
Ingester is shutting down
원인:
ingester가 종료 과정에 있어서 더 이상 쓰기를 받지 않아요. 이 오류(ErrReadOnly로도 알려져 있어요)는 우아한 종료 중에 push 요청이 도착하면 돌려줘요. 이 기간 동안 ingester는 메모리에 들고 있는 데이터에 대한 읽기는 계속 처리할 수 있어요.
해결 방법:
- 백오프를 두고 재시도하도록 클라이언트를 설정하세요. distributor는 다른 정상 ingester로 라우팅해요.
- 종료가 끝나고 새 인스턴스가 시작되길 기다리세요.
- 종료가 예상된 것인지 확인하세요 (롤링 업데이트, 스케일링 이벤트).
- 예상 밖이라면 OOM kill이나 헬스 체크 실패가 있는지 오케스트레이터 로그를 확인하세요.
속성:
- 적용 위치: Ingester
- 재시도 가능 여부: 부분적으로. distributor는 복제 집합의 모든 ingester에 병렬로 쓰기를 보내고 쿼럼 모델을 사용해요. 남은 ingester가 최소 성공 임계값을 충족하면 종료 중인 ingester의 이 오류에도 불구하고 전체 쓰기는 성공해요.
- HTTP 상태: 500 Internal Server Error
- 테넌트별 설정: 아니요
오류: Ingester is stopping or already stopped
오류 메시지:
Ingester is stopping or already stopped.
원인:
ingester의 종료 관리 엔드포인트(POST /loki/api/v1/ingester/shutdown)가 ingester가 Running 상태가 아닐 때 호출됐어요. 진행 중인 종료 도중에 두 번째로 호출되거나 ingester가 이미 멈춘 뒤에 호출될 때 발생해요. 이 오류는 로그 쓰기나 쿼리 경로가 아니라 종료 엔드포인트가 돌려주는 거예요.
해결 방법:
- 종료가 이미 진행 중이라면 종료 엔드포인트를 다시 호출하지 마세요.
- 중복 종료 신호나 재시작 정책이 있는지 오케스트레이터를 확인하세요.
- 중지가 예상 밖이라면 (pod 축출, OOM, 크래시) 조사하세요.
속성:
- 적용 위치: Ingester 종료 엔드포인트
- 재시도 가능 여부: 아니요 (종료 엔드포인트 호출 자체는 재시도할 수 없어요. 새 쓰기를 보내기 전에 ingester가 재시작되기를 기다리세요)
- HTTP 상태: 503 Service Unavailable (종료 엔드포인트의 응답)
- 테넌트별 설정: 아니요
오류: Failed to start partition reader
오류 메시지:
failed to start partition reader: <details>
원인:
ingester가 Kafka partition reader를 시작하지 못했어요. Kafka 수집이 활성화됐는데 partition reader 초기화에 실패할 때 발생해요.
해결 방법:
-
ingester에서 Kafka 연결을 확인하세요.
-
Kafka 토픽이 존재하고 ingester에 적절한 권한이 있는지 검증하세요.
-
Kafka 설정을 검토하세요:
kafka: address: kafka:9092 topic: loki-logs -
Kafka 브로커 상태를 확인하세요.
속성:
- 적용 위치: Ingester 시작
- 재시도 가능 여부: 아니요 (설정이나 인프라를 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Failed to start partition ring lifecycler
오류 메시지:
failed to start partition ring lifecycler: <details>
원인:
ingester가 시작 중에 Kafka partition ring lifecycler를 시작하지 못했어요. 이건 partition reader와 별개의 컴포넌트로, partition ring에서 ingester의 멤버십을 관리해요. Kafka 수집이 활성화된 경우에만 발생해요.
해결 방법:
- ingester에서 Kafka 연결을 확인하세요.
- partition ring에 쓰이는 KV 스토어가 도달 가능한지 검증하세요.
<details>에 감싸인 오류가 있는지 ingester 로그를 검토하세요.- Kafka 브로커 상태와 파티션 가용성을 확인하세요.
속성:
- 적용 위치: Ingester 시작
- 재시도 가능 여부: 아니요 (설정이나 인프라를 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Lifecycler failed
오류 메시지:
lifecycler failed: <details>
원인:
ingester의 lifecycler(ring 멤버십을 관리해요)가 치명적인 오류를 만났어요. 이러면 ingester가 ring에 참여할 수 없어요.
해결 방법:
- KV 스토어 연결을 확인하세요 (Consul, etcd, memberlist).
- 구체적인 lifecycler 오류가 있는지 ingester 로그를 검토하세요.
- 모든 ingester에서 ring 설정이 일관된지 검증하세요.
- 근본 문제를 고친 뒤 ingester를 재시작하세요.
속성:
- 적용 위치: Ingester lifecycler
- 재시도 가능 여부: 예 (수정과 재시작 후)
- HTTP 상태: N/A (내부 실패)
- 테넌트별 설정: 아니요
Pattern ingester 오류
Pattern ingester 오류는 자동 로그 패턴 탐지에 pattern ingester를 사용할 때 발생해요.
오류: Pattern ingester replication factor must be 1
오류 메시지:
pattern ingester replication factor must be 1
원인:
pattern ingester가 1이 아닌 복제 계수로 설정돼 있어요. 현재 pattern ingester는 복제 계수 1만 지원해요.
해결 방법:
-
복제 계수를 1로 설정하세요:
pattern_ingester: lifecycler: ring: replication_factor: 1
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Pattern ingester retain-for too short
오류 메시지:
retain-for (<duration>) must be greater than or equal to chunk-duration (<duration>)
원인:
pattern ingester의 retain_for duration이 max_chunk_age보다 짧아서 데이터 손실이 생길 수 있어요.
해결 방법:
-
max_chunk_age만큼 길거나 더 길도록 retain-for duration을 늘리세요:pattern_ingester: retain_for: 15m # Must be >= max_chunk_age max_chunk_age: 5m
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Pattern ingester chunk-duration too short
오류 메시지:
chunk-duration (<duration>) must be greater than or equal to sample-interval (<duration>)
원인:
pattern ingester의 max_chunk_age가 pattern_sample_interval보다 짧아요. 청크가 최소 하나의 샘플 간격을 포함해야 데이터를 담을 수 있어요.
해결 방법:
-
pattern_sample_interval만큼 길거나 더 길도록max_chunk_age를 늘리세요:pattern_ingester: max_chunk_age: 1h # Must be >= pattern_sample_interval (default: 1h) pattern_sample_interval: 10s # default: 10s
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
오류: Pattern ingester volume threshold out of range
오류 메시지:
volume_threshold (<value>) must be between 0 and 1
원인:
volume_threshold 값이 0과 1 사이의 유효 범위를 벗어났어요. 이 설정은 pattern ingester가 추적할 로그 볼륨의 비율을 조절해요. 로그 볼륨 상위 X%를 차지하는 패턴만 영속화돼요.
해결 방법:
-
volume_threshold를 0과 1 사이 값으로 설정하세요 (기본값은0.99):pattern_ingester: volume_threshold: 0.99
속성:
- 적용 위치: 설정 검증
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
API 파라미터 오류
이 오류들은 API 요청에 잘못된 파라미터가 있을 때 발생해요.
오류: Invalid direction
오류 메시지:
invalid direction '<value>'
원인:
direction 쿼리 파라미터에 잘못된 값이 들어 있어요.
해결 방법:
-
유효한 direction 값을 사용하세요:
forward- 오래된 것부터 최신 순backward- 최신 것부터 오래된 순 (기본값)
curl "http://loki:3100/loki/api/v1/query_range?query={job=\"app\"}&direction=forward"
속성:
- 적용 위치: API 핸들러
- 재시도 가능 여부: 아니요 (요청을 고쳐야 해요)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Limit must be a positive value
오류 메시지:
limit must be a positive value
원인:
limit 파라미터가 0이거나 음수예요.
해결 방법:
-
양수 limit을 제공하세요:
curl "http://loki:3100/loki/api/v1/query_range?query={job=\"app\"}&limit=100"
속성:
- 적용 위치: API 핸들러
- 재시도 가능 여부: 아니요 (요청을 고쳐야 해요)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: End timestamp must not be before start time
오류 메시지:
end timestamp must not be before or equal to start time
원인:
쿼리의 end 시간이 start 시간과 같거나 그보다 앞이에요.
해결 방법:
-
종료 시간이 시작 시간보다 뒤가 되도록 확인하세요:
curl "http://loki:3100/loki/api/v1/query_range?\ query={job=\"app\"}&\ start=2024-01-01T00:00:00Z&\ end=2024-01-02T00:00:00Z"
속성:
- 적용 위치: API 핸들러
- 재시도 가능 여부: 아니요 (요청을 고쳐야 해요)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Delay for tailing too large
오류 메시지:
delay_for can't be greater than <max>
원인:
tailing 쿼리의 delay_for 파라미터가 최대 허용 값을 초과했어요.
해결 방법:
-
delay_for 값을 줄이세요:
curl "http://loki:3100/loki/api/v1/tail?query={job=\"app\"}&delay_for=5"최댓값은 보통 5초예요.
속성:
- 적용 위치: API 핸들러
- 재시도 가능 여부: 아니요 (요청을 고쳐야 해요)
- HTTP 상태: 400 Bad Request
- 테넌트별 설정: 아니요
오류: Query filtering requires compactor address
오류 메시지:
query filtering for deletes requires 'compactor_grpc_address' or 'compactor_address' to be configured
원인:
삭제 요청에 대한 쿼리 시점 필터링이 활성화됐지만 Loki가 활성 삭제 요청을 가져오려고 compactor에 도달하는 방법을 모르는 상태예요.
해결 방법:
-
compactor 주소를 설정하세요:
compactor: compactor_grpc_address: compactor:9095 -
또는 HTTP 주소를 사용하세요:
compactor: compactor_address: http://compactor:3100
속성:
- 적용 위치: 모듈 초기화
- 재시도 가능 여부: 아니요 (설정을 고쳐야 해요)
- HTTP 상태: N/A (시작 실패)
- 테넌트별 설정: 아니요
더 알아보기 (Learn more)
- Troubleshoot Loki ingestion - 수집(쓰기 경로) 오류 문제 해결
- Troubleshoot Loki queries - 쿼리(읽기 경로) 오류 문제 해결
- Hash rings - Loki 해시 ring의 동작 원리와 구성 방법
- Configure Loki - 설정 파일 옵션 전체 참조
- Loki storage schema - 스키마 버전과 업데이트 절차 안내
- Loki operations - Loki 운영 관련 전체 문서 모음