Amazon EKS 故障排除 - Amazon EKS
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

Amazon EKS 故障排除

本章介绍使用 Amazon EKS 时可能遇到的一些常见错误以及相应的错误处理方式。

如果您在尝试创建 Amazon EKS 集群时收到以下错误,则表示所指定的某个可用区容量不足,无法支持集群。

Cannot create cluster 'example-cluster' because region-1d, the targeted Availability Zone, does not currently have sufficient capacity to support the cluster. Retry and choose from these Availability Zones: region-1a, region-1b, region-1c

在集群 VPC 中使用此错误消息所返回的可用区中托管的子网重新尝试创建集群。

有几种常见原因会阻止节点加入集群:

  • aws-auth-cm.yaml 文件没有用于节点的正确 IAM 角色 ARN。确保在 aws-auth-cm.yaml 文件中指定了节点 IAM 角色 ARN(非实例配置文件 ARN)。有关更多信息,请参阅启动自行管理的 Amazon Linux 节点

  • 节点 Amazon CloudFormation 模板中的 ClusterName 与您希望节点加入的集群的名称不完全匹配。将不正确的值传递到此字段会导致节点的 /var/lib/kubelet/kubeconfig 文件配置不正确,并且节点将无法加入集群。

  • 节点不会标记为由集群拥有。您的节点必须应用了以下标签,其中的 my-cluster 替换为集群的名称。

    密钥

    kubernetes.io/cluster/my-cluster

    owned

  • 节点可能无法使用公有 IP 地址访问集群。确保向部署在公有子网中的节点分配了公有 IP 地址。如果没有分配,您可以在节点启动后为其关联弹性 IP 地址。有关更多信息,请参阅将弹性 IP 地址与正在运行的实例或网络接口关联。如果公有子网未设置为自动将公有 IP 地址分配给部署到其中的实例,我们建议启用该设置。有关更多信息,请参阅修改子网的公有 IPv4 寻址属性。如果节点部署到私有子网,则该子网必须具有指向分配了公有 IP 地址的 NAT 网关的路由。

  • 您的账户未启用节点部署所在 Amazon Web Services 区域的 STS 端点。要启用该区域,请参阅在 Amazon Web Services 区域中激活和停用 Amazon STS

  • Worker 节点没有私有 DNS 条目,从而导致 kubelet 日志中包含 node "" not found 错误。确保创建工作线程节点的 VPC 在 DHCP options set 中以 Options 的形式设置了 domain-namedomain-name-servers 的值。默认值为 domain-name:<region>.compute.internaldomain-name-servers:AmazonProvidedDNS。有关更多信息,请参阅 Amazon VPC 用户指南 中的 DHCP 选项集

要确定导致 Worker 节点无法加入集群的常见原因并进行问题排查,您可以使用 AWSSupport-TroubleshootEKSWorkerNode 运行手册。有关更多信息,请参阅 Amazon Systems Manager Automation 运行手册参考中的 AWSSupport-TroubleshootEKSWorkerNode

如果您在运行 kubectl 命令时收到以下错误之一,则说明您的 kubectl 未针对 Amazon EKS 正确配置,或您使用的 IAM 用户或角色凭证未映射到 Amazon EKS 集群中具有足够权限的 Kubernetes RBAC 用户。

  • could not get token: AccessDenied: Access denied

  • error: You must be logged in to the server (Unauthorized)

  • error: the server doesn't have a resource type "svc"

这可能是因为集群是使用一组Amazon凭证(来自 IAM 用户或角色)创建的,而 kubectl 使用的是另一组凭证。

创建 Amazon EKS 集群后,创建集群的 IAM 实体(用户或角色)将作为管理员(具有 system:masters 权限)添加到 Kubernetes RBAC 授权表中。最初,仅该 IAM 用户可以使用 kubectl 调用 Kubernetes API 服务器。有关更多信息,请参阅让 IAM 用户和角色有权访问您的集群。如果使用控制台创建集群,则必须确保在集群上运行 kubectl 命令时,相同的 IAM 用户凭证位于Amazon开发工具包凭证链中。

如果安装和配置 Amazon CLI,则可为用户配置 IAM 凭证。有关更多信息,请参阅 Amazon Command Line Interface 用户指南中的配置 Amazon CLI

