LabHub
배우기 러닝패스 코스

Designing a Log Pipeline

What to index and what to leave in the body

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

로그 저장소가 느려지거나 비싸지는 이유는 거의 언제나 무엇을 색인할지 잘못 골랐기 때문입니다. 그 결정은 데이터가 쌓인 뒤에 되돌리기가 아주 어렵습니다.

여기서는 실제 로그를 세어 보고 숫자로 정합니다.

재료

/opt/lab/logidx/events.jsonl   로그 2만 줄 (약 4MB)
mkdir -p /root/logidx && cp /opt/lab/logidx/* /root/logidx/ && cd /root/logidx
head -1 events.jsonl | python3 -m json.tool

남길 것

01-cardinality.txt  필드마다 값이 몇 가지인가
02-labels.txt       라벨과 본문을 가른 결과
03-explode.txt      라벨 하나를 더하면 스트림이 몇 개가 되나
04-shards.txt       샤드 수
05-tiers.txt        보관 단계와 기간
06-cost.txt         색인과 검색의 비용
07-notes.md         왜 그런지

먼저 세어 본다

각 필드(service level env pod route request_id user_id)가 서로 다른 값을 몇 가지 갖는지 세어 01-cardinality.txt 에 적고, 높은 것과 낮은 것을 갈라 표시하세요.

python3 - <<'PY'
import json
rows = [json.loads(l) for l in open('events.jsonl')]
for k in ('service','level','env','pod','route','request_id','user_id'):
    print(k, len({r[k] for r in rows}))
PY

두 자리 이하와 만 단위가 섞여 있을 겁니다. 그 차이가 그대로 비용의 차이가 됩니다.

라벨과 본문을 가른다

라벨로 둘 것본문에 둘 것을 갈라 02-labels.txt 에 적으세요. 라벨로 고른 것들의 조합 수도 함께 계산합니다.

라벨은 곧 스트림(또는 시계열)입니다. 조합 수가 그대로 개수가 됩니다.

service · level · env 셋이면 5 × 3 × 2 이지만, 실제로 나타나는 조합만 세면 그보다 작을 수도 있습니다. 실제 데이터로 세어 보세요.

높은 기수 필드는 본문에 둡니다. 그러면 라벨로 먼저 좁힌 뒤 그 안에서 찾게 되고, 그것이 이런 저장소의 설계 의도입니다.

하나만 더해 본다

라벨 셋에 pod · route · request_id · user_id각각 하나씩 더했을 때 조합 수가 얼마가 되는지 03-explode.txt 에 적고, pod 하나로 몇 배가 되는지 적으세요.

네 번 계산해서 견줍니다. pod 는 서비스마다 여섯이니 곱해집니다.

"이 라벨 하나만 있으면 편한데" 가 사고의 시작입니다. 편의는 한 사람의 것이고 비용은 클러스터 전체의 것입니다.

샤드를 몇 개로 나눌 것인가

이 로그가 초당 500줄 들어온다고 보고 하루치 저장량과 샤드 수를 04-shards.txt 에 계산하세요. 목표 샤드 크기를 정하고, 하루치가 그보다 작으면 어떻게 할지도 적습니다.

한 줄의 크기는 파일 크기 ÷ 줄 수로 구합니다.

샤드 하나에 10~50GB 를 목표로 잡습니다. 작은 샤드가 수천 개면 메모리와 파일 핸들을 그만큼 먹고 클러스터가 느려집니다.

하루치가 목표보다 작으면 날짜별 대신 주별로 만들거나 롤오버 조건(크기 기준)에 맡깁니다.

언제 무엇을 버릴 것인가

hot · warm · cold · delete 네 단계의 기간을 정하고, 각 단계에 얼마가 쌓이는지 05-tiers.txt 에 계산하세요. warm 이나 cold 에서 무엇이 달라지는지도 적습니다.

hot 은 쓰기와 검색이 모두 일어나고, warm 은 읽기 전용이라 세그먼트를 합치고 복제본을 줄일 수 있습니다. cold 는 느린 저장소나 객체 스토리지로 옮깁니다.

정하지 않으면 어느 날 디스크가 차고, 그때는 급하게 지우느라 필요한 것까지 지웁니다.

비용은 어디서 나는가

색인 쪽 비용과 검색 쪽 비용을 갈라 06-cost.txt 에 적고, 색인 비용을 줄이는 방법검색하지 않는 필드를 어떻게 다룰지를 함께 쓰세요.

초당 문서 수가 곧 CPU 입니다. 디버그 수준 로그를 운영에서 그대로 보내면 그 비용을 매일 냅니다.

검색은 안 하고 보기만 하는 필드는 index: false 로 두면 색인 비용과 저장 공간이 줍니다. 반대로 집계만 하는 숫자는 doc_values 만 있으면 됩니다.

정상 요청은 추적으로 대신하고 로그는 이상한 경우에만 남기는 쪽으로 옮기는 것도 방법입니다.

다음에 읽을 사람에게

여기서 본 것 중 넷 이상을 골라 07-notes.md 에 정리하세요. 무엇을 했는지가 아니라 왜 그런지를 적습니다.

새 필드를 라벨에 넣을지 고민하는 자신이 읽는다고 생각하세요. "카디널리티를 셌다" 는 도움이 안 되고, "pod 를 라벨에 넣으면 스트림이 여섯 배가 된다 — 편의는 한 사람의 것이고 비용은 클러스터 전체의 것이다" 는 도움이 됩니다.