本文永久链接: https://www.xtplayer.cn/rancher/v3-connect-agent-unconditional-503-empty-body-blocks-new-node-registration/

描述

GET /v3/connect/agent 会无条件返回 503 Service Unavailable,且响应体为空,无论身份验证、请求头、CA 验证或 HTTP 协议版本如何。这导致所有通过 system-agent-install.sh 进行的新节点注册(无论是 nodeCommand 还是 insecureNodeCommand 变体)全部被阻塞,即便 Rancher 服务器、其管理控制器以及受影响下游集群的现有 Agent 隧道在其他方面都运行正常。

Rancher server 配置

  • Rancher 版本:v2.14.3(CATTLE_SERVER_VERSION=v2.14.3)

下游集群

  • 自定义/RKE2 集群(沙箱环境),通过 Rancher 的自定义节点注册流程创建
  • Cluster.provisioning.cattle.io 状态:ready: trueConnected: True
  • 现有的 cattle-cluster-agent 隧道健康——日志显示 Handling backend connection request [c-<cluster-id>][stv-cluster-c-<cluster-id>] 均正常连接,Steve 认证启动完成
  • 已重启下游集群上的 cattle-cluster-agent Deployment 以强制完全重建隧道——503 问题无任何变化。

复现步骤

  1. 通过 kubectl delete node 从现有的自定义 RKE2 集群中移除一个工作节点。
  2. 清理 fleet-default 中对应的 MachineCustomMachineRKEBootstrap 及相关 Secret(在带外删除节点后,这些资源都卡在了 finalizer 上——分别是 wrangler.cattle.io/unmanaged-machinemachine.cluster.x-k8s.io——已通过 kubectl patch --type json 手动移除)。
  3. 尝试使用集群管理 → sandbox → 注册(Registration)标签页中的注册命令注册一个替换节点。
  4. system-agent-install.sh 在 “downloading Rancher connection information” 步骤失败,并重复出现 503。

结果

[INFO]  Successfully tested Rancher connection
[INFO] Downloading rancher-system-agent binary from https://rancher.example.net/assets/rancher-system-agent-amd64
[INFO] Successfully downloaded the rancher-system-agent binary.
[INFO] Generating Cattle ID
[ERROR] 503 received while downloading Rancher connection information. Sleeping for 5 seconds and trying again

直接从 Rancher 主机进行复现,完全绕过安装脚本:

$ curl -kv https://localhost/v3/connect/agent
...
< HTTP/2 503
< cache-control: no-cache, no-store, must-revalidate
< x-api-cattle-auth: false
< x-content-type-options: nosniff
< content-length: 0

在所有测试过的变体中,该响应完全一致:

  • 匿名 GET 请求
  • Authorization: Bearer <有效、新生成的 ClusterRegistrationToken>
  • 与安装脚本中 retrieve_connection_info() 匹配的完整请求头集合(X-Cattle-Id、X-Cattle-Role-Worker、X-Cattle-Node-Name、X-Cattle-Address、X-Cattle-Internal-Address、X-Cattle-Labels、X-Cattle-Taints 等)
  • WebSocket 升级请求头(Connection: Upgrade、Upgrade: websocket、Sec-WebSocket-Key)
  • 强制 --http1.1(对比默认的 h2 ALPN 协商)
  • --insecure(完全跳过 CA 验证,排除 CA/校验和不匹配的可能)
  • 从 Rancher 主机本机的 localhost 发起(排除任何网络/代理路径问题)

每次响应中都存在且保持不变的 x-api-cattle-auth: false 表明,请求在到达任何认证评估之前就被拒绝了。

预期结果

对于携带有效 ClusterRegistrationToken bearer token 和正确 X-Cattle-* 请求头的请求,/v3/connect/agent 应返回有效的 connection-info 载荷,从而允许新节点注册继续进行。

