排查集群连接问题

本页介绍如何排查在将集群注册到舰队或使用 Google Cloud 控制台、Google Cloud CLI 或 kubectl 通过 Connect Gateway 连接到 Google Cloud 外部的集群时可能遇到的常见错误。

本地集群和其他公有云上的集群依赖于 Connect Agent 在集群和 Google Cloud 项目之间建立和维护连接,以及处理 Kubernetes 请求。如果您看到“无法访问代理”或“无法连接到集群的控制平面”等错误,这可能表明 Connect Agent 存在问题。

收集 Connect Agent 日志

当您在 Google Cloud 外部注册集群时,它会使用 Connect Agent 来处理您的集群和舰队宿主项目之间的通信。Connect Agent 是一个 Deployment (gke-connect-agent),通常安装在集群的 gke-connect 命名空间中。从此 Connect Agent 收集日志有助于排查注册和连接问题。

您可以通过运行以下命令来检索 Agent 的日志(必要情况下可调整行数):

kubectl logs -n gke-connect -l app=gke-connect-agent --tail=-1

如需获取在项目集群中运行的每个 Connect Agent 的相关信息,请运行以下命令:

kubectl describe deployment --all-namespaces -l app=gke-connect-agent

成功的连接应具有类似于以下示例的条目:

2019/02/16 17:28:43.312056 dialer.go:244: dialer: dial: connected to gkeconnect.googleapis.com:443
2019/02/16 17:28:43.312279 tunnel.go:234: serve: opening egress stream...
2019/02/16 17:28:43.312439 tunnel.go:248: serve: registering endpoint="442223602236", shard="88d2bca5-f40a-11e8-983e-42010a8000b2" {"Params":{"GkeConnect":{"endpoint_class":1,"metadata":{"Metadata":{"Default":{"manifest_version":"234227867"}}}}}} ...
2019/02/16 17:28:43.312656 tunnel.go:259: serve: serving requests...

收集 GKE Identity Service 日志

