排查 kubectl 命令行工具问题


本页面介绍了如何解决您在使用 Google Kubernetes Engine (GKE) 时出现的 kubectl 命令行工具问题。如需了解更多常规建议,请参阅 Kubernetes 文档中的排查 kubectl 问题

身份验证和授权错误

如果您在使用 kubectl 命令行工具命令时遇到与身份验证和授权相关的错误,请参阅以下部分以获取建议。

错误:401(未授权)

连接到 GKE 集群时,您可能会收到 HTTP 状态代码为 401 (Unauthorized) 的身份验证和授权错误。如果您尝试通过本地环境在 GKE 集群中运行 kubectl 命令,可能会遇到此问题。如需了解详情,请参阅问题:身份验证和授权错误

错误:身份验证范围不足

运行 gcloud container clusters get-credentials 时,您可能会收到以下错误:

ERROR: (gcloud.container.clusters.get-credentials) ResponseError: code=403, message=Request had insufficient authentication scopes.

出现此错误的原因是您正在尝试从没有 cloud-platform 范围的 Compute Engine 虚拟机访问 Kubernetes Engine API。

如需解决此错误,请授予缺少的 cloud-platform 范围。如需了解如何在 Compute Engine 虚拟机实例上更改范围,请参阅 Compute Engine 文档中的为实例创建和启用服务账号

错误:找不到可执行的 gke-gcloud-auth-plugin

在尝试运行 kubectl 命令或与 GKE 交互的自定义客户端时,可能会出现类似以下内容的错误消息:

Unable to connect to the server: getting credentials: exec: executable gke-gcloud-auth-plugin not found

It looks like you are trying to use a client-go credential plugin that is not installed.

To learn more about this feature, consult the documentation available at:
      https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins

Visit cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl#install_plugin to install gke-gcloud-auth-plugin.
Unable to connect to the server: getting credentials: exec: fork/exec /usr/lib/google-cloud-sdk/bin/gke-gcloud-auth-plugin: no such file or directory

如需解决此问题,请按照安装所需的插件中的说明安装 gke-gcloud-auth-plugin

错误:找不到身份验证提供方

如果 kubectl 或自定义 Kubernetes 客户端使用 Kubernetes client-go 1.26 版或更高版本构建,则会发生以下错误:

no Auth Provider found for name "gcp"

如需解决此问题,请完成以下步骤:

  1. 按照安装所需的插件中的说明安装 gke-gcloud-auth-plugin

  2. 更新到最新版 gcloud CLI:

    gcloud components update
    
  3. 更新 kubeconfig 文件。

    gcloud container clusters get-credentials CLUSTER_NAME \
        --region=COMPUTE_REGION
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • COMPUTE_REGION:集群的 Compute Engine 区域。 对于可用区级集群,请使用 --zone=COMPUTE_ZONE

错误:GCP 身份验证插件已弃用,请改用 gcloud

安装 gke-gcloud-auth-plugin 并对 GKE 集群运行 kubectl 命令后,您可能会看到以下警告消息:

WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead.

如果您的客户端版本低于 1.26,则会显示此消息。

如需解决此问题,请指示客户端改用 gke-gcloud-auth-plugin 身份验证插件:

  1. 在文本编辑器中打开 shell 登录脚本:

    Bash

    vi ~/.bashrc

    Zsh

    vi ~/.zshrc

    如果您使用的是 PowerShell,请跳过此步骤。

  2. 设置以下环境变量:

    Bash

    export USE_GKE_GCLOUD_AUTH_PLUGIN=True
    

    Zsh

    export USE_GKE_GCLOUD_AUTH_PLUGIN=True
    

    PowerShell

    [Environment]::SetEnvironmentVariable('USE_GKE_GCLOUD_AUTH_PLUGIN', True, 'Machine')
    
  3. 在您的环境中应用该变量:

    Bash

    source ~/.bashrc

    Zsh

    source ~/.zshrc
    

    PowerShell

    退出终端并打开新的终端会话。

  4. 更新 gcloud CLI:

    gcloud components update
    
  5. 向集群进行身份验证:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --region=COMPUTE_REGION
    

    请替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • COMPUTE_REGION:集群的 Compute Engine 区域。 对于可用区级集群,请使用 --zone=COMPUTE_ZONE

问题:找不到 kubectl 命令

如果您收到一条消息,提示您未找到 kubectl 命令,请重新安装 kubectl 二进制文件并设置 $PATH 环境变量:

  1. 安装 kubectl 二进制文件:

    gcloud components update kubectl
    
  2. 当安装程序提示您修改 $PATH 环境变量时,请输入 y 以继续。修改此变量后,您可以在使用 kubectl 命令时无需键入其完整路径。

    或者,将以下行添加到 shell 存储环境变量的任何位置,例如 ~/.bashrc(在 macOS 中是 ~/.bash_profile):

    export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/
    
  3. 运行以下命令以加载更新后的文件。以下示例使用 .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 无法与集群控制平面通信。

如需解决此问题,请验证并设置集群所在的上下文,并确保与集群的连接:

  1. 前往 $HOME/.kube/config 或运行命令 kubectl config view 以验证配置文件是否包含集群上下文和控制平面的外部 IP 地址。

  2. 设置集群凭据:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=COMPUTE_LOCATION \
        --project=PROJECT_ID
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • COMPUTE_LOCATIONCompute Engine 位置
    • PROJECT_ID:在其中创建集群的项目的 ID。
  3. 如果该集群是专用 GKE 集群,那么请确保其现有授权网络列表包含您尝试连接的计算机的传出 IP。您可以在控制台中查找现有授权网络,也可以通过运行以下命令来查找:

    gcloud container clusters describe CLUSTER_NAME \
        --location=COMPUTE_LOCATION \
        --project=PROJECT_ID \
        --format "flattened(masterAuthorizedNetworksConfig.cidrBlocks[])"
    

    如果上述命令输出的授权网络列表中未包含机器的传出 IP,请完成以下步骤之一:

错误:kubectl 命令返回“无法协商 API 版本”

如果 kubectl 命令返回 failed to negotiate an API version 错误,则需要确保 kubectl 具有身份验证凭据:

gcloud auth application-default login

问题:kubectl logsattachexecport-forward 命令停止响应

如果 kubectl logsattachexecport-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 密钥,因此如果您在集群的节点上专门设置了任何 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
    

后续步骤

如果您需要其他帮助,请与 Cloud Customer Care 联系。