TIL/Monitoring(k8s, grafana)

[Loki, K8s] 원인 불명의 Loki - CrashLoopBackOff 문제 해결 (EBS 용량 )

쓱쓱565 2025. 1. 7. 23:33

개요

  • 3개월 이상 안정적으로 작동하던 Loki pod가 알 수 없는 이유로 CrashLoopBackOff 상태가 됨.
  • 수동으로 Pod 삭제, Service enable / disable 등 처리를 했음에도 CrashLoopBackOff 상태에서 벗어나지 못함.
  • 에러 문구 확인 결과 loki init 단계에서 실패하는 것으로 판단됨.

원인

  • loki에 할당된 PV 가 모두 사용됨.

구체적인 원인

  • Kuberenetes Event exporter 설치 후 정상적인 dashboard 작동 위해 loki의 버전을 높임.
  • Loki의 버전업 (2.6.1 -> 2.9.6)에 따라 log retention 의 default 값이 off로 바뀜.
  • 구동 이후 약 2개월간의 로그가 누적 저장됨.
  • 정기적으로 쿼리가 retention 되지 않아 EBS 용량(10Gb) 이 모두 사용됨.
  • EBS의 용량이 가득 차 에러 발생

해결방법

  • PVC 사이즈를 키움. (10Gb -> 20Gb)
loki:
  enabled: true
  singleBinary:
    replicas: 1
    persistence:
      size: 20Gi
  • log retention 관련 설정을 추가한 후 Loki 재기동
loki:
  enabled: true
  loki:
    compactor:
      retention_enabled: true # retention 실행
      apply_retention_interval: 10m # 매 10분마다 실행
    limits_config:
      retention_period: 744h # 31일 지난 로그 삭제 

 

 

  • 위의 설정값을 입력한 뒤 loki에 잘 적용되었는지 확인할 수 있다. 
  • k8s 에서 구동중인 loki service를 localhost로 port-foward한 뒤 /config로 접속했다. 
    • ex) localhost:55555/config
  • compactor, limits_config에 적절히 의도가 반영되었는지 확인한다.
  • helm chart를 활용해 설치할 경우, helm chart 를 dry-run 한 결과물을 확인해도 무방하다.  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

참고(Loki ver 2.6) - Loki 데이터량 확인 및 유지기간 설정 방법 확인

 

[K8s, Grafana] Loki 데이터량 확인 및 유지기간 설정 방법 확인(2.6.1)

