LabHub
学习 学习路径 课程

日志流水线设计

create 与 copytruncate

在 LabHub 中继续学习

一句话总结

create虽然不会丢失日志,但需要过程的配合copytruncate虽然不需要**配合,但会失去一点日志。**两者都不是一劳永逸的。

概念图: 日志,但需要过程的配合 · 配合,但会失去一点日志。 · 打开文件 · create— 改名字重新制作

为什么需要这个?

日志文件越大,磁盘就会冻结。但是进程在打开文件的情况下使用,所以不能直接删除。在Linux上rm只删除目录项,打开的文件的块在最后一个手柄关闭之前不会返回。所以df说被挤得紧紧的du据说没有文件。

轮换以两种方式解决了这个问题。

create— 改名字重新制作

app.log → app.log.1 로 rename
새 app.log 생성
프로세스에 SIGHUP 을 보내 다시 열게 한다

rename 会保持inode的原样,所以进程会仍然用在旧文件上。所以必须重新打开。如果不这样做,新的app.log永远是0字节,实际日志是app.log.1继续流下去。虽然没有丢失日志,但没有人能找到。

copytruncate— 复制后剪下来

app.log → app.log.1 로 복사
app.log 를 0바이트로 truncate

因为文件是原样,所以进程什么都不用知道。相反,**复制和剪切之间使用的日志会消失。**如果每秒积累数千行日志,那么这个缝隙就很大。

怎么行动

/var/log/app/*.log {
    daily
    rotate 14              # 14개까지 보관
    size 100M              # 또는 100MB 넘으면
    compress
    delaycompress          # 직전 것은 압축하지 않는다(아직 쓰고 있을 수 있다)
    missingok
    notifempty
    create 0640 app app
    postrotate
        kill -HUP $(cat /run/app.pid) 2>/dev/null || true
    endscript
}

delaycompress去很重要。create虽然从方法上讲,过程可能还在旧文件中使用,但如果直接压缩的话,就会导致使用失败。

常见的误解

在容器中运行logrotate。容器通常将日志输出到stdout。然后容器运行时(containerd)将日志写入文件,并**运行时旋转。**kubelet的containerLogMaxSize(基本10Mi),containerLogMaxFiles(基本5)就是那个设置。没有理由在容器内运行logrotate。

**轮换会破坏收集器。**像Fluent Bit这样的收集器以inode为基准跟踪文件。create如果rename的话,收集器可能会一直读取旧的inode,然后错过新文件。Rotate_Wait设置填补了那个缝隙。

在集装箱上不直接进行轮换。

到目前为止的故事是关于在文件中使用的过程。在容器中标准输出 使用后,轮换交由运行时处理。

// /etc/docker/daemon.json 또는 containerd 설정
{"log-driver": "json-file",
 "log-opts": {"max-size": "10m", "max-file": "3"}}

如果没有这个设置,日志文件会无限增长**填满节点的磁盘。**然后 那个节点的所有派对都会死亡。在容器管理中,节点DiskPressure罗帕德 是驱逐事故的常见原因。

kubelet方面也有同样的设置(containerLogMaxSizecontainerLogMaxFiles). 容器运行时设置和kubelet设置中哪一个适用,取决于运行时。 因为不同,所以确定在节点上确认实际文件大小是确定的。

du -sh /var/log/pods/* | sort -h | tail -5

日志消失的三位数字

与轮换分开,日志在多个地方安静地消失。

**缓冲。**进程死亡时,缓冲中的内容会消失。Python是 PYTHONUNBUFFERED=1,Shell脚本是stdbuf -oL换算成罗单位。

收集器队列超出。 Fluent Bit·Vector 当内存缓冲区满了时会丢弃新日志 (基本政策)。换成磁盘缓冲区会减少丢失,但会写入节点磁盘。

# Fluent Bit — 넘칠 때 디스크로
[SERVICE]
    storage.path              /var/log/flb-storage/
    storage.max_chunks_up     128
[INPUT]
    storage.type              filesystem

删除容器。如果帕德被删除的话/var/log/pods下面也会消失。所以 要看死去的帕德的日志,以后必须收集器在之前拿走。收集器 每30秒扫描一次,如果中间有pad被抹掉的话,就没有最后的日志了。terminationGrace 稍微增加PeriodSeconds的话,那个窗口就会变小。

要留下什么日志呢?

无论如何设置轮换,如果**量太大的话,就会变成费用。**遵守三个条件的话 大大减少。

在实际工作中真正重要的东西

保管期限规定为需要调查法规,而不是磁盘。不是“磁盘剩余后90天”,而是“调查障碍一般需要2周,审计要求为1年”,则分为热存储2周+冷存储1年。

而且**压缩几乎总是有利的。**文本日志以gzip压缩,减少了10~20倍。稍微使用CPU,大大节省了磁盘空间。