节点

Kubernetes 通过将容器放入 Pod 中并在节点上运行来运行您的 工作负载。节点可以是虚拟机或物理机,具体取决于集群。每个节点都由 控制平面 管理,并包含运行 Pod 所需的服务。

通常,集群中会有多个节点;在学习或资源有限的环境中,您可能只有一个节点。

节点上的 组件 包括 kubelet容器运行时kube-proxy

管理

将节点添加到 API 服务器 主要有两种方法

  1. 节点上的 kubelet 向控制平面自我注册
  2. 您(或其他人类用户)手动添加一个 Node 对象

在您创建了一个 Node 对象 或节点上的 kubelet 自我注册后,控制平面会检查新的 Node 对象是否有效。例如,如果您尝试从以下 JSON 清单创建节点

{
  "kind": "Node",
  "apiVersion": "v1",
  "metadata": {
    "name": "10.240.79.157",
    "labels": {
      "name": "my-first-k8s-node"
    }
  }
}

Kubernetes 在内部创建一个 Node 对象(表示)。Kubernetes 检查 kubelet 是否已注册到与 Node 的 metadata.name 字段匹配的 API 服务器。如果节点处于健康状态(即所有必需的服务都在运行),那么它就有资格运行 Pod。否则,该节点将被忽略任何集群活动,直到它变得健康为止。

Node 对象的名称必须是有效的 DNS 子域名称

节点名称唯一性

名称 用于标识一个节点。两个节点不能同时具有相同的名称。Kubernetes 还假定具有相同名称的资源是同一个对象。对于 Node 而言,隐式假定使用相同名称的实例将具有相同的状态(例如,网络设置、根磁盘内容)和属性,例如节点标签。如果实例在不更改名称的情况下进行了修改,则这可能会导致不一致。如果需要替换或大幅更新 Node,则需要先从 API 服务器中删除现有的 Node 对象,并在更新后重新添加。

节点的自我注册

当 kubelet 标志 --register-node 为真(默认值)时,kubelet 将尝试向 API 服务器自我注册。这是大多数发行版使用的首选模式。

对于自我注册,kubelet 使用以下选项启动

  • --kubeconfig - 用于向 API 服务器进行身份验证的凭据的路径。

  • --cloud-provider - 如何与 云提供商 交谈以读取有关自身的信息。

  • --register-node - 自动向 API 服务器注册。

  • --register-with-taints - 使用给定的 污点 列表注册节点(逗号分隔的 <key>=<value>:<effect>)。

    如果 register-node 为假,则为无操作。

  • --node-ip - 节点的 IP 地址的可选逗号分隔列表。您只能为每个地址族指定一个地址。例如,在单栈 IPv4 集群中,您将此值设置为 kubelet 应为节点使用的 IPv4 地址。有关运行双栈集群的详细信息,请参见 配置 IPv4/IPv6 双栈

    如果您未提供此参数,kubelet 会使用节点的默认 IPv4 地址(如果有);如果节点没有 IPv4 地址,则 kubelet 会使用节点的默认 IPv6 地址。

  • --node-labels - 在集群中注册节点时要添加的 标签(请参见 NodeRestriction 准入插件 强制执行的标签限制)。

  • --node-status-update-frequency - 指定 kubelet 将其节点状态发布到 API 服务器的频率。

节点授权模式NodeRestriction 准入插件 启用时,kubelet 仅被授权创建/修改其自己的 Node 资源。

手动节点管理

您可以使用 kubectl 创建和修改 Node 对象。

当您要手动创建 Node 对象时,请将 kubelet 标志 --register-node=false 设置为 false

您可以修改 Node 对象,而与 --register-node 的设置无关。例如,您可以在现有节点上设置标签或将其标记为不可调度。

您可以将节点上的标签与 Pod 上的节点选择器结合使用来控制调度。例如,您可以将 Pod 限制为仅有资格在可用节点的子集上运行。

将节点标记为不可调度将阻止调度程序将新 Pod 放置到该节点上,但不影响该节点上现有的 Pod。这在节点重启或其他维护之前作为准备步骤非常有用。

要将节点标记为不可调度,请运行

kubectl cordon $NODENAME

有关更多详细信息,请参见 安全排空节点

节点状态

节点的状态包含以下信息

您可以使用 kubectl 查看节点的状态和其他详细信息

kubectl describe node <insert-node-name-here>

有关更多详细信息,请参见 节点状态

节点心跳

心跳由 Kubernetes 节点发送,帮助您的集群确定每个节点的可用性,并在检测到故障时采取措施。

对于节点,心跳有两种形式

  • 对 Node 的 .status 进行更新。
  • kube-node-lease 命名空间 中的 租约 对象。每个节点都有一个关联的租约对象。

节点控制器

节点 控制器 是 Kubernetes 控制平面的一个组件,它管理着节点的各个方面。

节点控制器在节点的生命周期中扮演着多个角色。第一个是在节点注册时为其分配一个 CIDR 块(如果启用了 CIDR 分配)。

第二个是使节点控制器内部的节点列表与云提供商的可用机器列表保持一致。在云环境中运行时,以及在节点不健康时,节点控制器会询问云提供商该节点的虚拟机是否仍然可用。如果不可用,节点控制器会从其节点列表中删除该节点。