如果您在适用于 Connect 网关的 Google 群组第三方支持方面遇到问题,检查 GKE Identity Service 日志可能会很有帮助。这种生成日志的方法仅适用于 VMware 或 Bare Metal 上的 Google Distributed Cloud 部署中的集群。

  1. 可提高 GKE Identity Service 日志的详细程度,具体方法是使用以下命令修改 clientconfig 自定义资源:

    kubectl edit deployment -n anthos-identity-service
    

    并在 containers 字段下添加 vmodule 标志,如下所示:

    spec:
      containers:
      ...
      - command:
        - --vmodule=cloud/identity/hybrid/charon/*=9
    
  2. 可使用以下命令删除 GKE Identity Service Pod,以进行重启:

    kubectl delete pods -l k8s-app=ais -n anthos-identity-service
    

    Pod 应在几秒钟内再次启动。

  3. Pod 重启后,运行返回非预期响应的原始命令,以使用更多详细信息填充 GKE Identity Service Pod 日志。

  4. 可使用以下命令将这些日志的输出保存到文件中:

    kubectl logs -l k8s-app=ais -n anthos-identity-service --tail=-1 > gke_id_service_logs.txt
    

如果 GKE Identity Service Pod 日志中缺少预期的群组,请验证集群的设置是否正确。如果存在其他与 GKE Identity Service 相关的问题,请参阅排查用户访问权限问题排查舰队级设置问题

tls: oversized record 个错误

症状

您可能会遇到类似这样的错误:

... dialer: dial: connection to gkeconnect.googleapis.com:443 failed after
388.080605ms: serve: egress call failed: rpc error: code = Unauthenticated
desc = transport: oauth2: cannot fetch token: Post
https://oauth2.googleapis.com/token: proxyconnect tcp: tls: oversized record
received with length 20527
可能的原因

这可能意味着 Connect Agent 尝试通过 HTTPS 连接到仅限 HTTP 的代理。Connect Agent 仅支持基于 CONNECT-的 HTTP 代理。

解决方法

您需要将代理环境变量重新配置为以下内容:

http_proxy=http://[PROXY_URL]:[PROXY_PORT]
https_proxy=http://[PROXY_URL]:[PROXY_PORT]

oauth2: cannot fetch token 错误

症状

您可能会遇到类似这样的错误:

...  dialer: dial: connection to gkeconnect.googleapis.com:443 failed
after 388.080605ms: serve: egress call failed: rpc error: code =
Unauthenticated desc = transport: oauth2: cannot fetch token: Post
https://oauth2.googleapis.com/token: read tcp 192.168.1.40:5570->1.1.1.1:80
read: connection reset by peer
可能的原因

这可能意味着上游 HTTP 代理重置了连接,这很可能是因为您的 HTTP 代理不允许使用此特定网址。在上面的示例中,1.1.1.1:80 是 HTTP 代理地址。

解决方法

检查您的 HTTP 代理许可名单是否包含以下网址/域名:

gkeconnect.googleapis.com
oauth2.googleapis.com/token
www.googleapis.com/oauth2/v1/certs

Connect Agent Pod 崩溃和重启错误

症状

集群在 Google Cloud 控制台中可能遇到间歇性的“无法访问代理”错误,并且/或者 Pod 可能多次重启:

$ kubectl get pods -n gke-connect
NAME                                                READY   STATUS    RESTARTS   AGE
gke-connect-agent-20230706-03-00-6b8f75dd58-dzwmt   1/1     Running   5          99m

如需排查此行为,请描述 Pod 以查看其上一个状态是否因内存不足错误 (OOMKilled) 而终止:

  kubectl describe pods/gke-connect-agent-20230706-03-00-6b8f75dd58-dzwmt -n gke-connect
        <some details skipped..>
        Last State:     Terminated
        Reason:       OOMKilled
可能的原因
默认情况下,Connect Agent Pod 的 RAM 限制为 256MiB。如果集群已安装大量工作负载,则某些请求和响应可能无法按预期处理。
解决方法

更新 Connect Agent 部署并为其指定更高的内存限制,例如:

containers:
  name: gke-connect-agent-20230706-03-00
  resources:
    limits:
      memory: 512Mi

PermissionDenied 个错误

症状

您可能会遇到类似这样的错误:

tunnel.go:250: serve: recv error: rpc error: code = PermissionDenied
desc = The caller does not have permission
dialer.go:210: dialer: dial: connection to gkeconnect.googleapis.com:443
failed after 335.153278ms: serve: receive request failed: rpc error:
code = PermissionDenied desc = The caller does not have permission
dialer.go:150: dialer: connection done: serve: receive request failed:
rpc error: code = PermissionDenied desc = The caller does not have permission
dialer.go:228: dialer: backoff: 1m14.1376766s
可能的原因

这可能意味着您尚未将必需的 Identity and Access Management (IAM) 角色绑定到您创建的 Google Cloud 服务账号以授权 Connect Agent 连接到 Google。Google Cloud 服务账号需要 gkehub.connect IAM 角色。

如果您在删除之后重新创建同名的 Google Cloud 服务账号,也可能会发生这种情况。在这种情况下,您还需要删除然后重新创建 IAM 角色绑定。如需了解详情,请参阅删除并重新创建服务账号

解决方法

gkehub.connect 角色绑定到您的服务账号(请注意,gkehub.admin 角色不具备适当的连接权限,不应被服务账号使用)。

例如,对于名为 my-project 的项目和名为 gkeconnect@my-project.iam.gserviceaccount.com 的 Google Cloud 服务账号,您可以运行以下命令来将该角色绑定到该服务账号:

gcloud projects add-iam-policy-binding my-project --member \
serviceAccount:gkeconnect@my-project.iam.gserviceaccount.com \
--role "roles/gkehub.connect"

您可以通过检查以下命令的输出来查看和验证服务账号权限是否已应用到 Google Cloud 服务账号,您应该会看到 role: roles/gkehub.connect 已绑定到关联的 Google Cloud 服务账号。

gcloud projects get-iam-policy my-project

将 IAM 角色绑定到 Google Cloud 服务账号时出错

症状

您可能会遇到类似这样的错误:

ERROR: (gcloud.projects.add-iam-policy-binding) PERMISSION_DENIED:
Service Management API has not been used in project [PROJECT_ID] before or it
is disabled. Enable it by visiting
https://console.developers.google.com/apis/api/servicemanagement.googleapis.com/overview?project=[PROJECT_ID]
then retry. If you enabled this API recently, wait a few minutes for the
action to propagate to our systems and retry.
可能的原因

您可能没有运行 gcloud projects add-iam-policy-binding 命令所需的 IAM 权限。

解决方法

您需要具有 resourcemanager.projects.setIamPolicy 权限。如果您拥有 Project IAM AdminOwnerEditor 角色,则应该可以运行该命令。如果内部安全政策禁止您运行该命令,请咨询您的管理员。

服务账号密钥无效导致错误

症状

您可能会遇到类似这样的错误:

2020/05/08 01:22:21.435104 environment.go:214: Got ExternalID 3770f509-b89b-48c4-96e0-860bb70b3a58 from namespace kube-system.
2020/05/08 01:22:21.437976 environment.go:485: Using gcp Service Account key
2020/05/08 01:22:21.438140 gkeconnect_agent.go:50: error creating kubernetes connect agent: failed to get tunnel config: unexpected end of JSON input
可能的原因

这些日志表明在安装过程中,为 Connect Agent 提供了无效的服务账号密钥

解决方法

创建一个包含服务账号凭据的新 JSON 文件,然后按照注册集群的步骤重新安装 Connect Agent。

服务账号密钥过期导致错误

症状

您可能会遇到类似这样的错误:

2020/05/08 01:22:21.435104 dialer.go:277: dialer: dial: connection to gkeconnect.googleapis.com:443 failed after 37.901608ms:
serve: egress call failed: rpc error: code = Unauthenticated desc = transport: oauth2: cannot fetch token: 400 Bad Request
Response: {"error":"invalid_grant","error_description":"Invalid JWT Signature."}
可能的原因

这些日志表明 Connect Agent 正在使用无效的服务账号密钥对 Connect 进行拨号。服务账号密钥文件可能包含错误,或者密钥可能已过期。

如需检查密钥是否已过期,请使用 Google Cloud 控制台列出您的服务账号密钥及其失效日期。

解决方法

创建一个包含服务账号凭据的新 JSON 文件,然后按照注册集群的步骤重新安装 Connect Agent。

系统时钟偏差所导致的错误

症状

您可能会遇到类似这样的错误:

acceptCall: failed to parse token in req [rpc_id=1]: Token used before issued [rpc_id=1]
可能的原因

日志消息通常表示集群上存在时钟偏差。集群发出的令牌具有不同步的时间戳,因此令牌被拒绝。

解决方法

如需查看时钟是否未正确同步,您可以在集群上运行 date 命令,并将其与标准时间进行比较。通常,几秒偏差就会造成此问题。如需解决此问题,请重新同步集群的时钟。

无法在 Google Cloud 控制台中查看工作负载

表现

在 Connect Agent 日志中,您可能会发现以下错误:

"https://10.0.10.6:443/api/v1/nodes" YYYY-MM-DDTHH mm:ss.sssZ http.go:86: GET
"https://10.0.10.6:443/api/v1/pods" YYYY-MM-DDTHH mm:ss.sssZ http.go:139:
Response status: "403 Forbidden" YYYY-MM-DDTHH mm:ss.sssZ http.go:139:
Response status: "403 Forbidden"`
可能的原因

这些日志表明 Google Cloud 正在尝试使用您在注册期间提供的凭据来访问集群。403 错误表明凭据没有访问集群所需的权限。

解决方法

检查凭据的令牌及其绑定的账号,并确保它在该集群上具有适当的权限。

已超出上下文截止期限

症状

您可能会遇到类似这样的错误:

2019/03/06 21:08:43.306625 dialer.go:235: dialer: dial: connecting to gkeconnect.googleapis.com:443...
2019/03/06 21:09:13.306893 dialer.go:240: dialer: dial: unable to connect to gkeconnect.googleapis.com:443: context deadline exceeded
2019/03/06 21:09:13.306943 dialer.go:183: dialer: connection done: context deadline exceeded
可能的原因

此错误表明 Connect Agent 无法与 gkeconnect.googleapis.com 通信的低级 TCP 网络问题。

解决方法

验证此集群中的 Pod 工作负载是否可以解析,以及连到端口 443 和 443 的出站连接。

Agent 连接间歇性故障

表现

在 Connect Agent 日志中,您可能会发现以下错误:

2020/10/06 18:02:34.409749 dialer.go:277: dialer: dial: connection to gkeconnect.googleapis.com:443 failed after 8m0.790286282s: serve: receive request failed: rpc error: code = Unavailable desc = transport is closing
2020/10/06 18:02:34.416618 dialer.go:207: dialer: connection done: serve: receive request failed: rpc error: code = Unavailable desc = transport is closing
2020/10/06 18:02:34.416722 dialer.go:295: dialer: backoff: 978.11948ms
2020/10/06 18:02:34.410097 tunnel.go:651: sendResponse: EOF [rpc_id=52]
2020/10/06 18:02:34.420077 tunnel.go:651: sendResponse: EOF [rpc_id=52]
2020/10/06 18:02:34.420204 tunnel.go:670: sendHalfClose: EOF [rpc_id=52]
2020/10/06 18:02:34.401412 tunnel.go:670: sendHalfClose: EOF [rpc_id=53]
可能的原因

如果 Connect Agent 没有足够资源(例如,在 t3.medium 等较小的 AWS EC2 实例上),与 Connect 的连接就会关闭。

解决方法

如果您使用 AWS 和 T3 实例类型,请启用 T3 无限制,或者使用具有更多资源的实例类型来处理节点池

Fleet 无法访问项目

表现

在执行某些 Fleet 操作(通常是集群注册)期间,您可能会观察到类似于以下内容的错误:

ERROR: (gcloud.container.hub.memberships.register) failed to initialize Feature
"authorizer", the fleet service account (service-PROJECT_NUMBER@gcp-sa-gkehub.iam.gserviceaccount.com) may not have access to your project
可能的原因

Fleet 的默认服务账号 gcp-sa-gkehub 可能会意外地从项目中解除绑定。Fleet Service Agent 是一种 IAM 角色,它授予服务账号管理集群资源的权限。如果从服务账号中移除此角色绑定,则默认服务账号将从项目中解除绑定,这可能会阻止您注册集群以及执行其他集群操作。

您可以使用 gcloud CLI 或 Google Cloud 控制台检查服务账号是否已从项目中移除。如果命令或信息中心未针对服务账号显示 gcp-sa-gkehub,则该服务账号已解除绑定。

gcloud

运行以下命令:

gcloud projects get-iam-policy PROJECT_NAME

其中,PROJECT_NAME 是您尝试在其中注册集群的项目的名称。

控制台

访问 Google Cloud 控制台中的 IAM 和管理页面。

解决方法

如果移除了 Fleet Service Agent 角色绑定,请运行以下命令以恢复角色绑定:

PROJECT_NUMBER=$(gcloud projects describe PROJECT_NAME --format "value(projectNumber)")
gcloud projects add-iam-policy-binding PROJECT_NAME \
  --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-gkehub.iam.gserviceaccount.com" \
  --role roles/gkehub.serviceAgent

要确认已授予角色绑定:

gcloud projects get-iam-policy PROJECT_NAME

如果您看到服务账号名称和 gkehub.serviceAgent 角色,则已授予角色绑定。例如:

- members:
  - serviceAccount:service-1234567890@gcp-sa-gkehub.iam.gserviceaccount.com
  role: roles/gkehub.serviceAgent

通过 Fleet 以外的项目注册 GKE 集群时出错

表现

通过舰队项目以外的项目注册 GKE 集群时,您可能会在 gcloud CLI 中看到类似于以下内容的错误:

...
message: 'DeployPatch failed'>
detail: 'DeployPatch failed'
...

可通过应用以下过滤条件在日志记录中进行验证:

resource.type="gke_cluster"
resource.labels.cluster_name="my-cluster"
protoPayload.methodName="google.container.v1beta1.ClusterManager.UpdateCluster"
protoPayload.status.code="13"
protoPayload.status.message="Internal error."
severity=ERROR

可能的原因

Fleet 默认服务账号在 GKE 集群项目中没有所需的权限。

解决方法

在注册集群之前,向 Fleet 默认服务账号授予所需的权限

在凭据轮替期间注册/取消注册 GKE 集群或更新已注册 GKE 集群的舰队成员资格详细信息时出错

表现

轮替集群凭据 (https://cloud.google.com/kubernetes-engine/docs/how-to/credential-rotation) 时,如果注册/取消注册 GKE 集群或更新已注册 GKE 的成员资格,您可能会发现错误簇。

ERROR: (gcloud.container.hub.memberships.unregister) "code": 13,
"message": "an internal error has occurred"
可能的原因

集群凭据处于中间状态,舰队服务无法访问它们。

解决方法

在注册/取消注册集群或更新已注册 GKE 集群的成员资格之前完成轮替

停用 Fleet API 时出错

表现

尝试停用 Fleet API (gkehub.googleapis.com) 时,您可能会看到类似如下的错误:

Not ready to deactivate the service on this project; ensure there are no more resources managed by this service.
可能的原因

此项目中仍然有集群注册到 Google Cloud(成员)或 fleet 级层功能。必须先取消注册或者停用所有成员资格或功能,然后才能停用 API。

  • 如需查看当前已注册的集群,请按照查看舰队成员中的说明进行操作

  • 如需查看项目的所有活跃的舰队级层功能,请执行以下操作:

gcloud 和 cURL

$ curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    https://gkehub.googleapis.com/v1alpha1/projects/PROJECT_NAME/locations/global/features

其中 PROJECT_NAME 是您要尝试在其中停用 Fleet API 的项目名称。

控制台

如果您在项目中启用了 GKE Enterprise,请访问 Google Cloud 控制台中的功能概览页面。列为已启用的功能属于活跃的舰队级功能。

解决方法

首先,取消注册任何集群(仍在您的项目舰队中注册的集群)。必须先取消注册所有集群,然后才能停用部分功能。

完成此操作后,将会停用所有舰队级功能。目前,只能通过 Fleet REST API 执行此操作。

  1. 停用您为项目启用的舰队级层功能

    $ gcloud alpha container hub FEATURE_COMMAND disable
    
  2. 停用 Feature Authorizer 和计量功能(该功能默认处于启用状态)。

    $ curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -X "DELETE" \
        https://gkehub.googleapis.com/v1alpha1/projects/PROJECT_NAME/locations/global/features/FEATURE
    

    其中 FEATURE 是要停用的功能的名称(例如 authorizermetering)。

注册集群时缺少集群权限

具体情况:

尝试使用用户账号或 Google Cloud 服务账号注册集群时,您可能会收到类似如下所示的错误:

ERROR: (gcloud.container.hub.memberships.register) ResponseError: code=403, message=Required "container.clusters.get" permission(s) for "projects/my-project/zones/zone-a/clusters/my-cluster"
可能的原因:

尝试注册集群的账号在集群中没有基于 cluster-admin 角色的必要访问权限控制 (RBAC) 角色。

解决方案:

在注册集群之前,向账号授予 cluster-admin RBAC 角色

注册集群时发生错误 Failed to check if the user is a cluster-admin: Unable to connect to the server

具体情况:

尝试注册集群时,您可能会收到类似于以下内容的错误:

ERROR: (gcloud.container.hub.memberships.register) Failed to check if the user is a cluster-admin: Unable to connect to the server: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

ERROR: (gcloud.container.hub.memberships.register) Failed to check if the user is a cluster-admin: Unable to connect to the server: dial tcp MASTER_ENDPOINT_IP:443: i/o timeout
可能的原因:

您正在其上运行注册 gcloud 命令的机器无法连接到集群的外部端点。此问题通常在以下情况下发生:您的集群是具有已停用的外部访问/IP 地址的专用集群,但您机器的外部 IP 地址未列入许可名单。请注意,在 gcloud 407.0.0 之后注册 GKE 集群没有此要求。

解决方案:

确保要运行 gcloud 注册命令的机器可以访问集群的 API 服务器。如果您的集群未启用外部访问权限,请向 Google Cloud 支持团队提交支持请求

获取更多帮助

您可以执行以下步骤,向 Google Cloud 支持团队提交 GKE Enterprise 支持服务工单:

  1. 向 Google Cloud 支持团队提交案例
  2. 按照收集 Connect Agent 日志中的说明以保存 Connect 日志。
  3. 如果使用 Google 群组或第三方支持对本地集群进行问题排查,请按照收集 GKE Identity Service 日志中的说明保存 GKE Identity Service 日志。如有必要,请务必清理已保存文件中的 Pod 日志。
  4. 将相关日志关联到您的案例。