关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

2026 服务器租用做 Bacula 备份架构怎么设计:Director/存储守护/恢复演练 对比 + 避坑手册

发布时间:2026-10-22

2026 服务器租用做 Bacula 备份架构怎么设计:Director/存储守护/恢复演练 对比 + 避坑手册

干了这么多年备份,我最怕听到的一句话是"我们备份一直很正常啊"。正常是指邮件报表里每晚都是 T(成功),可 T 只说明数据写出去了,不说明数据读得回来。Bacula 尤其如此——它不是装一个软件就完事,它是 Director、Storage Daemon、File Daemon、Catalog 这几块拼起来的系统,任何一块配歪,出事那天你会发现手里只有一堆读不懂的块文件。

这篇不聊 3-2-1 那套通论(本站已经有专门讲它的文章),只围着一件事写:在租来的服务器上自建 Bacula,角色怎么拆、对象怎么串、卷和保留期怎么算、Catalog 怎么自己备自己、演练怎么做才算数。顺序也是按这个走,你可以从任何一节跳进去看。

备份装上不等于能恢复:出问题的永远是恢复那一天

我给客户做第一次巡检,动作通常不是加机器,而是让对方当场做一次盲恢复:随机挑一台机器、随机挑三个月前某一天、随便指一个文件,恢复出来给我看。一半以上的环境在这一步就卡住了——要么 FileSet 里把关键目录 Exclude 掉了(数据库的数据目录被排除是最常见的),要么恢复链上某个卷读不出来,要么 Catalog 库和卷对不上号。

判断标准其实就两条:第一,能不能在半小时内给出一个任意时间点的任意文件;第二,原机没了的情况下,能不能在一台空机器上把业务跑起来。这两条过不了,备份做得再花哨都是心理安慰。后面所有架构设计——拆分角色也好、合成全备也好——本质上都是在给这两条标准服务。

Director、Storage Daemon、File Daemon 各自到底管什么

先把三个角色掰清楚,不然配置文件根本读不懂。Director(DIR)是大脑,也是唯一握着 Catalog 连接的进程:它决定跑哪个 Job、用哪个 FileSet、写到哪个 Pool、让哪台机器的 FD 去联系哪个 SD。DIR 自己不碰业务数据,管的是调度和账本。Console(bconsole)就是操作员跟 DIR 说话的界面,官方提供命令行、Qt 和 wxWidgets 三种。

Storage Daemon(SD)是唯一真正读写介质的进程。它不知道"这台机器该备什么",只知道"往这个卷里追加块"或"从某个卷的第几个块开始读"。卷可以是磁带,也可以就是目录里的一个大文件——把 SD 配置里的 Archive Device 指向一个目录,卷就落在这个目录里。

File Daemon(FD)装在被备份的机器上,也叫 Client。它把本机文件读出来、算签名、按 FileSet 里的压缩和加密选项处理,再把数据流推给 SD(也可以配成 SD 主动来找 FD,即 SD Calls Client,适合 FD 在 NAT 后面的情况)。恢复时反过来,SD 读卷、FD 落盘并还原属性。

记住这三条流:控制流是 DIR 到 FD/SD,数据流是 FD 到 SD(或 SD 到 SD),元数据流是 DIR 到 Catalog。正因为三条流分开,角色才可能拆到不同机器上——这是 Bacula 最大的架构弹性,也是最容易配错的地方。官方口径很明确:一次成功的备份或恢复,需要 Director、File Daemon、Storage Daemon 和 Catalog 数据库四者都配好且在运行。

三个守护进程拆不拆机:拆开的收益与合并的代价

拆开有三个实打实的理由。故障域:DIR 挂了只是不产生新备份,已写好的卷还在;如果 DIR、SD、Catalog 全在一台机器上,那台机器一挂就是连备份带元数据一起没。IO 争抢:SD 是磁盘写入大户,恢复时又是大块读,跟业务进程抢同一组盘会很惨。安全边界:DIR 的配置里有所有机器的口令,FD 在被备份的业务机上,业务机本身就是要被保护的对象,一旦被端掉,FD 和它自己的数据一起完蛋。

但小环境合并部署确实常见,代价也得说清。十几台机器以内,DIR+SD+FD 全挤一台能跑,省一台机器的钱:备份数据和原数据在同一块盘上,盘坏了双倍损失;Catalog 和卷一起丢;演练时整个备份系统都得停。我见过最尴尬的一种是"名义上拆了"——DIR 和 SD 装在不同机器,但 SD 的卷目录挂在 DIR 那台机器的 NFS 上,等于没拆。

我的折中方案:DIR 和 Catalog 放一台,SD 单独一台带自己的大容量盘阵,FD 各自待在业务机上。选机器也要分开看——DIR 那台挑内存和数据库盘的 IOPS,因为 Catalog 是张不断增长的表;SD 那台挑盘位数量和顺序写能力,CPU 真的无所谓。

Job、FileSet、Schedule、Pool、Client、Storage 怎么串起来,JobDefs 又该怎么复用