已执行的故障排查

  • 确认 Rancher 容器资源使用(CPU/内存/磁盘)均在限制范围内,无 OOM 历史记录
  • 确认没有 ext.cattle.io GVK 错误阻塞核心协调(仅在启动时有短暂的陈旧 GroupVersion 发现警告,可自行解决)
  • 确认 ClusterRegistrationToken 对象存在于集群命名空间下的 management.cattle.io/v3 中(crt-*default-tokensystem),且 status.token/status.command 有效且已填充——通过手动 kubectl apply 重新生成了新 token,无变化
  • 发现并修复了一个陈旧的 Cluster.provisioning.cattle.io 状态:Updated/Provisioned 条件卡在 Unknown 状态超过一个月,引用了一个在节点替换过程中被删除的 Machine 对象(通过 kubectl delete node 带外删除,而非通过 Rancher 的 UI/API,导致 wrangler.cattle.io/unmanaged-machinemachine.cluster.x-k8s.io finalizer 卡住)。直接对 status 子资源修补这些条件以强制重新计算——集群现在正确显示 ready: true,没有陈旧引用,但 503 问题不变。
  • 完全重启 Rancher 容器(docker stop && docker run,确认 --privileged,确认干净启动,所有 management.cattle.io/v3 控制器均已启动,leader election 成功,RDPClient: remotedialer session connected!)——无变化。
  • 启用 CATTLE_LOGLEVEL=debug 并复现请求——在任何日志级别下都没有与该请求相关的日志输出,包括请求相关字符串(connect、tunnel、authoriz、register、import、not ready、readiness、tunnel server not active)。
  • 重启下游集群上的 cattle-cluster-agent,以强制在传统通道和 Steve 聚合通道上完全重建隧道——无变化。

补充背景

这似乎与之前报告的 /v3/connect 503 问题(例如 #19025,“tunnel server not active”)不同,因为此处的响应体为空,而不是携带该特定错误字符串;也与 #52480(API 聚合未就绪)不同,因为 Rancher 的其他所有 API/UI 功能均不受影响——只有这个特定路由受到影响。

问题分析

看起来这是由于capi 不可用导致的,我们在进行任何身份验证检查之前就返回了 503 错误,并且没有返回任何响应体。我建议尝试以下命令手动检查所需的capi 凭据是否已准备就绪

kubectl get crd -o json |
jq '
. as $root
| [
"clusters.cluster.x-k8s.io",
"machines.cluster.x-k8s.io",
"machinesets.cluster.x-k8s.io",
"machinedeployments.cluster.x-k8s.io",
"machinehealthchecks.cluster.x-k8s.io"
]
| map(
. as $name
| {
name: $name,
established: any(
$root.items[]?;
.metadata.name == $name
and any(
.status.conditions[]?;
.type == "Established" and .status == "True"
)
)
}
)
'

在 local 集群中执行 kubectl get pods -A | grep -E 'cattle-turtles-system|cattle-capi-system',看是否有 capi-controller-manager-xxx 和 rancher-turtles-controller-manager-xxx pod 在 运行。

root@hxl-local-02:~# kubectl get pods -A | grep -E 'cattle-turtles-system|cattle-capi-system'
cattle-capi-system capi-controller-manager-7d6b8bd949-9vqzv 1/1 Running 0 7d12h
cattle-turtles-system rancher-turtles-controller-manager-5bdcb4f874-7j8pc 1/1 Running 0 7d12h
root@hxl-local-02:~#

也可以使用以下命令搜集相应 pod 的日志:

for ns in cattle-capi-system cattle-turtles-system;
do
for pod in $(kubectl -n "$ns" get pods -o jsonpath='{.items[*].metadata.name}'); do
echo "===== Namespace: $ns, Pod: $pod ====="
kubectl -n "$ns" logs "$pod" --all-containers=true > ${ns}_${pod}.log
done
done

相关issue: https://github.com/rancher/rancher/issues/56013