ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CentOS 7 整机镜像打包实战:Mondo 制作可引导 ISO 与恢复验证

CentOS 7 整机镜像打包实战:Mondo 制作可引导 ISO 与恢复验证

1. 为什么还要用 Mondo 做整机镜像

在虚拟化与容器化大行其道的今天,很多人会觉得"整机打包成 ISO"这件事已经过时了。但实际运维场景里,仍然有大量需求绕不开它:一批老旧的物理服务器要批量重装、一个已经调优到完美状态的运行环境需要原样复制到几十台机器、某些内网设备不允许联网只能靠光盘或 U 盘离线部署。这些场景下,逐台重装再手工配置,时间成本高得离谱,而且人为操作必然带来不一致。

Mondo Rescue(下文简称 Mondo)就是解决这类问题的老牌工具。它的核心能力是把一台正在运行的 Linux 系统的完整状态——包括内核、驱动、已安装软件、配置文件、用户数据、分区结构——打包成可引导的 ISO 镜像。恢复时用这张盘启动,就能把系统还原到打包那一刻的样子,连分区表都能一并还原。对于 CentOS 7 这种生命周期长、存量部署极广的系统来说,Mondo 依然是很多运维人员手里的"整机克隆"利器。

这篇文章面向的是有基本 Linux 操作经验、需要做系统级备份或批量部署的读者。我会从 Mondo 的工作原理讲起,把 CentOS 7 上的完整实操流程拆开揉碎,重点讲清楚那些官方文档里一笔带过、但实际会卡住你的细节:软件源怎么配、临时目录空间怎么算、镜像体积怎么压、恢复时分区对不上怎么办。全文基于我在实际项目中反复验证过的做法,参数和命令都可以直接抄。

需要先说明一点:Mondo 打包出来的是"整机快照",不是增量备份工具。它适合做基线镜像、交付镜像、灾备镜像,不适合做每日增量。搞清楚这个定位,后面的取舍就顺了。

2. Mondo 打包整机的底层逻辑

2.1 它到底打包了哪些东西

很多人第一次用 Mondo,会误以为它只是把根目录tar一遍。实际上它的工作范围要广得多。Mondo 在打包时会扫描并记录以下几类信息:

  • 分区布局:每块磁盘的分区表类型(MBR/GPT)、每个分区的起止扇区、文件系统类型、挂载点。这些信息会写进恢复时用的脚本里,所以恢复出来的分区结构和原机一致。
  • 引导加载程序:GRUB 的配置、/boot下的内核与 initramfs。这是镜像能引导的关键,也是出错最多的地方。
  • 文件系统内容:按挂载点逐个打包,默认排除/proc、/sys、/dev、/tmp这类虚拟或临时目录。
  • 软件包清单:记录已安装的 RPM 包列表,恢复后可用于校验。
  • 网络与系统配置:主机名、网络配置、/etc下的各类配置。

理解这一点很重要:Mondo 恢复的不只是"文件",而是"一台机器的完整形态"。这也是它和普通文件备份工具的本质区别。

2.2 镜像的两种形态:ISO 与 USB

Mondo 最终产物有两种常见形态。一种是可引导的 ISO 文件,刻盘或挂载后启动;另一种是直接写入 U 盘的镜像。两者内容基本一致,区别在于引导方式。ISO 走的是光盘引导路径(El Torito),U 盘则依赖 MBR 引导。实际项目中我更推荐先做出 ISO,再用工具写入 U 盘,因为 ISO 便于归档和校验,U 盘写入失败可以重来。

镜像内部通常分成多个文件:一个引导镜像、若干数据分片(*.afio之类)、一个恢复脚本。数据分片的大小可以控制,默认会按介质容量切分。如果你要刻 DVD,就得把分片控制在单张盘容量以内;如果只是存成一个大 ISO 文件,可以放宽。

2.3 为什么它对空间和内存敏感

Mondo 打包过程中会在临时目录里生成大量中间文件,体积可能接近甚至超过原始数据量。如果/var/cache/mondo或你指定的临时目录所在分区空间不够,打包会在中途失败,而且报错信息往往不直观。另外,Mondo 打包时会调用afio、gzip/lzo等压缩工具,这些是 CPU 和内存密集型操作。内存不足时,压缩进程可能被 OOM killer 干掉,表现为"打包到一半突然退出"。

所以正式打包前,务必确认两件事:临时目录有足够空间(经验值是原始数据量的 1.5 到 2 倍),以及机器有足够内存余量。这两点后面会给出具体的检查命令。