新手看 bacula-dir.conf 头大,是因为把配置当成一堆平铺的参数。其实它是六个对象回答六个问题:Job 是一张工作单;FileSet 回答"备什么"(包含列表、排除列表、压缩、签名、加密);Schedule 回答"什么时候跑";Pool 和它下面的 Volume 回答"写到哪、能留多久";Client 回答"哪台机器";Storage 回答"用哪个 SD 的哪个设备"。

JobDefs 是这一切的模板。把 Client、FileSet、Schedule、Storage、Pool、Messages、Priority 这些共性写进 JobDefs,具体的 Job 只写差异项——典型部署场景里二十台配置一样的 Web 机,就是一个 DefaultJob-JobDefs 加二十个只改 Client 名字的 Job。改一次模板全部生效,比逐条维护靠谱得多。

一个很多人不知道的点:Schedule 里的 Run 行可以带覆盖参数,写成 Run = Level=Full Pool=WeeklyPool 这样,能覆盖 Job 里定义的级别和池。也就是说"每周五全备、其余日子增量"这一整套策略可以完全写在 Schedule 里,Job 本身只留骨架。NextPool 同理,可写在 Pool、Job 或 Run 覆盖里,优先级 Run 覆盖 > Job > Pool。

还有个必须记住的:Director 里的 Storage 资源不是"一台机器",它是"某台 SD + 某个 Device + 某个 MediaType"的三元组。MediaType 写错,恢复时 Bacula 会挑错设备,这个坑后面单独讲。

Pool 与 Retention:新手最容易配错的一组参数

Bacula 里有两组保留期,混着配一定出事。第一组在 Client(或 Job)资源里:File Retention 和 Job Retention,管 Catalog 里文件记录和作业记录留多久,配合 AutoPrune 生效。第二组在 Pool 资源里:Volume Retention,管卷写完之后多久可以被回收,配合 AutoPrune 和 Recycle 生效。

最常见的错法是 Volume Retention 设 7 天、Job Retention 设 30 天。结果卷在第七天之后被 purge、被新数据覆盖,可 Catalog 里还记着"某某文件在某某卷上",你去恢复,卷里已经是别人的数据了。反过来,Job Retention 比 Volume Retention 短,记录先被清掉、卷还在,这时恢复要靠 bscan 把卷重新扫回 Catalog,慢得让人怀疑人生。

我给客户定的规则是:Volume Retention 至少是业务可恢复窗口的 1.5 倍,Job Retention 与之对齐,File Retention 可以稍短,但开了 Accurate 模式就别比 Job Retention 短太多,因为 Accurate 依赖文件记录判断哪些文件被删了。

还有一条必须理解的机制:Bacula 只在"需要新卷、且池里没有 Append 状态的卷"时才去回收,而且挑最老的已 purge 卷来覆盖。也就是说哪怕你把一批卷标成了 Purged,只要池里还留着一个 Append 卷,它就宁愿一直往那个卷里追加,不去动旧卷。这是官方为让数据尽可能久保留而设计的,后果是:不给卷设大小或时间上限,那个 Append 卷会一直长大直到把盘写满。

Full、Differential、Incremental 的恢复链到底要读几个卷

先对齐定义,因为各厂商叫法不一样。Bacula 口径下:Full 是 FileSet 里的全部文件;Differential 是上次 Full 以来发生变化的所有文件;Incremental 是上一次任意级别作业(Full、Differential、Incremental 都算)以来发生变化的文件。

恢复路径因此分四种。只做 Full:读最近那一个全备,最快也最费空间。Full+Differential:读最近 Full 加最近 Differential。Full+Incremental:读最近 Full 加上它之后全部增量,攒了多少个就要读多少个卷。Full+Differential+Incremental:读最近 Full、最近那个 Differential,以及该 Differential 之后的所有增量。

这就是"增量越攒越久、恢复越慢"的来历,而且慢的不只是字节数。每多一个卷就多一次挂载、定位、寻道;更糟的是链上任何一环坏了后面全部作废,你只能退回上一个可用时间点。Differential 的价值就在把一串增量合并成一份,把要读的卷数从 N 个压回两三个,同时给旧备份留一份冗余。

两种危险配置值得单独点名:一是全备做得极稀、中间靠几十个增量撑着,任何一个增量卷损坏都会让整段时间窗口失效;二是全备的保留期设得比增量短,全备先被回收,剩下一堆增量变成没有根的孤儿数据。后者在 Retention 配错的环境里特别常见。

再补一个容易踩的细节:从上次 Full 之后被删除的文件仍留在 Catalog 里,做 Differential 或 Incremental 时 Bacula 不会主动把它们从记录里去掉,恢复时这些"早就删了的文件"会被一起恢复出来。要让恢复结果和机器真实状态一致,得开 Accurate 模式——代价是内存和时间开销。

合成全备 VirtualFull 什么时候值得上

VirtualFull(有的产品叫合成备份或 Consolidation)做的事是:把上一次 Full、最近的 Differential 以及其后的 Incremental 在 SD 侧合并成一个新的 Full。关键在"不联系客户端"——整个过程不打扰业务机,IO 压力全落在 SD 上,合并出的新 Full 成为后续增量的基准。