如果您已代入一个角色来创建 Amazon EKS 集群,则必须确保 kubectl 已配置为代入相同的角色。使用以下命令更新您的 kubeconfig 文件以使用 IAM 角色。有关更多信息,请参阅为 Amazon EKS 集群创建或更新 kubeconfig 文件

aws eks update-kubeconfig \ --region region-code \ --name my-cluster \ --role-arn arn:aws:iam::111122223333:role/role_name

要将 IAM 用户映射到 Kubernetes RBAC 用户,请参阅 让 IAM 用户和角色有权访问您的集群

如果收到错误 "aws-iam-authenticator": executable file not found in $PATH,则表示未对 Amazon EKS 配置 kubectl。有关更多信息,请参阅安装 aws-iam-authenticator

注意

如果安装了 Amazon CLI 版本 1.16.156 或更高版本,则不需要 aws-iam-authenticator

系统的 Python 版本必须为 2.7.9 或更高版本。否则,在 Amazon CLI 调用 Amazon EKS 时会收到 hostname doesn't match 错误。有关更多信息,请参阅“Python 请求常见问题”中的什么是“主机名不匹配”错误?

Docker 在 Amazon EKS 集群中的 172.17.0.0/16 CIDR 范围内运行。我们建议您的集群的 VPC 子网不重叠此范围。否则,您将收到以下错误:

Error: : error upgrading connection: error dialing backend: dial tcp 172.17.<nn>.<nn>:10250: getsockopt: no route to host

如果您在 Amazon Web Services Management Console中收到“Instances failed to join the kubernetes cluster (实例无法加入 kubernetes 集群)”错误,请确保已启用集群的私有终端节点访问,或者您已正确配置 CIDR 块以用于公有终端节点访问。有关更多信息,请参阅Amazon EKS 集群端点访问控制

如果您的托管节点组遇到硬件运行状况问题,则 Amazon EKS 返回错误消息以帮助您诊断问题。这些运行状况检查无法检测到软件问题,因为它们基于 Amazon EC2 运行状况检查。以下列表展示了错误消息及其相关描述。

  • AccessDenied:Amazon EKS 或您的一个或多个托管节点无法向 Kubernetes 集群 API 服务器进行身份验证或授权。有关解决该错误的更多信息,请参阅 修复托管节点组的 AccessDenied 错误

  • AmiIdNotFound:找不到与您的启动模板关联的 AMI ID。确保 AMI 存在并与您的账户共享。

  • AutoScalingGroupNotFound:找不到与托管节点组关联的 Auto Scaling 组。您可以重新创建具有相同设置的 Auto Scaling 组进行恢复。

  • ClusterUnreachable:Amazon EKS 或您的一个或多个托管节点无法与 Kubernetes 集群 API 服务器通信。如果存在网络中断或 API 服务器处理请求时超时,则可能会发生这种情况。

  • Ec2SecurityGroupNotFound:找不到集群的集群安全组。您必须重新创建集群。

  • Ec2SecurityGroupDeletionFailure:无法删除托管节点组的远程访问安全组。从安全组中删除所有依赖关系。

  • Ec2LaunchTemplateNotFound:找不到托管节点组的 Amazon EC2 启动模板。您必须重新创建节点组才能恢复。

  • Ec2LaunchTemplateVersionMismatch:您托管节点组的 Amazon EC2 启动模板版本与 Amazon EKS 创建的版本不匹配。您可以恢复到 Amazon EKS 创建的版本以进行恢复。

  • IamInstanceProfileNotFound:找不到您的托管节点组的 IAM 实例配置文件。您可以重新创建具有相同设置的实例配置文件进行恢复。

  • IamNodeRoleNotFound:找不到您的托管节点组的 IAM 角色。您可以重新创建具有相同设置的 IAM 角色进行恢复。

  • AsgInstanceLaunchFailures:您的 Auto Scaling 组在尝试启动实例时出现故障。

  • NodeCreationFailure:您启动的实例无法注册到 Amazon EKS 集群。此故障的常见原因是节点 IAM 角色权限不足,或节点缺少出站 Internet 访问权限。您的节点必须符合以下要求之一:

  • InstanceLimitExceeded:您的Amazon账户无法启动指定实例类型的更多实例。您可以请求提高 Amazon EC2 实例限制以进行恢复。

  • InsufficientFreeAddresses:与您托管节点组关联的一个或多个子网没有足够的 IP 地址供新节点使用。

  • InternalFailure:这些错误一般由 Amazon EKS 服务器端问题导致。

