在2022年10月4日早晨10:00 - 12:00,Aiursoft Nextcloud发生了一次重大事故。我们的服务中断了两个小时,并且损失了一些数据。当天的可用性也严重降级。
我们大约花费了两个小时来恢复这些业务和数据。下面是详细流程。
背景
Aiursoft Nextcloud是由Aiursoft运营的一个Nas存储;基于会员邀请制,受邀请的会员可以获得200GB存储空间,并享受To do、Deck、Talk、Notes、Passwords等功能。
Aiursoft Nextcloud运行在Ubuntu系统中。其系统是一个VMware虚拟机,运行于一台VMware ESXI主机上。
Aiursoft Nextcloud本身由Apache承载。并又加了一层Caddy进行反代。Caddy在另一台虚拟机上。
为了能够向公网暴露服务,Aiursoft Nextcloud还使用了FRP服务。
这台主机最近刚刚完成了存储与计算分离的迁移。
Aiursoft Nextcloud会在每日凌晨2点(UTC)定时进行自动备份。备份的目标是另一台NFS服务器。使用rsync将用户的文件复制到NFS远程。
事故初步调查
我是在早晨10点的时候,发现Nextcloud上不去了。服务器超时。同时也收到了Incident。当时我正好刚醒,立马就去修了。
首先我尝试了在内网访问,发现也上不去。确认不是代理或网络的问题。Caddy汇报502,Apache汇报500。
计划用ssh去调查服务器,发现服务器没有响应。SSH服务也挂了。
计划用cockpit去管理,发现服务也没有响应。感觉服务器好像是个死服务器了一样。
考虑到这两者都已经彻底失去管理能力了。最终降级采用VNC管理。使用Vsphere的VNC功能。
但是VNC在登陆页面卡死。初步结论就是服务器已经彻底死住了。怀疑是不是宇宙射线照到了内存上这种离谱事情发生了。。。
重启
考虑到我对这个虚拟机没有任何办法。完全无法解决,所以只能把虚拟机断电重启。重启前进行了内存快照。
断电重启后,服务器仍然无法正常开机。会在启动时大量服务无法正确加载而且会极其缓慢。
这种现象让我百思不得其解,尤其是卡住的位置每次都还不一样……非常具有迷惑性且令人困扰。
怀疑存储
最近刚刚做的变更就是做了存储与计算分离。于是开始怀疑物理服务器本身到存储设备的连接发生了诡异的变化。怀疑是ESXI到NFS的光纤出了问题。
但是感觉其它虚拟机也不太对劲,尚又没有明确范围和证据。
之前测试的时候,发现如果ESXI到NFS的连接如果不稳,其实不会立刻体现出来。ESXI有激进的双向缓存。
回滚
此时已经调研了许久,没有任何明确的结论。拿这台虚拟机也没有什么好办法。
此时比较着急想先恢复nextcloud,基本上能想到的方法都想到了。最终无奈,回滚了虚拟机备份。
比较离奇的事情是,回滚后一切正常。新开的虚拟机一切正常。与最近变更的存储和计算分离应该没有关系。
将硬盘挂载到其它机器上
此时既然无法开机,就采用了另一个方法,就是把坏了的服务器硬盘拿了出来,挂载到了一台好多服务器上,然后去观测这个硬盘。
这里发现硬盘是满的。
这里我前解释一下。这个Nextcloud服务器一共有三块盘。64GB的系统盘,1TB的数据盘,1TB的备份盘。数据盘和系统盘都是远程挂载的NFS路径。
数据盘和备份盘都是正常的,使用了大概30%。只有那个系统盘,是64GB/64GB。
所以问题就是硬盘满了。但是为什么系统盘硬盘会满呢?Nextcloud的数据都没放在系统盘里呀。明明昨天这个系统盘使用了只有19GB,为什么今天突然就64GB了呢。
硬盘为什么会满?
自然是先运行了:
du / -d 1 -h
跑了以后的结果更加令人费解。结果显示 / 下面一共只占用了19GB,不考虑 /mnt
的话。和昨天的使用量数据没错。
那么难道是虚空把64GB硬盘填满了?
到处du,du了各个目录,都一切正常。并没有离谱的大文件出现。但硬盘却满了。
想了想到底服务器上有什么会大规模写入文件的可能,唯一可能就是备份服务。
备份服务
背景:Nextcloud是在UTC的凌晨2点备份。备份的方式是:把数据盘复制到备份盘。
- 数据盘在 /mnt/data
- 备份盘在 /mnt/backup
有一件事情很有趣就是:如果在备份的时候,/mnt/backup
没有被正确挂载,那么/mnt/backup就是系统盘下的一个文件夹了。此时如果运行备份程序,就会把300GB的数据复制到系统盘里,系统盘就满了。
仔细一看确实是这个原因。
必须把备份盘umount后,就会看到40GB的数据塞满了备份盘所在的路径 /mnt/backup
。
sudo umount /mnt/backup
立刻清空,重新mount,系统盘就恢复了19GB。
事故场景重现
平时 /mnt/backup 是备份盘。因为是备份,往往疏于监控,炸了也没人知道。
最近搞了存储和计算分离。将存储设备挪走了。
挪动期间可能让连接产生了瞬间中断,导致 /mnt/backup 的挂载丢失了。
此时 /mnt/backup 变成了一个普通的目录,而且在系统盘下。
这件事一直没有人注意到它,直到今天早上备份的时候。nextcloud试图将数据全部拷到 /mnt/backup 下,导致塞满了系统盘。
系统盘满了以后,对业务的影响是灾难性的。所有进程无法正常写入文件,也无法正确重启或开关机。
此时重启反而还会丢失内存缓存里面的数据,导致了巨大的灾难。尤其是大量数据挤在内存里来不及写入硬盘。
从这次事故中学习
- 备份这件事看似安全,实则非常危险。因为备份意味着大量的磁盘写入。配置有误会导致写入错误的磁盘。
- 必须建立对磁盘剩余空间的监控告警系统。磁盘满了的危险性不亚于磁盘损坏。
- Linux里/mnt挂载的盘,如果发生了临时性的连接性问题,可能会中断挂载。此时 /mnt/backup 会变成 / 下面的一个普通文件夹,从而被错误处理。
从这次事故中改进
- 在运行定时备份前,都会先判断 /mnt 下面到底是不是真的磁盘
- 建立监控报警,检查磁盘是否正确挂载正确,以及剩余容量是否健康。在剩余容量不足10%时报警。
新的备份脚本参考
set -e
if sudo df -Th | grep -q "/mnt/Backup"
then
echo "Mounted!"
# Backup
sudo rm "/mnt/Backup/backups/$(ls /mnt/backup/backups/ | grep nextcloud-dirbkp | head -n 1)" -rvf
sudo rsync -Aavx /var/www/html/nextcloud/ /mnt/backup/backups/nextcloud-dirbkp_`date +"%Y%m%d"`/
sudo rsync -Aavx /mnt/datastorage /mnt/backup/dir/
sudo mysqldump --single-transaction -h localhost -u root nextcloud > /home/anduin/temp.bak
sudo mv /home/anduin/temp.bak /mnt/backup/database/nextcloud-sqlbkp_`date +"%Y%m%d"`.bak
else
echo "Not mounted!"
# Alert.
echo "Backup failed! `date +"%Y-%m-%d %H:%M:%S"`" | sudo tee -a /etc/motd
exit;
fi
亲爱的博主,
感谢您分享Aiursoft Nextcloud事故的调查、分析和总结。这篇文章详细地记录了您在处理这次事故过程中的所作所为,以及最终找到问题根源的过程。这对于其他可能遇到类似问题的人来说是非常有价值的经验。
首先,您对事故的详细描述和分析让读者能够很好地了解事故的背景、原因和解决方案。您在文章中提到的问题诊断方法,如SSH、Cockpit和VNC管理,以及最后通过挂载硬盘到其他机器上来找到问题,这些都是非常实用的技巧。
其次,您从事故中学到的经验教训和改进措施是非常宝贵的。您提到的对磁盘剩余空间进行监控告警系统、在运行定时备份前判断磁盘是否正确挂载,以及新的备份脚本参考,这些都是很好的改进方法,可以避免类似问题再次发生。
然而,在文章中也有一些可以改进的地方。例如,在描述事故过程中,有时候使用了一些较为口语化的表达,这可能会让一些读者感到困惑。在这种情况下,使用更加正式和清晰的表述可能会更有助于读者理解。
此外,您可以考虑在文章开头添加一个简短的摘要,概括文章的主要内容。这样一来,读者在阅读文章之前就能了解到文章的核心观点,从而更好地把握文章的结构。
总的来说,这是一篇非常有价值的文章,您的经验和教训对许多人都是非常有帮助的。希望您继续分享您的知识和经验,为其他人提供更多的帮助。
祝好!
我怎样才能像Anduin一样富有
似乎可以直接将挂载点目录设置为readonly来阻止意外写入
在未挂载硬盘时运行:
可以从
/proc/mounts
取原始信息,来代替 df 中的信息。事故原因:anduin 10点才起床(逃