它解决的是"增量永久化"的痛点:生产机上只跑增量,业务几乎无感,恢复时依然有完整全备点可读,不用把几十个卷串起来。代价也实在:合并要把源卷全读一遍、再写一遍新卷,IO 和空间都是双倍开销;而且它通常写到 Next Pool 指定的另一个池(官方解释是避免同卷读写死锁),得为这个池单独预留空间。Next Pool 指回当前池也能工作,因为 Bacula 不允许同一卷同时读写。

版本支持这块公开资料口径不一,以官方文档为准——社区版 9.x 的 Director 配置章节已写明 VirtualFull,官方新特性文档里也有支持指定 jobid 合并某个时间点的增强;企业版文档标注从 14.0.4 起多数插件兼容。落地前先在你自己的版本上验证一遍。

我的取舍判断:文件数量在百万级、日变化率低的文件服务器和共享目录,上 VirtualFull 很划算,每天增量很小、合成一次就把恢复链砍断。数据库的数据目录基本整块变,增量跟全备差不多大,直接跑 Full 更简单。另外增量和差异没开 Accurate 的话,合成结果和"删除/移动文件"的真实状态会有出入,至少在合成前最后一次增量上打开。没有任何前置 Job 时跑 VirtualFull 会直接失败。

磁盘卷怎么切:卷大小、文件数与 SD 并发设备的算法

磁盘卷模式下,Archive Device 指向一个目录,一个卷就是目录里的一个文件。这个文件不能改名——卷的内部标签里含文件名,改名后 Bacula 就不认了,只能靠 bscan 之类的手段救。

第一条铁律:不设 Maximum Volume Bytes,Bacula 会一直往第一个卷里写,直到整个磁盘写满,官方手册把这条单独拎出来警告过。控制卷的切分有四个旋钮:Maximum Volume Bytes(按大小切)、Maximum Volume Jobs(按作业数切)、Volume Use Duration(按可写时长切,比如 23 小时实现一天一卷)、Use Volume Once(一作业一卷)。

切多大?官方参考量级:小站点(10–20 客户端)约 5G,中等(20–100)约 50G,大站点(100 以上)约 200G;卷总数建议控制在 5000 以内,否则 prune 会变慢。卷大则卷数少、prune 快、元数据轻;卷小则回收粒度细、空间浪费少。恢复性能上大卷没有惩罚,因为 Bacula 能直接定位到每个 Job 的起始块。

并发要分清两件事。一是多个 Job 交错写同一个卷(multiplexing),磁盘卷上影响不大;磁带卷上会让恢复明显变慢,官方给的经验是磁带上并发 5 到 10 个作业并打开 spooling 比较合适。二是同时写多个卷——一个 Device 同一时刻只能挂一个卷,想同时写多卷就得定义多个 Device 资源,编进一个虚拟自动机(Virtual Autochanger),Director 侧只看得到一个 Storage 资源,靠每个 Device 上的 Maximum Concurrent Jobs 分发作业。并发上限还得在 Director、Job、Client、Storage 四处同时打开,FD 和 SD 另有各自的总上限(默认 20,Director 默认只有 1),只改一处不生效。

容量用这个式子估:所需容量 ≈ 一份全备大小 + 日均增量 × 保留天数 × 安全系数。安全系数我取 1.3 到 1.5,用来吸收回收迟滞和突发的全量变更;再留 20% 到 30% 空闲,避免"盘满了但旧卷还没 purge"的僵局。合成全备和异地副本的空间要单独算,不能和主池共用一份预算。

回收、清除与截断搞错后的两种典型翻车

翻车一:磁盘满了,备份失败或卡死,表象是作业停在"等待挂载新卷"。根因通常是三个之一——卷一直处于 Append 状态没被封口(没设大小或时长上限);卷已 purge 但没配 ActionOnPurge=Truncate,空间没真正释放,df 看着快满却没人敢删;池里设了 Maximum Volumes 且已到上限,Bacula 找不到可写卷就只能等人。

翻车二:老数据被提前回收。根因是 Volume Retention 短于业务要求,或者误用了 Purge Oldest Volume——官方明确说这个指令忽略保留期,强烈建议改用 Recycle Oldest Volume。还有一种隐蔽情况:以为"配了 Recycle 就会自动回收",但因为池里始终有 Append 卷,回收压根没触发,直到某天突然一口气把最老的一批全备全覆盖了。

怎么判断?在 bconsole 里用 list volumes 或 llist volume 看 VolStatus(Append / Full / Used / Purged / Recycle)、LastWritten、VolRetention、VolJobs、VolBytes。卷是 Purged 但文件还在盘上占空间,就是没截断;最老的 Full 卷状态变成 Recycle,危险已经发生了。

怎么避?保留期和回收期写成一张表,和业务的 RPO 逐条对齐,别拍脑袋填数字;关掉 AutoPrune、按计划定期手工 prune(官方最佳实践的建议);磁盘卷一律配 ActionOnPurge=Truncate;强制循环用 Recycle Oldest Volume;卷文件不要手工 rm,要走 bconsole 的 prune / purge / truncate。

Catalog 丢了,备份就是一块砖:元数据库怎么自己备自己

