Vcenter 7.0.3.01000 的“no healthy upstream”这个报错,我前前后后碰到过三次,每次根因都不一样。你要是第一次遇到,大概率会慌,因为打开 vCenter 的 Web 管理界面直接给你甩个 502,点哪儿都没反应,想进 VAMI 看个状态都进不去。实际上这个报错的本意非常直白:vCenter 的 Web 反向代理层找不到一个能正常工作的后端服务,所以它拒绝转发请求。说白了,这是个“结果”而不是“原因”,真正要排查的是背后哪个服务挂了、为什么挂。
这篇文章我就把三次排查的经历和思路整理出来,把 SSH 进 VCSA、查看服务状态、翻日志、重启组件、处理证书和磁盘问题的完整过程都过一遍。如果你是做虚拟化运维的,或者公司里刚好跑着 vCenter 7.0.3 这个版本,建议收藏一下,等遇到同样问题的时候照着做,能省下大把踩坑时间。
1. 先搞清楚这个报错到底在说什么
1.1 “no healthy upstream”是怎么冒出来的
vCenter Server Appliance(VCSA)的 Web 界面不是一台 Web 服务器直接给你出页面,它前端挂了一个 Nginx 反向代理,后面还跟着一个叫 rhttpproxy 的内部代理组件,再往后才是真正的业务服务,比如 vpxd(管理服务)、vsphere-ui(Web 客户端)、sso(单点登录)、vpostgres(内嵌数据库)等等。
你浏览器访问https://vcsa-fqdn/ui的时候,请求会走这么一条链路:
浏览器 -> nginx -> rhttpproxy -> 后端服务Nginx 起了一个负载均衡的活儿,它会定期检查后端各服务是不是“活着”。这个健康检查不是简单的 Ping 通就行,而是要后端服务真正返回正常的 HTTP 响应。一旦某个上游服务没起来、起来了一半、或者进程活着但响应不了,Nginx 就会把这条上游标记为不健康,然后你在浏览器里就看到了那句经典的no healthy upstream。
这个报错的杀伤力在于,它把你框在了一个“结果”里,让你误以为是 Nginx 或者代理层坏了,其实绝大多数情况下代理层一点问题都没有,病根儿全在后端服务上。所以排查思路的第一步,就是千万别盯着 Nginx 死磕,而是想办法绕开 Web 界面,直接进系统看服务状态。
1.2 排查要抓住的几条主线
根据我自己的经验,VCSA 7.0.3 这个版本出现 no healthy upstream,原因基本跑不出下面这几类:
| 根因类别 | 典型表现 | 排查难度 |
|---|---|---|
| 核心服务未运行 | vpxd、vsphere-ui 等进程没起来 | 低 |
| 后端数据库异常 | vpostgres 启动失败或健康检查失败 | 中 |
| 磁盘空间耗尽 | /storage 分区满了,组件起不来 | 低,但容易忽略 |
| 证书过期或时间不同步 | STS 证书过期,组件间认证失败 | 中 |
| rhttpproxy 本身异常 | 代理缓存或路由表损坏 | 高 |
| 升级/迁移残留问题 | 组件未正确注册到 vCenter 服务列表 | 中 |
我个人遇到的三次,第一次是磁盘满了,第二次是 vpostgres 出问题,第三次是证书过期。共同点是:Web 界面全部报 no healthy upstream,但现象之前还是有一些细微差别的,后面我会在实操部分逐个说。
2. 从登录到定位:一步步拿到真实故障根因
2.1 用 SSH 进 VCSA,拿到 BASH Shell
vCenter 的 Web 管理面挂了,但底层的 Photon OS 通常还活着。这时候最直接的办法就是用 SSH 登录到 VCSA 的 IP 或者域名,用root账号进去。
登录之后默认会进入一个受限的 shell,需要手动敲一条命令来切换到真正的 BASH 环境:
shell这一步一定要记得,我见过不少人卡在这里,以为只能敲几个固定的运维命令。进入 BASH 之后,你才有权限去看日志、手动操作服务。
进了 BASH 之后,第一条建议是先看一下系统的基本状态,特别是磁盘空间。命令是:
df -h重点关注/storage、/、/var这几个挂载点。VCSA 的日志、数据库文件都放在/storage下面,这个分区一旦满了,vpostgres 第一个遭殃,紧接着 vpxd 也起不来。
2.2 查看服务状态,锁定谁不给面子
VCSA 7.x 里面管理服务用的命令是service-control,注意不是 systemctl。这个命令可以一次性列出所有后端服务的名字和健康状态:
service-control --status --all输出会很长,一屏可能看不完,建议加个 grep 过滤一下,重点看这几个服务:
service-control --status --all | grep -E "vpxd|vsphere-ui|vpostgres|rhttpproxy|sts"正常情况下,这几个服务都应该是Running状态。如果有显示Stopped,那它八成就是让你看到 no healthy upstream 的元凶。如果显示Running但 Web 界面还是报错,那就要往更深一层去查,比如服务进程是不是僵尸状态、健康检查接口是不是响应异常、数据库连接是不是断的。
我那次磁盘满的情况,当时看到 vpostgres 是Stopped,vpxd 是Stopped,但磁盘已经 100% 了,所以当时第一反应是清理空间而不是直接拉起服务,事实证明这个顺序很重要。你要是没查磁盘就贸然用service-control --start --all去把服务全部拉起,大概率会看到服务反复启动又退出,然后日志里刷一堆数据库错误。
2.3 快速定位日志,别瞎猜
如果service-control看不出明显问题,或者你想知道服务到底为什么起不来,那就必须看日志。
VCSA 的日志路径有一点绕,不是所有日志都在一个目录下。常用的几个位置如下:
| 日志内容 | 路径 |
|---|---|
| vpxd 详细日志 | /var/log/vmware/vpxd/vpxd.log |
| rhttpproxy 日志 | /var/log/vmware/rhttpproxy/rhttpproxy.log |
| VAMI 日志 | /var/log/vmware/vami/vami.log |
| vpostgres 日志 | /var/log/vmware/vpostgres/(子目录下) |
| 服务控制日志 | /var/log/vmware/vmon/vmon.log |
看日志的时候,不要漫无目的地从头翻到尾,要结合时间点去过滤。比如你知道故障大概是下午三点冒出来的,那就用tail配合sed或者awk去截取那个时间段的内容。
看 vpxd 日志的时候,我最常用的命令是:
tail -n 200 /var/log/vmware/vpxd/vpxd.log如果服务压根没起来,或者起来就挂,那vmon.log往往是更直接的线索,它会记录服务启动失败的退出码和具体报错。
我个人在实际排查时,会同时开三个终端窗口,分别tail -fvpxd.log、vpostgres 日志、vmon.log,然后尝试启动服务,这样能实时看到服务在启动过程中到底卡在哪一步。这个习惯帮我节省了大量时间,不用一个日志一个日志地反复翻。
3. 实操:几种典型场景下的解决过程
3.1 场景一:vpxd 服务没起来,直接拉起
这种属于最温和的情况。现象特征是 Web 界面报 no healthy upstream,但 VAMI 的 5480 端口可能还能访问,或者 SSH 进去看服务状态时,只有 vpxd 处于 Stopped。
解决方式很简单:
service-control --start vmware-vpxd如果只起 vpxd,可能会遇到依赖服务没起导致启动失败,稳妥起见可以直接拉起全部核心服务:
service-control --start --all注意,--start --all这个命令执行时间会比较长,不是立刻返回的,等它跑到 100% 才说明启动流程正常结束。如果中途报FAILED,那说明有组件启动异常,这时候就要回去看 vmon.log 和 vpxd.log,判断是依赖问题还是资源问题。
我的经验是,单独只拉起 vpxd 时,要盯一下 vpostgres 是不是正常。因为 vpxd 启动后第一件事就会去连数据库,如果 vpostgres 是挂着或者没完全就绪,vpxd 会一直重试,最终表现出"启动中"或者"启动失败"。与其单拉一个,不如先确认 vpostgres 正常,再拉 vpxd。
3.2 场景二:vpostgres 健康检查失败,核心组件连环挂
这个场景的报错逻辑是这样的:vpostgres 挂了,连带着 vpxd、vsphere-ui、sts 这些需要数据库支撑的服务全部不健康,Nginx 一看后端全是坏的,直接甩出 no healthy upstream。
如果你执行service-control --status --all看到一大片 Stopped 或者 Degraded,重点怀疑数据库。
vpostgres 起不来最常见的两个原因:磁盘满、数据目录权限或损坏。
先说磁盘满,处理方式:
df -h发现/storage/db或者/storage/log占用到 99% 甚至 100%,就去日志目录里找大文件:
du -sh /storage/log/* | sort -rh | head -20通常vpxd的日志文件或者dump目录会产生几个 GB 级别的文件,直接清理掉历史归档日志,或者把超过一定大小且不再使用的日志文件移动到别处,就能释放出大量空间。我在实际清理时,会先压缩再删除,比如把 30 天前的日志文件做成.gz,确定业务没问题之后再删掉压缩包,这样更稳妥。
空间释放完之后,再启动 vpostgres:
service-control --start vmware-vpostgres启动成功之后,接着启动其他组件:
service-control --start --all另一种情况是数据目录出问题。如果你看了 vpostgres 日志,发现里面出现could not open file、Permission denied、database system was interrupted之类的字样,说明数据库数据文件有可能损坏或者是异常断电导致的未正常关闭。这种时候先别急着重启,先检查一下磁盘有没有只读挂载:
mount | grep -E "storage|db"如果挂载正常,可以尝试用 vpostgres 自带的工具做一次恢复启动,但这一步有风险,我个人的建议是:如果配置有完整备份,优先考虑从备份恢复;如果没有备份,再尝试把 vpostgres 数据目录冷备份一份,然后做 PostgreSQL 层面的恢复启动尝试。vCenter 的数据库不是普通 PostgreSQL,里面的 schema 和 vCenter 自己写的数据结构绑定很深,千万不要随便拿 psql 去乱改表,否则后果可能比不能启动更严重。
3.3 场景三:证书过期导致的组件间认证失败
这一类问题在 vCenter 7.0.3 里尤其容易踩雷,因为 STS 证书的过期时间默认只有两年左右,很多环境从部署到现在已经过了这个期限。证书一过期,组件之间互相调用时做 TLS 握手直接失败,表现出来也是后端服务不健康。
怎么快速判断是证书问题?看 vpxd.log,通常会刷出大量类似certificate verify failed、SSL routines、tlsv1 alert certificate expired的报错。另外,执行下面的命令能直接查看机器证书的过期时间:
/usr/lib/vmware-vmafd/bin/certool --getservercert --server=localhost复现过程中,当时我看到的实际输出是一连串时间戳,对比当前日期之后确认证书早在两个月前就已经到期。这时候的处理方式有两个方向:一个是重新生成证书(相当于换新),另一个是恢复到 VAMI 备份的证书状态。
如果你有 VAMI 的备份,可以在 SSH 里直接跑:
/usr/lib/vmware-vpxd/migration/scripts/vami-password-reset.sh不对,这个命令不是用来恢复证书的。正确的思路是:证书过期后,通常用 vCenter 自带的证书管理工具去刷新。但如果是 STS 证书整体过期导致 Web 界面都进不去,那最省事的办法是登录 VAMI(5480 端口),虽然 UI 进不去,但 VAMI 通常还活着,在 VAMI 里面可以触发证书续期。如果连 VAMI 都进不去,那你只能通过 SSH 方式手工更新证书,具体操作比较复杂,这里只给一个方向,就是使用vmafd和certool配合刷新,操作前一定要先备份/etc/vmware-vmafd/目录,否则不小心改坏证书,整个环境会彻底失联。
我个人的建议是:证书过期这种事,预防远大于治疗。每个季度做一次 vCenter 巡检的时候,一定要检查证书剩余有效期,不要等到报错了才想起来。尤其是 VCSA 7.0.3 这种已经停止功能更新的老版本,证书策略变化不大,提前续期是最稳的。
3.4 场景四:rhttpproxy 本身变傻,重启大法兜底
如果服务全都在运行,vpostgres 也正常,证书也没过期,但 no healthy upstream 依然存在,那嫌疑就落在 rhttpproxy 身上。
rhttpproxy 是 vCenter 内部承担反向代理和路由的组件,它维护了一份内存中的路由表,把外部请求分发给后端的各个服务。如果这份路由表出了问题,或者它和后端服务之间的连接池满了,健康检查就会失败。
这种时候最直接的办法就是重启 rhttpproxy:
service-control --stop vmware-rhttpproxy service-control --start vmware-rhttpproxy如果重启之后马上恢复正常,那大概率就是连接池或者路由缓存的问题,属于偶发性故障。如果重启后还是不行,再看 rhttpproxy 的日志,确认它是否真的能把请求转发到后端。注意,有时候 rhttpproxy 日志里会显示后端地址是localhost:8080这种内网地址,如果你做过网络隔离或者防火墙限制,可能导致它访问不到后端,这时候检查的就不是服务本身,而是防火墙规则了。
4. 解决之后的验证,以及我踩过的一些坑
4.1 怎么确认 vCenter 真的恢复正常了
服务全部启动之后,不要急着就说修复了,要做几个层面的验证。
第一步,看服务状态是不是全部 Running:
service-control --status --all | grep -E "vpxd|vsphere-ui|vpostgres|rhttpproxy|sts"第二步,浏览器无痕模式访问 vCenter 的 Web 界面。无痕模式这个细节很重要,因为浏览器可能有缓存的证书和会话,普通模式刷新会看到假象,无痕模式下如果页面能正常弹出登录框,说明链路基本畅通了。
第三步,用登录后的界面做一次实际操作,比如创建一台虚拟机、迁移一次主机,确保不是"能登录但后面还会有隐性故障"。我在第三次处理证书问题时,就遇到过能登录但 vCenter 里主机显示断开的情况,那是因为 vpxd 和 ESXi 主机之间的通信也受证书影响,需要在 vCenter 里重新触发一下 SSL 证书校验。这一步不检查的话,等于问题只解决了一半,后续早晚还会暴露。
4.2 几个特别容易误判的点
第一个误判是"看到 no healthy upstream 就觉得 vCenter 彻底坏了"。这个报错其实只代表 Web 代理层连不上后端,不代表整个 VCSA 挂了。很多时候 SSH 还能进,VAMI 还能开,ESXi 主机上的虚拟机还在正常跑。所以不要一来就重装 vCenter,那是最坏的打算,放在最后。
第二个误判是"把所有服务重启一遍就万事大吉"。如果你不弄清楚为什么服务会挂,下次故障只会来得更快。磁盘空间、证书有效期、日志增长量,这些都是需要长期监控的指标,平台监控工具里最好把这几项都覆盖上。
第三个误判是"忽视 vCenter 版本的生命周期"。7.0.3.01000 这个版本号其实已经是 7.0 Update 3 系列里的一个修补版本,但 7.0 全系已经接近生命周期尾期。如果你还在 7.0.3 上拖着不升级,后续碰到类似的诡异问题只会越来越多。新装的业务环境,建议直接评估 vCenter 8.0,功能更新和安全性都会好很多。升级前务必确认兼容性列表里 ESXi 主机和 vCenter 版本的配套关系,别贪快。
4.3 巡检建议
处理完这次故障之后,我把巡检脚本里加了几项检查,推荐你也做一下:
- 每月检查一次
/storage分区使用率,超过 70% 就要关注,超过 85% 必须介入清理。 - 每季度检查一次 vCenter 证书有效期,主要看 STS 证书和 machine SSL 证书。
- 定期备份 VCSA 配置,备份文件最好放到 vCenter 本机之外的位置。
- 升级或补丁操作前,手动拍一次快照。vCenter 是管理面,快照恢复比数据面虚拟机容易接受得多。
vCenter 一旦出问题,整个虚拟化环境的"方向盘"就失灵了,所以这类管理面设备的运维,讲究的就是一个稳字。遇到 no healthy upstream 这种报错,别慌,按着服务、数据库、证书、代理这条线一层一层剥下去,基本上都能找到真凶。