节点

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

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

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

管理

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

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

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

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

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

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

节点名称唯一性

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

节点的自我注册

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

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

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

  • --cloud-provider - 如何与 云提供商 通信以读取关于自身的元数据。

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

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

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

  • --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创建和修改节点对象。

当你想要手动创建节点对象时,请设置 kubelet 标志 --register-node=false

无论 --register-node 的设置如何,你都可以修改节点对象。例如,你可以在现有节点上设置标签或将其标记为不可调度。

你可以将节点上的标签与 Pod 上的节点选择器结合使用,以控制调度。例如,你可以约束 Pod 仅在可用节点子集上运行。

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

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

kubectl cordon $NODENAME

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

节点状态

节点的状态包含以下信息:

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

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

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

节点心跳

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

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

  • 更新节点的 .status
  • kube-node-lease 命名空间内的 Lease 对象。每个节点都有一个关联的 Lease 对象。

节点控制器

节点控制器是 Kubernetes 控制平面组件,用于管理节点的各个方面。

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

第二个角色是使节点控制器的内部节点列表与云提供商的可用机器列表保持同步。在云环境中运行时,每当节点不健康时,节点控制器都会询问云提供商该节点的 VM 是否仍然可用。如果不可用,节点控制器会从其节点列表中删除该节点。

第三个角色是监视节点的运行状况。节点控制器负责:

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

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

驱逐速率限制

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

当给定可用区中的节点变得不健康时,节点驱逐行为会发生变化。节点控制器会检查区域中同时不健康(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](默认启用:true)

如果你已启用 TopologyManager 功能门,则 kubelet 可以在做出资源分配决策时使用拓扑提示。有关更多信息,请参阅控制节点上的拓扑管理策略

交换内存管理

功能状态: Kubernetes v1.30 [beta](默认启用:true)

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

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

memorySwap:
  swapBehavior: LimitedSwap
  • NoSwap(默认):Kubernetes 工作负载将不使用交换。
  • LimitedSwap:Kubernetes 工作负载对交换内存的利用受到限制。仅允许 Burstable QoS 的 Pod 使用交换。

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

使用 LimitedSwap,不属于 Burstable QoS 分类(即 BestEffort/Guaranteed Qos Pod)的 Pod 将被禁止使用交换内存。为了维持上述安全性和节点运行状况保证,当 LimitedSwap 生效时,不允许这些 Pod 使用交换内存。

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

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

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

请务必注意,对于 Burstable QoS Pod 中的容器,可以通过指定等于内存限制的内存请求来选择不使用交换。以这种方式配置的容器将无法访问交换内存。

仅支持带有 cgroup v2 的交换,不支持 cgroup v1。

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

下一步

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

上次修改时间:太平洋标准时间 2024 年 9 月 1 日凌晨 1:54:修复了从 "overview/components/#..." 到 "architecture/#..." 的断开链接 (#47724) (7e64c2db82)