Catalog 是 Bacula 和 tar 之间最大的区别,也是最大的单点。它记录了:用了哪些卷、跑了哪些作业、存了哪些文件、每个文件在卷上的具体位置(官方叫 Storage Coordinates)。没有 Catalog,卷就是一堆没有目录的书——数据可能完好无损,但你不知道哪块属于哪个文件。

数据库选型上官方支持 MySQL、PostgreSQL 和 SQLite 三种。SQLite 配置最简单,只适合极小规模或测试;生产环境我建议 MySQL 或 PostgreSQL,并给 Catalog 建专用账号、专用库,权限只给 Bacula 自己,报表类工具用只读角色——官方讲 Verify 作业时就强调过:Catalog 的可信度决定了所有校验结论的可信度。

数据库放哪?三条不要:不要和 SD 的卷目录放同一块盘;不要和被备份的业务数据放同一台机器;不要放在没有导出手段的单点存储上。Catalog 库跑着跑着就几十 GB 是常态,File Retention / Job Retention 加 AutoPrune 是唯一的减重手段——被 prune 的记录还能用 bscan 从卷里扫回来,前提是卷还没被回收。

自备份的标准做法是用官方包里的 make_catalog_backup / delete_catalog_backup 脚本:Runscript 在作业前把数据库 dump 成 bacula.sql,把这个 dump 当普通文件备份进专门的灾难恢复池,作业后再删掉临时文件,同时用 WriteBootstrap 生成 .bsr 引导文件。

引导文件(bootstrap)的意义必须单独讲:它用纯文本记录了"要恢复哪些文件、在哪个卷、在卷的什么位置",是 Catalog 全丢时唯一能快速定位的钥匙,官方建议转发到外部位置保存。灾难恢复路径是:重装同版本 Bacula → 取最新 .bsr → 用 bextract 抽出 bacula.sql → 灌回数据库 → 恢复配置文件 → 起守护进程 → 恢复业务数据。没有 .bsr 就只能 bscan 全卷扫描重建 Catalog,卷多时非常慢。

我的做法是双保险:自带的 Catalog 备份作业照常跑(配置文件先备、Catalog 后备,保证同一时刻快照一致),另外单独做一份数据库逻辑导出放异地,每季度真的导入一次验证能用。只导不验,等于没导。

恢复演练该做到什么颗粒度:单文件、异机、跨版本

先说单文件。bconsole 里 restore,可以按 jobid 选,也可以按时间点选("给我上周三下午三点那个版本"),再 mark 具体文件,done。这一档要验证两件事:能不能定位到某个时间点的某个版本;恢复出来的文件属性(属主、权限、时间戳、ACL)对不对。别只看内容,权限恢复错了一样跑不起来。

再说异机和异目录恢复。Bacula 提供 Where、Add Prefix、Strip Prefix、RegexWhere 这几个重定向手段,以及 Replace 决定遇到同名文件怎么办(always / ifnewer / ifolder / never)。典型部署场景里我从不建议直接覆盖生产路径:把数据库文件恢复到 /restore 之类的临时目录,人工核对后再导入,多花十分钟,少一次二次事故。Windows 上把 c:/files 恢复到 d:/files 就是 Strip Prefix 加 Add Prefix 的组合。

跨版本要保守一点。官方说卷的数据格式向上兼容,老卷可被新版读取;但大版本跨度、插件数据、schema 升级这些组合情况公开资料口径不一,以官方文档为准。我的习惯是基础设施重建时用同版本 Bacula 恢复,确认业务跑起来之后再考虑升级。

演练周期我这么定:每季度一次完整恢复演练(恢复到一台空机器并真的把服务拉起来),每月一次抽样单文件恢复(随机挑)。每次记录:选取的恢复时间点、实际恢复到的数据时间点、参与的卷名与卷数、耗时、校验结果、有没有缺失或多余的文件。没有记录的演练等于没做,下次你还是不知道自己的 RTO 是多少。

校验与静默损坏:Verify 作业、签名与抽查

FileSet 里可以配 Signature = MD5 或 SHA1,备份时 FD 算签名、把签名写进 Catalog。这是后面所有校验的基础,代价是备份时要多读一遍文件数据(Accurate 叠加校验和的作业尤其明显)。

Verify 作业有几个级别,别用混。InitCatalog:扫一遍 FileSet 把属性存进 Catalog 当基线,不存文件数据,类似 Tripwire。Catalog:把当前文件状态和基线比,报差异,适合盯 /sbin、/boot、/bin 这类不该变的东西。VolumeToCatalog:读卷上记录的属性和签名,跟 Catalog 比。这里有个官方明确的限制——它比的是属性和签名,不会重新读一遍实际文件数据来比对,所以发现不了"卷上某个数据块位翻转了"这种情况。

静默损坏是真实存在的:磁盘位翻转、文件系统 bug、RAID 写洞、传输偶发错误,写入时是好的,半年后读出来是坏的,而"备份作业成功"这个统计完全发现不了它。所以除了 Verify,我还会安排真正的读校验——定期挑一个全备卷完整读一遍(社区版有校验卷数据的相关能力,具体支持范围以官方文档为准),再挑几个关键文件真实恢复并比对哈希。

