Loki
는 Grafana
플랫폼의 일부이며, 메트릭 데이터와 로그 데이터를 인덱싱하고 관리하는 시스템입니다. 다른 로깅 제품들과 달리 Loki
의 인덱스는 레이블로부터 작성되고, 원본 데이터는 변경없이 보존합니다. 에이전트(혹은 클라이언트)는 로그를 수집하여 스트림으로 변환하고, 이를 HTTP API를 통해 Loki에 푸시합니다.레이블을 인덱싱함으로써, 로그의 인덱스가 다른 로깅 제품들보다 상당히 작습니다. 이는 곧 적은 리소스 비용으로 로그를 처리할 수 있다는 장점입니다.
Loki
의 여러 테넌트가 하나의 Loki
인스턴스를 활용할 수 있습니다. 별개의 테넌트의 데이터는 다른 테넌트로부터 완전히 격리됩니다. 멀티 테넌시는 에이전트에서 테넌트 ID를 할당하여 구성됩니다.Loki
인스턴스(쉽게 말해 서비스)를 공유하되, 각각의 로그 데이터는 테넌트 ID를 기준으로 서로 분리되어 있음을 나타냅니다. 이를 통해 각 사용자 혹은 팀이 자신들의 데이터를 안전하게 관리하고 검색할 수 있는 이점을 제공합니다.<aside>
💡 테넌트(Tenant)
는 "다중 사용자" 또는 “다중 렌트" 환경에서 사용되는 용어입니다. 소프트웨어 아키텍처 측면에서 테넌트는 독립적인 인스턴스를 참조합니다. 각각의 테넌느는 별도로 격리되어 있어, 자신들의 데이터와 프로세스가 다른 테넌트와 상호 작용하지 않습니다.
</aside>
loki
는 확장성을 고려하여 설계되어 싱글 바이너리(하나의 파일에 모든 컴포넌트가 포함된 파일)외에도 마이크로 서비스 형태로 배포할 수 있습니다. loki를 마이크로 서비스로 배포할 경우 설정을 통해 각 컴포넌트들을 개별적으로 확장할 수 있어 유연하게 대규모 배포가 가능합니다.테넌트 ID(Tenant ID)
X-Scope-OrgID
’을 통해 얻을 수 있습니다. 단, Loki
가 멀티 테넌트 모드(multi-tenant mode
)일 때만 동작하며 만약 멀티 테넌트 모드가 아닌 경우 헤더값(X-Scope-OrgID
)이 무시되고, 테넌트 ID는 ‘fake
’가 됩니다. 테넌트 ID는 인덱스와 저장된 청크에서 확인 가능합니다.청크 포맷(Chunk Format)
Loki
는 로그 데이터를 청크로 분할하여 저장하고, 각 청크는 레이블 세트와 일련의 로그 라인(시간+로그 라인)으로 구성됩니다. 이러한 청크는 시간 범위별로 분리되어 저장됩니다. Loki
는 로그 라인을 압축하고 이들을 청크에 저장하여 공간을 절약합니다. 이는 저장 공간을 절약하고 로그 데이터의 쿼리 속도를 높이는 데 도움이 됩니다.v1
이 아닌 v2
를 기본으로 사용하고 있습니다. 새로운 청크 포맷 v2
는 훨씬 더 효율적인 압축 방식을 사용하며, 이로 인해 저장 공간이 더욱 절약되고 쿼리 시간이 더욱 단축되었습니다. -------------------------------------------------------------------
| | |
| MagicNumber(4b) | version(1b) |
| | |
-------------------------------------------------------------------
| block-1 bytes | checksum (4b) |
-------------------------------------------------------------------
| block-2 bytes | checksum (4b) |
-------------------------------------------------------------------
| block-n bytes | checksum (4b) |
-------------------------------------------------------------------
| #blocks (uvarint) |
-------------------------------------------------------------------
| #entries(uvarint) | mint, maxt (varint) | offset, len (uvarint) |
-------------------------------------------------------------------
| #entries(uvarint) | mint, maxt (varint) | offset, len (uvarint) |
-------------------------------------------------------------------
| #entries(uvarint) | mint, maxt (varint) | offset, len (uvarint) |
-------------------------------------------------------------------
| #entries(uvarint) | mint, maxt (varint) | offset, len (uvarint) |
-------------------------------------------------------------------
| checksum(from #blocks) |
-------------------------------------------------------------------
| #blocks section byte offset |
-------------------------------------------------------------------
MagicNumber
는 청크 파일이 Loki에서 사용하는 특정 포맷인지 확인하는 데 사용되며, version
은 청크 포맷의 버전을 나타냅니다.#entries
는 해당 청크에 저장된 로그 라인의 수를 나타냅니다. mint
와 maxt
는 청크의 최소 시간과 최대 시간을 나타내며, offset
과 len
은 해당 로그 라인의 바이트 오프셋과 길이를 나타냅니다.#blocks
필드의 체크섬을 나타냅니다.#blocks
섹션이 시작하는 위치를 나타냅니다.블록 포맷(Block Format)
-------------------------------------------------------------------
| ts (varint) | len (uvarint) | log-1 bytes |
-------------------------------------------------------------------
| ts (varint) | len (uvarint) | log-2 bytes |
-------------------------------------------------------------------
| ts (varint) | len (uvarint) | log-3 bytes |
-------------------------------------------------------------------
| ts (varint) | len (uvarint) | log-n bytes |
-------------------------------------------------------------------
Block Format
)은 로그 데이터를 저장하는 데 사용되는 데이터 구조를 의미합니다. Loki
에서, 로그 데이터는 블록(block)이라는 단위로 구분되어 저장됩니다. 각 블록은 하나 이상의 로그 라인을 포함하고 있으며, 이러한 로그 라인들은 블록 내에서 시간 순서대로 정렬되어 있습니다.Loki
는 각 블록을 개별적으로 압축하고, 이들을 청크(chunk)에 묶어 저장합니다. 이는 데이터의 중복을 줄이고, 공간을 절약하는 데 도움이 됩니다.Loki
는 데이터의 검색 속도를 높일 수 있습니다. 예를 들어, 특정 시간 범위의 로그를 검색할 때 Loki
는 해당 시간 범위에 해당하는 블록만을 압축 해제하고 읽을 수 있습니다.