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接下来会依次询问:
- 备份介质类型:选
ISO(生成 ISO 文件)或DVD(按光盘容量切分)。第一次建议选 ISO。 - 备份路径:ISO 文件输出到哪个目录,比如
/mnt/backup。 - 压缩方式:
gzip通用、bzip2压缩率高但慢、lzo快但压缩率一般。追求体积选 bzip2,追求速度选 lzo。 - 压缩级别:1 到 9,数字越大压缩越狠、越慢。一般选 6。
- 分片大小:单个数据分片的最大体积。存成一个大 ISO 就选大一点,比如 4096MB。
- 排除目录:默认已排除虚拟目录,可以再补充,比如
/mnt、/data这类不需要备份的挂载点。 - 确认内核与模块: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 这种老工具,用对了场景,依然能发挥很大价值。