还有一条常被忽略:官方提醒不要在同一台客户端上同时跑两个 Verify Catalog 作业,因为该级别会修改 Catalog 来跟踪新增文件,并发跑结果一定是错的。

异地副本用 Copy 还是 Migration:独立凭据与网络路径

Copy 作业复制一份已存在的备份,可改变保留策略、介质类型和物理存放位置,原作业记录保留;Migration 作业则是"搬"——数据从源卷读到新池的卷之后,源作业在 Catalog 里的 File 记录会被 purge 掉。做异地副本我一律选 Copy:本地留一份快速恢复用,异地留一份抗机房级事故,两边在 Catalog 里各有独立记录。

传输机制上,社区版从 7.0 起、企业版从 8.0 起支持 SD 到 SD 直接传输:只要 Copy 或 Migration 的源 SD 和目标 SD 不是同一个,数据就自动在两台 SD 之间走,不经过被备份的业务机(此时源 SD 在目标 SD 眼里扮演 FD 的角色)。这对异地复制很关键——业务机不用再扛一遍读放大。

配置上,Selection Type 常用 PoolUncopiedJobs(把池里还没复制过的作业都复制一遍),配合 NextPool 指向异地池。要复制到多个目标就配多个 Copy 作业分别指向不同的 NextPool。

凭据和网络路径是安全底线,我单独强调:每个 SD 在 bacula-sd.conf 里都有自己的 Director 资源和独立口令,Director 侧两个 Storage 资源各用各的密码,异地那份绝不能复用本地口令,也不要共用数据库账号;组件之间默认 CRAM-MD5 认证,通信可开 TLS,卷上数据可按客户端开加密。网络上要放通源 SD 到目标 SD 的对应 TCP 端口(SD 默认 9103),走独立链路或加密隧道。异地池的 Media Type 必须和本地不同——不同物理位置用不同 Media Type 是官方和社区反复强调的规则,否则恢复时 Bacula 会试图从错误的设备读卷。这里只谈架构,任何绕过访问控制的做法都不在讨论范围内。

小技巧一条:SD 的 Device 可以设成 Read Only,专门留一两个设备给恢复用,避免备份高峰占满所有设备、恢复作业排队干等。异地那台机器不需要多强 CPU,但要盘位够、链路稳、和本地不在同一机房——像一万网络这类在多个地区有自营节点的服务商,把副本 SD 放到不同城市的节点上是成本可控的做法,具体节点与带宽形态需询价,以官方实时报价为准。

四种部署形态的横向对比:角色拆分、介质、恢复粒度与适用规模

把前面拆开的要素收拢成一张表,方便对着自己的环境选。

部署形态 角色是否拆分 介质 恢复粒度 适用规模
DIR+SD+FD+Catalog 全合一 不拆分,单台承载 本机磁盘卷,单目录单设备 单文件、整机均可,但盘坏即全损 1–5 台,测试环境或极小站点
DIR+Catalog 一台,SD 独立带大盘位 部分拆分,DIR 与 SD 分离 磁盘卷 + 虚拟自动机多 Device 单文件、整机、异机恢复都支持 10–50 台,中小企业最主流的形态
DIR+Catalog 主备 + 本地 SD + 异地 SD 完全拆分,跨机房 两地磁盘卷,Copy 作业做副本 单文件、整机、异地副本独立可恢复 50–200 台,有异地与保留期要求
多 SD 分层,磁盘暂存 + 磁带库或 VTL 归档 完全拆分,多层 SD 磁盘卷暂存,Migration 下沉磁带 整机与长期归档为主,单文件需回迁 200 台以上,长期归档与合规留存
DIR 与 SD 分机但共用同一块盘阵 名义拆分,存储未分离 共享盘阵上的磁盘卷 单文件可,整机恢复受单点制约 不推荐,仅作临时过渡形态

这张表别从"我有多少台机器"开始读,按固定顺序判断。第一步定恢复粒度目标:要"任意文件几分钟内可取",还是能接受几小时甚至回迁磁带的时间。第二步由粒度反推介质——分钟级就必须是在线磁盘卷,磁带和 VTL 只能做归档层。第三步由介质反推 SD 要不要独立:介质是独立盘阵,SD 就该独立成机,否则 IO 照样打架。第四步才看副本和分层:有没有机房级故障应对要求和半年以上留存要求,决定上不上 Copy 作业和磁带层。规模数最后才看,它只决定设备数和卷大小,不决定架构形态。

按这个顺序走,大部分中小环境落在第二种形态上:不用为用不上的磁带库付钱,也不会把鸡蛋放一个篮子里。

资源账:CPU 基本不是瓶颈,磁盘 IO 和网络才是

Bacula 对 CPU 很温和。DIR 的开销主要是往 Catalog 里插记录——文件数上百万时,这是实打实的数据库写入 IOPS 压力;Accurate 模式还要在内存里维护文件清单,官方直接说这个模式"相当消耗内存"。所以 DIR 那台的选型重点是内存容量和数据库盘的随机写能力,数据库我建议单独放 SSD。