3. CentOS 7 上的环境准备与依赖安装

3.1 软件源配置:最容易卡住的第一步

CentOS 7 已经停止常规维护,默认的镜像源大多失效。Mondo 本身不在基础仓库里,需要额外配置源。这一步是新手最容易翻车的地方——直接yum install mondo大概率报"找不到软件包"。

我的做法是先把基础源指向可用的归档地址,再引入 Mondo 所在的仓库。具体操作如下:

# 备份原有源配置 mkdir -p /etc/yum.repos.d/bak mv /etc/yum.repos.d/CentOS-*.repo /etc/yum.repos.d/bak/ 2>/dev/null # 写入可用的基础源(归档地址) cat > /etc/yum.repos.d/CentOS-Base.repo <<'EOF' [base] name=CentOS-7-Base baseurl=http://mirror.example.org/centos/7/os/x86_64/ gpgcheck=0 enabled=1 [updates] name=CentOS-7-Updates baseurl=http://mirror.example.org/centos/7/updates/x86_64/ gpgcheck=0 enabled=1 [extras] name=CentOS-7-Extras baseurl=http://mirror.example.org/centos/7/extras/x86_64/ gpgcheck=0 enabled=1 EOF # 清理并重建缓存 yum clean all yum makecache

注意:上面的mirror.example.org是占位地址,实际使用时替换成你所在网络能访问的镜像地址。内网环境建议自建镜像站,避免打包时因网络抖动中断。

基础源通了之后,再配置 Mondo 的仓库。Mondo 官方为 CentOS 7 提供过 RPM 包,通常放在第三方仓库里。配置好之后执行安装:

yum install -y mondo

如果仓库里确实找不到,也可以下载 RPM 包本地安装,但要手动解决依赖,比较麻烦。我一般优先走仓库方式。

3.2 依赖组件逐个确认

Mondo 依赖一批工具,安装时 yum 会自动拉取,但有几个关键组件值得单独确认,因为它们直接影响打包能否成功:

组件作用缺失后果
afio归档与压缩引擎打包直接无法启动
gzip/bzip2/lzo压缩算法支持无法压缩,镜像巨大
mkisofs/genisoimage生成 ISO无法产出 ISO 文件
syslinux/isolinux引导支持镜像无法引导
mkfs.*系列恢复时格式化分区恢复阶段失败
parted/fdisk分区操作分区还原失败

一条命令确认它们是否就位:

for pkg in afio gzip bzip2 lzo mkisofs genisoimage syslinux parted; do rpm -q $pkg >/dev/null 2>&1 && echo "$pkg OK" || echo "$pkg MISSING" done

任何一项显示 MISSING,都要先补装再继续。

3.3 临时目录与空间规划

Mondo 默认使用/var/cache/mondo作为工作目录。这个目录所在分区必须有充足空间。先看当前磁盘使用情况:

df -h du -sh --exclude=/proc --exclude=/sys --exclude=/dev --exclude=/tmp /

第二条命令估算的是需要打包的数据总量。把它的结果乘以 1.5 到 2,就是临时目录至少需要的空间。如果/var分区不够,可以改到别的分区,比如挂载一块大容量数据盘到/mnt/mondo-work,然后在配置里指定。

修改工作目录有两种方式:一是改配置文件/etc/mondo/mondorescue.conf里的tmpdir项;二是打包时用命令行参数覆盖。我倾向于后者,灵活且不污染全局配置。

内存方面,用free -h看一眼。压缩过程对内存有要求,如果可用内存低于 1GB,建议改用lzo这种低内存占用的压缩算法,或者干脆不压缩(镜像会很大)。

4. 一次完整的 ISO 打包实操

4.1 交互式打包:适合第一次上手

Mondo 提供交互式向导,第一次用强烈建议走这条路,因为它会一步步问你关键参数,帮你建立直观认识。启动命令:

mondoarchive

接下来会依次询问:

  1. 备份介质类型:选ISO(生成 ISO 文件)或DVD(按光盘容量切分)。第一次建议选 ISO。
  2. 备份路径:ISO 文件输出到哪个目录,比如/mnt/backup。
  3. 压缩方式:gzip通用、bzip2压缩率高但慢、lzo快但压缩率一般。追求体积选 bzip2,追求速度选 lzo。
  4. 压缩级别:1 到 9,数字越大压缩越狠、越慢。一般选 6。
  5. 分片大小:单个数据分片的最大体积。存成一个大 ISO 就选大一点,比如 4096MB。
  6. 排除目录:默认已排除虚拟目录,可以再补充,比如/mnt、/data这类不需要备份的挂载点。
  7. 确认内核与模块:Mondo 会列出它识别到的内核,确认无误后继续。