在托管节点组上执行操作时最常见的 AccessDenied 错误原因是缺少 eks:node-manager ClusterRoleClusterRoleBinding。Amazon EKS 会在托管节点组启动的过程中在您的集群中设置这些资源,这些资源是管理节点组所必需的。

ClusterRole 可能随着时间的推移而改变,但它应该类似于以下示例:

apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: eks:node-manager rules: - apiGroups: - '' resources: - pods verbs: - get - list - watch - delete - apiGroups: - '' resources: - nodes verbs: - get - list - watch - patch - apiGroups: - '' resources: - pods/eviction verbs: - create

ClusterRoleBinding 可能随着时间的推移而改变,但它应该类似于以下示例:

apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: eks:node-manager roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: eks:node-manager subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: eks:node-manager

验证 eks:node-manager ClusterRole 是否存在。

kubectl describe clusterrole eks:node-manager

如果存在,则将输出与上一个 ClusterRole 示例进行比较。

验证 eks:node-manager ClusterRoleBinding 是否存在。

kubectl describe clusterrolebinding eks:node-manager

如果存在,则将输出与上一个 ClusterRoleBinding 示例进行比较。

如果您发现在请求托管节点组操作期间,由于 ClusterRoleClusterRoleBinding 缺失或损坏造成了 AcessDenied 错误,则可还原它们。将以下内容保存到名为 eks-node-manager-role.yaml 的文件中。

apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: eks:node-manager rules: - apiGroups: - '' resources: - pods verbs: - get - list - watch - delete - apiGroups: - '' resources: - nodes verbs: - get - list - watch - patch - apiGroups: - '' resources: - pods/eviction verbs: - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: eks:node-manager roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: eks:node-manager subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: eks:node-manager

应用文件。

kubectl apply -f eks-node-manager-role.yaml

重试节点组操作,查看是否解决了您的问题。

Amazon VPC CNI plugin for Kubernetes 具有自己的问题排查脚本,该脚本可在 /opt/cni/bin/aws-cni-support.sh 的节点上找到。您可以使用该脚本收集有关支持案例和常规故障排除的诊断日志。

使用以下命令可在您的节点上运行脚本:

sudo bash /opt/cni/bin/aws-cni-support.sh
注意

如果脚本在该位置不存在,CNI 容器将无法运行。可以使用以下命令手动下载并运行脚本:

curl -O https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/log-collector-script/linux/eks-log-collector.sh sudo bash eks-log-collector.sh

该脚本收集以下诊断信息。您已部署的 CNI 版本可以早于脚本版本。

This is version 0.6.1. New versions can be found at https://github.com/awslabs/amazon-eks-ami Trying to collect common operating system logs... Trying to collect kernel logs... Trying to collect mount points and volume information... Trying to collect SELinux status... Trying to collect iptables information... Trying to collect installed packages... Trying to collect active system services... Trying to collect Docker daemon information... Trying to collect kubelet information... Trying to collect L-IPAMD information... Trying to collect sysctls information... Trying to collect networking information... Trying to collect CNI configuration information... Trying to collect running Docker containers and gather container data... Trying to collect Docker daemon logs... Trying to archive gathered information... Done... your bundled logs are located in /var/log/eks_i-0717c9d54b6cfaa19_2020-03-24_0103-UTC_0.6.1.tar.gz

诊断信息收集并存储在:

/var/log/eks_i-0717c9d54b6cfaa19_2020-03-24_0103-UTC_0.6.1.tar.gz

您可能会收到类似于以下内容的 Container runtime network not ready 错误和授权错误:

4191 kubelet.go:2130] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized 4191 reflector.go:205] k8s.io/kubernetes/pkg/kubelet/kubelet.go:452: Failed to list *v1.Service: Unauthorized 4191 kubelet_node_status.go:106] Unable to register node "ip-10-40-175-122.ec2.internal" with API server: Unauthorized 4191 reflector.go:205] k8s.io/kubernetes/pkg/kubelet/kubelet.go:452: Failed to list *v1.Service: Unauthorized

这些错误最有可能与 Amazon IAM Authenticator (aws-auth) 配置映射未应用到集群有关。配置映射提供了 system:bootstrapperssystem:nodes Kubernetes RBAC 权限,以便节点注册到集群。要将配置映射应用于集群,请参阅 将 aws-authConfigMap 应用到集群

