节点
Kubernetes 通过将容器放入 Pod 中并在节点上运行来运行您的 工作负载。节点可以是虚拟机或物理机,具体取决于集群。每个节点都由 控制平面 管理,并包含运行 Pod 所需的服务。
通常,集群中会有多个节点;在学习或资源有限的环境中,您可能只有一个节点。
节点上的 组件 包括 kubelet、容器运行时 和 kube-proxy。
管理
将节点添加到 API 服务器 主要有两种方法
- 节点上的 kubelet 向控制平面自我注册
- 您(或其他人类用户)手动添加一个 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 资源。
注意
如 节点名称唯一性 部分所述,当需要更新节点配置时,最好重新向 API 服务器注册节点。例如,如果 kubelet 使用一组新的 --node-labels
重新启动,但使用相同的节点名称,则更改将不会生效,因为标签仅在节点向 API 服务器注册时设置(或修改)。
如果在 kubelet 重新启动时更改节点配置,则已调度到该节点上的 Pod 可能出现故障或导致问题。例如,正在运行的 Pod 可能被标记为与新分配给该节点的标签不兼容,而与该 Pod 不兼容的其他 Pod 将基于该新标签进行调度。节点重新注册确保所有 Pod 都将被排空并正确重新调度。
手动节点管理
您可以使用 kubectl 创建和修改 Node 对象。
当您要手动创建 Node 对象时,请将 kubelet 标志 --register-node=false
设置为 false
。
您可以修改 Node 对象,而与 --register-node
的设置无关。例如,您可以在现有节点上设置标签或将其标记为不可调度。
您可以将节点上的标签与 Pod 上的节点选择器结合使用来控制调度。例如,您可以将 Pod 限制为仅有资格在可用节点的子集上运行。
将节点标记为不可调度将阻止调度程序将新 Pod 放置到该节点上,但不影响该节点上现有的 Pod。这在节点重启或其他维护之前作为准备步骤非常有用。
要将节点标记为不可调度,请运行
kubectl cordon $NODENAME
有关更多详细信息,请参见 安全排空节点。
注意
作为 DaemonSet 一部分的 Pod 可以容忍在不可调度节点上运行。DaemonSet 通常提供节点本地服务,即使节点正在排空工作负载应用程序,这些服务也应该在节点上运行。节点状态
节点的状态包含以下信息
您可以使用 kubectl
查看节点的状态和其他详细信息
kubectl describe node <insert-node-name-here>
有关更多详细信息,请参见 节点状态。
节点心跳
心跳由 Kubernetes 节点发送,帮助您的集群确定每个节点的可用性,并在检测到故障时采取措施。
对于节点,心跳有两种形式
节点控制器
节点 控制器 是 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
状态为 Unknown
或 False
)
- 如果不健康节点的比例至少为
--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 控制之外运行的任何进程。
注意
如果您想为非 Pod 进程显式保留资源,请参阅 为系统守护程序保留资源。节点拓扑
Kubernetes v1.27 [stable]
如果您启用了 TopologyManager
功能网关,则 kubelet 可以在进行资源分配决策时使用拓扑提示。有关详细信息,请参阅 控制节点上的拓扑管理策略。
交换内存管理
Kubernetes v1.30 [beta]
要在节点上启用交换,必须在 kubelet 上启用 NodeSwap
功能网关(默认值为 true),并且必须将 --fail-swap-on
命令行标志或 failSwapOn
配置设置 设置为 false。要允许 Pod 使用交换,swapBehavior
在 kubelet 配置中不应设置为 NoSwap
(默认行为)。
警告
当内存交换功能打开时,Kubernetes 数据(例如写入 tmpfs 的 Secret 对象的内容)现在可能会被交换到磁盘。用户还可以选择配置 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 及其 设计提案。
下一步
了解有关以下内容的更多信息
- 组件,它们构成了一个节点。
- 节点的 API 定义.
- 节点 架构设计文档部分。
- 优雅/非优雅节点关闭.
- 集群自动扩展 用于管理集群中节点的数量和大小。
- 污点和容忍.
- 节点资源管理器.
- Windows 节点的资源管理.