先说明一个背景:我写这篇东西,是因为最近接手了一台跑在 ESXi 上的 VCSA 6.0,客户报障说 vCenter 服务全挂,进管理界面一看,根分区 100% 满。清理完日志和临时文件之后,service-control --start vmware-invsvc还是起不来,折腾了大半天才发现是内置 PostgreSQL 的数据目录里有大量残留 WAL 文件,手动删掉之后服务才恢复正常。这件事让我意识到,平时大家对 VCSA 的关注点都放在 Web Client、补丁、证书这些看得见摸得着的地方,真正核心的配置和清单数据其实都在它自带的 PostgreSQL 数据库里,而很多人从来没有想过要给这个库做一次主动备份。
如果你也管着 VCSA,或者你正在学习 vSphere 环境下的数据保护,这篇文章就把我这次备份 VCSA 内置 PostgreSQL 数据库的完整过程、踩坑记录和最终可用的脚本方案写出来。内容不绕弯子,直接讲怎么登录 VCSA 底层系统、怎么找到嵌入式数据库、怎么用 pg_dump 做逻辑备份、怎么恢复验证,以及备份完怎么处理“服务起不来”“磁盘又满”等一系列后续细节。
1. 备份前先搞清楚:VCSA 里的 PostgreSQL 到底是什么角色
1.1 VCSA 内置数据库的结构与职责
VCSA(vCenter Server Appliance)本身就是一套优化过的 Linux 虚拟机,里面预装了一个 PostgreSQL 实例,这个实例承载了 vCenter 几乎所有核心业务数据。常见的库有 VCDB(vCenter 配置和清单库)、VUMDB(Update Manager 数据库)、SBRS 相关的组件库等。对于绝大多数中小型环境来说,这个内置库就是 vCenter 的“大脑”——一旦损坏且没有备份,重建 vCenter 几乎等于重新梳理全部主机、虚拟机、权限、告警规则和分布式交换机配置。
需要注意,VCSA 内置 PostgreSQL 的服务名不是直接的postgresql,而是vmware-vpostgres。服务管理的底层工具是service-control,不是 systemctl(VCSA 6.x 时代还没有完全切到 systemd)。第一次操作时不熟悉这套命令,很容易用错启动方式,这是后话。
1.2 数据库备份不等于“快照备份”
很多人习惯在 vSphere 里直接给 VCSA 打快照,认为这样就算备份了。快照确实是很好的临时回滚手段,但对于生产环境里的 VCSA,长时间挂快照会带来两个问题:一是快照文件持续膨胀,占满存储;二是 VCSA 内部对数据库文件的操作非常频繁,长期带快照运行会影响磁盘 IO,增加故障概率。快照只适合“准备升级前临时做一次”的场景,而真正可长期保存、可移植、可验证的备份应该是数据库逻辑备份(也就是 PostgreSQL 的 dump 文件)。
我个人的建议是:快照用于短期回滚,逻辑备份用于长期灾备。两者不可互相替代。这篇文章讲的备份方式,正是后者。
1.3 备份时机与频率的判断
VCSA 内置库的备份不能过于频繁,因为 pg_dump 全量备份会产生不小的 IO 和 CPU 消耗。对于中小环境(几十台主机,几百台虚拟机),一周一次全量备份基本够用。如果环境变更频繁(大量创建删除虚拟机、调整权限、批量增删主机),建议把周期缩短到每天一次。另外,在进行任何升级、补丁安装、证书更换、存储迁移操作之前,必须手动触发一次备份。
2. 实操第一步:登进 VCSA 底层系统,确认数据库引擎状态
2.1 启用 SSH 和 Bash Shell
VCSA 默认 SSH 是关闭的。要通过命令行操作内置数据库,必须先在 VAMI(VCSA 管理界面,端口 5480)里开启 SSH 和 Bash Shell。
登录 https://vcsa-ip:5480,使用 root 账号进入,在“访问”-“SSH 和 Bash Shell”里把 SSH 服务设为“启用”,Bash Shell 设为“启用”。这个操作本质是为了让你可以通过 SSH 连到 VCSA 的底层操作系统,并在 shell 里执行 manage 命令。等备份完成后,建议把 SSH 重新关闭,减少暴露面。
2.2 检查 vmware-vpostgres 服务状态
SSH 登录 VCSA 后,第一件事是确认数据库服务没有异常。
service-control --status vmware-vpostgres正常输出会包含类似vmware-vpostgres is running的信息。如果服务是停止状态,需要先启动:
service-control --start vmware-vpostgres如果出现服务起不来的情况,不要急着继续备份,先排查数据目录、磁盘空间、日志目录。那次客户的 VCSA 一直报vmware-invsvc起不来,查到最后就是 postgresql 的 WAL 文件把数据目录塞满了,数据库一直处于恢复状态。这种情况下备份出来的文件也不一定完整,先修复再备份。
2.3 查看磁盘空间是否足够
数据库 dump 文件虽然通常不大,但 VCSA 根分区本身就比较紧张。备份前必须确认/storage/db和/tmp目录所在分区的剩余空间:
df -h du -sh /storage/db/pgdata如果根分区剩余空间不到 10GB,先把日志、临时文件、旧的备份清一清,否则 dump 过程中磁盘写满,容易把整个数据库目录搞出问题。
2.4 确认数据库版本和连接方式
VCSA 内置 PostgreSQL 的版本随 VCSA 版本不同而不同,早期 6.0 用的是 PostgreSQL 9.3 左右,6.5 之后版本有所提升,7.0 之后可能更高。可以通过下面命令确认版本:
/opt/vmware/vpostgres/9.3/bin/psql --version具体路径以实际目录结构为准,7.0 的 VCSA 中路径可能变成/opt/vmware/vpostgres/current/bin/psql。知道版本是为了避免后续恢复时出现工具版本不匹配问题。
3. 核心备份操作:用 pg_dump 和 pg_dumpall 做逻辑备份
3.1 切换到 vpostgres 用户
VCSA 内置 PostgreSQL 不允许 root 直接连接本地实例,必须切换到名为vpostgres的操作系统用户。这个用户的 home 目录是/var/lib/vmware/vpostgres,它拥有数据目录和数据库进程的权限。
chsh -s /bin/bash vpostgres su - vpostgres为什么需要chsh?因为 VCSA 里 vpostgres 用户默认 shell 是/bin/false,直接su - vpostgres会直接退出。有的版本里 vpostgres 的 shell 本身就是可用的,具体可以先grep vpostgres /etc/passwd看一下。如果已经是/bin/bash或/bin/sh,就不用改。
3.2 列出当前所有数据库
切换用户后,先看看实例里有哪些数据库:
/opt/vmware/vpostgres/9.3/bin/psql -U postgres -lVCSA 6.x 通常能看到的库包括VCDB、VUMDB和一些内部维护库。加-U postgres是因为 vpostgres 用户对应 PostgreSQL 的超级用户 postgres,本地 socket 认证默认是 trust,不需要密码。
3.3 单库备份:VCDB、VUMDB 分开处理
对于 VCSA 来说,最核心的库是 VCDB。建议每个业务库单独 dump,这样恢复时更灵活,单独一个库损坏时不会牵连其他库。
/opt/vmware/vpostgres/9.3/bin/pg_dump -U postgres -Fc -d VCDB -f /tmp/VCDB_$(date +%Y%m%d).dump /opt/vmware/vpostgres/9.3/bin/pg_dump -U postgres -Fc -d VUMDB -f /tmp/VUMDB_$(date +%Y%m%d).dump参数说明:
-Fc表示自定义格式,压缩比高,配合pg_restore可以灵活恢复单表,是运维备份首选。-f指定输出文件。$(date +%Y%m%d)让文件名带上日期,方便保留多份。- 如果库比较大,可以加
-j 4并发提升速度(配合-Fd目录格式使用)。
需要注意的是,-Fc是“自定义格式”,不是明文 SQL,不要拿文本编辑器打开看内容,也不要直接 psql 导入。恢复要用pg_restore,这一点新手很容易搞错。如果不放心,可以加一条明文 SQL 备份作为双保险:
/opt/vmware/vpostgres/9.3/bin/pg_dump -U postgres -d VCDB -f /tmp/VCDB_$(date +%Y%m%d).sql3.4 全实例备份:pg_dumpall 的适用场景
如果想一次性把所有数据库和全局对象(角色、表空间、权限)都导出来,可以使用pg_dumpall:
/opt/vmware/vpostgres/9.3/bin/pg_dumpall -U postgres -f /tmp/vpostgres_all_$(date +%Y%m%d).sqlpg_dumpall默认输出明文 SQL,包含角色定义、表空间定义和所有数据库的完整数据。它的优点是“全”,缺点是恢复时是一条大 SQL,没有单表恢复能力。作为 VCSA 的应急兜底方案很合适,但日常我仍以分库pg_dump -Fc为主。
为什么不能只用 pg_dumpall?因为 VCSA 里的库之间可能有依赖关系,跨库备份与恢复要格外小心。分库备份加全库备份,等于“点”和“面”都有了。
3.5 检查备份文件完整性
备份完成后,立即用ls -lh看文件大小是否合理。一个几百个虚拟机的环境,VCDB 备份通常有几十到几百 MB;如果你导出来只有几 KB,很可能是连接到了错误实例,或者 dump 过程被中断。
还可以用 pg_restore 查看归档内容:
/opt/vmware/vpostgres/9.3/bin/pg_restore -l /tmp/VCDB_$(date +%Y%m%d).dump | head -20如果能看到表、索引、序列等信息,说明备份文件结构正常。这一步虽然简单,但能从源头避免“备份了个寂寞”。
3.6 备份文件必须复制出 VCSA
备份文件如果只留在 VCSA 本机的/tmp,那等于白备份——VCSA 本身盘挂了文件也没了。需要把 dump 文件下载到本地电脑或复制到独立的备份存储。
我个人常用方法:
# 在本地电脑执行 scp root@vcsa-ip:/tmp/VCDB_*.dump /backup/vcsa/ scp root@vcsa-ip:/tmp/vpostgres_all_*.sql /backup/vcsa/如果有集中备份服务器,也可以从 VCSA 反向推送到 NFS 共享或 FTP。注意 scp 在 VCSA 6.0 上默认可能不带,可以改用 SFTP 工具(如 WinSCP、FileZilla)通过 SSH 协议下载。下载完成后再回到 VCSA 清理/tmp下的临时文件,避免给本来就紧张的磁盘添堵。
4. 恢复演练:验证备份能否真正救命
备份不经过恢复验证,就不能叫备份,只能叫“心理安慰”。我建议每次备份后都至少在测试环境做一次恢复演练,尤其是第一次搭建备份方案时,必须完整走一遍恢复流程。
4.1 在临时实例上恢复 dump 文件
在 VCSA 上不要随意覆盖现有数据库。恢复演练最好在另外一套环境(比如一台安装了相同 PostgreSQL 版本的 Linux 虚拟机)上进行。
# 先创建一个空库 /opt/vmware/vpostgres/9.3/bin/createdb -U postgres VCDB_test # 用 pg_restore 恢复自定义格式备份 /opt/vmware/vpostgres/9.3/bin/pg_restore -U postgres -d VCDB_test /tmp/VCDB_$(date +%Y%m%d).dump如果备份是明文 SQL:
/opt/vmware/vpostgres/9.3/bin/psql -U postgres -d VCDB_test -f /tmp/VCDB_$(date +%Y%m%d).sql4.2 恢复常见报错与处理
恢复过程中大概率会遇到对象已存在、权限不足、序列冲突等问题。VCSA 内置库依赖很强,直接恢复到全新库时,部分扩展(如plpgsql)可能需要提前创建。pg_restore加--clean和--if-exists可以清理已存在对象并容错:
/opt/vmware/vpostgres/9.3/bin/pg_restore -U postgres -d VCDB_test --clean --if-exists /tmp/VCDB_$(date +%Y%m%d).dump需要注意,正式恢复进 VCSA 的库时,--clean要非常谨慎,它会先删掉现有对象再创建,操作不当会加重破坏。这也是为什么我强调恢复演练一定要在独立环境先做。
4.3 恢复后验证清单
恢复完可以执行几个查询验证数据:
SELECT count(*) FROM vpx_vm; SELECT count(*) FROM vpx_host; SELECT count(*) FROM vpx_alarm;如果查询结果和备份前对得上,说明库基本可用。如果能启动 vCenter 服务并正常显示清单,才算恢复成功。VCSA 的组件之间习惯相互调用数据库存储过程,光看表数量还不够。
5. 自动化备份脚本:让备份变成习惯,而不是临时抱佛脚
5.1 脚本核心思路
手动备份容易忘记,生产环境一定要写成脚本配合 crontab 定时执行。脚本的核心逻辑是:
- 检查 db 服务状态。
- 创建备份目录(区分日期)。
- 执行 pg_dumpall 和分库 pg_dump。
- 删除超过保留天数的旧备份。
- 可选:推送备份到远端备份服务器。
5.2 可直接使用的备份脚本
下面这个脚本我在 VCSA 6.0 上验证过,VCSA 6.5、6.7 也能用,核心是路径要根据find /opt/vmware/vpostgres -name psql的结果调整。
#!/bin/bash export PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin DATE=$(date +%Y%m%d_%H%M%S) BK_DIR=/storage/backup/vcsa-pg RETENTION_DAYS=14 PGBIN=/opt/vmware/vpostgres/9.3/bin PGUSER=postgres mkdir -p ${BK_DIR}/${DATE} # 检查数据库服务 ${PGBIN}/pg_isready -U ${PGUSER} > /dev/null 2>&1 if [ $? -ne 0 ]; then echo "[ERROR] PostgreSQL is not ready at ${DATE}" >> ${BK_DIR}/backup.log exit 1 fi # 全实例备份 ${PGBIN}/pg_dumpall -U ${PGUSER} -f ${BK_DIR}/${DATE}/all_databases.sql # 分库备份:按需调整库名 for DB in VCDB VUMDB; do ${PGBIN}/pg_dump -U ${PGUSER} -Fc -d ${DB} -f ${BK_DIR}/${DATE}/${DB}.dump done # 清理旧备份 find ${BK_DIR} -maxdepth 1 -type d -mtime +${RETENTION_DAYS} -exec rm -rf {} \; echo "[OK] Backup completed at ${DATE}" >> ${BK_DIR}/backup.log关于脚本有两个细节说明:
- 备份目录我习惯放在
/storage/backup,而不是/tmp,因为 VCSA 临时目录容易在重启后被清理,而且/tmp空间通常不大。 - 保留天数写了 14,对于大多数环境足够了。如果想要更长保留周期,可以放到外部存储再归档。
5.3 配置 crontab 定时任务
使用 root 身份执行:
crontab -e添加一行:
0 1 * * 0 /root/backup_vcsa_pg.sh > /dev/null 2>&1这表示每周日凌晨 1 点执行一次。如果变更频繁,可以改成每天一次:0 1 * * *。
5.4 注意 VCSA 系统升级后脚本路径变化
VCSA 大版本升级后,PostgreSQL 的安装路径可能从/opt/vmware/vpostgres/9.3变成/opt/vmware/vpostgres/current,或者二进制版本变成 12、14 等。脚本里的路径要跟着改。我吃过一次亏:升级 VCSA 后脚本报错找不到 psql,但 crontab 又不会弹邮件提醒,直到某天要恢复备份才发现过去一个月备份全是空目录。
6. 常见问题与排查技巧实录
6.1 磁盘满导致 vpostgres 无法启动
这是 VCSA 最经典的“隐形杀手”。根分区一旦满了,vmware-vpostgres会拒绝启动,同时service-control --start vmware-invsvc这类命令也会因为依赖的数据库还挂着而反复失败。排查时先别急着重启服务,按这个顺序处理:
# 查看空间占用 df -h # 找到大文件目录 du -xh --max-depth=2 / 2>/dev/null | sort -rh | head -20常见占用大头是/storage/log、/storage/db/pgdata/pg_xlog(或pg_wal),以及/tmp。清理时不要直接删数据目录文件,优先清/storage/log下旧日志,再考虑 WAL 归档。
6.2psql: could not connect to server: No such file or directory
执行 psql 连不上,很多情况下是因为 socket 目录不对。VCSA 默认 socket 路径可能是/var/run/vmware/vpostgres,使用 psql 时指定-h为 socket 目录位置:
/opt/vmware/vpostgres/9.3/bin/psql -h /var/run/vmware/vpostgres -U postgres -l6.3 备份文件过大或者过小
备份文件如果超出预期很多倍,通常是因为 VCDB 里积累了太多历史性能数据、事件数据或任务数据。VCSA 6.x 里有vpx_history_*等表,会保留大量历史数据。如果备份太大影响备份速度和迁移效率,可以考虑在 vCenter 管理界面调整统计数据的保留时间,或清理过期事件后再备份。
备份文件如果过小,比如 VCDB 导出来只有几 MB,多见于 vCenter 运行时并没有把数据写入这个库(数据库只是空壳),或者你连到了错误的实例。VCSA 里可能同时存在postgres默认库和 VCDB 库,注意区分。
6.4 恢复时提示role "vsphere" does not exist
VCSA 内部库有很多专属角色和用户,比如vsphere、vc、vumadmin等。如果你的分库 dump 文件没有包含全局角色定义,只导出了表数据,恢复到新实例时会因为角色缺失报错。解决办法是先恢复pg_dumpall生成的包含角色定义的文件,再恢复分库数据;或者在 pg_restore 前手动创建缺失角色。
6.5 备份目录权限导致的执行失败
VCSA 对操作系统用户的权限检查比较严格。如果/storage/backup目录是 root 创建的,vpostgres 用户写不进去,脚本会执行到 pg_dump 那一步失败。创建目录后记得授权:
mkdir -p /storage/backup/vcsa-pg chown -R vpostgres:vpostgres /storage/backup6.6 VCSA 7.0 及以上版本的备份差异
VCSA 7.x 内置的 PostgreSQL 版本更高,同时多了更多内部组件,service-control --status看到的服务更多了。但核心思路不变:找到vmware-vpostgres,使用内置 psql 和 pg_dump。唯一要注意的是路径变成了/opt/vmware/vpostgres/current/bin/,如果还按 9.3 找肯定会撞墙。另外,VCSA 7 以后官方开始推荐用 VAMI 里的“备份与还原”功能做整体备份,那个方式会把全套配置文件带出来,恢复时更省事。不过数据库粒度的 pg_dump 备份仍然有独特价值——当只需要救援 VCDB 时,它更直接。
7. 备份策略与最终建议
7.1 推荐的备份组合方案
我把这套环境里最终落地的备份方案写出来供参考:
| 备份类型 | 方式 | 频率 | 保存周期 |
|---|---|---|---|
| 系统级快照 | vSphere 打快照 | 升级/补丁前临时做 | 升级完成后删除 |
| 全库逻辑备份 | pg_dumpall | 每周 | 30 天 |
| 分库逻辑备份 | pg_dump -Fc | 每天 | 14 天 |
| 配置文件备份 | /etc/vmware-vpx 目录打包 | 每周 | 30 天 |
配置文件打包虽然不属于数据库备份,但对恢复 VCSA 同样重要。可以加一行脚本:
tar czf ${BK_DIR}/${DATE}/etc_vpx.tar.gz /etc/vmware-vpx7.2 卡片式经验:如果从头再做一次
根据我这次处理的经历,如果再让我给一套新的 VCSA 建立备份机制,我会按这个顺序走:
- 先在 VAMI 开启 SSH 和 Bash Shell。
- 用
df -h和du -sh摸清磁盘现状,确保根分区有充足余量。 - 确认 vmware-vpostgres 服务健康。
- 手动执行一次分库 pg_dump 和 pg_dumpall,测试命令路径和权限。
- 把 dump 文件 scp 到外部存储,验证文件大小。
- 写自动化脚本,加入 crontab。
- 在测试环境做一次恢复演练。
- 把 SSH 关掉,只在需要维护时临时开启。
7.3 我的一些额外提醒
备份这事,最怕的不是技术不懂,而是“以为备份了”。我见过太多朋友拍着胸脯说“VCSA 我有快照”,结果快照跟 VCSA 放在同一个数据存储里,存储一坏全完;也见过备份脚本跑了半年,文件全是 0 字节,因为脚本里的用户名写错了。一定要像验证生产数据一样去验证备份,这与 vSphere 本身的稳定性同样重要。
另外,VCSA 的数据库备份有个天然局限:直接恢复到同一台 VCSA 上不一定能完美还原整个 vCenter 全貌,因为 VCSA 还有证书、身份来源、VAMI 配置等”库外“组件。所以如果你的目标是“整机灾难恢复”,我更推荐结合 VAMI 的整体备份方案,把数据库备份当作第一道防线和应急手段来用。两者搭配,既能在关键时刻救回数据,又能减少维护负担。