角色 ARN包含 / 以外的路径,如下面的示例所示,则身份验证器无法识别该 ARN:

arn:aws:iam::111122223333:role/development/apps/prod-iam-role-NodeInstanceRole-621LVEXAMPLE

当配置映射中指定的角色 ARN 包含非 / 的路径时,必须删除该路径。应将前述 ARN 指定为以下内容:

arn:aws:iam::111122223333:role/prod-iam-role-NodeInstanceRole-621LVEXAMPLE

当节点无法建立到公有 API 服务器端点的连接时,您可能会遇到类似如下的错误。

server.go:233] failed to run Kubelet: could not init cloud provider "aws": error finding instance i-1111f2222f333e44c: "error listing Amazon instances: \"RequestError: send request failed\\ncaused by: Post net/http: TLS handshake timeout\""

kubelet 进程将持续重新生成并测试 API 服务器终端节点。在控制层面中执行集群滚动更新(例如配置更改或版本更新)的任何过程中,也可能临时发生此错误。

要解决此问题,请检查路由表和安全组,以确保来自节点的流量可以到达公有端点。

如果您将 IAM 角色用于部署于中国 Amazon Web Services 区域 的集群的 pod 或 DaemonSet 的服务账户,但尚未在规范中设置 AWS_DEFAULT_REGION 环境变量,则 pod 或 DaemonSet 可能会收到以下错误:

An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid

要解决此问题,您需要将 AWS_DEFAULT_REGION 环境变量添加到您的 pod 或 DaemonSet 规范中,如以下示例 pod 规范中所示。

apiVersion: v1 kind: Pod metadata: name: envar-demo labels: purpose: demonstrate-envars spec: containers: - name: envar-demo-container image: gcr.io/google-samples/node-hello:1.0 env: - name: AWS_DEFAULT_REGION value: "region-code"

如果用于签署 VPC 准入 Webhook 的证书过期,则新的 Windows pod 部署的状态将保持在 ContainerCreating

要解决数据面板有旧版 Windows 支持的问题,请参阅 更新 VPC 准入 Webhook 证书。如果您的集群和平台版本高于 Windows 支持先决条件部分中列出的版本,则建议删除数据面板上的旧版 Windows 支持,然后为控制面板启用新版支持。执行此操作后,无需管理 webhook 证书。有关更多信息,请参阅为 Amazon EKS 集群启用 Windows 支持

集群中的托管节点和 Fargate 节点的次要版本必须与控制面板的当前版本相同,然后才能将控制面板更新为新的 Kubernetes 版本。EKS update-cluster-version API 会拒绝请求,直到您将所有 EKS 托管节点更新为当前集群版本。EKS 提供 API 来更新托管节点。有关更新托管节点组 Kubernetes 版本的信息,请参阅 更新托管节点组。要更新 Fargate 节点的版本,请删除节点所表示的 pod,然后在更新控制面板后重新部署 pod。有关更多信息,请参阅更新 Amazon EKS 集群 Kubernetes 版本

如果同时启动多个节点,您可能会在表示 Too Many RequestsAmazon EC2 用户数据执行日志中看到错误消息。发生这种情况的原因是控制层面被 describeCluster 调用过载。过载导致节流,节点无法运行引导脚本,节点无法完全加入集群。

确保 --apiserver-endpoint--b64-cluster-ca--dns-cluster-ip 参数正在传递给 Worker 节点引导脚本。加入这些参数后,引导脚本无需调用 describeCluster,这有助于防止控制层面过载。有关更多信息,请参阅提供用户数据以将实际参数传递给随 Amazon EKS 优化版 AMI 一起提供的 bootstrap.sh 文件

如果 1.21 或更高版本集群上的 pod 的服务账户令牌已过期,您将会看到这些错误。

Amazon EKS 1.21 版或更高版本集群的 Kubernetes API 服务器拒绝令牌超过 90 天的请求。在之前的 Kubernetes 版本中,令牌没有过期时间。这意味着依赖这些令牌的客户端必须在一小时内刷新它们。为防止 Kubernetes API 服务器因令牌无效而拒绝您的请求,您的工作负载使用的 Kubernetes 客户端 SDK 版本必须与以下版本相同或高于以下版本:

  • Go 版本 0.15.7 和更高版本

  • Python 版本 12.0.0 和更高版本

  • Java 版本 9.0.0 和更高版本

  • JavaScript 版本 0.10.3 和更高版本

  • Ruby master 分支

  • Haskell 版本 0.3.0.0

  • C# 版本 7.0.5 和更高版本