第三个是监控节点的健康状况。节点控制器负责

  • 在节点变得不可访问的情况下,更新节点的 .status 字段中的 Ready 状态。在这种情况下,节点控制器会将 Ready 状态设置为 Unknown
  • 如果节点仍然不可访问:对不可访问节点上的所有 Pod 触发 API 初始化驱逐。默认情况下,节点控制器会在将节点标记为 Unknown 和提交第一个驱逐请求之间等待 5 分钟。

默认情况下,节点控制器每 5 秒检查一次每个节点的状态。可以使用 kube-controller-manager 组件上的 --node-monitor-period 标志配置此周期。

驱逐速率限制

在大多数情况下,节点控制器将驱逐速率限制为每秒 --node-eviction-rate(默认值 0.1),这意味着它不会从超过 1 个节点驱逐 Pod,每 10 秒一次。

当给定可用区中的节点变得不健康时,节点驱逐行为会发生变化。节点控制器检查该可用区中不健康的节点百分比(Ready 状态为 UnknownFalse

  • 如果不健康节点的比例至少为 --unhealthy-zone-threshold(默认值 0.55),则驱逐速率会降低。
  • 如果集群规模较小(即节点数量小于或等于 --large-cluster-size-threshold - 默认值 50),则驱逐操作会停止。
  • 否则,驱逐速率会降低至每秒 --secondary-node-eviction-rate(默认值 0.01)。

这些策略在每个可用区实施的原因是,一个可用区可能会与控制平面分离,而其他可用区保持连接。如果您的集群不跨越多个云提供商可用区,则驱逐机制不会考虑每个可用区的不可用性。

将节点分布在可用区中的一个关键原因是,当一个可用区出现故障时,工作负载可以转移到健康的可用区。因此,如果可用区中的所有节点都不健康,节点控制器会以 --node-eviction-rate 的正常速率执行驱逐。特殊情况是当所有可用区都完全不健康时(集群中没有一个节点是健康的)。在这种情况下,节点控制器假设控制平面与节点之间存在一些连接问题,并且不会执行任何驱逐操作。(如果出现中断并且一些节点重新出现,节点控制器会从剩余的不健康或不可访问的节点上驱逐 Pod)。

节点控制器还负责驱逐运行在带有 NoExecute 污点的节点上的 Pod,除非这些 Pod 容忍该污点。节点控制器还会添加与节点问题(如节点不可访问或未就绪)相对应的 污点。这意味着调度程序不会将 Pod 放置到不健康的节点上。

资源容量跟踪

节点对象跟踪有关节点资源容量的信息:例如,可用的内存量和 CPU 数量。自动注册 的节点在注册期间报告其容量。如果您 手动 添加节点,则需要在添加节点时设置节点的容量信息。

Kubernetes 调度程序 确保节点上有足够的资源来运行所有 Pod。调度程序检查节点上容器请求的总和是否不超过节点的容量。该请求总和包括 kubelet 管理的所有容器,但不包括由容器运行时直接启动的任何容器,也不包括 kubelet 控制之外运行的任何进程。

节点拓扑

功能状态: Kubernetes v1.27 [stable]

如果您启用了 TopologyManager 功能网关,则 kubelet 可以在进行资源分配决策时使用拓扑提示。有关详细信息,请参阅 控制节点上的拓扑管理策略

交换内存管理

功能状态: Kubernetes v1.30 [beta]

要在节点上启用交换,必须在 kubelet 上启用 NodeSwap 功能网关(默认值为 true),并且必须将 --fail-swap-on 命令行标志或 failSwapOn 配置设置 设置为 false。要允许 Pod 使用交换,swapBehavior 在 kubelet 配置中不应设置为 NoSwap(默认行为)。

用户还可以选择配置 memorySwap.swapBehavior 以指定节点将如何使用交换内存。例如,

memorySwap:
  swapBehavior: LimitedSwap
  • NoSwap(默认):Kubernetes 工作负载不会使用交换。
  • LimitedSwap:Kubernetes 工作负载对交换内存的使用受到限制。只有可爆发的 QoS Pod 才能使用交换。

如果未指定 memorySwap 的配置并且启用了功能网关,默认情况下 kubelet 将应用与 NoSwap 设置相同的行为。

使用 LimitedSwap,不属于可爆发的 QoS 类别(即 BestEffort/Guaranteed Qos Pod)的 Pod 被禁止使用交换内存。为了维护上述安全性和节点健康保证,当 LimitedSwap 生效时,这些 Pod 不允许使用交换内存。

在详细说明交换限制的计算之前,有必要定义以下术语

  • nodeTotalMemory:节点上可用的物理内存总量。
  • totalPodsSwapAvailable:节点上可供 Pod 使用的交换内存总量(一些交换内存可能被保留供系统使用)。
  • containerMemoryRequest:容器的内存请求。

交换限制配置为:(containerMemoryRequest / nodeTotalMemory) * totalPodsSwapAvailable

需要注意的是,对于可爆发的 QoS Pod 中的容器,可以通过指定等于内存限制的内存请求来选择退出交换使用。以这种方式配置的容器将无法访问交换内存。

交换仅支持 cgroup v2,不支持 cgroup v1。

有关更多信息,以及帮助测试和提供反馈,请参阅有关 Kubernetes 1.28:NodeSwap 升级到 Beta1 的博客文章,KEP-2400 及其 设计提案

下一步

了解有关以下内容的更多信息

最后修改时间:2024 年 4 月 24 日凌晨 12:43 PST:将节点关闭部分移至集群管理(f32bcaf081)