节点

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

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

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

管理

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

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

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

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

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

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

节点名称唯一性

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

节点的自注册

当 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 只能创建/修改其自己的节点资源。

手动节点管理

您可以使用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 命名空间 中的 租约 对象。每个节点都有一个关联的租约对象。

节点控制器

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

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

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

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

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

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

驱逐的速率限制

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

当给定可用区中的节点变得不健康时,节点驱逐行为会发生变化。节点控制器会检查该区域中同时有多少百分比的节点不健康(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 [稳定]

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

交换内存管理

功能状态: Kubernetes v1.30 [测试版]

要在节点上启用交换,必须在 kubelet 上启用 NodeSwap 功能门控(默认值为 true),并且必须将 --fail-swap-on 命令行标志或 failSwapOn 配置设置 设置为 false。要允许 Pod 使用交换,不应在 kubelet 配置中将 swapBehavior 设置为 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 升级到 Beta1的博客文章、KEP-2400及其设计提案

下一步

详细了解以下内容

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