回答完这些问题,它就开始扫描、打包、生成 ISO。整个过程耗时取决于数据量和压缩级别,几十 GB 的数据可能要跑一两个小时。

4.2 命令行打包:适合脚本化和批量

交互式适合摸索,但真正在生产里用,还是命令行更可控。下面这条是我常用的模板:

mondoarchive \ -O /mnt/backup \ -o \ -E "/mnt /data /proc /sys /dev /tmp" \ -N \ -s 4096m \ -z bzip2 \ -l 6 \ -I \ -p $(hostname)-$(date +%Y%m%d)

逐个解释这些参数,理解了才能按需调整:

  • -O /mnt/backup:输出目录。
  • -o:生成 ISO 镜像。
  • -E "...":排除的目录列表,用空格分隔。
  • -N:不备份网络文件系统(NFS 等),避免把远程挂载也打进去。
  • -s 4096m:分片大小 4GB。
  • -z bzip2:压缩算法。
  • -l 6:压缩级别。
  • -I:交互确认后开始(去掉它则全自动,但风险高,建议保留)。
  • -p 前缀:输出文件的前缀名,用主机名加日期,便于归档管理。

提示:-E里的排除项一定要想清楚。把数据盘排除掉能大幅缩小镜像,但恢复后那些数据就不在了,需要另行恢复。这是取舍,不是对错。

4.3 打包过程中的正常输出与异常信号

打包时终端会滚动大量日志。正常的流程大致是:扫描分区 → 挂载点检查 → 逐个文件系统打包 → 生成引导 → 合成 ISO。看到类似Making ISO image的字样,说明接近尾声。

需要警惕的信号有几个:

  • 长时间卡在某个百分比不动,可能是某个大文件压缩慢,也可能是磁盘 I/O 瓶颈。用iostat看一眼就知道。
  • 出现afio: ... No space left on device,说明临时目录满了,必须清理后重来。
  • 出现Killed字样,多半是内存不足被系统杀进程,换低内存压缩算法或加内存。

打包完成后,输出目录里会出现.iso文件以及若干辅助文件。用ls -lh确认体积,用md5sum记录校验值,方便后续验证。

5. 镜像瘦身与体积控制的实战技巧

5.1 打包前先做减法

镜像体积直接决定刻盘张数和传输时间。与其事后压缩,不如打包前就清理。我通常会在打包前做这几件事:

# 清理 yum 缓存 yum clean all # 清理日志(保留最近的即可) find /var/log -type f -name "*.log" -exec truncate -s 0 {} \; # 清理临时文件 rm -rf /tmp/* /var/tmp/* # 查看大目录,找出可以排除的 du -sh /var/* 2>/dev/null | sort -rh | head -20

/var/log、/var/cache、/tmp往往是体积大户,清理后能省下可观的量。如果系统里有测试数据、下载的安装包,也一并清掉。

5.2 压缩算法的选择逻辑

三种压缩算法的取舍,我用一张表说清楚:

算法压缩率速度内存占用适用场景
gzip中等中等中等通用,兼容性最好
bzip2高慢较高追求最小体积,不赶时间
lzo低快低内存紧张或赶时间

实测下来,同一份数据 bzip2 比 gzip 能小 10% 到 20%,但耗时可能翻倍。如果只是内部使用、不刻盘,gzip 级别 6 是性价比最高的选择。如果内存只有 1GB 出头,老老实实用 lzo。

5.3 分片大小的权衡

分片大小决定了单个文件的上限。如果目标是刻 DVD(单层 4.7GB,实际可用约 4.3GB),分片要控制在 4GB 以内,留出引导和脚本的空间。如果只是存成一个大 ISO 文件,分片可以设大,比如 8GB 甚至更大,减少文件数量。

这里有个容易忽略的点:ISO 文件本身也有 4GB 的经典限制(ISO9660 格式)。虽然现在多数工具支持大文件扩展,但为了兼容性,我一般把单张 ISO 控制在 4GB 以内。超过就分片。

6. 恢复验证:不做这一步等于没备份

6.1 用虚拟机先验证

