排查正常节点更改为“未就绪”状态的更改问题

本文讨论在节点处于正常状态一段时间后,Azure Kubernetes 服务(AKS)群集节点的状态更改为“未就绪”的方案。 本文概述了特定原因,并提供了一个可能的解决方案。

先决条件

现象

群集节点的状态(正在运行的所有服务)意外更改为 “未就绪”。 若要查看节点的状态,请运行以下 kubectl describe 命令:

kubectl describe nodes

原因

kubelet 停止发布其就绪状态。

检查命令的kubectl describe nodes输出以查找“条件”字段和“容量”和“可分配块”。 这些字段的内容是否按预期显示? (例如,在 条件 字段,属性是否 message 包含“kubelet 正在发布就绪状态”字符串?)在这种情况下,如果具有对节点的直接安全外壳(SSH)访问权限,请检查最近的事件以了解错误。 查看 /var/log/messages 文件。 或者,通过运行以下 shell 命令生成 kubelet 和容器守护程序日志文件:

# To check messages file,
cat /var/log/messages

# To check kubelet and containerd daemon logs,
journalctl -u kubelet > kubelet.log
journalctl -u containerd > containerd.log

运行这些命令后,请检查消息和守护程序日志文件,了解有关错误的详细信息。

解决方案

步骤 1:检查网络级别的更改

如果所有群集节点都回归到 “未就绪 ”状态,请检查网络级别是否发生了任何更改。 网络级别更改的示例包括:

  • 域名系统 (DNS) 更改
  • 防火墙规则更改,例如端口、完全限定的域名(FQDN),等等。
  • 添加的网络安全组 (NSG)
  • 为 AKS 流量应用或更改了路由表配置

如果网络级别发生了更改,请进行任何必要的更正。 如果具有对节点的直接安全外壳(SSH)访问权限,则可以使用 curltelnet 命令检查与 AKS 出站要求的连接。 修复问题后,请停止并重启节点。 如果这些修复后节点保持正常状态,则可以安全地跳过其余步骤。

步骤 2:停止并重启节点

如果只有几个节点回归到 “未就绪 ”状态,只需停止并重启节点。 仅执行此操作可能会将节点返回到正常运行状态。 然后,检查Azure Kubernetes 服务诊断概述以确定是否存在任何问题,例如以下问题:

  • 节点错误
  • 源网络地址转换 (SNAT) 失败
  • 每秒节点输入/输出操作 (IOPS) 性能问题
  • 其他问题

如果诊断未发现任何基础问题,并且节点返回到“就绪”状态,则可以安全地跳过其余步骤。

步骤 3:修复公共 AKS API 群集的 SNAT 问题

AKS 诊断是否发现任何 SNAT 问题? 如果是,请根据需要执行以下一些操作:

  • 检查连接是否长时间保持空闲状态,并依赖于默认空闲超时释放其端口。 如果连接显示此行为,可能需要将默认超时减少 30 分钟。

  • 确定应用程序如何创建出站连接。 例如,它是否使用代码评审或数据包捕获?

  • 确定此活动是表示预期行为,还是显示应用程序行为不正常。 使用 Azure Monitor 中的指标和日志来证实发现结果。 例如,可以使用“失败”类别作为 SNAT 连接指标。

  • 评估是否遵循适当的模式。

  • 评估你是否应通过使用额外的出站 IP 地址和更多分配的出站端口来缓解 SNAT 端口耗尽的问题。 有关详细信息,请参阅 缩放托管出站公共 IP 的数量并 配置分配的出站端口

有关如何排查 SNAT 端口外泄问题的详细信息,请参阅 对 AKS 节点上的 SNAT 端口耗尽进行故障排除。

步骤 4:修复 IOPS 性能问题

如果 AKS 诊断发现降低 IOPS 性能的问题,请适当采取以下一些操作:

  • 若要增加虚拟机(VM)规模集上的 IOPS,请选择更大的磁盘大小,通过部署新的节点池来提供更好的 IOPS 性能。 不支持直接调整 VMSS 的大小。 有关调整节点池大小的详细信息,请参阅调整Azure Kubernetes 服务(AKS)中的节点池大小。

  • 请增加节点 SKU 大小,以提高内存和 CPU 处理能力。

  • 请考虑使用 临时 OS

  • 限制 Pod 的 CPU 和内存使用量。 这些限制有助于防止节点 CPU 消耗和内存不足的情况。

  • 使用计划拓扑方法添加更多节点,并在节点之间分配负载。 有关详细信息,请参阅 Pod 拓扑分布约束

步骤 5:修复线程处理问题

Kubernetes 组件(如 kubelets 和 容器运行时) 在很大程度上依赖于线程处理,它们定期生成新线程。 如果新线程的分配失败,则此失败可能会影响服务就绪情况,如下所示:

  • 节点状态更改为 “未就绪”,但由修正程序重启,并且能够恢复。

  • /var/log/messages/var/log/syslog 日志文件中,重复出现以下错误条目:

    pthread_create 失败:资源暂时无法被各种进程使用

    引用的进程包括 containerd 及可能的 kubelet。

  • 将失败条目写入日志文件后pthread_create,节点状态会很快更改为“未就绪”。

进程 ID (PID) 表示线程。 Pod 可以使用的默认 PID 数量可能取决于操作系统。 但是,默认数字至少为 32768。 对于大多数情况,此数量已超过 PID 数量。 是否存在针对更高 PID 资源的已知应用程序要求? 如果没有,甚至增加 8 倍到 262144 个 PID 也可能不足以容纳高资源应用程序。

请改为标识有问题的应用程序,然后再采取相应的措施。 请考虑其他选项,例如增加 VM 大小或者升级 AKS。 这些操作可以暂时缓解问题,但不能保证问题不会再次发生。

若要监视每个控制组 (cgroup) 的线程计数并打印前八个 cgroup,请运行以下 shell 命令:

watch 'ps -e -w -o "thcount,cgname" --no-headers | awk "{a[\$2] += \$1} END{for (i in a) print a[i], i}" | sort --numeric-sort --reverse | head --lines=8'

有关详细信息,请参阅 进程 ID 限制和预留

Kubernetes 提供了两种方法来管理节点级别的 PID 耗尽问题:

  1. 使用 --pod-max-pids 参数配置 kubelet 中 Pod 上允许的最大 PID 数。 此配置设置 pids.max 在每个 Pod 的 c 组中的设置。 还可以分别使用 --system-reserved--kube-reserved 参数来配置系统和 kubelet 限制。

  2. 配置基于 PID 的逐出。

注意

默认情况下,这两种方法都不会被设置。 此外,目前无法使用 AKS 节点池的节点配置来配置任一方法

步骤 6:使用更高的服务层级

可以使用更高的服务层确保 AKS API 服务器具有高可用性。 有关详细信息,请参阅 Azure Kubernetes 服务 (AKS) 运行时间 SLA

详细信息

  • 若要查看 AKS API 服务器和 kubelets 的运行状况和性能,请参阅 托管 AKS 组件

  • 有关常规故障排除步骤,请参阅 节点未就绪故障的基本故障排除。