Loki — 로그를 색인하지 않는 로그 저장소 · 보존과 삭제 · 이론
켜지 않으면 로그는 영원히 남는다
한 줄 요약
Loki 는 보존을 꺼 둔 채로 출발한다. 켜지 않으면 넣은 로그는 영원히 남고, 켜더라도 삭제는 컴팩터가 자기 주기에 하는 비동기 작업이라 "지웠다" 와 "안 보인다" 사이에 시간 간격이 있다.
왜 이게 필요했나
스토리지 청구서가 석 달 만에 네 배가 된 팀이 있었다. 대시보드에서 오래된 구간을 열어 보면 1년 전 로그까지 나왔다. 아무도 보존을 설정하지 않았고, 아무도 그 사실을 몰랐다 — 기본값이 "지우지 않음" 이기 때문이다.
반대 방향의 사고도 있다. 개인정보가 섞여 들어간 것을 발견하고 삭제 요청을 넣은 팀이, 요청 직후 그 줄이 조회에서 사라지는 것을 보고 "지웠다" 고 보고했다. 한 달 뒤 저장소 용량은 그대로였다. 기본 삭제 방식(filter-and-delete)은 요청이 접수되는 즉시 질의 시점에 걸러 주지만, 객체에서 실제로 지우는 일은 취소 대기 기간(기본 24시간)이 지난 뒤 컴팩터가 한다. 안 보이는 것과 지워진 것은 다르다.
어떻게 동작하나
보존은 컴팩터가 한다. 세 가지를 같이 봐야 한다.
| 설정 | 기본값 | 뜻 |
| --- | --- | --- |
| compactor.retention_enabled | false | 꺼져 있으면 아무것도 지우지 않는다 |
| compactor.compaction_interval | 10m | 압축과 보존을 돌리는 주기 |
| compactor.retention_delete_delay | 2h | 지울 대상으로 표시한 뒤 실제 삭제까지 기다리는 시간 |
보존 기간 자체는 limits_config.retention_period 로 정하고, 스트림마다 다르게 걸고 싶으면 retention_stream 목록에 선택자·우선순위·기간을 적는다. 여러 규칙이 겹치면 우선순위가 높은 것이 이긴다. 감사 로그는 1년, 디버그 로그는 하루 — 같은 클러스터에서 이렇게 갈라 두는 것이 비용을 줄이는 가장 큰 손잡이다.
특정 줄을 지우는 일은 보존과 다른 길이다. POST /loki/api/v1/delete 에 선택자와 구간을 주면 삭제 요청이 접수되고 상태가 received 가 된다. 기본 deletion_mode 인 filter-and-delete 에서는 그 순간부터 질의가 해당 줄을 걸러 내므로 조회는 즉시 비어 보인다. 하지만 요청은 delete_request_cancel_period(기본 24시간) 동안 취소할 수 있고, 저장된 객체에서 실제로 지워지는 것은 그 시간이 지난 뒤 컴팩터의 몫이다.
여기서 흔히 어긋나는 것이 기대와 보장이다. "조회에서 사라졌다" 는 표시이지 "지워졌다" 는 증거가 아니다. 규제 대응으로 시한이 있다면 그 시한과 취소 대기 기간·컴팩터 주기를 같이 계산해야 하고, 용량이 줄기를 기다린다면 더더욱 그렇다.
용량 계획은 오히려 단순하다. 질의 응답에 실려 오는 totalBytesProcessed 로 한 시간치의 실제 바이트를 재고, 하루·한 달로 곱하고, 스트림별 보존 기간을 곱해 더한다. 압축률은 실제로 저장된 청크 파일의 크기와 견주어 보정한다. 추정이 아니라 실측에서 출발하면 보존 기간을 줄이자는 논의가 숫자로 진행된다.
현장에서 만나는 모습
가장 자주 보는 실수는 보존을 켜 놓고 컴팩터를 띄우지 않는 것이다. 마이크로서비스 배치에서 컴팩터는 별도 구성 요소이고, 클러스터에 정확히 하나만 떠 있어야 한다. 설정에 retention_enabled: true 를 적어 두고 컴팩터가 없으면 아무 일도 일어나지 않는데, 설정 파일만 보면 켜져 있는 것처럼 보인다.
두 번째는 스트림 규칙의 우선순위를 빠뜨리는 것이다. 우선순위가 같은 두 규칙이 같은 스트림에 걸리면 어느 쪽이 이길지 예측하기 어려워진다. 규칙을 넣을 때마다 우선순위를 명시하는 습관이 안전하다.
세 번째는 "지웠는데 용량이 안 줄었다" 이다. 삭제 표시와 실제 객체 삭제 사이에는 대기 시간이 있고, 객체 저장소 쪽의 수명 주기 정책이 또 한 겹 있을 수 있다.
다음 실습에서 할 것
보존을 켜고 스트림마다 다른 기간을 거는 설정 파일을 직접 쓰고, loki -verify-config 로 문법이 아니라 설정 자체가 유효한지 확인한다. 그 설정으로 두 번째 Loki 를 다른 포트에 띄우고(gRPC 포트까지 바꿔야 한다), 서버가 실제로 그 값을 들고 떴는지 /config 로 확인한 뒤, 삭제 요청을 넣어 접수되는 것과 즉시 사라지지 않는 것을 함께 기록한다. 마지막으로 실측 바이트에서 보존 예산을 계산해 정책 문서를 만든다.