SD 是典型的顺序写加大块读,恢复时尤其吃读吞吐。并发作业一多,原本顺序的写会退化成多个卷之间的交错写,机械盘上明显掉速。所以 SD 的卷目录一定要挂在独立盘或阵列上,跟系统盘、数据库盘分开,这是最划算的一笔硬件投资。

FD 在被备份的业务机上,开销是"读业务盘 + 算签名 + 压缩"。开了 SHA1 签名,等于每次备份都要把文件完整读一遍来计算,这部分 IO 躲不掉;压缩(GZIP、LZO 等)在 FD 侧做,额外吃 CPU。业务机本身就忙的话必须限速,别让备份把生产 IO 抢光。网络同理:备份窗口内 FD 到 SD 是一路持续大流量,再加异地 Copy 就是第二路 SD 到 SD 长流,两路跑同一张网卡业务访问就会被挤,最好规划到不同网卡或内网段。

落到选机器上,这套拆法翻译成一句采购清单:一台内存充裕、带 SSD 数据库盘的机器给 DIR 和 Catalog,一台盘位多、顺序写好的机器给 SD,有条件再加一台异地机器放副本 SD。一万网络深耕 IDC 行业 19 年(成立于 2007 年),在华南、华东、华北及中国香港、海外多地整合自营节点与 BGP 多线资源,提供服务器租用、机柜托管与带宽接入的一体化交付;具体机型、带宽与报价以官网实时信息或咨询确认为准。角色不同、机型不同,一次性把盘位、内存和内网带宽说清楚,比事后加盘加内存省事得多。

备份窗口、压缩与限速:取舍怎么定

错峰是第一原则。Schedule 里把不同 Client 的启动时间错开,或者用 Job 的 Priority 排先后顺序,比堆硬件有效得多。判断窗口够不够的方法很朴素:看最近一个月的作业耗时曲线,最长那次已经吃掉窗口七成,就该考虑拆分或合成全备了,别等某天突然跑不完。

压缩是拿 CPU 换空间和带宽。FileSet 里的 Compression 在 FD 侧生效;如果目标是自带硬件压缩的磁带机,可以在 Director 的 Storage 资源上设 AllowCompression = No 关掉客户端压缩,省下 FD 的 CPU(官方例子就是 LTO 的场景)。我的取舍:内网千兆万兆、CPU 有富余,用轻量压缩(LZO)甚至不压;跨公网或按流量计费的链路,压得更狠并限速。

限速开关有三个层次:FileDaemon 资源里的 Maximum Bandwidth Per Job、Job 资源里的 Maximum Bandwidth、运行时用 setbandwidth 命令动态调整。异地副本那条链路必配限速。

Spooling(SpoolData)是把数据先落到 SD 本地的 spool 文件、再从 spool 写到介质,价值主要在磁带上——避免磁带机因数据断断续续而反复启停(行话叫 shoe-shine)。磁盘卷上意义不大,反而多一次写入,我一般不打开。

最后提醒一句:别指望用文件级备份去备份正在运行的 MySQL 或 PostgreSQL 数据目录,拿不到一致性快照。先用 mysqldump / pg_dump 或官方插件导出一致性副本,再把导出文件纳入 FileSet,恢复时先恢复 dump 再导入。

监控与告警到底该看哪几个数

只看作业成功与否是不够的。真正要看的有四组。第一组是作业:除了失败,还要抓"带告警的成功"(比如有文件打不开被跳过)、"连续两天没有成功备份"(机器可能已经下线了)、"作业卡在等待介质超过 N 分钟"(多半是卷或设备出问题)。

第二组是卷和池:可用卷数量、Append 状态的卷数、最老卷的 LastWritten、池占用比例、SD 卷目录所在磁盘的剩余空间,这几个数能在作业失败之前预警。第三组是 Catalog:库大小增长速率、prune 是否按计划执行、数据库连接是否正常。第四组是耗时和字节数的趋势——某个作业数据量突然掉到接近零,十有八九是 FileSet 里的路径变了或者目录被清空,这比作业失败更危险,因为它不报错。

告警我只配三条硬线:作业失败或告警立即发;同一客户端连续两次没有成功备份立即发;池可用空间低于阈值(我习惯设 20%)立即发。剩下的做成日报慢慢看。Messages 资源记得按级别分路由,别把所有输出塞进同一封邮件,那样三个月后你就再也不打开了。另外我自己加了一条非技术告警:上次成功演练距今超过 90 天就发提醒,这一条救过我两次。

租用服务器上跑 Bacula 的五个坑

坑一:两个目录共用一个 Media Type。问题——不同 Archive Device 目录的 Device 用了同一个 Media Type,恢复时 Bacula 只认 Media Type 和卷名,不知道卷在哪个目录,于是挑错设备、读不到数据。为什么——Catalog 里不存 Archive Device 的完整路径。怎么判断——list volumes 里卷存在,恢复却报找不到卷或挂错设备。怎么避——同一自动机内各 Device 要么指向同一目录,要么用不同 Media Type;不同机房、不同物理位置一律用不同 Media Type。

