技术指南

Linux 数据盘上线:识别签名、验证 fstab 与安全扩容

先识别云卷与存储层,再用候选 fstab、真实写入探针和分层扩容完成可回滚的数据盘上线。

数据盘上线最危险的误判,是把“没有挂载点”当成“没有数据”。`MOUNTPOINTS` 只描述当前挂载关系;磁盘还可能带有文件系统、分区表、LVM、LUKS 或 RAID 签名。安全流程应先把云卷身份、块设备、存储层和现有签名对应起来,再决定复用、创建文件系统或扩容。

先看清从云卷到目录的每一层

要回答的问题常用只读证据
云平台卷 ID、区域、容量和挂载实例是否正确控制台/API 记录与变更单
块设备稳定路径实际指向哪个 disk/partition`readlink`、`lsblk`、`/dev/disk/by-id`
容器层是否存在 MD、LUKS、LVM 或分区`lsblk` 的 TYPE、父子关系与专用工具
文件系统类型、UUID、标签和签名是否唯一`blkid -p`、只读 `wipefs`
挂载来源、目标和实际选项是什么`findmnt` 与候选 fstab

用固定列保存现状

保留命令版本、UTC 时间和完整输出;脚本中显式指定列,避免依赖可能变化的默认格式
date --utc --iso-8601=seconds
lsblk --paths --bytes --output NAME,TYPE,SIZE,FSTYPE,FSVER,LABEL,UUID,PARTUUID,MOUNTPOINTS
findmnt --real --output TARGET,SOURCE,FSTYPE,OPTIONS
findmnt --fstab --evaluate --output TARGET,SOURCE,FSTYPE,OPTIONS
ls -l /dev/disk/by-id/

设备与文件系统不是一一对应关系:一个文件系统可能跨多个设备,一个磁盘也可能通过分区、加密、RAID 和 LVM 才到达文件系统。`findmnt --target /path` 会返回包含该路径的文件系统;要确认某个目录本身就是挂载点,应使用 `--mountpoint`,避免把父文件系统误认为目标盘。

把提供商卷 ID 落到稳定设备路径

REPLACE_WITH_PROVIDER_VOLUME_ID 必须替换为本次变更单中的真实稳定路径;最后一条命令没有擦除选项,只列出可见签名
device=/dev/disk/by-id/REPLACE_WITH_PROVIDER_VOLUME_ID
test -b "$device"
readlink -f "$device"
lsblk --paths --bytes --output NAME,TYPE,SIZE,FSTYPE,FSVER,LABEL,UUID,PARTUUID,MOUNTPOINTS "$device"
sudo blkid -p "$device"
sudo wipefs --noheadings --output DEVICE,OFFSET,TYPE,UUID,LABEL "$device"

低层 `blkid -p` 返回 0 表示识别到内容,返回 8 表示检测到冲突签名;这两种情况都不能进入新建文件系统步骤。返回 2 只说明本次探测没有识别到设备标识或内容,并不单独证明设备可安全覆盖,还必须核对卷身份、父子层、持有者、挂载和备份。

把结果归入复用、创建或恢复

观察结果下一步禁止的捷径
已知文件系统且 UUID/容量符合记录只读挂载或离线检查后复用重新格式化“确保干净”
分区、LVM、LUKS 或 RAID 签名用对应层的工具继续识别直接在外层设备创建文件系统
冲突、未知或卷身份不一致停止并做恢复取证擦签名后重试
所有身份与空白条件均被正向确认在维护窗口创建文件系统仅凭探测无输出执行

新建文件系统是一条单独审批的破坏性动作

只有在卷 ID、稳定路径、容量、父子关系、签名、持有者与备份全部核对后,才执行下面的 ext4 示例。不要加 `-F` 绕过工具的设备形态保护;若目标是分区,应把稳定路径指向已审批的分区而不是整盘。执行人应再次口头或书面核对解析后的真实路径。

