Loki — 로그를 색인하지 않는 로그 저장소 · LogQL 로 묻는다 · 실습
로그는 다 들어 있는데 무엇을 물어야 할지 몰랐다
목표
파드 안의 진짜 Loki 에 LogQL 을 직접 던져, 스트림 선택자와 줄 필터로 원하는 줄만 꺼내고 돌아온 JSON 의 모양까지 읽을 수 있게 됩니다.
왜 중요한가
Loki 에 질문을 던지는 일은 두 층으로 나뉜다. 먼저 선택자가 어느 스트림의 청크를 읽을지 정하고, 그 다음 줄 필터가 읽어 온 줄을 하나씩 맞춰 본다. 이 순서를 모르면 '왜 이 질의는 빠르고 저 질의는 느린가' 를 영원히 설명하지 못한다. 본문은 색인되어 있지 않으므로 줄 필터는 선택자가 고른 만큼을 전부 읽는다 — 그래서 사고 조사에서 가장 먼저 하는 일이 선택자와 시간 구간을 좁히는 일이다. limit 과 direction 도 사고 조사의 결과를 바꾼다. 방향을 모르고 limit 을 걸면 가장 중요한 첫 오류 대신 마지막 오류만 보게 된다.
단계
1. /root/lk-logql 에서 Loki 를 띄우고, date +%s 값을 /root/lk-logql/anchor.txt 에 한 줄로 적은 뒤 python3 /opt/lab/d5/gen.py logql "$(cat anchor.txt)" 로 자료를 넣으세요. 그리고 지금 Loki 에 스트림이 몇 개인지 세어 /root/lk-logql/01-boot.txt 에 streams=<정수> 한 줄로 적으세요.
2. 기준 시각에서 과거 한 시간 동안 app 이 web 이고 level 이 error 인 줄이 몇 줄인지 구하세요. 쓴 질의를 /root/lk-logql/02-selector.logql 에, 줄 수를 /root/lk-logql/02-selector.txt 에 lines=<정수> 한 줄로 적습니다.
3. 같은 한 시간 동안 세 서비스(web·api·worker) 전체에서 본문에 timeout 이 든 줄이 몇 줄인지 구하세요. 질의는 /root/lk-logql/03-line.logql, 답은 /root/lk-logql/03-line.txt 에 lines=<정수> 로 적습니다.
4. 세 서비스 전체에서 본문에 refused 가 들어 있고 rpc 는 들어 있지 않은 줄을 세세요. 질의는 /root/lk-logql/04-chain.logql, 답은 /root/lk-logql/04-chain.txt 에 lines=<정수> 로 적습니다.
5. 세 서비스 전체에서 본문에 500 또는 503 이라는 세 자리 숫자가 든 줄을 정규식 줄 필터 하나로 세세요. 질의는 /root/lk-logql/05-regex.logql, 답은 /root/lk-logql/05-regex.txt 에 lines=<정수> 로 적습니다. 질의에는 정규식 줄 필터 연산자가 반드시 들어가야 합니다.
6. {app="web",level="error"} 를 같은 한 시간 구간에 limit=5 로 두 번 질의하세요. 한 번은 direction=forward, 한 번은 direction=backward 입니다. 결과를 /root/lk-logql/06-order.txt 에 세 줄로 적습니다 — forward_first=<나노초 타임스탬프>, backward_first=<나노초 타임스탬프>, total=<구간 전체 줄 수>.
7. 아무 로그 질의나 한 번 던져 원본 JSON 을 보고 /root/lk-logql/07-shape.txt 에 세 줄을 적으세요. result_type= 뒤에는 data.resultType 의 값, ts_unit= 뒤에는 values 의 첫 칸이 어떤 시간 단위인지(ns·us·ms·s 중 하나), entry_len= 뒤에는 values 의 원소 하나가 몇 칸짜리 배열인지 정수로 적습니다.
8. web 과 api 두 서비스에서 본문에 timeout 또는 refused 가 든 줄만 골라, 그 중 가장 이른 줄의 나노초 타임스탬프와 전체 줄 수를 구하세요. 질의는 /root/lk-logql/08-triage.logql, 답은 /root/lk-logql/08-triage.txt 에 lines=<정수> 와 first_ts=<나노초> 두 줄로 적습니다. 질의에는 정규식 줄 필터가 들어가야 하고, worker 는 들어가면 안 됩니다.
참고
- 작업 디렉터리는
/root/lk-logql입니다. Loki 는 파드가 뜰 때 자동으로 켜지지 않습니다 — 1단계에서 직접 띄웁니다. - 자료 생성기는
/opt/lab/d5/gen.py입니다.logql자료를 기준 시각 인자와 함께 돌립니다. 채점기는 읽지 않으니 내용을 고칠 필요는 없습니다. - 질의는
logcli로도 던질 수 있습니다:LOKI_ADDR=http://localhost:3100 logcli query --limit=5 '{app="web"}'. 다만 이 실습의 답은 절대 구간으로 재야 하므로query_rangeAPI 를 직접 부르는 쪽이 정확합니다. - 흔한 실수:
since=1h로 재는 것. 시간이 흐르면 답이 달라져 재채점에서 떨어집니다.anchor.txt의 기준 시각으로start·end를 주세요. - 흔한 실수: 줄 필터의 문자열을 큰따옴표로 감싸는 것. LogQL 에서는 역따옴표가 안전합니다 — 역슬래시가 이스케이프로 해석되지 않습니다.
- [LogQL 개요](https://grafana.com/docs/loki/latest/query/) · [로그 질의](https://grafana.com/docs/loki/latest/query/log_queries/) · [HTTP API](https://grafana.com/docs/loki/latest/reference/loki-http-api/) · [라벨](https://grafana.com/docs/loki/latest/get-started/labels/)
단계 8개
- Loki 를 띄우고 하루치 대신 한 시간치를 넣는다
- 선택자만으로 볼 곳을 정한다
- 줄 필터로 본문을 뒤진다
- 필터를 이어 붙여 걸러 낸다
- 정규식 줄 필터
- limit 과 direction — 무엇이 잘려 나가는가
- 돌아온 JSON 을 읽는다
- 응용 — 한 질의로 사고 구간을 좁힌다