vCenter Server 7.0 完全宕机恢复实录 — STS 证书过期 + 连环故障排查

vCenter Server 7.0 完全宕机恢复实录 — STS 证书过期 + 连环故障排查

故障时间:2026-06-24 ~ 2026-06-25 vCenter 版本:7.0U3c (build 19234570) VCSA FQDN:vcenter.streamcomputing.com SSO 域:vsphere.local

一、故障现象

vCenter 完全不可用,vmware-vpxd-svcs 服务启动失败,所有依赖服务连锁宕机:

service-control --start vmware-vpxd-svcs
Error executing start on service vpxd-svcs. Details {
    "id": "install.ciscommon.service.failstart",
    "localized": "An error occurred while starting service 'vpxd-svcs'"
}

vSphere Client 无法访问,ESXi 主机失联,vCenter 管理功能完全中断。


二、根因总结

这次故障是三个独立问题叠加造成的连环宕机:

#问题根因影响
1STS 签名证书过期证书有效期 2024-03-21 ~ 2026-03-21,certificate-manager 不更新此证书SAML token 签发失败 → vpxd-svcs pre-start 脚本崩溃
2MACHINE_SSL_CERT VECS 存储为空6月6日证书更新操作不完整,清空了存储但没重新导入STS Tomcat SSL connector 初始化失败 → STS 服务崩溃
3vpxd-svcs.json 配置文件丢失原因不明,可能在某次操作中被误删vmon 无法识别 vpxd-svcs 服务 → 服务完全不可管理

故障链:

STS 签名证书过期 (2026-03-21)
    ↓
SAML token 签发被拒绝 ("Signing certificate is not valid")
    ↓
tagging_grpc_registration.py reregister_service() 失败
    ↓
vpxd-svcs pre-start 脚本退出 (exit code 1)
    ↓
vpxd-svcs JVM 从未启动 → 端口 10080 不监听
    ↓
vpxd 连接 localhost:10080 被拒 (Connection refused)
    ↓
vpxd Authz 初始化失败,重试 60 次后退出
    ↓
VCSA 完全宕机

三、详细排查过程

3.1 初始诊断:排除基础问题

# 磁盘空间(正常)
df -h  # 所有分区使用率 < 35%

# 内存(正常)
free -h  # 27G total, 6G used

# OOM(无)
dmesg | grep -i "oom\|killed"  # 空

# PostgreSQL(正常运行)
service-control --status vmware-vpostgres  # Running

3.2 分析 vpxd 日志:发现 Authz 连接失败

tail -100 /var/log/vmware/vpxd/vpxd.log

关键错误:

Failed to connect; <TCP '127.0.0.1 : 10080'>, e: 111(Connection refused)
Failed to connect to Authz service: vmodl.fault.HostCommunication
Failed to instantiate AuthzStorageProvider
Failed to initialize authorizeManager
Failed to start VMware VirtualCenter. Shutting down

vpxd 在尝试连接 localhost:10080 (vpxd-svcs 的 Authz 接口),但连接被拒绝 — 说明 vpxd-svcs 没有运行。

3.3 分析 vpxd-svcs pre-start 日志:发现 STS 证书过期

tail -50 /var/log/vmware/vpxd-svcs/pre-start-vpxd-svcs.log

关键错误:

ERROR:tagging_grpc_registration:Failed to reregister Tagging service grpc endpoints
invalidProperty = 'Invalid certificate'

进一步查看 vmon 日志:

grep "vpxd-svcs" /var/log/vmware/vmon/vmon.log | tail -20

发现 pre-start 脚本在 tagging_grpc_registration.py 第 119 行崩溃。

深入查看完整的 pre-start 日志,找到根本原因:

faultstring: The token authority rejected an issue request for
TimePeriod [startTime=Wed Jun 24 08:38:21 GMT 2026, endTime=...]
:: Signing certificate is not valid at Wed Jun 24 08:38:21 GMT 2026,
cert validity: TimePeriod [startTime=Thu Mar 21 03:41:59 GMT 2024,
endTime=Sat Mar 21 03:41:59 GMT 2026]

STS 签名证书在 2026-03-21 过期了!

3.4 检查证书状态

# 检查 VECS 所有证书存储
for i in $(/usr/lib/vmware-vmafd/bin/vecs-cli store list); do
  echo "=== STORE: $i ==="
  /usr/lib/vmware-vmafd/bin/vecs-cli entry list --store $i --text | grep -A2 "Not After"
done

发现:

  • `MACHINE_SSL_CERT` 存储:**0 个条目(空!)**
  • Solution User 证书(machine, vpxd 等):有效至 2036 年
  • `BACKUP_STORE` 中有旧证书备份,Mar 21 2026 过期

