问题排查

收集 Connect Agent 日志

Connect Agent 是一个 gke-connect-agent Deployment,用于将集群连接到 Google。它通常安装在集群的命名空间 gke-connect 中。进行问题排查时,从此 Connect Agent 收集的日志非常有用。

您可以通过运行以下命令来检索 Agent 的日志:

for ns in $(kubectl get ns -o jsonpath={.items..metadata.name} -l hub.gke.io/project); do
  echo "======= Logs $ns ======="
  kubectl logs -n $ns -l app=gke-connect-agent
done

如需获取在项目集群中运行的每个 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...

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

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 提供的 Service Account 密钥无效。

解决方法

创建一个包含服务帐号凭据的新 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 注解服务不接受此密钥。服务帐号密钥文件可能已损坏,或者密钥已过期。

如需确定密钥已过期,您可以在 Google Cloud Console 服务帐号详情页面上找到“密钥失效日期”。但在某些情况下,您的项目/组织可能具有一些特殊原则,默认情况下,服务帐号的生命周期期限可能有限。

解决方法

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

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

症状

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

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

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

解决方法

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

无法在 Cloud Console 中查看工作负载

表现

在 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 的连接就会关闭。

解决方法

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

Fleet 无法访问项目

表现

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

ERROR: (gcloud.container.hub.memberships.register) failed to initialize Default 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 工具或 Cloud Console 检查服务帐号是否已从项目中移除。 如果命令或信息中心未针对服务帐号显示 gcp-sa-gkehub,则该服务帐号已解除绑定。

gcloud

运行以下命令:

gcloud projects get-iam-policy PROJECT_NAME

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

控制台

访问 Cloud Console 中的 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 集群时出错

表现

通过 Fleet 项目以外的项目注册 GKE 集群时,您可能会观察到类似于以下内容的错误:

ERROR: (gcloud.container.hub.memberships.register) hub default service account
does not have access to the GKE cluster project for //container.googleapis.com/v1/projects/my-project/zones/zone-a/clusters/my-cluster
可能的原因

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

解决方法

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

停用 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 的项目名称。

Cloud Console

如果您在项目中启用了 Anthos,请访问 Cloud Console 中的功能概览页面。列为已启用的功能属于活跃的队列级功能。

解决方法

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

完成此操作后,将会停用所有队列级功能。目前,只能通过 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.alpha.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.alpha.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 地址未列入许可名单。

解决方案:

添加外部 IP 地址(指您要在其上运行 gcloud 注册命令的机器的外部 IP 地址)到集群的已获授权的网络。如果您的集群未启用外部访问权限,请向 Google Cloud 支持团队提交案例

获取更多帮助

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

  1. 向 Google Cloud 支持团队提交案例
  2. 按照收集 Connect Agent 日志中的说明以保存 Connect 日志。
  3. 将 Connect Agent 日志关联到您的案例。