服务器升级记——运维血泪史
服务器升级记——运维血泪史
事情是这样的, 老师最近的服务器需要新增两个4090显卡, 需要我去升级, 后续的管理可能也会交给我. 对于这种大展身手的好机会, 我还是很想尝试的. 一是还没有亲手升级过服务器, 二是一直心心念念的服务器管理最佳实践终于有了”落地”的对象. 于是, 我满怀信心的答应下来, 但没想到, 随之而来的是一大段意料之中, 但情况之外的情况.
开端: 重装
我一直对电脑上的文件排列, 软件安装之类的有一些洁癖(但是Linux下的FHS规范随着时代发展已经不太适用了, 部分软件理念为给每个用户单独安装, 部分软件安装到/opt下, 部分在/usr/local下, 这些软件又与我的理念有冲突, 可恶捏😧), 所以进入服务器的那一刻, 我就有点受不了了:
系统共有4个16T的机械硬盘与一个1T的固态, 系统装在固态之中, 每个固态硬盘都分为4个分区(有一个固态分为两个分区), 并各自分派给不同的用户, 挂载到用户home目录下. 但/home目录本身仍然处在固态硬盘中. 且, 用户名相当相当的混乱, 我并没有危言耸听, 因为现在用户名叫User1, User2…
以上操作会存在几个问题:
- 硬盘职责不清: 虽然给每个用户都分派了一个分区(一般在4T), 但是用户的home目录仍然在固态硬盘中, 如果后续涉及到系统损坏, 需要重装的话, 数据又在机械, 又在固态中, 不利于运维管理
- 用户管理混乱: 很明显, 实验室这种级别的服务器, 按理说用户名应该实名才对. 人员流动本来就大, 随着人员的不断毕业, 最后鬼知道
UserX是谁在用, 不会真打算靠”口口相传”吧 - 抗风险能力弱: 这条其实是第一条的衍生点. 硬盘有价, 数据无价, 现有的方案直接将分区分派给用户, 对于计算机专业学生来说, 4T过于大了, 无疑会造成空间的浪费; 对于生物信息的学生来说, 数据集特别大, 4T可能又放不下. 且, 损坏任意一个分区/硬盘, 对应上面的数据都会收到损坏.
基于以上几点, 促使我迫不及待地相对服务器系统进行重装, 之后按照我上面的问题一一针对性的进行解决与管理. 最终让我决定重装的导火索是: 服务器连不上网!(后续复盘才想到: 服务器上有两个网口, 其中一个网口有问题, 且他们给的网线也可能有问题)
这里我们选择了Ubuntu-2204-Desktop, 主要出于几点考量:
- 实验室服务器的网络不像云服务器那么那么的稳定, 如果使用
Server镜像, 那么默认没有图形桌面, 如果服务器出现了各种问题, 不利于排查 - 其他用户可能要用一些图形化的软件, 不太清楚是否能通过X11转发, 稳妥起见
所以稳妥起见, 还是安装桌面端比较合适.
于是就开始重装! 从这里开始, 坑就来了.
- 我有让他们对关键数据进行备份, 不过鉴于他们的数据过于大, 还有一些沟通问题, 最后并没有对数据进行备份. 另外, 当时我也还没有想到他们的用户/home目录上还存了东西(有4T了为什么还要存到home里, 或者说, 为什么不把用户home挂到机械上😭)
- 重装的时候, 我特地叫了室友在旁边一一确认, 重装之前最后确认了, 需要留下来的用户是
User1,User2,User4,User5, 对应的分区分别为sda1,sda2,sda4,sdd1. - 重装不涉及机械硬盘, 只是抹除了固态, 配置完网络, 皆大欢喜!
可以说, 重装过程还是非常谨慎的, 对于机械硬盘里面海量的数据, 确实是承载不起丢失的风险, 这锅太大了. 不过后面的一系列操作, 最终还是导致了坏的结局😢
关键节点: 升级硬件
接下来就是加装显卡与风扇, 还有更换电源了. 这部分实际上的工作量不小, 尤其是那个该死的机箱, 里面有个硬盘笼, 根本取不出来, 为了安装风扇, 减轻显卡散热压力, 只能一路拆下去: 拆了主板, 拆了风扇, 拔了SATA硬盘线(重点在这里), 最后花了两个小时, 才把那个硬盘笼给暴力拆出来.
接下来就是安装显卡驱动. 我们是魔改的48G显存4090, 不需要特殊的驱动, 直接打官方驱动就可以. 不过这里注意, 我们实际上并没有按照官方文档走, 而是使用以下命令:参考文档
# 查看可用驱动
ubuntu-drivers devices
# 安装推荐驱动即可
sudo ubuntu-drivers autoinstall接下来我们就可以通过nvidia-smi看到香喷喷的两张显卡了. 96G的显存确实任性😎
之后我们又开始更换电源, 买的金河田2000W真是一点没浪费, 整个电源基本上插的满满当当.
伏笔回收: 清理硬盘
硬件升级完毕之后, 我们就可以开始进行系统管理了, 以下是我的改造计划:
- 由于
sda和sdd两个盘不能动, 剩下两个盘不足以组成RAIDZ1, 如果配置为RAID1, 那么可用的空间只有16T, 无法满足现有用户的需求. 所以计划直接配置为ZFS的RAID0, 这样速度翻倍, 空间有32T. 不过损坏任意一个硬盘, 仍然会导致数据不可读, 不过原来也是损坏一个硬盘, 盘上数据不可读, 我觉得风险相较于原来并没有大更多(已经看过SMART信息, 两个盘都比较健康没有坏道), 且另外两个盘不是永远不能动, 等用户备份完毕之后, 我们就可以将其也加入进来, 重新组为RAIDZ1或者其他阵列, 总体风险是可控的. - 为每个用户创立自己的数据卷, 并设置限额1T, 这样即使用户后面有更大的空间需求, 我们一个set quota命令就可以实现.
- 每个用户的数据卷挂载到/home目录的用户同名目录下, 这样所有用户数据都放在机械硬盘里, 系统和机械硬盘职责划分清楚, 后面就算固态炸了数据也不会没.
- 用户命令采用实名制, 只有manager(管理账户)可以创建新用户, 只需要运行我提前写好的
create_zfs_user.sh脚本即可.
上面的方案是不是很舒服, 我也这么认为, 但是当我执行完毕之后, 真正的灾难开始了.
用户说sda和sdd的数据没了!!! 是不是令人十分困惑, 一路上我都是十分小心, 重装之前已经确定了, 可以删除的是sdb和sdc, 但是数据还是丢了. 后面复盘的时候想起来了, 之前重装的时候拔了SATA线, 后面插回去的时候, 槽位就可嫩和之前不一样了, 原来的sda现在可能变为sdb, 然后就被我删掉了🤡
其实在操作之前, 我还是想要再确认一次的. 我进行了以下尝试:
- 因为重装了系统, 所以原来的
/etc/fstab也没了, 排序命令肯定不会找到机械硬盘里面的文件. - 我挂载上去之后, 搜索文件并按文件大小降序排列, 但是死活都搜索不到机械硬盘里面, 只能搜索到固态硬盘里面的部分.
出于上面的原因, 最终并没有成功运行检查, 我最后向用户确认是否能够删除, 之后就开始操作了, 现在想想, 还是不够谨慎.
灾难恢复: 找回数据
操作完之后, 心里就隐隐感觉不对, 但是这个事儿实在是令人嗨怕, 不敢想不敢想. 直到用户直接反馈, 我才正式确认: 天塌了!!!
之后所有的锅都到我头上了: 什么一年的研究成果都在里面(我心想又不是运算数据, 代码而已, 我之前看到的那个效果也就是本科毕设水平, 需要用一年吗😠), 什么我不该删除之类的, 吧啦吧啦… 心累.(当初谁催我说, 我们的研究进度被我拖慢了, 服务器一直没搞好…)
没办法, 扛着巨大的道德压力, 只能尝试恢复看看了. 基于我对Linux和文件系统的理解, 我当时认为找回完整数据的可能性不大, 主要出于几点考虑:
- 原来是
ext4文件系统, 我换为了ZFS且组成了RAID0, 两个盘都会受影响 - 新的
ZFS系统, 已经写入了几个G的数据了, 所以数据肯定保不住
当时我就向他们释放了消极信号, 一个是让他们提前做好心理准备, 我也好根据他们的心理预期, 来调整方案(如果里面的数据不是那么重要, 或者已经备份了, 我也就不必要去恢复了). 不过我也还没有放弃, 问了AI之后, 给我推荐了testdisk软件包. 让我用里面的photorec对文件进行修复.
于是我开始使用photorec, photorec的原理是遍历整个盘, 然后根据文件特征来恢复数据(举个例子, .class文件的魔数CAFEBABE, 或者读取到的数据可读性等). 我开始运行之后, 预计30+小时, 且恢复出来的数据丧失了目录结构与文件名, 也就是说, 只能找回文件内容本身.
怎么说呢, 通过关键字, 还是能够找到关键数据的, 不过原来的硬盘里面, 到处都是Anaconda, RStudio之类的类库, 严重污染正常内容的查找与梳理. 心情没有变得更好, 也没有更坏, 只能说能找, 只有一点点.
随即我便将情况通知给了用户. 他们在与老师沟通之后, 决定让外面的人来进行恢复. 不过我觉得, 如果我不行, 外面的人应该也没戏. 所以, 还是靠我吧.
我找了淘宝店家, 部分店家提出了photorec的方案, 即”丢失文件名和目录结构”, 部分店家说前面的分区肯定寄, 后面的分区可以试试. 总得来说, 还是有一点希望的. 接着, 我又仔细地将我的情况叙述给了AI, 这次AI让我用testdisk命令本身. 之前AI预估的情况过于悲观, 但实际上, 我们的写入量并不大, 还没有覆盖盘内的绝大部分文件. testdisk可以查找硬盘的”原分区表”, 有了分区表, 我们就可以找到原来的分区, 而找到了原来的分区, 我们就可以找到分区里面的超级块(superblock), 有了超级块, 文件回来的概率就特别大了.
谢天谢地, testdisk一找就找到了, 它找到了所有的分区. 我执行了恢复, 并对硬盘进行检查, 发现两个盘除了第一个分区, 其他分区的数据全部找回来了. 达到这样的效果我已经很满意了, 而且重要的是, 那个用户号称”一年的成果”在第二个分区, 全都找回来了.
经验总结
经过这次升级服务器之后, 我得到了深刻的教训与经验, 说实话, 这种东西只有自己经历之后才会长记性, 所以总得来说是个好事.
表面来看, 每个操作都是合理的, 但是, 每个操作累积下来的疏忽, 导致了最终的问题. 所以, 这提醒我们在日常的操作中, 还是尽量避免侥幸心理. 我总结了一下几点:
- 如果可以, 不要接这种需求😂. 这是最快最简单的规避坑, 规避锅的办法, 没有金刚钻, 别揽瓷器活. 如果对Linux一知半解, 千万不要尝试直接上手处理别人的真实需求, hold不住的.
- 如果我们接收了, 谨慎接收”升级”类需求, 因为升级类需求不可避免的会涉及到数据保留的问题, 只要沾了手, 后续文件丢失的锅就是你的, 即使你提前问过有哪些要备份的.(他们会忘记一些文件, 然后在需要用的时候才想起来, 然后埋怨当时为什么要删除).
- 对于服务器的升级操作, 尽一切可能, 找一个对这方面熟悉一点的homie在旁边, 两个人一起商量, 监督命令的执行. 这样能够有效避免误操作, 就算是最后抗压, 也少一半压力.
- 如果可以, 尽量建群, 将自己的操作通知到可能受影响的所有人, 并征得所有人的同意, 或者, 征得”领导层”同意.
- 对服务器的”升级”操作, 在上述条件不能完全满足的情况下, 应尽可能保守, 尽可能不采取破坏性的操作, 避免造成无法挽回的后果.
每一个规定背后, 都是血淋淋的教训, 我们总是撞到南墙之后才会重新正视这些规则, 不过早些知道总归是好的. 不是说要将运维中的规则当做圣经和教条, 那样的话就死板成国企了(并非无脑黑🤪). 而是要时刻谨慎, 越是关键操作越是谨慎, 而在一些操作上可以适当灵活处理, 这样才能达到效率和安全的最大化.
附录: 文件查找及相关概念辨析
我让AI总结了一下文件的查找过程, 跟本文相关度较高, 这里作一个备忘与快查表
一、 文件查找流程:从物理硬盘到文件数据
操作系统定位并读取一个文件的过程,是一个从宏观到微观、层层递进的查询过程。以查找文件 /home/user/report.docx 为例,其完整流程如下:
- 定位物理硬盘与分区表 (Partition Table)
- 操作系统首先访问指定的物理硬盘。
- 它会读取硬盘的第一个扇区(对于MBR分区方案)或头部区域(对于GPT分区方案),以获取分区表。
- 分区表告知系统该硬盘被划分成了几个逻辑区域(即“分区”),以及每个分区的起始位置、大小和文件系统类型(如Ext4, NTFS)。
- ** 定位分区与超级块 (Superblock)**
- 根据分区表信息,系统找到包含
/home目录的根分区(/)的起始位置。 - 系统会读取该分区的引导扇区(Boot Sector),从中找到超级块 (Superblock) 的位置。超级块是整个文件系统的“总纲”,记录了此分区的宏观信息,例如区块大小、Inode 总数、数据块总数等。
- 遍历目录项 (Directory Entry) 以查找 Inode
- 文件系统从根目录
/开始查找。它会读取根目录的 Inode,找到其对应的数据块,这些数据块中存储着根目录下的所有目录项。 - 一个目录项是一条简单的记录,格式为 <文件名, Inode编号>。
- 系统在根目录的数据中搜索名为
home的目录项,从中获得home目录的 Inode 编号。 - 接着,系统重复此过程:读取
home目录的 Inode,找到其数据块,在其中搜索名为user的目录项,获得user目录的 Inode 编号。 - 最后,在
user目录的数据块中,找到名为report.docx的目录项,最终获得report.docx文件自身的 Inode 编号。
- 读取 Inode 以定位数据块 (Data Block)
- 有了
report.docx的 Inode 编号,系统便可以从 Inode 表中读取这个文件专属的 Inode。 - 这个 Inode 包含了
report.docx的所有元数据(文件大小、权限、创建时间等),以及最关键的信息:一个指针列表,该列表指向存储着文件实际内容的数据块 (Data Blocks)。
- 读取数据块获取文件内容 (Data)
- 最后,系统根据 Inode 中的指针,到磁盘的相应位置读取一个或多个数据块的内容,并将它们组合起来,从而获得完整的
report.docx文件数据。
二、 核心概念辨析
为了更清晰地理解上述流程,以下是对关键术语的辨析。
| 术语 (Concept) | 通俗比喻 (Analogy) | 核心作用 (Core Function) |
|---|---|---|
| 分区表 (Partition Table) | 一栋大楼的楼层分布图 | 在整块物理硬盘上划分出独立的逻辑区域(分区),并记录每个分区的边界和类型。 |
| 超级块 (Superblock) | 一个图书馆的中央索引台 | 描述单个文件系统(分区)的总体布局和状态,如存储容量、区块大小、Inode数量等。是文件系统的“户口本”。 |
| 目录项 (Directory Entry) | 图书馆目录卡片上的一行记录 | 建立 文件名 和 Inode编号 之间的关联。它是连接人类可读名称与系统内部标识的桥梁。 |
| Inode (索引节点) | 一张完整的图书馆目录卡片 | 存储文件的全部元数据(大小、权限、所有者等),并包含指向文件实际内容的数据块指针。 |
| 数据块 (Data Block) | 存放书籍的真实书架 | 文件系统中存储文件内容的最小物理单元。文件的实际字节流就保存在这些数据块中。 |
三、 流程总结
文件查找的完整链路可以简化为以下查询链:
文件名 → 目录项 (查找Inode编号) → Inode (查找数据块地址) → 数据块 (读取文件内容)