Loki(2.6.1) 데이터량 확인 및 유지기간 설정 방법 확인1. 데이터량 확인 방법Prometheus 에서 아래 metric을 쿼리loki_ingester_chunk_stored_bytes_total백분율 등의 형태로도 쿼리 가능.(sum(loki_ingester_chunk_stored_byt

programmer-565.tistory.com

 

 

 

후속 조치 (예정)

Object storage 설치 전까지

  • Monitoring stack(Loki, Prometheus)의 Storage 사용량 모니터링
  • 부하 테스트 시 생성되는 Log / Metric 정보 크기들 함께 모니터링
  • 지정된 retention 에 비해 log limit에 빨리 다다를 경우 알람 발송

Object Storage 설치 이후 (minIO 예상중)

  • Loki 고가용성 확보 (single binary 모드 대신)
  • Prometheus 고가용성 확보(with Thanos)

참고 자료들

https://grafana.com/docs/loki/latest/operations/storage/retention/#retention-configuration

 

Log retention | Grafana Loki documentation

Log retention Retention in Grafana Loki is achieved through the Compactor. By default the compactor.retention-enabled flag is not set, so the logs sent to Loki live forever. NoteIf you have a lifecycle policy configured on the object store, please ensure t

grafana.com

 

https://grafana.com/docs/loki/latest/operations/storage/retention/#compactor

 

Log retention | Grafana Loki documentation

Log retention Retention in Grafana Loki is achieved through the Compactor. By default the compactor.retention-enabled flag is not set, so the logs sent to Loki live forever. NoteIf you have a lifecycle policy configured on the object store, please ensure t

grafana.com

 

예상되는 원인

Loki 2.6는 기본적으로 single binary (1개의 loki 컨테이너가 모든 역할을 수행) 모드로 실행됨.

Loki 2.9에서는 기본적으로 Object storage와 함께 고가용성 모드로 실행하는 것을 권장함. 

 

외부 Object storage 사용 시 용량 부담이 줄어들고 가용성 확보가 용이하므로, default retention 설정을 off 처리해둔 것으로 판단됨. 

 

기타 - 에러 문구 일부


panic: runtime error: invalid memory address or nil pointer dereference
goroutine 307 [running]:
github.com/grafana/loki/pkg/storage/stores/shipper/util.logPanic({0x2558160, 0xc000a76930})
/src/loki/pkg/storage/stores/shipper/util/util.go:95 +0x47
github.com/grafana/loki/pkg/storage/stores/shipper/util.safeOpenBoltDbFile.func1()
/src/loki/pkg/storage/stores/shipper/util/util.go:54 +0x45
panic({0x2558160?, 0xc000a76930?})
/usr/local/go/src/runtime/panic.go:914 +0x21f
go.etcd.io/bbolt.(*freelist).read(0x0?, 0x0?)
/src/loki/vendor/go.etcd.io/bbolt/freelist.go:265 +0x1a
go.etcd.io/bbolt.(*DB).loadFreelist.func1()
/src/loki/vendor/go.etcd.io/bbolt/db.go:323 +0xaf
sync.(*Once).doSlow(0xc000aaa408?, 0x10?)
/usr/local/go/src/sync/once.go:74 +0xbf
sync.(*Once).Do(...)
/usr/local/go/src/sync/once.go:65
go.etcd.io/bbolt.(*DB).loadFreelist(0xc000aaa240?)\
/src/loki/vendor/go.etcd.io/bbolt/db.go:316 +0x45
go.etcd.io/bbolt.Open({0xc000835c80, 0x3b}, 0x1b6?, 0xc000523f48)
/src/loki/vendor/go.etcd.io/bbolt/db.go:293 +0x458
github.com/grafana/loki/pkg/storage/chunk/client/local.OpenBoltdbFile(...)
/src/loki/pkg/storage/chunk/client/local/boltdb_index_client.go:404
github.com/grafana/loki/pkg/storage/stores/shipper/util.safeOpenBoltDbFile({0xc000835c80, 0x3b}, 0xc000a9a2a0)
/src/loki/pkg/storage/stores/shipper/util/util.go:62 +0x105
created by github.com/grafana/loki/pkg/storage/stores/shipper/util.SafeOpenBoltdbFile in goroutine 1
/src/loki/pkg/storage/stores/shipper/util/util.go:42 +0x86
goroutine 1 [chan receive]:
github.com/grafana/loki/pkg/storage/stores/shipper/util.SafeOpenBoltdbFile({0xc000835c80, 0x3b})
/src/loki/pkg/storage/stores/shipper/util/util.go:43 +0x9e
github.com/grafana/loki/pkg/storage/stores/shipper/index.loadBoltDBsFromDir({0xc000b12a50, 0x30}, 0xc0005d7fa0)
/src/loki/pkg/storage/stores/shipper/index/table.go:373 +0x3ee
github.com/grafana/loki/pkg/storage/stores/shipper/index.LoadTable({0xc000b12a50, 0x30}, {0xc000b129f0, 0x29}, {0x7f66892838a0, 0xc000a2ad80}, 0x0?, 0x0?)
/src/loki/pkg/storage/stores/shipper/index/table.go:75 +0x45
github.com/grafana/loki/pkg/storage/stores/shipper/index.(*TableManager).loadTables(0xc00066f2c0)
/src/loki/pkg/storage/stores/shipper/index/table_manager.go:241 +0x9f4
github.com/grafana/loki/pkg/storage/stores/shipper/index.NewTableManager({{0xc000b129f0, 0x29}, {0xc000c2d380, 0x1f}, 0x1176592e000, 0x0}, {0x7f66892838a0, 0xc000a2ad80}, {0x4a3b, 0x18daea1d7f, ...}, ...)
/src/loki/pkg/storage/stores/shipper/index/table_manager.go:70 +0x2a5
github.com/grafana/loki/pkg/storage/stores/shipper.(*indexClient).init(0xc000a2ab40, {0x2ec2690, 0xc0005c6380}, {0x7f668927d670, 0xc00062a330}, 0x0?, {0x0?, 0x0?, 0xc000549dd0?}, {0x2eadac0, ...})
/src/loki/pkg/storage/stores/shipper/shipper_index_client.go:102 +0x34f
github.com/grafana/loki/pkg/storage/stores/shipper.NewShipper({{{0xc000c2d380, 0x1f}, {0x0, 0x0}, {0x2794db7, 0x6}, {0xc000c2d3a0, 0x1e}, 0x4e94914f0000, 0x45d964b800, ...}, ...}, ...)
/src/loki/pkg/storage/stores/shipper/shipper_index_client.go:71 +0x1d3
github.com/grafana/loki/pkg/storage.NewIndexClient({{0x17e466f3400}, {0xc0006eb6f0, 0xe}, {0xc0006eb670, 0xa}, {0xc0006eb698, 0x3}, {{0xc0006eb5f0, 0xb}, 0x4e94914f0000, ...}, ...}, ...)
/src/loki/pkg/storage/factory.go:420 +0x1173
github.com/grafana/loki/pkg/storage.(*store).storeForPeriod(0xc00084aa00, {{0x17e466f3400}, {0xc0006eb6f0, 0xe}, {0xc0006eb670, 0xa}, {0xc0006eb698, 0x3}, {{0xc0006eb5f0, 0xb}, ...}, ...}, ...)
/src/loki/pkg/storage/store.go:293 +0x1109
github.com/grafana/loki/pkg/storage.(*store).init(0xc00084aa00)
/src/loki/pkg/storage/store.go:177 +0x397
github.com/grafana/loki/pkg/storage.NewStore({{{0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}}, {{{0x0}, 0x4000000000000000, ...}, ...}, ...}, ...)
/src/loki/pkg/storage/store.go:155 +0xbd3
github.com/grafana/loki/pkg/loki.(*Loki).initStore(0xc000bc6000)
/src/loki/pkg/loki/modules.go:690 +0x5c5
github.com/grafana/dskit/modules.(*Manager).initModule(0xc000ba42e8, {0x7ffcab445e84, 0x3}, 0xc000d35070?, 0x1?)
/src/loki/vendor/github.com/grafana/dskit/modules/modules.go:136 +0x1f7
github.com/grafana/dskit/modules.(*Manager).InitModuleServices(0x1?, {0xc000d34930, 0x1, 0xc000cc3080?})
/src/loki/vendor/github.com/grafana/dskit/modules/modules.go:108 +0xd8
github.com/grafana/loki/pkg/loki.(*Loki).Run(0xc000bc6000, {0xc000d4d680?})
/src/loki/pkg/loki/loki.go:461 +0x4a
main.main()
/src/loki/cmd/loki/main.go:110 +0xe45
goroutine 18 [select]:
github.com/baidubce/bce-sdk-go/util/log.NewLogger.func1()
/src/loki/vendor/github.com/baidubce/bce-sdk-go/util/log/logger.go:375 +0xa
created by github.com/baidubce/bce-sdk-go/util/log.NewLogger in goroutine 1
/src/loki/vendor/github.com/baidubce/bce-sdk-go/util/log/logger.go:368 +0x125
goroutine 20 [select]:
go.opencensus.io/stats/view.(*worker).start(0xc0000c1300)
/src/loki/vendor/go.opencensus.io/stats/view/worker.go:292 +0x9f
created by go.opencensus.io/stats/view.init.0 in goroutine 1
/src/loki/vendor/go.opencensus.io/stats/view/worker.go:34 +0x8d
goroutine 111 [select]:
google.golang.org/grpc/internal/grpcsync.(*CallbackSerializer).run(0xc000148e40, {0x2eb9168, 0xc000d296d0})
/src/loki/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go:83 +0x112