3.5 检查 VMCA 根证书

openssl x509 -in /var/lib/vmware/vmca/root.cer -noout -dates
# notBefore=Jun  9 09:47:53 2026 GMT
# notAfter=Jun  6 09:47:53 2036 GMT

VMCA 根证书是有效的(2026-06-09 到 2036-06-06),只有 STS 签名证书过期了。

3.6 检查 STS 服务状态

cat /var/log/vmware/sso/sts-runtime.log.stderr

发现 STS 也崩溃了:

java.lang.Error: org.apache.catalina.LifecycleException:
Failed to initialize connector [Connector[...VECSAwareHttp11NioProtocol-7444]]

STS 的 Tomcat 需要从 MACHINE_SSL_CERT VECS 存储读取 SSL 证书,但存储是空的,所以 connector 初始化失败。


四、修复步骤

4.1 修复 MACHINE_SSL_CERT VECS 存储(修复 STS 崩溃)

# 1. 生成新私钥
/usr/lib/vmware-vmca/bin/certool --genkey \
  --privkey=/tmp/machine_ssl.key \
  --pubkey=/tmp/machine_ssl.pub \
  --server=localhost

# 2. 创建证书配置(certool 使用 [Key = Value] 格式)
cat > /tmp/machine_ssl.cfg << 'EOF'
[Country = US]
[Name = vcenter.streamcomputing.com]
[Organization = vcenter.streamcomputing.com]
[OrgUnit = VMware Engineering]
[State = California]
[Locality = Palo Alto]
[IPAddress = ]
[FQDN = vcenter.streamcomputing.com]
[AltName = vcenter.streamcomputing.com]
EOF

# 3. 用 VMCA 签发新 Machine SSL 证书
/usr/lib/vmware-vmca/bin/certool --gencert \
  --privkey=/tmp/machine_ssl.key \
  --cert=/tmp/machine_ssl.cer \
  --config=/tmp/machine_ssl.cfg \
  --Name=vcenter.streamcomputing.com \
  --server=localhost

# 4. 验证新证书
openssl x509 -in /tmp/machine_ssl.cer -noout -dates -subject -issuer
# notBefore=Jun 24 10:40:06 2026 GMT
# notAfter=Jun 23 10:40:06 2028 GMT
# subject= /CN=vcenter.streamcomputing.com

# 5. 导入到 MACHINE_SSL_CERT store
/usr/lib/vmware-vmafd/bin/vecs-cli entry create \
  --store MACHINE_SSL_CERT \
  --alias __MACHINE_CERT \
  --cert /tmp/machine_ssl.cer \
  --key /tmp/machine_ssl.key

# 6. 确认导入
/usr/lib/vmware-vmafd/bin/vecs-cli entry list --store MACHINE_SSL_CERT
# Number of entries in store : 1

# 7. 重启 STS
service-control --stop vmware-stsd
sleep 3
service-control --start vmware-stsd
sleep 15
service-control --status vmware-stsd  # Running!
netstat -tlnp | grep 7444  # LISTENING!

4.2 确认 STS 签名证书在 vmdir 中的状态

使用 Python + ldap3 库连接 vmdir (LDAPS):

import ldap3, subprocess, os

WORK = "/tmp/sts-fix"
SSO_USER_DN = "cn=Administrator,cn=Users,dc=vsphere,dc=local"
sso_pass = "你的SSO密码"

server = ldap3.Server("ldaps://localhost:636", get_info=ldap3.ALL)
conn = ldap3.Connection(server, user=SSO_USER_DN, password=sso_pass, auto_bind=True)

# 搜索所有带 userCertificate 的对象
conn.search("dc=vsphere,dc=local", "(userCertificate=*)",
            attributes=["dn", "cn", "userCertificate"])

for entry in conn.entries:
    dn = str(entry.entry_dn)
    if entry.userCertificate:
        for i, cert_data in enumerate(entry.userCertificate):
            if isinstance(cert_data, bytes):
                with open(f"{WORK}/check_cert.der", 'wb') as f:
                    f.write(cert_data)
                r = subprocess.run(["openssl", "x509", "-in", f"{WORK}/check_cert.der",
                    "-inform", "DER", "-noout", "-dates", "-subject"],
                    capture_output=True, text=True)
                print(f"  {dn}\n  Cert {i}: {r.stdout.strip()}")

发现 TenantCredential-1 对象中的 STS 签名证书已经是新的(notBefore=Jun 24 08:59:53 2026, notAfter=Jun 6 2036),说明 vmdir 中的 STS 证书已经在之前某次操作中更新过了。