坑二:Volume Retention 和 Job Retention 各写各的。问题——两组保留期不一致,卷先被覆盖或记录先被清掉。为什么——回收只看 Volume Retention,Catalog 记录清理只看 File/Job Retention,两者没有联动校验。怎么判断——恢复时提示卷上找不到数据,或 Catalog 里查不到本该存在的作业记录。怎么避——保留期写成一张和业务 RPO 对齐的表,Volume Retention 至少是保留窗口的 1.5 倍,Job Retention 与之对齐。

坑三:磁盘卷没设上限、也没配截断。问题——卷无限长大直到盘满,或卷已 purge 但空间没释放。为什么——Bacula 默认一直往同一个 Append 卷写;purge 只清 Catalog 记录,不删文件。怎么判断——df 快满但旧卷状态已是 Purged,或作业停在等待新卷。怎么避——按规模设 Maximum Volume Bytes(参考 5G/50G/200G 量级),配 ActionOnPurge=Truncate,必要时配合 Maximum Volumes 固定卷集合。

坑四:Catalog 有备份但引导文件没外发。问题——整机损毁后 Catalog 备份虽在卷里,却不知道在哪个卷、卷的哪个位置,只能全量 bscan。为什么——bootstrap 文件默认写在 DIR 本机工作目录,和它要保护的机器同生共死。怎么判断——问一句:DIR 这台机器整块盘没了,我手上有 .bsr 吗?怎么避——把 .bsr 同步到异地,另做一份数据库逻辑导出放异地并定期导入验证。

坑五:只信报表,从不演练。问题——FileSet 漏了关键目录、恢复链断了、异机路径没验证,全要到出事那天才发现。为什么——作业成功只证明写成功,不证明读得回、也不证明备对了东西。怎么判断——问"上一次真正恢复出业务数据是什么时候",答不上来就是没做。怎么避——季度整机演练、月度单文件抽样,每次留记录,尤其把 RTO 实测值记下来。

Bacula 落地前最容易被问到的八个问题

问:三个守护进程能不能全装在一台租用服务器上?能跑,但我只建议在五台以内的测试或极小环境这么干。代价是备份数据和原数据很可能落在同一块盘上,DIR、SD、Catalog 一起挂就全没了,演练时整个备份系统都得停,而且事后想拆分要重新规划卷路径和 Media Type,迁移成本比当初多买一台机器高得多。真正省钱又不埋雷的做法是至少把 SD 拆出去——它要的是大盘位和独立盘阵,DIR 那台要的是内存和数据库 IOPS,两台的硬件诉求本来就不一样,拆开反而更好选机型。

问:Catalog 数据库用 MySQL、PostgreSQL 还是 SQLite?官方支持这三种,构建时选一种。SQLite 配置最简单,适合测试和极小规模;生产环境我建议 MySQL 或 PostgreSQL,理由是并发写入能力、逻辑导出工具链和运维手段都成熟,出了问题也容易找人排查。无论选哪个,都要建专用库和专用账号,权限只给 Bacula 自己,报表类工具另开只读角色。库要放在独立的 SSD 上,不要和 SD 的卷目录共用一块盘,也要盯住库的增长速率——几十 GB 的 Catalog 很常见,靠 File Retention 和 Job Retention 加 AutoPrune 定期减重,prune 掉的记录还可以用 bscan 从卷里扫回来。

问:增量攒多久做一次全备合适?没有放之四海皆准的数字,取决于你的日变化率和能接受的恢复时间。判断方法很直接:数一数从上个全备到最坏情况下要读多少个卷,如果这个数超过五六个,就该做全备或者上合成全备了。日变化率低的文件服务器可以一周一全备加每日增量;数据库目录基本整块变,增量和全备差不多大,直接每天全备更省事。关键别让全备的保留期短于增量的保留期。

问:VirtualFull 和重新跑一次 Full 有什么区别,什么时候选前者?重新跑 Full 要 FD 把数据从业务机上再读一遍、再传一遍,占用业务机 IO 和网络;VirtualFull 完全不联系客户端,只在 SD 侧读旧卷写新卷。所以业务机 IO 紧张、或者客户端在远端慢链路上时,合成全备优势明显。但合成要额外占用一个池的空间,合并过程本身也是一次完整的读加写,SD 的 IO 压力不小。文件数百万级、日变化率低的环境值得上;数据每次都整块变的场景不划算。版本支持情况公开资料口径不一,落地前先在测试环境验证。

问:磁盘卷大小到底定多少?官方给的参考量级是小站点(10–20 客户端)约 5G、中等(20–100)约 50G、大站点(100 以上)约 200G,同时建议 Catalog 里卷总数控制在 5000 以内以免 prune 变慢。卷大则卷数少、元数据轻、prune 快;卷小则回收粒度细、空间浪费少。恢复性能上大卷基本没有惩罚,因为 Bacula 能直接定位到每个作业的起始块,不用从头扫。除了按大小切,还可以用 Maximum Volume Jobs 按作业数切、用 Volume Use Duration 按可写时长切——想实现"一天一卷",把时长设成 23 小时比按大小切更直观。

