节点是私有的,VPN 能到达它们,但 kubectl 仍然无法与集群通信。这两件事互不相关。kubectl 使用的地址来自获取凭据时写入 kubeconfig 的服务器 URL,你添加的任何路由都不会改变它。与此同时,kubectl 想访问的对象从一开始就不是节点。

五项检查,从唯一真正重要的值开始。

检查 1:读取 kubeconfig 中的服务器 URL

在不泄露凭据的前提下打印端点:kubectl config view --minify -o jsonpath="{.clusters[0].cluster.server}"。这一行字符串会告诉你客户端指向的是 IP 地址、DNS 名称,还是你并不想要的外部地址。这项排查的其余部分都由它推导而来。

如果 URL 并不是你以为配置好的端点,那么剩下的诊断只会分散注意力。

检查 2:把 URL 与端点类型对应起来

当前的 GKE 同时支持基于 IP 和基于 DNS 的控制平面访问,你获取的凭据会从中选择其一。gcloud container clusters get-credentials NAME --location REGION --internal-ip 写入的是内部 IP 端点,而 --dns-endpoint 选择基于 DNS 的访问。两个标志都不提供网络路径,这让期望“拉取凭据就能修好连通性”的人感到意外。有意识地重新获取一次,然后再读一遍 URL。

不重读 URL 就切换标志,正是笔记本最后同时持有两个集群的凭据和一个令人困惑的错误的原因。

已授权网络条目决定谁能访问外部端点,并不适用于内部端点。为了让私有路径通过而放宽它,改变的是你的暴露面,而不是诊断结论。

检查 3:证明到该端点的路径

如果 URL 是内部 IP,请从客户端实际所在的网络、允许的源地址范围以及集群的区域或全局访问设置来验证路由。控制平面范围与节点子网并不是同一个目标,因此通往节点的路由不能证明端点可达。对于基于 DNS 的访问,路径是 Google API 连通性及其文档化的 Private Google Access 安排,而不是通往工作节点子网的路由。在责怪 kubectl 之前,先用普通 TCP 连接测试端点。

超时是路径问题。403 是策略问题。两者没有共同的修复办法。

检查 4:把日志和 exec 与 API 调用分开

如果普通 API 请求成功,而 kubectl logs 或 kubectl exec 失败,你已经越过了端点选择这一步。这些操作需要相应的 Kubernetes 权限,并依赖控制平面到节点的通信,失败可能是 Forbidden 响应而不是超时。通过 SSH 登录节点测试的是完全另一个服务,并不能证明这些。

在重新打开 VPN 工单之前,先读错误类别,因为这两类问题住在不同的地方。

检查 5:为下一个人保留三条观察

记录所选 API URL、一个已授权 API 请求是否成功,以及具体是哪个后续操作失败,并附上错误文本。这三行把端点选择与节点访问分开,也能避免一条本来完好的 VPN 路由替它从未承载过的请求背锅。

下一位工程师会问隧道是不是坏了。你的笔记应该已经回答了这个问题。

相关文章