但 Lookup Service 中存储的服务注册信息仍然引用了过期的证书(Mar 21 2026),导致 reregister_service() 报 "Invalid certificate"。

4.3 重建 vpxd-svcs.json 配置文件

发现 /etc/vmware/vmware-vmon/svcCfgfiles/ 目录中缺少 vpxd-svcs.json:

ls /etc/vmware/vmware-vmon/svcCfgfiles/ | grep vpxd
# 只有 vpxd.json,没有 vpxd-svcs.json

vmon 日志确认:

Service vpxd-svcs not found.
Invalid service vpxd-svcs in profile CRITICAL. Ignoring.

在安装目录找到原始模板:

find /usr/lib/vmware-vpxd-svcs -name "*.json"
# /usr/lib/vmware-vpxd-svcs/scripts/conf/vpxd-svcs-lin.json  ← 这就是原始配置!

复制到 vmon 配置目录:

cp /usr/lib/vmware-vpxd-svcs/scripts/conf/vpxd-svcs-lin.json \
   /etc/vmware/vmware-vmon/svcCfgfiles/vpxd-svcs.json
chmod 644 /etc/vmware/vmware-vmon/svcCfgfiles/vpxd-svcs.json
chown root:cis /etc/vmware/vmware-vmon/svcCfgfiles/vpxd-svcs.json

重启 vmon daemon 让它重新加载配置:

service-control --stop vmware-vmon
sleep 5
service-control --start vmware-vmon
sleep 10

# 确认 vmon 现在能识别 vpxd-svcs
service-control --status vmware-vpxd-svcs
# Stopped: vmware-vpxd-svcs  (之前是 "not found",现在是 "Stopped" — 成功!)

grep "vpxd-svcs" /var/log/vmware/vmon/vmon.log | tail -5
# Adding service vpxd-svcs.  ← vmon 加载了新配置!

4.4 Patch pre-start 脚本绕过证书验证

tagging_grpc_registration.py 在调用 reregister_service() 时,Lookup Service 验证 spec 中的证书发现过期,返回 "Invalid certificate"。这个 gRPC 端点注册不是 vCenter 运行的核心功能,可以临时绕过:

# 备份原始脚本
cp /usr/lib/vmware-vpxd-svcs/scripts/linux/pre-start/tagging_grpc_registration.py \
   /usr/lib/vmware-vpxd-svcs/scripts/linux/pre-start/tagging_grpc_registration.py.bak

# Patch:将 raise Exception 改为 warning,让脚本在 reregister 失败时继续执行
python3 << 'PYEOF'
path = "/usr/lib/vmware-vpxd-svcs/scripts/linux/pre-start/tagging_grpc_registration.py"
with open(path, 'r') as f:
    content = f.read()

old = '''raise Exception("Tagging grpc reregistration failed while"
                        " executing vpxd-svcs prestart commands")'''
new = '''self.logger.warning("Continuing despite reregistration failure"
                        " - will retry on next restart")'''

content = content.replace(old, new)
with open(path, 'w') as f:
    f.write(content)
print("Patched successfully!")
PYEOF

**注意**: 这是临时方案。后续需要通过 vSphere Client 的证书管理功能正确更新 Lookup Service 中的服务注册证书,然后恢复原始脚本。

4.5 按顺序启动所有服务

# 1. 确保核心基础服务在运行
service-control --start lookupsvc
sleep 10
service-control --start vmware-vapi-endpoint
sleep 10

# 2. 启动 vpxd-svcs(关键!)
service-control --start vmware-vpxd-svcs
sleep 20
service-control --status vmware-vpxd-svcs  # Running!
netstat -tlnp | grep 10080  # LISTENING!

# 3. 启动 vpxd
service-control --start vmware-vpxd
sleep 60
service-control --status vmware-vpxd  # Running!

# 4. 启动所有剩余服务
service-control --start --all
sleep 30

# 5. 最终状态
service-control --status --all
netstat -tlnp | grep -E "10080|443|7444"

4.6 验证恢复

# vpxd-svcs 健康检查
curl -sk http://localhost:10080/invsvc/invsvc-health
# <status>GREEN</status> ✅

# vpxd 日志确认正常
tail -30 /var/log/vmware/vpxd/vpxd.log
# 正在处理 loginByToken、retrieveContent 等正常请求 ✅

# 所有服务状态
service-control --status --all
# 35+ 个服务 Running ✅

五、关键经验教训

5.1 STS 签名证书 ≠ VECS 证书

