TT Lab
开始
学习 学习路径 课程

Loki — 不索引日志的日志库

一提交就从界面上消失了,存储用量却一个月没变

在 TT Lab 中继续学习

目标

亲手写出打开保留并按流设置不同期限的设置并验证,用这份设置启动第二个 Loki,再提交删除请求,用数字确认接收与真正删除之间的时间间隔。

为什么重要

Loki 出厂时保留功能是关闭的。如果没有人打开它,放进去的日志就永远留着,直到账单变成四倍才发现这件事。删除请求也同样有两层——在默认方式下,请求一被接收,查询就会立刻过滤掉那些行,但从存储的对象中真正删除,要等取消等待期过后由 compactor 来做。把“看不见”读成“已删除”,合规报告就会出错,容量规划也会错位。确定保留期限,必须从实测而不是估算出发——查询响应附带的字节数,就是这个出发点。

步骤

  1. 在 /root/lk-retention 中启动 Loki,把 date +%s 写入 /root/lk-retention/anchor.txt,然后用 python3 /opt/lab/d5/gen.py retention "$(cat anchor.txt)" 放入数据。接着用一小时区间分别查询 audit 和 debug 两个流,把响应统计中读取的字节数,以 audit_bytes=<정수> 和 debug_bytes=<정수>(占位符为整数)两行写入 /root/lk-retention/01-bytes.txt。
  2. 用第 1 步一小时的字节数,计算每个流的存储量,做出 /root/lk-retention/budget.tsv。不要表头,共两行,每行是用制表符分隔的四列 <스트림><탭><한시간바이트><탭><보존일수><탭><보존기간총바이트>(占位符依次为流、制表符、每小时字节数、制表符、保留天数、制表符、保留期内总字节数)。流依次为 audit、debug,保留天数分别取 365 和 1。总字节数是 한시간바이트 × 24 × 보존일수(占位符依次为每小时字节数、保留天数)。
  3. 写出 /root/lk-retention/loki-ret.yaml。以现在在用的 loki.yaml 为基础,再加上以下内容——server.http_listen_port 为 3200,server.grpc_listen_port 为 9096,存储路径放在 /tmp/lokiret 之下,compactor.retention_enabled 为 true,compactor.delete_request_store 为 filesystem,指定 compactor.working_directory,limits_config.retention_period 为 720h。并且 loki -config.file=/root/lk-retention/loki-ret.yaml -verify-config 必须没有任何错误地结束。
  4. 在 /root/lk-retention/loki-ret.yaml 的 limits_config 里加上 retention_stream 列表,让 {app="debug"} 保留 24h,{app="audit"} 保留 8760h。优先级分别明确写为 1 和 2。然后在 /root/lk-retention/04-rules.txt 中写两行——rules=<규칙 개수>(占位符为规则个数)和 verify=ok(在 -verify-config 通过时)。
  5. 用 /root/lk-retention/loki-ret.yaml 启动第二个 Loki,等到 http://localhost:3200/ready 返回 ready 为止。然后从该服务器的 /config 里读出三个值,写入 /root/lk-retention/05-run.txt——retention_enabled=<값>、retention_period=<값>、compaction_interval=<값>(占位符均为值)。
  6. 往 3200 端口的 Loki 里放几行,然后请求删除其中一个流的一个区间。请求是向 POST /loki/api/v1/delete 传入 query、start、end。再在 /root/lk-retention/06-delete.txt 中写三行——post_code=<HTTP 상태 코드>、requests=<목록에 있는 요청 수>、status=<그 요청의 status 값>(占位符依次为 HTTP 状态码、列表中的请求数、该请求的 status 值)。
  7. 再次查询你请求删除的那个区间,数一数现在能出来几行,并在服务器设置里找出实际删除是什么时候发生的并确认。在 /root/lk-retention/07-async.txt 中写四行——still_visible=<정수>、mode=<deletion_mode 값>、param=<실제 삭제까지 기다리는 시간을 정하는 설정 이름>、value=<서버가 찍은 값 그대로>(占位符依次为整数、deletion_mode 的值、决定等待多久才真正删除的设置名称、服务器印出的值原样)。
  8. 在 /root/lk-retention/policy.txt 中写五行——audit_period=、debug_period=(两者都原样取设置里写的值)、audit_bytes_total=、debug_bytes_total=(第 2 步表中的最后一列)、note=(去掉空格后至少 60 个字,同时写出为什么把两个期限定得不同,以及删除请求不会立即生效这一事实)。

参考

放入两种日志,测量实际字节数

在 /root/lk-retention 中启动 Loki,把 date +%s 写入 /root/lk-retention/anchor.txt,然后用 python3 /opt/lab/d5/gen.py retention "$(cat anchor.txt)" 放入数据。接着用一小时区间分别查询 audit 和 debug 两个流,把响应统计中读取的字节数,以 audit_bytes=<정수> 和 debug_bytes=<정수>(占位符为整数)两行写入 /root/lk-retention/01-bytes.txt。

