本页面介绍了针对使用 Google Kubernetes Engine (GKE) 时遇到的问题的排查步骤。
如果您需要其他帮助,请与 Cloud Customer Care 联系。调试 Kubernetes 资源
对于 Kubernetes 资源,如果您遇到以下问题:
排查 kubectl
命令问题
本部分介绍了针对 kubectl
命令的几种问题类型的排查步骤。
问题:找不到 kubectl
命令
如果您收到一条消息,提示您未找到 kubectl
命令,请重新安装 kubectl
二进制文件并设置 $PATH
环境变量:
通过运行以下命令,安装
kubectl
二进制文件:gcloud components update kubectl
当安装程序弹出提示您修改
$PATH
环境变量时,请选择“是”。修改此变量后,您可以在使用kubectl
命令时无需输入其完整路径。或者,将以下行添加到 shell 存储环境变量的任何位置,例如
~/.bashrc
(在 macOS 中是~/.bash_profile
):export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/
运行以下命令以加载更新后的文件。以下示例使用
.bashrc
。source ~/.bashrc
如果您使用的是 macOS,请使用
~/.bash_profile
而不是.bashrc
。
问题:kubectl
命令返回“连接被拒绝”错误
如果 kubectl
命令返回“连接被拒绝”错误,则需要使用以下命令设置集群上下文:
gcloud container clusters get-credentials CLUSTER_NAME
如果您不确定要为 CLUSTER_NAME
输入什么内容,请使用以下命令列出您的集群:
gcloud container clusters list
错误:kubectl
命令超时
如果您创建了集群并尝试针对该集群运行 kubectl
命令,但 kubectl
命令超时,您会看到如下错误:
Unable to connect to the server: dial tcp IP_ADDRESS: connect: connection timed out
Unable to connect to the server: dial tcp IP_ADDRESS: i/o timeout
。
这些错误表示 kubectl
无法与集群控制平面通信。
如需解决此问题,请验证并设置在其中设置集群的上下文,并确保与集群的连接:
前往
$HOME/.kube/config
或运行命令kubectl config view
以验证配置文件是否包含集群上下文和控制平面的外部 IP 地址。设置集群凭据:
gcloud container clusters get-credentials CLUSTER_NAME \ --location=COMPUTE_LOCATION \ --project=PROJECT_ID
替换以下内容:
CLUSTER_NAME
:您的集群的名称。COMPUTE_LOCATION
:Compute Engine 位置。PROJECT_ID
:在其中创建 GKE 集群的项目的 ID。
如果该集群是专用 GKE 集群,请确保其现有授权网络列表包含您尝试从中连接的机器的传出 IP。您可以在控制台中查找现有授权网络,也可以通过运行以下命令来查找:
gcloud container clusters describe CLUSTER_NAME \ --location=COMPUTE_LOCATION \ --project=PROJECT_ID \ --format "flattened(masterAuthorizedNetworksConfig.cidrBlocks[])"
如果上述命令输出的授权网络列表中未包含机器的传出 IP,请执行以下操作:
- 如果您使用的是控制台,请按照无法连接专用集群的控制平面中的说明操作
- 如果从 Cloud Shell 连接,请按照使用 Cloud Shell 访问专用集群中的说明操作。
错误:kubectl
命令返回“无法协商 API 版本”错误
如果 kubectl
命令返回“无法协商 API 版本”错误,则需要确保 kubectl
具有身份验证凭据:
gcloud auth application-default login
问题:kubectl
logs
、attach
、exec
和 port-forward
命令停止响应
如果 kubectl
logs
、attach
、exec
或 port-forward
命令停止响应,通常表示 API 服务器无法与节点通信。
首先,检查集群是否具有任何节点。如果您已将集群中的节点数缩减至零,则命令将无法运行。如需解决此问题,请调整集群大小,使其至少具有一个节点。
如果集群至少具有一个节点,请检查您是使用 SSH 还是 Konnectivity 代理隧道来实现安全通信。以下各部分介绍了特定于每种方法的问题排查步骤:
排查 SSH 问题
如果您使用的是 SSH,GKE 会在您的 Compute Engine 项目元数据中保存 SSH 公钥文件。使用 Google 提供的映像的所有 Compute Engine 虚拟机都会定期检查其项目的共同元数据及其实例的元数据,以使 SSH 公钥添加到虚拟机的授权用户列表中。GKE 还会为您的 Compute Engine 网络添加防火墙规则,以允许通过 SSH 实现从控制平面的 IP 地址到集群中每个节点的访问。
SSH 的问题可能是由以下原因造成的:
您的网络的防火墙规则不允许通过 SSH 从控制平面访问。
所有 Compute Engine 网络都使用名为
default-allow-ssh
的防火墙规则创建,该规则允许从所有 IP 地址进行 SSH 访问(需要使用有效的私钥)。GKE 还为每个公共集群插入一项 SSH 规则(格式为gke-CLUSTER_NAME-RANDOM_CHARACTERS-ssh
),该规则允许通过 SSH 实现专门从集群的控制平面到集群的节点的访问。若没有这些规则,则控制平面无法打开 SSH 隧道。
如需验证是否是此原因导致的问题,请检查您的配置是否包含这些规则。
如需解决此问题,请确定集群所有节点上的标记,然后重新添加防火墙规则,以允许从控制平面的 IP 地址访问具有该标记的虚拟机。
您的项目的
ssh-keys
的公共元数据条目已满。如果项目名为“ssh-keys”的元数据条目接近大小上限,则 GKE 无法添加自己的 SSH 密钥来打开 SSH 隧道。
如需验证是否存在此问题,请检查 ssh-keys 列表的长度。您可以通过运行以下命令并视情况添加
--project
标志来查看项目的元数据:gcloud compute project-info describe [--project=PROJECT_ID]
如需解决此问题,请删除一些不再需要的 SSH 密钥。
您已在集群中的虚拟机上使用密钥“ssh-keys”设置元数据字段。
相比项目范围的 SSH 密钥,虚拟机上的节点代理会优先使用每个实例的 ssh-keys,因此如果您在集群的节点上专门设置了任何 SSH 密钥,则节点不会采用项目元数据中控制平面的 SSH 密钥。
如需验证是否存在此问题,请运行
gcloud compute instances describe VM_NAME
并在元数据中查找ssh-keys
字段。如需解决此问题,请从实例元数据中删除每个实例的 SSH 密钥。
排查 Konnectivity 代理问题
您可以通过检查以下系统 Deployment 来确定集群是否使用 Konnectivity 代理:
kubectl get deployments konnectivity-agent --namespace kube-system
Konnectivity 代理的问题可能是由以下原因造成的:
您的网络的防火墙规则不允许 Konnectivity 代理访问控制平面。
在创建集群时,Konnectivity 代理 Pod 会在端口
8132
上建立并维护与控制平面的连接。运行其中一个kubectl
命令时,API 服务器会使用此连接与集群进行通信。如果您的网络的防火墙规则包含出站流量拒绝规则,则可能会阻止代理建立连接。
如需验证问题是否由此原因引起,请检查网络的防火墙规则,看看它们是否包含出站流量拒绝规则。
如需解决此问题,请允许出站流量通过端口 8132 进入集群控制平面。(相比之下,API 服务器使用 443)。
您的集群的网络政策会阻止从
kube-system
命名空间到workload
命名空间的入站流量。集群的正确运行并不需要这些功能。如果您希望集群的网络拒绝所有外部访问,请注意这些功能将停止工作。
如需验证问题是否由此原因引起,请通过运行以下命令查找受影响命名空间中的网络政策:
kubectl get networkpolicy --namespace AFFECTED_NAMESPACE
如需解决此问题,请将以下内容添加到网络政策的
spec.ingress
字段中:- from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: konnectivity-agent
排查错误 4xx 问题
以下部分可帮助您排查错误 400、401、403、404 以及相关的身份验证和授权错误。
问题:连接到 GKE 集群时出现身份验证和授权错误
连接到 GKE 集群时,您可能会收到 HTTP 状态代码为 401(未经授权)的身份验证和授权错误。如果您尝试在本地环境的 GKE 集群中运行 kubectl
命令,可能会出现此问题。
此问题可能是由以下某种原因造成的:
gke-gcloud-auth-plugin
身份验证插件未正确安装或配置。- 您无权连接到集群 API 服务器并运行
kubectl
命令。
如需诊断原因,请按照以下部分中的步骤操作:
使用 curl
连接到集群
如需诊断身份验证和授权错误的原因,请使用 curl
连接到集群。使用 curl
可绕过 kubectl
CLI 和 gke-gcloud-auth-plugin
插件。
设置环境变量:
APISERVER=https://$(gcloud container clusters describe CLUSTER_NAME --location=COMPUTE_LOCATION --format "value(endpoint)") TOKEN=$(gcloud auth print-access-token)
验证您的访问令牌是否有效:
curl https://oauth2.googleapis.com/tokeninfo?access_token=$TOKEN
尝试连接到 API 服务器中的核心 API 端点:
gcloud container clusters describe CLUSTER_NAME --location=COMPUTE_LOCATION --format "value(masterAuth.clusterCaCertificate)" | base64 -d > /tmp/ca.crt curl -s -X GET "${APISERVER}/api/v1/namespaces" --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
如果
curl
命令成功,请按照在 kubeconfig 中配置插件部分中的步骤检查插件是否是原因。如果
curl
命令失败,并且输出类似于以下内容,则表示您没有正确的权限来访问集群:{ "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "Unauthorized", "reason": "Unauthorized", "code": 401 }
如需解决此问题,请获取正确的权限来访问集群。
在 kubeconfig 中配置插件的使用
如果您在连接到集群时收到身份验证和授权错误,但能够使用 curl
连接到集群,请确保您无需 gke-gcloud-auth-plugin
插件即可访问集群。
如需解决此问题,请将您的本地环境配置为在向集群进行身份验证时忽略 gke-gcloud-auth-plugin
二进制文件。在运行 1.25 版及更高版本的 Kubernetes 客户端中,gke-gcloud-auth-plugin
二进制文件是必需的,因此您需要使用 kubectl
CLI 1.24 版或更低版本。
请按照以下步骤操作,以便在无需插件的情况下即可访问集群:
使用
curl
安装kubectl
CLI 1.24 版:curl -LO https://dl.k8s.io/release/v1.24.0/bin/linux/amd64/kubectl
您可以使用任何
kubectl
CLI 1.24 版或更低版本。在文本编辑器中打开 shell 启动脚本文件,例如对于 Bash shell 为
.bashrc
:vi ~/.bashrc
如果您使用的是 MacOS,请在这些指令中使用
~/.bash_profile
而不是.bashrc
。将以下行添加到文件中并保存:
export USE_GKE_GCLOUD_AUTH_PLUGIN=False
运行启动脚本:
source ~/.bashrc
获取集群的凭据,以设置
.kube/config
文件:gcloud container clusters get-credentials CLUSTER_NAME \ --location=COMPUTE_LOCATION
替换以下内容:
CLUSTER_NAME
:集群的名称。COMPUTE_LOCATION
:Compute Engine 位置。
运行
kubectl
命令:kubectl cluster-info
如果您在运行这些命令时收到 401 错误或类似的授权错误,请确保您拥有正确的权限,然后重新运行返回错误的步骤。
错误 400:节点池需要重新创建
错误 400“节点池需要重新创建”类似于以下内容:
ERROR: (gcloud.container.clusters.update) ResponseError: code=400, message=Node pool "test-pool-1" requires recreation.
当您尝试执行重新创建控制平面和节点的操作时,会发生此错误。例如,当您完成正在进行的凭据变换时,可能会发生此错误。
在后端,节点池会标记为要进行重新创建,但实际的重新创建操作可能需要一些时间才能开始。因此,该操作会失败,因为 GKE 尚未在集群中重新创建一个或多个节点池。
如需解决此问题,请执行以下某项操作:
- 等待重新创建完成。这可能需要几个小时、几天或几周的时间,具体取决于现有维护窗口和排除项等因素。
通过启动与控制平面相同的版本升级,手动开始重新创建受影响的节点池。
如需开始重新创建,请运行以下命令:
gcloud container clusters upgrade CLUSTER_NAME \ --node-pool=POOL_NAME
升级完成后,请重试该操作。
错误 403:权限不足
错误 403,权限不足,类似于以下内容:
ERROR: (gcloud.container.clusters.get-credentials) ResponseError: code=403, message=Required "container.clusters.get" permission(s) for "projects/<your-project>/locations/<region>/clusters/<your-cluster>".
当您尝试使用 gcloud container clusters get-credentials
连接到 GKE 集群,但账号无权访问 Kubernetes API 服务器时,会发生此错误:
如需解决此问题,请执行以下操作:
确定存在访问权限问题的账号:
gcloud auth list
按照向 Kubernetes API 服务器进行身份验证中的说明,向该账号授予所需的访问权限。
错误 403:重试预算用尽
当您尝试创建 GKE 集群时,会发生以下错误:
Error: googleapi: Error 403: Retry budget exhausted: Google Compute Engine:
Required permission 'PERMISSION_NAME' for 'RESOURCE_NAME'.
在此错误消息中,以下变量适用:
PERMISSION_NAME
:权限的名称,例如compute.regions.get
。RESOURCE_NAME
:您尝试访问的 Google Cloud 资源的路径,例如 Compute Engine 区域。
如果关联到集群的 IAM 服务账号没有创建集群所需的最低权限,则会发生此错误。
如需解决此问题,请执行以下操作:
- 创建或修改 IAM 服务账号,使其拥有运行 GKE 集群所需的所有权限。如需查看相关说明,请参阅使用最小权限 IAM 服务账号。
- 使用
--service-account
标志在集群创建命令中指定更新后的 IAM 服务账号。如需查看相关说明,请参阅创建 Autopilot 集群。
或者,省略 --service-account
标记,让 GKE 使用项目中的 Compute Engine 默认服务账号,该账号默认具有所需权限。
错误 404:调用 gcloud container
命令时“找不到”资源
如果您在调用 gcloud container
命令时收到错误 403(找不到资源),请通过重新向 Google Cloud CLI 进行身份验证来解决此问题:
gcloud auth login
错误 400/403:缺少账号的修改权限
缺少账号的修改权限错误(错误 400 或 403)表示以下任一项已被手动删除或修改:
启用 Compute Engine 或 Kubernetes Engine API 时,Google Cloud 会创建以下服务账号和代理:
- 具有项目的修改权限的 Compute Engine 默认服务账号。
- 具有项目的修改权限的 Google API 服务代理。
- 具有项目的 Kubernetes Engine Service Agent 角色的 Google Kubernetes Engine 服务账号。
如果有人在任何时候修改了这些权限、移除了项目的角色绑定、完全移除了服务账号或停用了 API,则集群创建和所有管理功能都将失败。
如需验证 Google Kubernetes Engine 服务账号是否分配了项目的 Kubernetes Engine Service Agent 角色,请执行以下步骤:
使用以下格式计算 Google Kubernetes Engine 服务账号的名称:
service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
将
PROJECT_NUMBER
替换为您的项目编号。验证您的 Google Kubernetes Engine 服务账号是否尚未分配项目的 Kubernetes Engine Service Agent 角色。在此命令中,将
PROJECT_ID
替换为您的项目 ID:gcloud projects get-iam-policy PROJECT_ID
如需解决此问题,请按照以下步骤操作:
- 如果有人从您的 Google Kubernetes Engine 服务账号中移除了 Kubernetes Engine Service Agent 角色,请重新添加该角色。
否则,请按照以下说明重新启用 Kubernetes Engine API,以正确恢复您的服务账号和权限。
控制台
转到 Google Cloud 控制台中的 API 和服务页面。
选择您的项目。
点击启用 API 和服务。
搜索 Kubernetes,然后从搜索结果中选择 API。
点击启用。如果您之前已启用 API,则必须先停用,然后再次启用。API 和相关服务的启用可能需要几分钟才能完成。
gcloud
在 gcloud CLI 中运行以下命令:
PROJECT_NUMBER=$(gcloud projects describe "PROJECT_ID"
--format 'get(projectNumber)')
gcloud projects add-iam-policy-binding PROJECT_ID \
--member "serviceAccount:service-${PROJECT_NUMBER?}@container-engine-robot.iam.gserviceaccount.com" \
--role roles/container.serviceAgent
排查 GKE 集群创建问题
错误 CONDITION_NOT_MET:违反了限制条件 constraints/compute.vmExternalIpAccess
您将组织政策限制条件 constraints/compute.vmExternalIpAccess 配置为 Deny All
,或者将外部 IP 限制为您尝试在其中创建公共 GKE 集群的组织、文件夹或项目级层的特定虚拟机实例。
当您创建公共 GKE 集群时,构成该集群的工作器节点的底层 Compute Engine 虚拟机会分配外部 IP 地址。如果您将组织政策限制条件 constraints/compute.vmExternalIpAccess 配置为 Deny All
,或者将外部 IP 限制为仅用于特定虚拟机实例,则该政策会阻止 GKE 工作节点获取外部 IP 地址,从而导致集群创建失败。
如需查找集群创建操作的日志,您可以使用 Logs Explorer 以及类似于以下内容的搜索查询来查看 GKE 集群操作审核日志:
resource.type="gke_cluster"
logName="projects/test-last-gke-sa/logs/cloudaudit.googleapis.com%2Factivity"
protoPayload.methodName="google.container.v1beta1.ClusterManager.CreateCluster"
resource.labels.cluster_name="CLUSTER_NAME"
resource.labels.project_id="PROJECT_ID"
如需解决此问题,请确保在您尝试创建 GKE 公共集群的项目中,限制条件 constraints/compute.vmExternalIpAccess
的有效政策为 Allow All
。如需了解如何使用此限制条件,请参阅将外部 IP 地址限制为仅用于特定虚拟机实例。将限制条件设置为 Allow All
后,请删除失败的集群并创建新集群。这是必需的,因为无法修复失败的集群。
排查已部署工作负载的问题
如果工作负载的 Pod 存在问题,GKE 将返回错误。
您可以使用 kubectl
命令行工具或 Google Cloud 控制台检查 Pod 的状态。
kubectl
如需查看集群中正在运行的所有 Pod,请运行以下命令:
kubectl get pods
输出:
NAME READY STATUS RESTARTS AGE
POD_NAME 0/1 CrashLoopBackOff 23 8d
如需获取有关特定 Pod 的更多详细信息,请运行以下命令:
kubectl describe pod POD_NAME
将 POD_NAME
替换为所需 Pod 的名称。
控制台
执行以下步骤:
进入 Google Cloud 控制台中的工作负载页面。
选择工作负载。概览标签页显示工作负载的状态。
在托管 Pod 部分,点击错误状态消息。
以下部分介绍了工作负载返回的一些常见错误以及解决方法。
错误:CrashLoopBackOff
CrashLoopBackOff
表示容器在重新启动后反复崩溃。容器可能由于多种原因而崩溃,通常检查 Pod 的日志即可排除根本原因。
默认情况下,崩溃的容器重新启动,指数延迟限制为五分钟。您可以通过在 spec: restartPolicy
下设置 restartPolicy
字段 Deployment 的 Pod 规范来更改此行为。该字段的默认值为 Always
。
您可以使用 Google Cloud 控制台排查 CrashLoopBackOff
错误:
转至崩溃循环的 Pod 交互式 playbook:
在
集群部分,输入要进行问题排查的集群的名称。在
命名空间部分,输入要进行问题排查的命名空间。(可选)创建提醒,以便在日后发生
CrashLoopBackOff
错误时通知您:- 在未来应对措施提示部分中,选择创建提醒。
检查日志
您可以使用 kubectl
命令行工具或 Google Cloud 控制台找出 Pod 容器崩溃的原因。
kubectl
如需查看集群中正在运行的所有 Pod,请运行以下命令:
kubectl get pods
查找具有 CrashLoopBackOff
错误的 Pod。
如需获取 Pod 的日志,请运行以下命令:
kubectl logs POD_NAME
将 POD_NAME
替换为有问题的 Pod 的名称。
您还可以传递 -p
标志,以获取 Pod 容器的上一个实例的日志(如果存在)。
控制台
执行以下步骤:
进入 Google Cloud 控制台中的工作负载页面。
选择工作负载。概览标签页显示工作负载的状态。
在托管 Pod 部分中,点击有问题的 Pod。
在 Pod 的菜单中,点击日志标签页。
检查崩溃容器的“退出代码”
您可以通过执行以下任务找到退出代码:
运行以下命令:
kubectl describe pod POD_NAME
将
POD_NAME
替换为 Pod 的名称。查看
containers: CONTAINER_NAME: last state: exit code
字段中的值:- 如果退出代码为 1,表示容器因为应用崩溃而崩溃。
- 如果退出代码为 0,请验证您的应用运行了多长时间。
当应用的主进程退出时,容器将退出。如果您的应用很快完成执行,容器可能仍会继续重新启动。
连接到正在运行的容器
打开一个连接至 Pod 的 shell:
kubectl exec -it POD_NAME -- /bin/bash
如果您的 Pod 中有多个容器,请添加 -c CONTAINER_NAME
。
现在,您可以从容器运行 bash 命令:您可以测试网络或检查您是否可以访问应用使用的文件或数据库。
错误 ImagePullBackOff 和 ErrImagePull
ImagePullBackOff
和 ErrImagePull
指示无法从映像注册表加载容器使用的映像。
您可以使用 Google Cloud 控制台或 kubectl
命令行工具验证此问题。
kubectl
要获取有关 Pod 容器映像的更多信息,请运行以下命令:
kubectl describe pod POD_NAME
控制台
执行以下步骤:
进入 Google Cloud 控制台中的工作负载页面。
选择工作负载。概览标签页显示工作负载的状态。
在托管 Pod 部分中,点击有问题的 Pod。
在 Pod 的菜单中,点击事件标签页。
问题:如果找不到映像
如果找不到您的映像:
- 验证映像的名称是否正确。
- 验证映像的标记正确。(尝试使用
:latest
命令或不添加标记来获取最新映像)。 - 如果映像具有完整的注册表路径,请验证它是否存在于您正在使用的 Docker 注册表中。如果仅提供映像名称,请检查 Docker Hub 注册表。
尝试手动拉取 docker 映像:
使用 SSH 连接到节点:
例如,如需通过 SSH 连接到虚拟机,请运行以下命令:
gcloud compute ssh VM_NAME --zone=ZONE_NAME
替换以下内容:
VM_NAME
:虚拟机的名称。ZONE_NAME
:Compute Engine 可用区。
运行
docker-credential-gcr configure-docker
。此命令会在/home/[USER]/.docker/config.json
中生成一个配置文件。确保此文件在credHelpers
字段中包含映像的注册表。例如,以下文件包含托管在 asia.gcr.io、eu.gcr.io、gcr.io、marketplace.gcr.io 和 us.gcr.io 中的映像的身份验证信息:{ "auths": {}, "credHelpers": { "asia.gcr.io": "gcr", "eu.gcr.io": "gcr", "gcr.io": "gcr", "marketplace.gcr.io": "gcr", "us.gcr.io": "gcr" } }
运行
docker pull IMAGE_NAME
。
如果此选项有效,则可能需要在 Pod 上指定 ImagePullSecrets。Pod 只能在自己的命名空间中引用映像拉取密钥,因此每个命名空间需要执行一次此过程。
错误:权限遭拒
如果您遇到“权限被拒绝”或“无拉取路径”错误,请确认您已登录并有权访问该映像。根据您托管映像的注册表,尝试以下方法之一。
Artifact Registry
如果您的映像位于 Artifact Registry 中,您的节点池的服务账号需要对包含该映像的代码库拥有读取访问权限。
将 artifactregistry.reader
角色授予服务账号:
gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \
--location=REPOSITORY_LOCATION \
--member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
--role="roles/artifactregistry.reader"
替换以下内容:
REPOSITORY_NAME
:您的 Artifact Registry 代码库的名称。REPOSITORY_LOCATION
:您的 Artifact Registry 代码库的区域。SERVICE_ACCOUNT_EMAIL
:与节点池关联的 IAM 服务账号的电子邮件地址。
Container Registry
如果您的映像位于 Container Registry 中,您的节点池的服务账号需要对包含该映像的 Cloud Storage 存储桶拥有读取访问权限。
将 roles/storage.objectViewer
角色授予服务账号,以便它可以从存储桶读取数据:
gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
--member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
--role=roles/storage.objectViewer
替换以下内容:
SERVICE_ACCOUNT_EMAIL
:与节点池关联的服务账号的电子邮件。您可以使用gcloud iam service-accounts list
列出项目中的所有服务账号。BUCKET_NAME
:包含您的映像的 Cloud Storage 存储桶的名称。您可以使用gcloud storage ls
列出项目中的所有存储桶。
如果您的注册表管理员在 Artifact Registry 中设置 gcr.io 代码库,以存储 gcr.io
网域(而非 Container Registry)的映像,您必须授予对 Artifact Registry(而不是 Container Registry)的读取权限。
私有注册表
如果您的映像位于私有注册表中,您可能需要密钥才能访问映像。如需了解详情,请参阅使用私有注册表。
错误 401 未经授权:无法从私有 Container Registry 仓库中拉取映像
从私有 Container Registry 仓库中拉取映像时,可能会发生类似于以下内容的错误:
gcr.io/PROJECT_ID/IMAGE:TAG: rpc error: code = Unknown desc = failed to pull and
unpack image gcr.io/PROJECT_ID/IMAGE:TAG: failed to resolve reference
gcr.io/PROJECT_ID/IMAGE]:TAG: unexpected status code [manifests 1.0]: 401 Unauthorized
Warning Failed 3m39s (x4 over 5m12s) kubelet Error: ErrImagePull
Warning Failed 3m9s (x6 over 5m12s) kubelet Error: ImagePullBackOff
Normal BackOff 2s (x18 over 5m12s) kubelet Back-off pulling image
确定运行 Pod 的节点:
kubectl describe pod POD_NAME | grep "Node:"
验证节点是否具有存储范围:
gcloud compute instances describe NODE_NAME \ --zone=COMPUTE_ZONE --format="flattened(serviceAccounts[].scopes)"
节点的访问权限范围应至少包含以下一个范围:
serviceAccounts[0].scopes[0]: https://www.googleapis.com/auth/devstorage.read_only serviceAccounts[0].scopes[0]: https://www.googleapis.com/auth/cloud-platform
使用足够的范围重新创建节点所属的节点池。您无法修改现有节点,必须使用正确的范围重新创建节点。
推荐:使用
gke-default
范围创建新的节点池:gcloud container node-pools create NODE_POOL_NAME \ --cluster=CLUSTER_NAME \ --zone=COMPUTE_ZONE \ --scopes="gke-default"
仅使用存储范围创建新的节点池:
gcloud container node-pools create NODE_POOL_NAME \ --cluster=CLUSTER_NAME \ --zone=COMPUTE_ZONE \ --scopes="https://www.googleapis.com/auth/devstorage.read_only"
错误:Pod 无法调度
PodUnschedulable
表示由于资源不足或某些配置错误而无法调度 Pod。
如果您已配置您的 GKE 集群,用于将 Kubernetes API 服务器和 Kubernetes 调度器指标发送到 Cloud Monitoring,您可以在调度器指标和 API 服务器指标中找到有关这些错误的详细信息。
您可以使用 Google Cloud 控制台排查 PodUnschedulable
错误:
前往无法调度的 Pod 交互式 Playbook:
在
集群部分,输入要进行问题排查的集群的名称。在
命名空间部分,输入要进行问题排查的命名空间。(可选)创建提醒,以便在日后发生
PodUnschedulable
错误时通知您:- 在未来应对措施提示部分中,选择创建提醒。
错误:资源不足
您可能会遇到指示缺少 CPU、内存或其他资源的错误。例如:“没有可用的节点匹配所有谓词:cpu(2)不足”,表明在两个节点上没有足够的 CPU 可用于满足 Pod 的请求。
如果您的 Pod 资源请求量超过任何符合条件的节点池中单个节点所能提供的资源,则 GKE 不会安排 Pod,也不会触发扩容以添加新节点。要让 GKE 对 Pod 进行安排,您必须为 Pod 请求少量的资源,或者创建具有足够资源的新节点池。
此外,您还可以启用节点自动预配功能,以便 GKE 能够自动创建节点池,这类节点池具有可运行未安排的 Pod 的节点。
默认 CPU 请求是 100M 或 CPU(或一个核心)的 10%。
如果您想请求更多或更少的资源,请在 spec: containers: resources: requests
下的 Pod 规范中指定该值
错误:MatchNodeSelector
MatchNodeSelector
指示没有与 Pod 的标签选择器匹配的节点。
如需验证这一点,请在 spec: nodeSelector
下,检查 Pod 规范中的 nodeSelector
字段指定的标签。
如需查看集群中节点的标签,请运行以下命令:
kubectl get nodes --show-labels
如需将标签附加到节点,请运行以下命令:
kubectl label nodes NODE_NAME LABEL_KEY=LABEL_VALUE
请替换以下内容:
NODE_NAME
:所需的节点。LABEL_KEY
:标签的键。LABEL_VALUE
:标签的值。
如需了解详情,请参阅将 Pod 分配给节点。
错误:PodToleratesNodeTaints
PodToleratesNodeTaints
指示 Pod 无法调度到任何节点上,因为当前没有节点可容忍其节点污点。
如需验证属于这种情况,请运行以下命令:
kubectl describe nodes NODE_NAME
在输出中,选中 Taints
字段,该字段列出了键值对和调度效果。
如果列出的效果是 NoSchedule
,则在该节点上没有 Pod 可以计划,除非它有一个匹配的负荷。
解决此问题的一种方法是移除污点。例如,如需移除 NoSchedule 污点,请运行以下命令:
kubectl taint nodes NODE_NAME key:NoSchedule-
错误:PodFitsHostPorts
PodFitsHostPorts
指示节点正在尝试使用的端口已在使用中。
如需解决此问题,请在 spec: containers: ports: hostPort
下查看 Pod 规范的 hostPort
值。您可能需要将此值更改为另一个端口。
错误:不具备最低限度的可用性
如果节点有足够的资源但仍然显示 Does not have minimum availability
消息,请查看 Pod 的状态。如果状态为 SchedulingDisabled
或 Cordoned
状态,则该节点无法调度新的 Pod。您可以使用 Google Cloud 控制台或 kubectl
命令行工具检查节点的状态。
kubectl
如需获取节点的状态,请运行以下命令:
kubectl get nodes
如需在节点上启用调度,请运行:
kubectl uncordon NODE_NAME
控制台
执行以下步骤:
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
选择集群。节点标签页显示节点及其状态。
如需在节点上启用调度,请执行以下步骤:
从列表中,点击所需的节点。
从“节点详细信息”中,点击取消封锁按钮。
错误:已达到每个节点的 Pod 数上限
如果集群中的所有节点都达到每个节点的 Pod 数上限,Pod 会卡在“无法调度”状态。在 Pod 事件标签页下,您会看到包含 Too many pods
字词的消息。
在 Google Cloud 控制台中,通过 GKE 集群详情中的“节点”标签页查看
Maximum pods per node
配置。获取节点列表:
kubectl get nodes
对于每个节点,请验证在节点上运行的 Pod 数量:
kubectl get pods -o wide | grep NODE_NAME | wc -l
如果达到了上限,请添加新的节点池,或向现有节点池添加更多节点。
问题:在启用集群自动扩缩器的情况下,已达到节点池大小上限
如果节点池已达到大小上限,根据集群自动扩缩器配置,GKE 不会触发使用此节点池安排的 Pod 纵向扩容。如果您希望使用此节点池调度 Pod,请更改集群自动扩缩器配置。
问题:在停用集群自动扩缩器的情况下,已达到节点池大小上限
如果节点池已达到节点数量上限,并且集群自动扩缩器已停用,则 GKE 无法使用节点池调度 Pod。增加节点池的大小或启用集群自动扩缩器,以便 GKE 自动调整集群的大小。
错误:PersistentVolumeClaims 未绑定
Unbound PersistentVolumeClaims
指示 Pod 引用了未绑定的 PersistentVolumeClaim。如果您的 PersistentVolume 预配失败,可能会发生此错误。您可以通过获取 PersistentVolumeClaim 事件并检查其是否失败来验证预配是否失败。
如需获取事件,请运行以下命令:
kubectl describe pvc STATEFULSET_NAME-PVC_NAME-0
请替换以下内容:
STATEFULSET_NAME
:StatefulSet 对象的名称。PVC_NAME
:PersistentVolumeClaim 对象的名称。
如果您在手动预配 PersistentVolume 并将其绑定到 PersistentVolumeClaim 期间遇到配置错误,也可能会出现此问题。您可以尝试再次预配卷。
错误:配额不足
验证您的项目是否有足够的 Compute Engine 配额供 GKE 纵向扩容集群。如果 GKE 尝试向集群添加节点以安排 Pod,并且扩容将超出项目的可用配额,则您会收到 scale.up.error.quota.exceeded
错误消息。
如需了解详情,请参阅扩容错误。
问题:API 已弃用
确保您没有使用已弃用的 API,这些 API 已与集群的次要版本一起移除。如需了解详情,请参阅 GKE 弃用。
错误:“无法为范围 0 分配:没有设置范围内的 IP 地址”
GKE 1.18.17 版及更高版本修复了以下问题:如果在容器启动之前删除了 Pod,则内存不足 (OOM) 事件会导致 Pod 被错误逐出。这种错误的逐出操作可能会导致孤立的 Pod 继续使用分配的节点范围内的预留 IP 地址。随着时间的推移,由于孤立 Pod 逐渐增多,GKE 会用完要分配给新 Pod 的 IP 地址。这导致出现错误消息 failed
to allocate for range 0: no IP addresses in range set
,因为分配的节点范围没有可用的 IP 分配给新 Pod。
如需解决此问题,请将集群和节点池升级到 GKE 1.18.17 版或更高版本。
如需在 GKE 版本在 1.18.17 之前的集群上防止和解决此问题,请提高资源限制以避免将来发生 OOM 事件,然后通过移除孤立的 Pod 来收回 IP 地址。
您还可以查看 GKE IP 地址利用率数据分析。
从受影响的节点中移除孤立的 Pod
您可以通过排空节点、升级节点池或移动受影响的目录来移除孤立的 Pod。
排空节点(推荐)
封锁节点,以防止新 Pod 调度到该节点上:
kubectl cordon NODE
将
NODE
替换为您要排空的节点的名称。排空节点。 GKE 会自动将部署管理的 Pod 重新调度到其他节点上。使用
--force
标志可排空没有管理资源的孤立 Pod。kubectl drain NODE --force
取消封锁节点,以允许 GKE 将新 Pod 调度到该节点上:
kubectl uncordon NODE
移动受影响的目录
您可以识别 /var/lib/kubelet/pods
中孤立的 Pod 目录,并将其移出主目录,以允许 GKE 终止 Pod。
排查终止资源存在的问题
问题:命名空间卡在 Terminating
状态
## Debug GKE Cluster Austoscaler issues with gcpdiag
gcpdiag
is an open source tool. It is not an officially supported Google Cloud product.
You can use the gcpdiag
tool to help you identify and fix Google Cloud
project issues. For more information, see the
gcpdiag project on GitHub.
This gcpdiag runbook investigates potential causes for GKE
Cluster Autoscaler failures while performing scale up or scale down operations.
It looks for the following error message in logs:
<ul>
<li><strong>scale.up.error.out.of.resources</strong></li>
<li><strong>scale.up.error.quota.exceeded</strong></li>
<li><strong>scale.up.error.waiting.for.instances.timeout</strong></li>
<li><strong>scale.up.error.ip.space.exhausted</strong></li>
<li><strong>scale.up.error.service.account.deleted</strong></li>
<li><strong>scale.down.error.failed.to.evict.pods</strong></li>
<li><strong>no.scale.down.node.node.group.min.size.reached</strong></li>
</ul>
Google Cloud console
- Complete and then copy the following command.
gcpdiag runbook gke/cluster-autoscaler --project=<var>PROJECT_ID</var> \\
--parameter name=<var>CLUSTER_NAME</var> \\
--parameter location=<var>LOCATION</var>
gcpdiag
命令以下载 gcpdiag
Docker 映像,然后执行诊断检查。如果适用,请按照输出说明修复失败的检查。Docker
您可以使用封装容器运行 gcpdiag
,以在 Docker 容器中启动 gcpdiag
。必须安装 Docker 或 Podman。
- 在本地工作站上复制并运行以下命令。
curl https://gcpdiag.dev/gcpdiag.sh >gcpdiag && chmod +x gcpdiag
- 执行
gcpdiag
命令:./gcpdiag runbook gke/cluster-autoscaler --project=<var>PROJECT_ID</var> \\ --parameter name=<var>CLUSTER_NAME</var> \\ --parameter location=<var>LOCATION</var>
查看此 Runbook 的可用参数。
替换以下内容:
- PROJECT_ID:资源所在项目的 ID <li><var>CLUSTER_NAME</var>:项目中目标 GKE 集群的名称。</li> <li><var>LOCATION</var>:目标 GKE 集群所在的位置(对于可用区级集群,此位置是可用区;对于区域级集群,此位置是区域)。</li>
实用标志:
--project
:PROJECT_ID--universe-domain
:如果适用,则为托管资源的可信合作伙伴主权云网域--parameter
或-p
:Runbook 参数
如需查看所有 gcpdiag
工具标志的列表和说明,请参阅 gcpdiag
使用说明。