vCenter 有两套证书系统:

  • **VECS 存储**:Machine SSL、Solution User 证书,可用 `certificate-manager` 更新
  • **vmdir LDAP**:STS 签名证书,存在 `TenantCredential-1` 对象中,`certificate-manager` **不会更新**

certificate-manager 的 8 个选项覆盖了 VECS 证书,但不包含 STS 签名证书。这是 vCenter 7.0 的已知缺陷。

5.2 MACHINE_SSL_CERT 为空导致 STS 崩溃

STS 的 Tomcat 使用 VECSAwareSSLImplementation,从 MACHINE_SSL_CERT VECS 存储读取 SSL 证书。如果存储为空,STS connector 初始化直接失败。

检查方法:

/usr/lib/vmware-vmafd/bin/vecs-cli entry list --store MACHINE_SSL_CERT
# 如果 "Number of entries in store : 0" 就是空的

5.3 vmon 配置文件丢失的恢复

vmon 的服务配置文件在 /etc/vmware/vmware-vmon/svcCfgfiles/ 目录。如果丢失,可以从安装目录恢复:

服务模板位置
vpxd-svcs`/usr/lib/vmware-vpxd-svcs/scripts/conf/vpxd-svcs-lin.json`
其他对应的 `/usr/lib/vmware-/scripts/conf/` 目录

恢复后必须重启 vmon daemon:

service-control --stop vmware-vmon
service-control --start vmware-vmon

5.4 vmdir LDAP 认证方式

vmdir 不支持 SASL DIGEST-MD5 和 StartTLS,但支持:

  • **LDAPS (636) + simple bind**: `ldapsearch -x -H ldaps://localhost:636 -D "cn=Administrator,cn=Users,dc=vsphere,dc=local" -W`
  • **Python ldap3 库**:比命令行 ldapsearch 更可靠

5.5 服务启动顺序很重要

vmdir → vmafd → vmcad → STS → lookupsvc → vapi-endpoint → vpxd-svcs → vpxd → 其他

vpxd-svcs 依赖 STS(签发 SAML token)、lookupsvc(服务发现)、vpostgres(数据库)。必须按顺序启动。


六、预防措施

6.1 定期检查证书过期

# 检查所有 VECS 证书
for i in $(/usr/lib/vmware-vmafd/bin/vecs-cli store list); do
  echo "=== $i ==="
  /usr/lib/vmware-vmafd/bin/vecs-cli entry list --store $i --text | grep "Not After"
done

# 检查 VMCA 根证书
openssl x509 -in /var/lib/vmware/vmca/root.cer -noout -dates

# 检查 STS 签名证书(在 vmdir 中)
# 用 Python ldap3 查询 TenantCredential-1 对象

6.2 设置证书过期告警

建议创建 cron job 定期检查证书有效期,提前 30 天告警:

#!/bin/bash
# /etc/cron.weekly/check-vcenter-certs.sh
WARN_DAYS=30
NOW=$(date +%s)

for store in MACHINE_SSL_CERT machine vpxd vpxd-extension vsphere-webclient hvc wcp; do
  /usr/lib/vmware-vmafd/bin/vecs-cli entry list --store $store --text 2>/dev/null | \
  grep "Not After" | while read line; do
    date_str=$(echo $line | awk '{print $3, $4, $5, $6, $7}')
    exp_date=$(date -d "$date_str" +%s 2>/dev/null)
    days_left=$(( (exp_date - NOW) / 86400 ))
    if [ "$days_left" -lt "$WARN_DAYS" ]; then
      echo "WARNING: $store certificate expires in $days_left days ($date_str)"
    fi
  done
done

6.3 vCenter 7.0 STS 证书续期

VMware KB 有专门的 STS 证书续期文档。关键点是: 1. STS 签名证书存在 vmdir LDAP 中,不在 VECS 2. certificate-manager 不更新 STS 证书 3. 需要用 certool 生成新证书,通过 LDAPS 更新 vmdir


七、故障处理决策树

vpxd-svcs 启动失败
├── 检查磁盘空间 → df -h
├── 检查 vpxd 日志 → tail /var/log/vmware/vpxd/vpxd.log
│   └── Connection refused to localhost:10080?
│       └── vpxd-svcs 没运行 → 检查 pre-start 日志
│           └── tail /var/log/vmware/vpxd-svcs/pre-start-vpxd-svcs.log
│               ├── "Signing certificate is not valid"?
│               │   └── STS 签名证书过期 → 检查/更新 vmdir 中的 TenantCredential-1
│               ├── "Invalid certificate"?
│               │   └── Lookup Service 服务注册中证书过期 → patch pre-start 脚本
│               └── "Service not found"?
│                   └── vpxd-svcs.json 丢失 → 从安装目录恢复
├── 检查 STS 状态 → service-control --status vmware-stsd
│   └── STS 崩溃?
│       └── 检查 sts-runtime.log.stderr
│           └── "Failed to initialize connector"?
│               └── MACHINE_SSL_CERT 为空 → 生成并导入新证书
├── 检查 VMCA 根证书 → openssl x509 -in /var/lib/vmware/vmca/root.cer -dates
└── 检查 vmdir → service-control --status vmdird (或 vmafdd)