镜像做出来,最忌讳直接拿去生产机恢复。正确做法是先在一台虚拟机里验证。步骤是:新建虚拟机 → 挂载 ISO → 从光盘引导 → 进入 Mondo 恢复界面 → 选择恢复目标磁盘 → 执行恢复。

恢复界面会列出镜像里的分区布局,让你确认恢复到哪块盘。如果虚拟机磁盘比原机小,恢复会失败,因为分区放不下。所以验证用的虚拟磁盘要等于或大于原机磁盘。

6.2 分区对不上的处理

实际恢复时最常见的报错就是分区空间不足。原因通常是目标磁盘比源磁盘小,或者分区顺序不一致。Mondo 恢复时允许你手动调整分区大小,但操作有风险。我的经验是:目标磁盘容量必须大于等于源磁盘,这是硬性前提,不要试图在更小的盘上恢复。

如果目标盘更大,Mondo 默认按原分区大小恢复,剩余空间闲置。想利用多余空间,需要在恢复后手动扩容分区和文件系统,这是另一套操作,不在本文范围。

6.3 引导修复

恢复完成后第一次重启,如果卡在 GRUB 或直接进不去系统,多半是引导没装好。用救援模式进去,重新安装 GRUB:

# 假设系统根分区在 /dev/sda2 mount /dev/sda2 /mnt mount --bind /dev /mnt/dev mount --bind /proc /mnt/proc mount --bind /sys /mnt/sys chroot /mnt grub2-install /dev/sda grub2-mkconfig -o /boot/grub2/grub.cfg exit

这套流程能解决绝大多数引导问题。关键点是grub2-install要指向磁盘设备(/dev/sda)而不是分区(/dev/sda2),这是新手常犯的错。

7. 踩过的坑与经验沉淀

7.1 临时目录爆满导致中途失败

这个坑我踩过不止一次。表现是打包跑到一半突然报错退出,日志里翻半天才看到No space left on device。根因是临时目录所在分区空间不足。后来我养成了习惯:打包前先df -h看临时目录,再du -sh估算数据量,两者对比确认余量。如果不够,提前把工作目录改到大分区。

7.2 排除列表写错导致数据丢失

有一次我把/data排除了,本意是数据盘单独备份,结果恢复后忘了恢复数据,业务直接起不来。教训是:排除列表要写进文档,恢复流程里要有对应的数据恢复步骤。排除不是删除,但恢复时如果没人记得,就等于丢了。

7.3 内核更新后镜像引导失败

如果打包后系统又更新了内核,而镜像里还是旧内核,恢复出来的系统可能因为驱动不匹配出问题。所以打包镜像的时机最好选在系统状态稳定、近期不打算大改的时候。打完包到实际使用之间,尽量不要再动内核和关键驱动。

7.4 网络源不稳定导致依赖装不上

内网环境访问外部源经常超时。我的做法是在内网自建一个镜像站,把 CentOS 7 的基础源和 Mondo 相关包都同步进去。这样打包时依赖安装稳定,速度也快。自建镜像站虽然前期有投入,但对于需要频繁打包的团队来说,回报很高。

7.5 校验值一定要留

ISO 文件在传输、刻盘过程中可能损坏。每次打包完,我都会生成校验值并存档:

md5sum /mnt/backup/*.iso > /mnt/backup/checksum.md5

恢复前先校验,能避免很多"镜像明明在却装不上"的玄学问题。

8. 关于自动化与批量部署的延伸

单机打包跑通之后,自然会想到批量。如果手头有几十台配置相同的机器,没必要每台都单独打包。更高效的做法是:精心配置一台"模板机",把它打包成基线镜像,然后批量恢复到其他机器,恢复后再做少量个性化配置(主机名、IP、密钥等)。

个性化配置可以写成一个首次启动脚本,放在镜像里,系统第一次启动时自动执行。这样基线镜像保持通用,差异部分由脚本处理。这个思路在批量交付场景里非常实用,能省下大量重复劳动。

另外,Mondo 的镜像也可以配合 PXE 网络引导使用,实现无人值守的批量恢复。不过这涉及 DHCP、TFTP、HTTP 等一整套网络引导环境的搭建,复杂度较高,适合有专门运维团队的场景。个人或小团队用 U 盘逐台恢复,反而更简单可靠。

我在实际项目里的体会是:工具本身不难,难的是把"打包—验证—归档—恢复"这条链路固化下来,形成可重复的流程。每次打包都记录数据量、压缩方式、校验值、恢复验证结果,时间久了就是一套可靠的资产。Mondo 这种老工具,用对了场景,依然能发挥很大价值。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进