这段命令会在目标设备上创建新文件系统;不要作为无人值守脚本运行,也不要粘贴未替换的占位符
device=/dev/disk/by-id/REPLACE_WITH_PROVIDER_VOLUME_ID
test -b "$device"
resolved=$(readlink -f "$device")
printf 'DESTRUCTIVE TARGET: %s -> %s\n' "$device" "$resolved"
lsblk --paths --output NAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS "$device"
# 审批人核对上述输出后,才单独执行下一行
sudo mke2fs -t ext4 -L data -- "$device"
sudo blkid -p "$device"

创建后重新读取 TYPE、UUID 与 LABEL,并把新 UUID 写入变更记录。UUID 比 `/dev/vdb` 之类的探测顺序名称更适合 fstab,但克隆卷可能复制 UUID;上线前用 `lsblk -o +UUID,PARTUUID` 检查系统内是否重复。

先生成候选 fstab,不直接追加生产文件

先创建 `/srv/data` 并设置预期的所有者与模式;候选文件验证失败时不要安装,也不要运行挂载
work=$(mktemp -d)
sudo cp --preserve=mode,ownership /etc/fstab "$work/fstab.candidate"
uuid=$(sudo blkid -p -s UUID -o value "$device")
test -n "$uuid"
printf 'UUID=%s /srv/data ext4 defaults 0 2\n' "$uuid" \
  | sudo tee -a "$work/fstab.candidate" >/dev/null
sudo findmnt --verify --verbose --tab-file "$work/fstab.candidate"

`findmnt --verify` 检查候选表的可解析性和可用性,是 util-linux 推荐的 fstab 检查入口。它不是实际 I/O 验收:UUID 指向的设备、挂载权限、文件系统状态和应用写入路径仍要通过真实挂载验证。第六字段 `2` 表示非根文件系统的启动检查顺序;是否适合目标文件系统和发行版仍需确认。

是否使用 nofail 是业务可用性决策

`nofail` 的定义是设备不存在时不报告错误,它不等于数据服务安全降级。可选缓存盘可以考虑 `nofail`,但应用必须先确认 `/srv/data` 确实是目标挂载点;否则进程可能把数据写进根文件系统上的同名空目录。持久数据盘通常应让依赖服务等待正确挂载,并把缺盘视为启动失败。

实际挂载、写入探针和安装配置分三步

APP_USER 替换为真实服务账号;`mount --all` 会执行挂载,不是语法检查,只能在维护窗口运行
# 先停掉会读写 /srv/data 的服务,并保留独立控制台
sudo mount --all --fstab "$work/fstab.candidate"
findmnt --mountpoint /srv/data --output TARGET,SOURCE,FSTYPE,OPTIONS
df --output=source,fstype,size,used,avail,target /srv/data
sudo -u APP_USER sh -c 'printf write-probe > /srv/data/.vpscope-write-probe && sync'
sudo -u APP_USER grep -qx write-probe /srv/data/.vpscope-write-probe
sudo -u APP_USER rm /srv/data/.vpscope-write-probe

挂载成功后还要核对来源、类型、容量和实际选项;写入探针验证的是目标服务账号,而不是 root。若任一项不符,先停止应用并卸载本次挂载,再修正候选。只有全部通过后,才保存受保护的 `/etc/fstab` 备份并用候选文件替换;随后再次运行 `findmnt --verify`。

记录备份路径与 SHA-256;不要删除备份,直到重启和应用验收完成
stamp=$(date --utc +%Y%m%dT%H%M%SZ)
sudo install -m 0600 -o root -g root /etc/fstab "/root/fstab.before-data-$stamp"
sudo install -m 0644 -o root -g root "$work/fstab.candidate" /etc/fstab
sudo findmnt --verify --verbose

回滚同时处理挂载和配置

  1. 应用尚未写入时:停止相关服务,卸载本次目标挂载,恢复已记录的 fstab 备份并重新验证。
  2. 应用已经写入时:先冻结写入并判断数据落在目标盘还是根目录;不要直接卸载或覆盖,以免制造第二份分叉数据。
  3. 挂载失败但目录可见时:用 `findmnt --mountpoint /srv/data` 判断它是否真是挂载点,不要把目录存在当作恢复。
  4. 启动失败时:使用已验证的提供商控制台进入恢复环境,恢复 fstab 后再检查文件系统;`nofail` 不能替代这条路径。