问:卷已经被回收覆盖了,但那份数据我还没恢复,还能救吗?坦白说,一旦卷被真正重写,数据就没了,任何软件都救不回来。能做的是在它发生之前拦住:Bacula 只有在需要新卷且池里没有 Append 卷时才回收,而且优先挑最老的已 purge 卷,所以从卷状态变成 Purged 到真正被覆盖之间有一个窗口。发现误配后第一件事是立刻停掉相关作业,把该卷文件复制出来,再用 bls 和 bextract 这类工具离线提取。平时把 Volume Retention 留足余量,比事后抢救现实得多。

问:异地副本该用 Copy 还是 Migration?做异地副本我一律选 Copy。Migration 是把数据从源池搬到目标池,搬完源作业在 Catalog 里的文件记录会被 purge 掉,本地那份等于没了,以后恢复就得到异地去读,延迟和带宽都不划算。Copy 保留两边独立的记录,本地留一份快速恢复用,异地留一份抗机房级事故,恢复时想从哪边读都行。配置上用 Selection Type = PoolUncopiedJobs 加 NextPool 指向异地池,社区版 7.0 起源和目标 SD 不同时会自动走 SD 到 SD 传输,不经过业务机。两边的口令、Media Type 都必须独立设置,异地池的保留期一般设得比本地更长。

问:恢复演练多久做一次,做一次要记录什么?我的节奏是每季度一次完整演练——挑一台机器,恢复到一台空机器上,真的把服务拉起来;每月一次抽样单文件恢复,随机挑时间和文件,别每次挑同一个做样子。每次必须记录:选取的恢复时间点、实际恢复到的数据时间点、参与的卷名与卷数、总耗时、恢复后的校验方式(哈希比对或应用自检)、有没有缺失或多余的文件。最后一个字段最重要,它直接决定你对外承诺的 RTO 是不是真的。

数据来源

Bacula 官方手册《Main Reference》组件与服务章节:Director、Console、File(FD)、Storage(SD)、Catalog、Monitor 的职责定义,以及"成功的备份或恢复需要 DIR、FD、SD 与 Catalog 四者均配置并运行"的说明。

Bacula 官方手册《Configuring Director》:Full / Differential / Incremental 级别定义、Accurate 模式限制、VirtualFull 说明、Verify 作业的 InitCatalog / Catalog / VolumeToCatalog 等级别及其限制。

Bacula 官方手册《Automatic Volume Recycling》:AutoPrune、VolumeRetention、Recycle、RecyclePool 四项指令、Pruning 机制、回收触发条件、Purge Oldest Volume 与 Recycle Oldest Volume 的区别与官方建议。

Bacula 官方手册《Basic Volume Management》:磁盘卷的 Archive Device 配置、Maximum Volume Bytes / Maximum Volume Jobs / Volume Use Duration 等切分指令、小中大规模站点的卷大小参考量级、卷总数建议、并发磁盘作业与 Media Type 冲突的警告。

Bacula 官方手册《Storage Daemon Configuration》:Device 资源的 Maximum Concurrent Jobs、Maximum Open Wait、Always Open、Removable Media、Read Only 等指令说明。

Bacula 官方手册《The Bootstrap File》与《Disaster Recovery Using Bacula》:bootstrap 文件结构与 VolSessionId / VolSessionTime 用法、bscan 与 bextract 的使用场景、服务器整体损毁后的恢复路径。

Bacula 官方《New Features in 7.0.0》《New Features in 5.0.0》:SD 到 SD 的 Copy / Migration 传输、Next Pool 在 Job 与 Schedule Run 覆盖中的优先级、truncate 命令、Device 级 Maximum Concurrent Jobs、AllowCompression、Accurate FileSet 选项。

Bacula Systems 白皮书《Best Practices for Disk Based Backup》与《Disk Backup Design》:用 Pool 分发并发、Device 上的 Maximum Concurrent Jobs、专用恢复设备、ActionOnPurge=Truncate、关闭 AutoPrune 定期 prune、不同物理位置使用不同 Media Type、卷内作业块交错对恢复的影响、虚拟自动机的定义方式与磁带并发作业数经验值。

Bacula Systems《Bacula Enterprise Advanced Features Usage》:Virtual Full Jobs 章节(14.0.4 起插件兼容性、Next Pool 与死锁说明、Accurate 建议)与 Verify 章节对 Catalog 可信度前提的说明。

Bacula Systems《Bacula Infrastructure Recovery》文档:Catalog 备份作业与 DisasterRecovery-pool 的配置示例、make_catalog_backup / delete_catalog_backup 脚本用法、配置与 Catalog 的备份顺序与优先级安排。

Bacula 社区邮件列表 bacula-users 关于虚拟自动机与 Media Type 的讨论:同一自动机内各 Device 指向不同目录时必须区分 Media Type。

workaround.org 的 Bareos/Bacula Cheat Sheet:备份级别定义、Full / Differential / Incremental 组合下的恢复链示意与危险配置提示。

一万网络官网服务器租用、机柜托管与带宽接入产品页:机型、带宽、节点分布与报价以官网实时信息或咨询确认为准,本文不列举具体成交价格。


上一篇:机柜还剩一半 U 位却装不进新机器:托管扩容先卡电力还是先卡空间

下一篇:2026 服务器租用自建 Zimbra 协作邮箱怎么配:内存/存储/反垃圾 三本账 对比 + 避雷全攻略