VPN 服务器的磁盘增长从何而来,以及如何设上限
日志增长、被改名的 inode 和无上限的 journal,最终都表现为一块满盘。测出增长速率,给写入方设上限,并在重启后验证上限。
隧道不再接受连接,服务重启了两次,随后日志里什么都没有。这份沉默就是线索:填满磁盘的正是日志,而守护进程已无处写下你正在等的那个错误。任何长期运行的服务都可能走到这一步,删掉一个叫 logs 的目录很少能解决。持久的办法是弄清哪个存储长大了、谁拥有它的保留策略,以及写入方究竟有没有真正把空间还回来。
找出长大的那个存储,以及它的增长速度
从两个容易被忘记的数字开始:空闲块和空闲 inode。文件系统可能报告空间充足,却因为 inode 用完而拒绝写入,这在服务为每个会话建一个文件时就会发生。要在同一个卷上同时要这两项读数,因为同一场下午它们就可能互相打架。请在主机健康时做,这样数字描述的是正常运行,而不是一次故障。
df -h /var
df -i /var然后把增长归到某个责任方。journal 自己的用量数字只覆盖 journal,它永远看不到某个守护进程按配置文件里的路径写文件。
journalctl --disk-usage随时间变化的增长比任何单次读数都说明问题。一直开着的调试级别、每条尝试都记录的重复重试循环,或者没人停下的抓包文件:每一样都可能在一刻显得平常,一小时后变得刺眼。测一次,等过一个忙碌时段,再测一次,然后除以间隔。一个你说得出口的速率,能把容量问题变成决定,而不是火警。
轮转对打开的文件做了什么
日志文件是指向某个 inode 的名字,空间只有在最后一个打开的句柄关闭时才归还。把文件改名,写入方仍往同一个 inode 里填;把它删掉,写入方仍往一个完全没有名字的 inode 里填。正因为如此,「我删了文件但磁盘还是满的」说的是文件描述符,而不是坏掉的文件系统。重启写入方,或者选一种会重新打开文件的轮转方式,才真正把块还回来。
lsof +L1 | head策略属于写文件的那个组件。journal 从自己的配置文件执行存储上限,而以文件为基础的服务通常依赖 logrotate:要么用创建规则加重新打开信号,要么在写入方无法重开时用就地截断。先什么都不改,把决定确认下来:
logrotate -d /etc/logrotate.conf上限该放在哪里,又该有多大
把上限放在写入方被配置的地方,而不是挂载点。对整个卷设配额能保护主机,却说不清哪个服务先挂,而全局清理脚本往往会把下一次事故需要的证据删掉。journal 的上限、带最大大小的轮转份数、应用层的保留,各自约束一个生产者。合起来才约束总量;单独看,每一个都只是猜测。
按你站得住脚的保留期来定这个上限,而不是按剩余空间。如果一次复查需要一周的连接尝试,journal 就必须在最忙的预期速率下留够一周,而那个速率正是此前测出的数字。
调试日志是有开始时间的临时模式,不是存储方案。把隐私问题放进同一个决定里,因为连接日志带着地址和标识。更长的保留期也是数据处理上的选择,应当由同时了解这两项约束的人来定。
重启之后验证上限
只撑到下次重启的保留期改动不算改动。重启写入方,确认新上限生效,再检查轮转之后仍然运行。对 journal 来说,一次重启加一次用量读数就回答了这两个问题:
systemctl restart systemd-journald
journalctl --disk-usage对以文件为基础的服务,手动跑一次轮转任务,确认文件被替换、描述符被重新打开。还握着旧句柄的写入方能通过表面检查,却会在卷再次填满时失败。测试期间盯着剩余空间,因为文件变小而空间没回来,说明旧的 inode 仍被占着。
把下一次读数与这次对比
一周后回来,把增长速率与记录值对比。速率相符意味着上限站得住、负载稳定;速率翻倍意味着有东西变了,而有用的问题是变了什么。先读日志内容找重复失败,因为重试循环既是症状也是量的原因。再检查任何新开的东西,包括事故中打开后再没关掉的调试级别。
把备份放到同一个卷之外,或者接受一块满盘会把备份一起带走。写在它所保护的主机上的副本不是恢复方案,它的保留也要有自己的答案。
写下保留什么、放在哪里、保留多久、由谁删除。这句话就是交付物,也是这项工作里唯一能活过下次重启的部分。