扩容要按层从外向内推进

实际栈必须先扩大的下层最后一步
云卷 → ext4云卷与来宾块设备扩大 ext4
云卷 → partition → ext4云卷、分区边界扩大 ext4
云卷 → partition → LVM → ext4云卷、分区、PV、目标 LV扩大 ext4
云卷 → MD/LUKS/LVM → 文件系统按真实父子关系逐层处理使用该文件系统的专用扩容工具

先在云平台完成容量变更,再确认来宾系统看见新字节数。`resize2fs` 只调整 ext2/3/4 文件系统,不会修改分区;文件系统也不能超过承载它的分区或逻辑卷。不要把“云卷已变大”或“LV 已变大”当作目录已经获得空间,也不要用 `+100%FREE` 把卷组剩余空间无条件交给一个 LV。

ext4 只在底层容量确认后扩展

此步骤只适用于已经完成所有下层扩容且确认可在线增长的 ext4;其他文件系统使用其官方专用流程
target=/srv/data
source=$(findmnt --noheadings --output SOURCE --target "$target")
fstype=$(findmnt --noheadings --output FSTYPE --target "$target")
test "$fstype" = ext4
lsblk --paths --bytes --output NAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS "$source"
findmnt --mountpoint "$target" --output TARGET,SOURCE,FSTYPE,OPTIONS
sudo resize2fs "$source"
findmnt --bytes --mountpoint "$target" --output TARGET,SOURCE,FSTYPE,SIZE,USED,AVAIL

ext4 可在现代内核上在线扩大,但缩小需要卸载并遵守不同顺序。若计划离线检查,先确认目标未挂载,再运行 `e2fsck`;官方文档明确指出,对挂载中的文件系统运行检查通常不安全,即使只读检查的输出也不可靠。任何缩容、层级迁移或恢复操作都应独立设计并先在副本演练。

清理、swap 和性能调优不是数据盘上线步骤

包自动清理、日志真空、容器全局 prune、删除占用文件、固定 swap 大小和统一设置 swappiness 都有独立的所有权与恢复边界。它们不能证明磁盘可安全格式化,也不应夹在同一个变更窗口里“顺便执行”。空间不足先定位具体文件系统、目录、打开文件与业务保留策略,再为明确对象设计删除和回滚。

本次隔离演练验证了什么

本批在 Ubuntu 24.04 的临时目录中创建 64 MiB ext4 镜像,使用 `blkid -p` 与只读 `wipefs` 识别 TYPE、UUID、标签和签名;另一个无签名镜像按文档返回状态 2。随后在未挂载状态下通过 `e2fsck` 检查,把承载文件从 64 MiB 扩到 96 MiB,再运行 `resize2fs`,文件系统 block count 从 16384 增至 24576。

候选 fstab 用 `findmnt --verify` 通过,故意损坏的记录被拒绝。有效候选随后只在 private mount namespace 内执行:tmpfs 成功挂载、接受服务侧写入探针并卸载;命名空间退出后宿主机没有残留挂载。演练没有修改真实块设备、`/etc/fstab`、云卷、分区或 LVM,也没有证明目标提供商的设备 ID、控制台和重启路径可用。

数据盘上线的闭环验收

  • 提供商卷 ID、容量、实例、稳定设备路径和解析后的真实设备完全对应。
  • 块设备树、所有签名、持有者与现有挂载已保存;空白结论不是从 MOUNTPOINTS 推断。
  • 格式化作为单独破坏性动作审批,目标再次核对,备份与控制台恢复路径可用。
  • 候选 fstab 使用唯一 UUID,通过 `findmnt --verify`,并明确是否允许缺盘启动。
  • 真实挂载的来源、类型、容量、选项和服务账号写入探针全部符合预期。
  • 生产 fstab 有受保护的旧版备份;配置回滚和数据分叉处理方式已记录。
  • 扩容按云卷、分区、PV/LV、文件系统逐层完成,没有把 `resize2fs` 当作分区工具。
  • 重启后目标盘、依赖服务、容量、权限和应用读写再次验收,临时文件与测试挂载已清理。

返回知识库