统计是 query_range 响应中的 data.stats.summary.totalBytesProcessed。两个流的性质不同——一个是偶尔才积累的审计记录,一个是每秒喷出好几行的调试日志。容量规划就从这个差别开始。

从实测值计算保留预算

用第 1 步一小时的字节数,计算每个流的存储量,做出 /root/lk-retention/budget.tsv。不要表头,共两行,每行是用制表符分隔的四列 <스트림><탭><한시간바이트><탭><보존일수><탭><보존기간총바이트>(占位符依次为流、制表符、每小时字节数、制表符、保留天数、制表符、保留期内总字节数)。流依次为 audit、debug,保留天数分别取 365 和 1。总字节数是 한시간바이트 × 24 × 보존일수(占位符依次为每小时字节数、保留天数)。

这个计算的要点,是把两行的最后一列并排放着看。行数多十倍的一方如果保留期限短,总量可能会反过来——这种逆转,就是保留策略要按流区分的原因。

写出打开保留的设置并验证

写出 /root/lk-retention/loki-ret.yaml。以现在在用的 loki.yaml 为基础,再加上以下内容——server.http_listen_port 为 3200,server.grpc_listen_port 为 9096,存储路径放在 /tmp/lokiret 之下,compactor.retention_enabled 为 true,compactor.delete_request_store 为 filesystem,指定 compactor.working_directory,limits_config.retention_period 为 720h。并且 loki -config.file=/root/lk-retention/loki-ret.yaml -verify-config 必须没有任何错误地结束。

-verify-config 不仅检查语法,也检查设置的组合是否讲得通——通过的话没有输出。两个端口都要改的原因,在下一步就会显露出来。如果不改存储路径,两个进程就会使用与现在运行的 Loki 相同的目录。

按流设置不同的保留期限

在 /root/lk-retention/loki-ret.yaml 的 limits_config 里加上 retention_stream 列表,让 {app="debug"} 保留 24h,{app="audit"} 保留 8760h。优先级分别明确写为 1 和 2。然后在 /root/lk-retention/04-rules.txt 中写两行——rules=<규칙 개수>(占位符为规则个数)和 verify=ok(在 -verify-config 通过时)。

retention_stream 是由 selector、priority、period 三项组成的条目列表。选择器就是 LogQL 流选择器的语法,要放在引号里。如果不写优先级,重叠的规则里哪边获胜就难以预测。

启动第二个 Loki——端口有两个

用 /root/lk-retention/loki-ret.yaml 启动第二个 Loki,等到 http://localhost:3200/ready 返回 ready 为止。然后从该服务器的 /config 里读出三个值,写入 /root/lk-retention/05-run.txt——retention_enabled=<값>、retention_period=<값>、compaction_interval=<값>(占位符均为值)。

日志要留成文件(> ret.log 2>&1)。如果马上就挂了,看那个文件的最后一行——只改一个端口时出的错就原样写在那里。/ready 要 20 秒左右,所以不要用固定的 sleep,要用检查条件的循环。

提交删除请求并查看列表

往 3200 端口的 Loki 里放几行,然后请求删除其中一个流的一个区间。请求是向 POST /loki/api/v1/delete 传入 query、start、end。再在 /root/lk-retention/06-delete.txt 中写三行——post_code=<HTTP 상태 코드>、requests=<목록에 있는 요청 수>、status=<그 요청의 status 값>(占位符依次为 HTTP 状态码、列表中的请求数、该请求的 status 值)。

区间要用以秒为单位的整数给出(不是纳秒)。列表用 GET 向同一个路径询问。如果请求被以 400 拒绝,看看有没有设置 delete_request_store,区间是不是写反了。

应用 ① ——看不见和被删掉是两回事

再次查询你请求删除的那个区间,数一数现在能出来几行,并在服务器设置里找出实际删除是什么时候发生的并确认。在 /root/lk-retention/07-async.txt 中写四行——still_visible=<정수>、mode=<deletion_mode 값>、param=<실제 삭제까지 기다리는 시간을 정하는 설정 이름>、value=<서버가 찍은 값 그대로>(占位符依次为整数、deletion_mode 的值、决定等待多久才真正删除的设置名称、服务器印出的值原样)。

查询结果为 0,不等于存储里已经删掉了。在 /config 里找出表示删除方式的设置,以及 compactor: 块里的“可以取消请求的期间”。把两个值并排放在一起,就能得出“为什么容量不降”的答案。

应用 ② ——把保留策略钉成文档

在 /root/lk-retention/policy.txt 中写五行——audit_period=、debug_period=(两者都原样取设置里写的值)、audit_bytes_total=、debug_bytes_total=(第 2 步表中的最后一列)、note=(去掉空格后至少 60 个字,同时写出为什么把两个期限定得不同,以及删除请求不会立即生效这一事实)。

策略文档里的值如果与设置文件错位,这份文档还不如没有。要原样从设置里取。最后一行是写给下一个接手这个集群的人读的句子——把数字的依据和时间延迟一起写下来,就不会被问两遍同样的问题。