八、涉及的日志文件清单

日志文件用途
`/var/log/vmware/vpxd/vpxd.log`vpxd 主服务日志,看 Authz 连接错误
`/var/log/vmware/vpxd-svcs/pre-start-vpxd-svcs.log`vpxd-svcs pre-start 脚本日志,**最关键**
`/var/log/vmware/vmon/vmon.log`vmon 服务管理器日志,看服务启动/崩溃记录
`/var/log/vmware/sso/sts-runtime.log.stderr`STS Java 进程 stderr,看 Tomcat 崩溃原因
`/var/log/vmware/sso/vmware-identity-sts.log`STS 详细运行日志
`/var/log/vmware/sso/sts-prestart.log`STS pre-start 日志

九、涉及的配置文件清单

文件用途
`/etc/vmware/vmware-vmon/svcCfgfiles/vpxd-svcs.json`vpxd-svcs 的 vmon 服务定义
`/usr/lib/vmware-vpxd-svcs/scripts/conf/vpxd-svcs-lin.json`vpxd-svcs 配置模板(恢复用)
`/usr/lib/vmware-vpxd-svcs/scripts/linux/pre-start/tagging_grpc_registration.py`pre-start 脚本(gRPC 端点注册)
`/usr/lib/vmware-vpxd-svcs/lib/server/config/dataservice.properties`vpxd-svcs 配置(端口等)
`/var/lib/vmware/vmca/root.cer`VMCA 根证书
`/etc/vmware/install-defaults/vpxd-svcs.int.http`vpxd-svcs HTTP 端口(10080)

十、关键命令速查

# === 证书操作 ===
# 列出所有 VECS 存储
/usr/lib/vmware-vmafd/bin/vecs-cli store list
# 查看某个存储的证书
/usr/lib/vmware-vmafd/bin/vecs-cli entry list --store MACHINE_SSL_CERT --text
# 导入证书到 VECS
/usr/lib/vmware-vmafd/bin/vecs-cli entry create --store MACHINE_SSL_CERT --alias __MACHINE_CERT --cert /tmp/cert.cer --key /tmp/cert.key

# 生成新证书(certool 配置格式: [Key = Value])
/usr/lib/vmware-vmca/bin/certool --genkey --privkey=/tmp/key --pubkey=/tmp/pub --server=localhost
/usr/lib/vmware-vmca/bin/certool --gencert --privkey=/tmp/key --cert=/tmp/cert --config=/tmp/cfg --Name=xxx --server=localhost

# === vmdir LDAP 操作 ===
# LDAPS 查询
ldapsearch -x -H ldaps://localhost:636 -D "cn=Administrator,cn=Users,dc=vsphere,dc=local" -W -b "dc=vsphere,dc=local" "(userCertificate=*)" dn

# === 服务管理 ===
service-control --status --all           # 查看所有服务状态
service-control --start vmware-vpxd-svcs  # 启动单个服务
service-control --start --all             # 启动所有服务
service-control --stop vmware-vmon        # 重启 vmon(重新加载配置)

# === 日志查看 ===
tail -50 /var/log/vmware/vpxd-svcs/pre-start-vpxd-svcs.log  # 最关键的日志
tail -50 /var/log/vmware/vmon/vmon.log                      # vmon 日志
cat /var/log/vmware/sso/sts-runtime.log.stderr              # STS 崩溃日志

结语

这次故障的核心教训是:vCenter 证书管理远比想象中复杂certificate-manager 工具只管 VECS 证书,STS 签名证书需要单独处理。建议:

  1. **定期检查所有证书**,包括 VECS 和 vmdir 中的 STS 证书
  2. **了解证书层次结构**:VMCA Root → Machine SSL / Solution Users / STS Signing
  3. **保留配置文件备份**:`/etc/vmware/vmware-vmon/svcCfgfiles/` 目录
  4. **理解服务依赖链**:STS → SAML token → vpxd-svcs pre-start → vpxd-svcs → vpxd

希望这篇文章能帮助遇到同样问题的同行。如果有疑问,欢迎留言交流。


最后更新:2026-06-25

发表回复

后才能评论