您可以识别您的集群中使用过时令牌的所有现有 pods。有关更多信息,请参阅 Kubernetes 服务账户

当 Amazon EKS 无法自动更新集群的平台版本时,可能会发生这种情况。造成这种情况的原因有很多,而一些常见的原因如下。如果这些问题中的任何一个适用于您的集群,该集群可能仍然可以正常工作,但 Amazon EKS 不会更新其平台版本。

问题

集群 IAM 角色被删除 – 该角色是在创建集群时指定的。可使用以下命令查看所指定的角色。将 my-cluster 替换为您集群的名称。

aws eks describe-cluster --name my-cluster --query cluster.roleArn --output text | cut -d / -f 2

输出示例如下。

eksClusterRole

解决方案

创建具有相同名称的新集群 IAM 角色

问题

集群创建期间指定的子网被删除 – 用于集群的子网是在集群创建期间指定的。可使用以下命令查看所指定的子网。将 my-cluster 替换为您集群的名称。

aws eks describe-cluster --name my-cluster --query cluster.resourcesVpcConfig.subnetIds

输出示例如下。

[ "subnet-EXAMPLE1", "subnet-EXAMPLE2" ]

解决方案

确认您的账户中是否存在这些子网 ID。

vpc_id=$(aws eks describe-cluster --name my-cluster --query cluster.resourcesVpcConfig.vpcId --output text) aws ec2 describe-subnets --filters "Name=vpc-id,Values=$vpc_id" --query "Subnets[*].SubnetId"

输出示例如下。

[ "subnet-EXAMPLE3", "subnet-EXAMPLE4" ]

如果输出中返回的子网 ID 与创建集群时指定的子网 ID 不匹配,若您希望 Amazon EKS 更新集群,则可能需要创建一个新集群。这是因为,如果您在创建集群时指定了两个以上的子网,Amazon EKS 会随机选择您指定的子网,以便在其中创建新的弹性网络接口。这些网络接口使控制面板能够与您的节点进行通信。如果 Amazon EKS 选择的子网不存在,则不会更新集群。您在创建集群时指定了一些子网,但您无法控制 Amazon EKS 会选择哪个子网来创建新的网络接口。创建集群后,您无法创建新的子网以供集群使用。

当您对集群进行 Kubernetes 版本更新时,更新可能会因为同样的原因而失败。

问题

集群创建期间指定的安全组被删除 – 如果您在集群创建期间指定了安全组,则可以使用以下命令查看其 ID。将 my-cluster 替换为您集群的名称。

aws eks describe-cluster --name my-cluster --query cluster.resourcesVpcConfig.securityGroupIds

输出示例如下。

[ "sg-EXAMPLE1" ]

如果返回 [],则在创建集群时未指定安全组,且缺少安全组也不是问题所在。如果返回安全组,请确认您的账户中存在这些安全组。

解决方案

确认您的账户中是否存在这些安全组。

vpc_id=$(aws eks describe-cluster --name my-cluster --query cluster.resourcesVpcConfig.vpcId --output text) aws ec2 describe-security-groups --filters "Name=vpc-id,Values=$vpc_id" --query "SecurityGroups[*].GroupId"

输出示例如下。

[ "sg-EXAMPLE2" ]

如果输出中返回的安全组 ID 与创建集群时指定的安全组 ID 不匹配,若您希望 Amazon EKS 更新集群,则需要创建一个新集群。如果创建集群时指定的安全组 ID 不存在,Amazon EKS 将不会更新集群。创建集群后,您无法指定不同的安全组。

当您对集群进行 Kubernetes 版本更新时,更新可能会因为同样的原因而失败。

Amazon EKS 不更新集群平台版本的其他原因

  • 在创建集群时指定的每个子网中,可用 IP 地址达不到至少 6 个(而我们建议 16 个)。如果子网中没有足够的可用 IP 地址,则需要释放子网中的 IP 地址,或者创建一个新集群,且该集群使用的子网具有足够的可用 IP 地址。

  • 您在创建集群时启用了密钥加密,但您指定的 Amazon KMS 密钥已被删除。如果您希望 Amazon EKS 更新集群,则需要创建一个新集群