如何使用 Amazon EKS 中的 Karpenter 自动缩放对集群扩缩进行故障排除?
我想使用 Amazon Elastic Kubernetes Service (Amazon EKS) 中的 Karpenter 自动缩放程序对集群扩缩进行故障排除。
解决方法
根据您收到的错误消息对问题进行故障排除。
由于 Amazon EKS 节点组实例不足,无法调度 Karpenter 容器组
**注意:**如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请参阅 AWS CLI 错误故障排除。此外,请确保您使用的是最新版本的 AWS CLI。
在 Karpenter 版本 0.16.0 及更高版本中,默认副本数量从 1 更改为 2。有关详细信息,请参阅 GitHub 网站上的 v0.16.0。如果集群中没有足够的节点容量来支持配置的副本数量,则无法调度 Karpenter 容器组。由于 Karpenter 无法预置节点来运行自己的容器组,它会因为容量不足而失败,并导致容器组未调度。然后,您会收到以下错误消息:
“Warning FailedScheduling 3m default-scheduler 0/1 nodes are available: 1 Insufficient memory.”
要解决此错误,请执行以下操作之一:
将 Karpenter 部署副本减少到一个
如果您的 Karpenter 部署不需要冗余,请将其更改为使用单个副本。运行以下命令:
kubectl scale deployment karpenter --replicas=1
增加 Karpenter 容器组的节点容量
要运行 Karpenter 的两个副本,请确保有足够的容量容纳两个副本。选择以下任一方案:
横向扩展自动扩缩组
- 增加自动扩缩组中的最小实例数。运行以下命令:
**注意:**将 your-node-group-name 替换为您的自动扩缩组的名称。aws autoscaling update-auto-scaling-group --auto-scaling-group-name your-node-group-name --min-size 2 --desired-capacity 2 - 确保有些节点不是 Karpenter 管理的。检查节点标签中是否有 Karpenter 标签,例如 karpenter.sh/nodepool。运行以下命令:
kubectl get nodes --show-labels | grep karpenter.sh/nodepool
使用现有节点
如果目标现有节点有 Karpenter 标签,例如 karpenter.sh/nodepool,请移除这些标签。运行以下命令:
kubectl label nodes your-node-name karpenter.sh/nodepool-
**注意:**将 your-node-name 替换为您的节点名称。
卷附加和挂载故障
当多个具有持久性卷声明 (PVC) 的容器组调度在同一个节点上时,该节点可能会超过其卷附加限制。然后,您可能会收到以下任一错误消息:
“Warning FailedAttachVolume pod/example-pod AttachVolume.Attach failed for volume " " : rpc error: code = Internal desc = Could not attach volume " " to node " ": attachment of disk " " failed, expected device to be attached but was attaching”
“Warning FailedMount pod/example-pod Unable to attach or mount volumes: unmounted volumes=[], unattached volumes=[]: timed out waiting for the condition”
要解决 PVC 密集型工作负载的卷附加和挂载故障,请完成以下步骤:
- 应用 topologySpreadConstraints 和 podAntiAffinity 来防止 PVC 密集型容器组调度在同一个节点上。有关详细信息,请参阅 Kubernetes 网站上的 topologySpreadConstraints 字段和容器组关联性示例。此操作会将 PVC 密集型容器组分布在不同的节点上,以避免卷附加集中在单个节点上。
- 使用 Amazon Elastic Block Store (Amazon EBS) 容器存储接口 (CSI) 驱动程序 (aws-ebs-csi-driver) 等 CSI 驱动程序,并将启动污点添加到您的 NodePool 中。这些操作可确保容器组在完全准备就绪之前不会过早调度到节点上。
Amazon EBS 中的启动污点配置示例:--yaml-- apiVersion: karpenter.sh/v1 kind: NodePool spec: template: spec: startupTaints: - key: ebs.csi.aws.com/agent-not-ready effect: NoExecute
已弃用的存储插件错误
Karpenter 不支持已弃用的树内存储插件,例如 Amazon EBS。如果您将静态配置的持久性卷 (PV) 与树内插件一起使用,则 Karpenter 无法发现该节点的卷附加限制。这种情况可能会导致调度失败,并且您可能会收到以下错误消息:
“ERROR controller.node_state PersistentVolume source 'AWSElasticBlockStore' uses an in-tree storage plugin which is unsupported by Karpenter and is deprecated by Kubernetes.”
要解决此问题,请使用适用于 Amazon EBS 的 CSI 驱动程序并更新您的 PV 配置以使用 CSI 驱动程序。
由于未指定的资源请求而导致调度或装箱失败
Karpenter 根据资源请求将容器组装箱。如果请求量过低或缺失,则 Karpenter 可能会将过多的容器组分配给同一个节点。这种情况可能导致资源争用和 CPU 限制。此外,如果设置了内存限制且容器组尝试使用超过其限制的内存,则可能会出现内存不足 (OOM) 终止的情况。您可能会收到以下错误消息:
“Warning OOMKilled pod/your-pod-name Container "container-name" was killed due to OOM (Out of Memory).Memory limit: 512Mi, Memory usage: 513Mi”
为防止这些问题,请使用 LimitRange 配置来设置最低资源请求,以实现准确的装箱。LimitRange 配置有助于建立最大限值以防止过度消耗。这些配置还为未指定的容器组提供了默认限制。有关详细信息,请参阅使用 LimitRanges 配置资源请求和限制的默认值。
Windows 容器组因映像拉取错误而无法启动
如果容器组的容器操作系统 (OS) 版本与 Windows 操作系统版本不匹配,则该容器组无法启动。您会收到一条类似于以下内容的错误消息:
“Failed to pull image "mcr.microsoft.com/windows/servercore:xxx": rpc error: code = NotFound desc = failed to pull and unpack image "mcr.microsoft.com/windows/servercore:xxx": no match for platform in manifest: not found”
要解决此问题,请定义您的容器组的 nodeSelector 以确保您的容器调度在兼容的操作系统主机版本上。有关详细信息,请参阅 Microsoft 网站上的 Windows 容器版本兼容性。
节点未正确初始化
系统根据节点就绪情况、预期资源注册和移除 NodePool 启动污点来确定节点初始化。如果不满足这些条件中的任何一个,则 Karpenter 节点无法正确初始化,并且该节点仍处于 NotReady 状态。因此,系统无法使用该节点来调度或整合工作负载。您可能会收到以下错误消息:
“Nodes provisioned by Karpenter are in a NotReady state”
验证节点状态是否为 Ready(就绪)。如果不是,请检查 Kubelet 日志以确定权限、安全组或网络方面的潜在问题。
验证所有必需的资源(例如 nvidia.com/gpu 或 vpc.amazonaws.com/pod-eni)是否已在节点上正确注册。
要检查节点上的 nvidia.com/gpu 资源,请运行以下命令:
kubectl describe node your-node-name
**注意:**请将 your-node-name 替换为您的节点名称。
输出示例:
... Capacity: nvidia.com/gpu.shared: 80 ...
如果缺少这些资源,请验证相应的进程守护程序集或插件是否正在运行。要检查进程守护程序集,请运行以下命令:
kubectl get ds -n your-daemonset-namespace
**注意:**将 your-daemonset-namespace 替换为您的进程守护程序集命名空间。
由于各种约束条件和限制而导致调度失败
由于关联性、反关联性或拓扑分布约束条件而导致无法调度容器组
如果关联性、反关联性或拓扑分布约束需要特定的节点或区域,但所需的位置中不存在合适的节点,则不会调度容器组。如果由于未满足节点或区域要求而导致系统无法放置容器组,则可能会收到以下错误消息:
“Warning FailedScheduling pod/"pod-name" 0/3 nodes are available: 1 node(s) didn't match pod affinity rules, 2 node(s) didn't match pod topology spread constraints rules, 3 nodes(s) didn't match inter-pod anti-affinity rules.”
要解决此错误,请检查并调整容器组的关联性和反关联性设置或拓扑分布约束条件,以使其与可用节点保持一致。您可以放宽这些约束条件,或者在所需区域中配置更多节点。
由于资源不足而导致无法调度容器组
由于资源请求超出可用节点容量,容器组仍处于未调度状态。如果没有任何节点有足够的 CPU、内存或其他资源来接受容器组,则可能会收到以下错误消息:
“Warning FailedScheduling 30s (x13 over 60m) default-scheduler 0/5 nodes are available: 1 Insufficient memory. preemption: 0/5 nodes are available: 5 No preemption victims found for incoming pod.”
要解决此问题,请确保容器组规范中的资源请求反映实际使用情况。必要时调整资源请求和限制,或为更大的节点配置更多容量以满足资源需求。
污点会阻止容器组被调度
当集群管理员将自定义污点应用于特定节点时,容器组必须具有匹配的容忍。如果它们的容忍不匹配,则系统无法在这些节点上调度容器组。您会收到以下错误消息:
“0/5 nodes are available: 3 node(s) had taint {dedicated: gpu}, that the pod didn't tolerate, 2 node(s) had taint {dedicated: non-gpu}, that the pod didn't tolerate.”
要解决此错误,请在容器组规范中添加适当的容忍以允许其容忍污点。或者,如果节点上不必要的自定义污点过于严格,您可以移除或修改这些污点。
要移除节点上的污点,请运行以下命令:
kubectl taint nodes your-node-name your-custom-taint-
**注意:**将 your-node-name 替换为您的节点名称,将 your-custom-taint 替换为您的自定义污点的名称。
不满足 NodeAffinity 或 NodeSelector 约束条件
如果节点关联性或节点选择器约束条件与集群中的任何可用节点都不匹配,则调度器无法放置容器组。您会收到以下错误消息:
“Warning FailedScheduling 3m default-scheduler 0/4 nodes are available: 1 node(s) didn't match Pod's node affinity/selector, 3 node(s) didn't satisfy existing pods anti-affinity rules, 4 node(s) didn't match Pod's node affinity rules.”
要解决此错误,请修改容器组的节点关联性或节点选择器要求,使其更加灵活。或者,如有必要,您可以预置符合容器组标准的其他节点。有关详细信息,请参阅 Kubernetes 网站上的节点关联性和 nodeSelector。
子网中的 IP 地址不足
当 Karpenter 尝试配置新节点时,由于子网中的 IP 地址不足,它会失败。当子网的无类别域间路由 (CIDR) 范围用尽且无法容纳新的 Amazon Elastic Compute Cloud (Amazon EC2) 实例时,就会出现这种情况。您会收到以下错误消息:
“error": "creating machine, creating instance, with fleet error(s), InsufficientFreeAddressesInSubnet: There are not enough free addresses in subnet 'subnet-a to satisfy the requested number of instances.”
要解决此错误,请执行以下任一操作:
如果子网的 IP 地址已耗尽,请向您的 Amazon Virtual Private Cloud (Amazon VPC) 添加额外的 IPv4 CIDR 数据块作为辅助 CIDR。
-或-
使用自定义网络为您的容器组和节点分配单独的 IP 地址空间。要激活自定义网络,请运行以下命令:
kubectl set env daemonset aws-node -n kube-system AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG=true
有关自定义网络的详细信息,请参阅如何为 Amazon EKS 集群中的容器组选择特定 IP 地址子网?
由于要求不兼容而导致无法调度容器组
Karpenter 无法调度指定节点组标签(例如 eks.amazonaws.com/nodegroup)的容器组,这些标签与节点池配置中定义的任何值都不匹配。如果出现这种不匹配,则 Karpenter 无法将容器组放置在节点上,因为缺少必需的节点标签。您会收到以下错误消息之一:
“incompatible requirements, label \"eks.amazonaws.com/nodegroup\" does not have known values"”
“incompatible requirements, key topology.kubernetes.io/zone, topology.kubernetes.io/zone In [us-east-1a] not in topology.kubernetes.io/zone In [us-east-1b us-east-1c]”
“incompatible requirements, key nodes.ktp.io/role, nodes.ktp.io/role In [ktp-atom-apps] not in nodes.ktp.io/role In [kube-apps]”
如果您想让容器组可由 Karpenter 调度,请移除托管节点组特定的 nodeSelector 来解决此错误。
示例:
kubectl edit pod your-pod-name or kubectl edit deployment your-deployment-name or kubectl edit daemonset your-daemonset-name
**注意:**将 your-pod-name、your-deployment-name 或 your-daemonset-name 替换为您的容器组、部署或进程守护程序集的名称。
节点整合失败
由于调度约束条件或阻止容器组迁移的特定容器组配置,Karpenter 的节点整合可能会失败。
调度约束条件
由于以下原因,当容器组无法迁移时,节点整合失败:
- 容器组间关联性或反关联性: 需要或避免与其他容器组同位的容器组。
- 拓扑分布约束条件: 必须分布在不同区域、节点或机架上的容器组。
- 其他调度限制: 阻止容器组迁移到其他节点的任何其他约束条件。
查看并调整容器组关联性和反关联性规则,以减少限制。调整拓扑分布约束条件以提供更大的灵活性,并允许其他可能过于严格的调度限制。
特定于容器组的预防
如果有某些类型的容器组在您的节点上运行,则 Karpenter 可能无法整合节点。由于注释、调度约束条件、容器组中断预算 (PDB) 或缺少控制器所有者,Karpenter 无法驱逐这些容器组。整合可能会失败,因为 Karpenter 不会违反这些偏好,即使 kube-scheduler 在技术上可以将容器组安排到其他地方。
- 语言
- 中文 (简体)
