From e0302f46f2d1f9a386fa6646f548caae37da47a5 Mon Sep 17 00:00:00 2001 From: Qiming Teng Date: Sun, 10 Apr 2022 18:27:36 +0800 Subject: [PATCH] [zh] Resync nodes page --- .../zh/docs/concepts/architecture/nodes.md | 570 ++++++++++++------ 1 file changed, 390 insertions(+), 180 deletions(-) diff --git a/content/zh/docs/concepts/architecture/nodes.md b/content/zh/docs/concepts/architecture/nodes.md index 11fbc9294b..68ffb345b1 100644 --- a/content/zh/docs/concepts/architecture/nodes.md +++ b/content/zh/docs/concepts/architecture/nodes.md @@ -52,21 +52,20 @@ There are two main ways to have Nodes added to the {{< glossary_tooltip text="AP 1. The kubelet on a node self-registers to the control plane 2. You, or another human user, manually add a Node object -After you create a Node object, or the kubelet on a node self-registers, the -control plane checks whether the new Node object is valid. For example, if you -try to create a Node from the following JSON manifest: +After you create a Node {{< glossary_tooltip text="object" term_id="object" >}}, +or the kubelet on a node self-registers, the control plane checks whether the new Node object is +valid. For example, if you try to create a Node from the following JSON manifest: --> ## 管理 {#management} -向 {{< glossary_tooltip text="API 服务器" term_id="kube-apiserver" ->}}添加节点的方式主要有两种: +向 {{< glossary_tooltip text="API 服务器" term_id="kube-apiserver" >}}添加节点的方式主要有两种: 1. 节点上的 `kubelet` 向控制面执行自注册; 2. 你,或者别的什么人,手动添加一个 Node 对象。 -在你创建了 Node 对象或者节点上的 `kubelet` 执行了自注册操作之后, -控制面会检查新的 Node 对象是否合法。例如,如果你使用下面的 JSON -对象来创建 Node 对象: +在你创建了 Node {{< glossary_tooltip text="object" term_id="object" >}}或者节点上的 +`kubelet` 执行了自注册操作之后,控制面会检查新的 Node 对象是否合法。 +例如,如果你尝试使用下面的 JSON 对象来创建 Node 对象: ```json { @@ -93,13 +92,14 @@ Kubernetes 会在内部创建一个 Node 对象作为节点的表示。Kubernete 如果节点是健康的(即所有必要的服务都在运行中),则该节点可以用来运行 Pod。 否则,直到该节点变为健康之前,所有的集群活动都会忽略该节点。 +{{< note >}} -{{< note >}} Kubernetes 会一直保存着非法节点对应的对象,并持续检查该节点是否已经 变得健康。 你,或者某个{{< glossary_tooltip term_id="controller" text="控制器">}}必需显式地 @@ -113,6 +113,27 @@ The name of a Node object must be a valid Node 对象的名称必须是合法的 [DNS 子域名](/zh/docs/concepts/overview/working-with-objects/names#dns-subdomain-names)。 + +### 节点名称唯一性 {#node-name-uniqueness} + +节点的[名称](/docs/concepts/overview/working-with-objects/names#names)用来标识 Node 对象。 +没有两个 Node 可以同时使用相同的名称。 Kubernetes 还假定名字相同的资源是同一个对象。 +就 Node 而言,隐式假定使用相同名称的实例会具有相同的状态(例如网络配置、根磁盘内容) +和类似节点标签这类属性。这可能在节点被更改但其名称未变时导致系统状态不一致。 +如果某个 Node 需要被替换或者大量变更,需要从 API 服务器移除现有的 Node 对象, +之后再在更新之后重新将其加入。 + - - `--kubeconfig` - 用于向 API 服务器表明身份的凭据路径。 - - `--cloud-provider` - 与某{{< glossary_tooltip text="云驱动" term_id="cloud-provider" >}} - 进行通信以读取与自身相关的元数据的方式。 - - `--register-node` - 自动向 API 服务注册。 - - `--register-with-taints` - 使用所给的污点列表(逗号分隔的 `=:`)注册节点。 - 当 `register-node` 为 false 时无效。 - - `--node-ip` - 节点 IP 地址。 - - `--node-labels` - 在集群中注册节点时要添加的 - {{< glossary_tooltip text="标签" term_id="label" >}}。 - (参见 [NodeRestriction 准入控制插件](/zh/docs/reference/access-authn-authz/admission-controllers/#noderestriction)所实施的标签限制)。 - - `--node-status-update-frequency` - 指定 kubelet 向控制面发送状态的频率。 +- `--kubeconfig` - 用于向 API 服务器执行身份认证所用的凭据的路径。 +- `--cloud-provider` - 与某{{< glossary_tooltip text="云驱动" term_id="cloud-provider" >}} + 进行通信以读取与自身相关的元数据的方式。 +- `--register-node` - 自动向 API 服务注册。 +- `--register-with-taints` - 使用所给的{{< glossary_tooltip text="污点" term_id="taint" >}}列表 + (逗号分隔的 `=:`)注册节点。当 `register-node` 为 false 时无效。 +- `--node-ip` - 节点 IP 地址。 +- `--node-labels` - 在集群中注册节点时要添加的{{< glossary_tooltip text="标签" term_id="label" >}}。 + (参见 [NodeRestriction 准入控制插件](/zh/docs/reference/access-authn-authz/admission-controllers/#noderestriction)所实施的标签限制)。 +- `--node-status-update-frequency` - 指定 kubelet 向控制面发送状态的频率。 -启用[节点授权模式](/zh/docs/reference/access-authn-authz/node/)和 +启用[Node 鉴权模式](/zh/docs/reference/access-authn-authz/node/)和 [NodeRestriction 准入插件](/zh/docs/reference/access-authn-authz/admission-controllers/#noderestriction) 时,仅授权 `kubelet` 创建或修改其自己的节点资源。 +{{< note >}} + +正如[节点名称唯一性](#node-name-uniqueness)一节所述,当 Node 的配置需要被更新时, +一种好的做法是重新向 API 服务器注册该节点。例如,如果 kubelet 重启时其 `--node-labels` +是新的值集,但同一个 Node 名称已经被使用,则所作变更不会起作用, +因为节点标签是在 Node 注册时完成的。 + + +如果在 kubelet 重启期间 Node 配置发生了变化,已经被调度到某 Node 上的 Pod +可能会出现行为不正常或者出现其他问题,例如,已经运行的 Pod +可能通过污点机制设置了与 Node 上新设置的标签相排斥的规则,也有一些其他 Pod, +本来与此 Pod 之间存在不兼容的问题,也会因为新的标签设置而被调到到同一节点。 +节点重新注册操作可以确保节点上所有 Pod 都被排空并被正确地重新调度。 +{{< /note >}} + -你可以结合使用节点上的标签和 Pod 上的选择算符来控制调度。 +你可以结合使用 Node 上的标签和 Pod 上的选择算符来控制调度。 例如,你可以限制某 Pod 只能在符合要求的节点子集上运行。 -如果标记节点为不可调度(unschedulable),将阻止新 Pod 调度到该节点之上,但不会 -影响任何已经在其上的 Pod。 +如果标记节点为不可调度(unschedulable),将阻止新 Pod 调度到该 Node 之上, +但不会影响任何已经在其上的 Pod。 这是重启节点或者执行其他维护操作之前的一个有用的准备步骤。 -要标记一个节点为不可调度,执行以下命令: +要标记一个 Node 为不可调度,执行以下命令: ```shell kubectl cordon $NODENAME ``` + 更多细节参考[安全腾空节点](/zh/docs/tasks/administer-cluster/safely-drain-node/)。 +{{< note >}} -{{< note >}} 被 {{< glossary_tooltip term_id="daemonset" text="DaemonSet" >}} 控制器创建的 Pod 能够容忍节点的不可调度属性。 -DaemonSet 通常提供节点本地的服务,即使节点上的负载应用已经被腾空,这些服务也仍需 -运行在节点之上。 +DaemonSet 通常提供节点本地的服务,即使节点上的负载应用已经被腾空, +这些服务也仍需运行在节点之上。 {{< /note >}} -* HostName:由节点的内核设置。可以通过 kubelet 的 `--hostname-override` 参数覆盖。 +* HostName:由节点的内核报告。可以通过 kubelet 的 `--hostname-override` 参数覆盖。 * ExternalIP:通常是节点的可外部路由(从集群外可访问)的 IP 地址。 * InternalIP:通常是节点的仅可在集群内部路由的 IP 地址。 @@ -301,14 +350,14 @@ The `conditions` field describes the status of all `Running` nodes. Examples of | `NetworkUnavailable` | `True` 表示节点网络配置不正确;否则为 `False` | {{< /table >}} +{{< note >}} -{{< note >}} -如果使用命令行工具来打印已保护(Cordoned)节点的细节,其中的 Condition 字段可能 -包括 `SchedulingDisabled`。`SchedulingDisabled` 不是 Kubernetes API 中定义的 +如果使用命令行工具来打印已保护(Cordoned)节点的细节,其中的 Condition 字段可能包括 +`SchedulingDisabled`。`SchedulingDisabled` 不是 Kubernetes API 中定义的 Condition,被保护起来的节点在其规约中被标记为不可调度(Unschedulable)。 {{< /note >}} @@ -340,16 +389,20 @@ than the `pod-eviction-timeout` (an argument passed to the {{< glossary_tooltip text="API-initiated eviction" term_id="api-eviction" >}} for all Pods assigned to that node. The default eviction timeout duration is **five minutes**. +--> +如果 Ready 状况的 `status` 处于 `Unknown` 或者 `False` 状态的时间超过了 +`pod-eviction-timeout` 值(一个传递给 +{{< glossary_tooltip text="kube-controller-manager" term_id="kube-controller-manager" >}} +的参数),[节点控制器](#node-controller) 会对节点上的所有 Pod 触发 +{{< glossary_tooltip text="API-发起的驱逐" term_id="api-eviction" >}}。 +默认的逐出超时时长为 **5 分钟**。 + + -如果 Ready 条件的 `status` 处于 `Unknown` 或者 `False` 状态的时间超过了 `pod-eviction-timeout` 值, -(一个传递给 {{< glossary_tooltip text="kube-controller-manager" term_id="kube-controller-manager" >}} 的参数), -[节点控制器](#node-controller) 会对节点上的所有 Pod 触发 -{{< glossary_tooltip text="API-发起的驱逐" term_id="api-eviction" >}}。 -默认的逐出超时时长为 **5 分钟**。 某些情况下,当节点不可达时,API 服务器不能和其上的 kubelet 通信。 删除 Pod 的决定不能传达给 kubelet,直到它重新建立和 API 服务器的连接为止。 与此同时,被计划删除的 Pod 可能会继续在游离的节点上运行。 @@ -370,15 +423,24 @@ names. 从 Kubernetes 删除节点对象将导致 API 服务器删除节点上所有运行的 Pod 对象并释放它们的名字。 -节点生命周期控制器会自动创建代表状况的 +当节点上出现问题时,Kubernetes 控制面会自动创建与影响节点的状况对应的 [污点](/zh/docs/concepts/scheduling-eviction/taint-and-toleration/)。 -当调度器将 Pod 指派给某节点时,会考虑节点上的污点。 -Pod 则可以通过容忍度(Toleration)表达所能容忍的污点。 +调度器在将 Pod 指派到某 Node 时会考虑 Node 上的污点设置。 +Pod 也可以设置{{< glossary_tooltip text="容忍度" term_id="toleration" >}}, +以便能够在设置了特定污点的 Node 上运行。 + + +进一步的细节可参阅[根据状况为节点设置污点](/zh/docs/concepts/scheduling-eviction/taint-and-toleration/#taint-nodes-by-condition)。 -### 容量与可分配 {#capacity} +### 容量(Capacity)与可分配(Allocatable) {#capacity} -描述节点上的可用资源:CPU、内存和可以调度到节点上的 Pod 的个数上限。 +这两个值描述节点上的可用资源:CPU、内存和可以调度到节点上的 Pod 的个数上限。 -### 信息 {#info} +### 信息(Info) {#info} -描述节点的一般信息,如内核版本、Kubernetes 版本(`kubelet` 和 `kube-proxy` 版本)、 +Info 指的是节点的一般信息,如内核版本、Kubernetes 版本(`kubelet` 和 `kube-proxy` 版本)、 容器运行时详细信息,以及 节点使用的操作系统。 `kubelet` 从节点收集这些信息并将其发布到 Kubernetes API。 +## 心跳 {#heartbeats} +Kubernetes 节点发送的心跳帮助你的集群确定每个节点的可用性,并在检测到故障时采取行动。 +对于节点,有两种形式的心跳: + + +* 更新节点的 `.status` +* `kube-node-lease` {{}}中的 + [Lease(租约)](/docs/reference/kubernetes-api/cluster-resources/lease-v1/)对象。 + 每个节点都有一个关联的 Lease 对象。 + +与 Node 的 `.status` 更新相比,Lease 是一种轻量级资源。 +使用 Lease 来表达心跳在大型集群中可以减少这些更新对性能的影响。 +kubelet 负责创建和更新节点的 `.status`,以及更新它们对应的 Lease。 + + -## 心跳 {#heartbeats} -Kubernetes 节点发送的心跳帮助你的集群确定每个节点的可用性,并在检测到故障时采取行动。 - -对于节点,有两种形式的心跳: - -* 更新节点的 `.status` -* [Lease](/docs/reference/kubernetes-api/cluster-resources/lease-v1/) 对象 - 在 `kube-node-lease` {{}}中。 - 每个节点都有一个关联的 Lease 对象。 - -与 Node 的 `.status` 更新相比,`Lease` 是一种轻量级资源。 -使用 `Leases` 心跳在大型集群中可以减少这些更新对性能的影响。 - -kubelet 负责创建和更新节点的 `.status`,以及更新它们对应的 `Lease`。 - -- 当状态发生变化时,或者在配置的时间间隔内没有更新事件时,kubelet 会更新 `.status`。 - `.status` 更新的默认间隔为 5 分钟(比不可达节点的 40 秒默认超时时间长很多)。 -- `kubelet` 会每 10 秒(默认更新间隔时间)创建并更新其 `Lease` 对象。 - `Lease` 更新独立于 `NodeStatus` 更新而发生。 - 如果 `Lease` 的更新操作失败,`kubelet` 会采用指数回退机制,从 200 毫秒开始 - 重试,最长重试间隔为 7 秒钟。 +- 当节点状态发生变化时,或者在配置的时间间隔内没有更新事件时,kubelet 会更新 `.status`。 + `.status` 更新的默认间隔为 5 分钟(比节点不可达事件的 40 秒默认超时时间长很多)。 +- `kubelet` 会创建并每 10 秒(默认更新间隔时间)更新 Lease 对象。 + Lease 的更新独立于 Node 的 `.status` 更新而发生。 + 如果 Lease 的更新操作失败,kubelet 会采用指数回退机制,从 200 毫秒开始重试, + 最长重试间隔为 7 秒钟。 ## 节点控制器 {#node-controller} -节点{{< glossary_tooltip text="控制器" term_id="controller" >}}是 -Kubernetes 控制面组件,管理节点的方方面面。 +节点{{< glossary_tooltip text="控制器" term_id="controller" >}}是 Kubernetes 控制面组件, +管理节点的方方面面。 节点控制器在节点的生命周期中扮演多个角色。 第一个是当节点注册时为它分配一个 CIDR 区段(如果启用了 CIDR 分配)。 @@ -505,6 +569,7 @@ controller deletes the node from its list of nodes. -第三个是监控节点的健康状况。 节点控制器是负责: -- 在节点节点不可达的情况下,在 Node 的 `.status` 中更新 `NodeReady` 状况。 - 在这种情况下,节点控制器将 `NodeReady` 状况更新为 `ConditionUnknown` 。 -- 如果节点仍然无法访问:对于不可达节点上的所有 Pod触发 +第三个是监控节点的健康状况。节点控制器负责: + +- 在节点不可达的情况下,在 Node 的 `.status` 中更新 NodeReady 状况。 + 在这种情况下,节点控制器将 NodeReady 状况更新为 `Unknown` 。 +- 如果节点仍然无法访问:对于不可达节点上的所有 Pod 触发 [API-发起的逐出](/zh/docs/concepts/scheduling-eviction/api-eviction/)。 - 默认情况下,节点控制器 在将节点标记为 `ConditionUnknown` 后等待 5 分钟 提交第一个驱逐请求。 + 默认情况下,节点控制器在将节点标记为 `Unknown` 后等待 5 分钟提交第一个驱逐请求。 节点控制器每隔 `--node-monitor-period` 秒检查每个节点的状态。 @@ -542,29 +608,33 @@ The node eviction behavior changes when a node in a given availability zone becomes unhealthy. The node controller checks what percentage of nodes in the zone are unhealthy (NodeReady condition is `ConditionUnknown` or `ConditionFalse`) at the same time: +--> +当一个可用区域(Availability Zone)中的节点变为不健康时,节点的驱逐行为将发生改变。 +节点控制器会同时检查可用区域中不健康(NodeReady 状况为 `Unknown` 或 `False`) +的节点的百分比: + + +- 如果不健康节点的比例超过 `--unhealthy-zone-threshold` (默认为 0.55), + 驱逐速率将会降低。 +- 如果集群较小(意即小于等于 `--large-cluster-size-threshold` 个节点 - 默认为 50), + 驱逐操作将会停止。 +- 否则驱逐速率将降为每秒 `--secondary-node-eviction-rate` 个(默认为 0.01)。 + -当一个可用区域(Availability Zone)中的节点变为不健康时,节点的驱逐行为将发生改变。 -节点控制器会同时检查可用区域中不健康(NodeReady 状况为 `ConditionUnknown` 或 `ConditionFalse`) -的节点的百分比: -- 如果不健康节点的比例超过 `--unhealthy-zone-threshold` (默认为 0.55), -驱逐速率将会降低。 -- 如果集群较小(意即小于等于 `--large-cluster-size-threshold` -个节点 - 默认为 50),驱逐操作将会停止。 -- 否则驱逐速率将降为每秒 `--secondary-node-eviction-rate` 个(默认为 0.01)。 - -在单个可用区域实施这些策略的原因是当一个可用区域可能从控制面脱离时其它可用区域 -可能仍然保持连接。 +在逐个可用区域中实施这些策略的原因是, +当一个可用区域可能从控制面脱离时其它可用区域可能仍然保持连接。 如果你的集群没有跨越云服务商的多个可用区域,那(整个集群)就只有一个可用区域。 节点控制器还负责驱逐运行在拥有 `NoExecute` 污点的节点上的 Pod, 除非这些 Pod 能够容忍此污点。 -节点控制器还负责根据节点故障(例如节点不可访问或没有就绪)为其添加 -{{< glossary_tooltip text="污点" term_id="taint" >}}。 +节点控制器还负责根据节点故障(例如节点不可访问或没有就绪) +为其添加{{< glossary_tooltip text="污点" term_id="taint" >}}。 这意味着调度器不会将 Pod 调度到不健康的节点上。 -Kubernetes {{< glossary_tooltip text="调度器" term_id="kube-scheduler" >}}保证节点上 -有足够的资源供其上的所有 Pod 使用。它会检查节点上所有容器的请求的总和不会超过节点的容量。 +Kubernetes {{< glossary_tooltip text="调度器" term_id="kube-scheduler" >}} +保证节点上有足够的资源供其上的所有 Pod 使用。 +它会检查节点上所有容器的请求的总和不会超过节点的容量。 总的请求包括由 kubelet 启动的所有容器,但不包括由容器运行时直接启动的容器, 也不包括不受 `kubelet` 控制的其他进程。 +{{< note >}} -{{< note >}} -如果要为非 Pod 进程显式保留资源。请参考 -[为系统守护进程预留资源](/zh/docs/tasks/administer-cluster/reserve-compute-resources/#system-reserved)。 +如果要为非 Pod 进程显式保留资源。 +请参考[为系统守护进程预留资源](/zh/docs/tasks/administer-cluster/reserve-compute-resources/#system-reserved)。 {{< /note >}} 如果启用了 `TopologyManager` [特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/), `kubelet` 可以在作出资源分配决策时使用拓扑提示。 -参考[控制节点上拓扑管理策略](/zh/docs/tasks/administer-cluster/topology-manager/) -了解详细信息。 +参考[控制节点上拓扑管理策略](/zh/docs/tasks/administer-cluster/topology-manager/)了解详细信息。 kubelet 会尝试检测节点系统关闭事件并终止在节点上运行的 Pods。 -在节点终止期间,kubelet 保证 Pod 遵从常规的 [Pod 终止流程](/zh/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination)。 +在节点终止期间,kubelet 保证 Pod 遵从常规的 +[Pod 终止流程](/zh/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination)。 体面节点关闭特性依赖于 systemd,因为它要利用 -[systemd 抑制器锁](https://www.freedesktop.org/wiki/Software/systemd/inhibit/) +[systemd 抑制器锁](https://www.freedesktop.org/wiki/Software/systemd/inhibit/)机制, 在给定的期限内延迟节点关闭。 体面节点关闭特性受 `GracefulNodeShutdown` -[特性门控](/docs/reference/command-line-tools-reference/feature-gates/) -控制,在 1.21 版本中是默认启用的。 +[特性门控](/docs/reference/command-line-tools-reference/feature-gates/)控制, +在 1.21 版本中是默认启用的。 注意,默认情况下,下面描述的两个配置选项,`ShutdownGracePeriod` 和 -`ShutdownGracePeriodCriticalPods` 都是被设置为 0 的,因此不会激活 -体面节点关闭功能。 +`ShutdownGracePeriodCriticalPods` 都是被设置为 0 的,因此不会激活体面节点关闭功能。 要激活此功能特性,这两个 kubelet 配置选项要适当配置,并设置为非零值。 -在体面关闭节点过程中,kubelet 分两个阶段来终止 Pods: +在体面关闭节点过程中,kubelet 分两个阶段来终止 Pod: 1. 终止在节点上运行的常规 Pod。 2. 终止在节点上运行的[关键 Pod](/zh/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/#marking-pod-as-critical)。 @@ -723,11 +795,10 @@ Graceful Node Shutdown feature is configured with two [`KubeletConfiguration`](/ [`KubeletConfiguration`](/zh/docs/tasks/administer-cluster/kubelet-config-file/) 选项: * `ShutdownGracePeriod`: - * 指定节点应延迟关闭的总持续时间。此时间是 Pod 体面终止的时间总和,不区分常规 Pod 还是 - [关键 Pod](/zh/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/#marking-pod-as-critical)。 + * 指定节点应延迟关闭的总持续时间。此时间是 Pod 体面终止的时间总和,不区分常规 Pod + 还是[关键 Pod](/zh/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/#marking-pod-as-critical)。 * `ShutdownGracePeriodCriticalPods`: - * 在节点关闭期间指定用于终止 - [关键 Pod](/zh/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/#marking-pod-as-critical) + * 在节点关闭期间指定用于终止[关键 Pod](/zh/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/#marking-pod-as-critical) 的持续时间。该值应小于 `ShutdownGracePeriod`。 - {{< note >}} -当 Pod 在正常节点关闭期间被驱逐时,它们会被标记为 `failed`。 -运行 `kubectl get pods` 将被驱逐的 pod 的状态显示为 `Shutdown`。 -并且 `kubectl describe pod` 表示 pod 因节点关闭而被驱逐: +当 Pod 在正常节点关闭期间被驱逐时,它们会被标记为已经失败(Failed)。 +运行 `kubectl get pods` 时,被驱逐的 Pod 的状态显示为 `Shutdown`。 +并且 `kubectl describe pod` 表示 Pod 因节点关闭而被驱逐: ``` -Status: Failed -Reason: Shutdown -Message: Node is shutting, evicting pods +Reason: Terminated +Message: Pod was terminated in response to imminent node shutdown. ``` - -`Failed` 的 pod 对象将被保留,直到被明确删除或 -[由 GC 清理](/zh/docs/concepts/workloads/pods/pod-lifecycle/#pod-garbage-collection)。 -与突然的节点终止相比这是一种行为变化。 {{< /note >}} + +### 基于 Pod 优先级的体面节点关闭 {#pod-priority-graceful-node-shutdown} + +{{< feature-state state="alpha" for_k8s_version="v1.23" >}} + + +为了在体面节点关闭期间提供更多的灵活性,尤其是处理关闭期间的 Pod 排序问题, +体面节点关闭机制能够关注 Pod 的 PriorityClass 设置,前提是你已经在集群中启用了此功能特性。 +此功能特性允许集群管理员基于 Pod +的[优先级类(Priority Class)](/zh/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass) +显式地定义体面节点关闭期间 Pod 的处理顺序。 + + +前文所述的[体面节点关闭](#graceful-node-shutdown)特性能够分两个阶段关闭 Pod, +首先关闭的是非关键的 Pod,之后再处理关键 Pod。 +如果需要显式地以更细粒度定义关闭期间 Pod 的处理顺序,需要一定的灵活度, +这时可以使用基于 Pod 优先级的体面关闭机制。 + + +当体面节点关闭能够处理 Pod 优先级时,体面节点关闭的处理可以分为多个阶段, +每个阶段关闭特定优先级类的 Pod。kubelet 可以被配置为按确切的阶段处理 Pod, +且每个阶段可以独立设置关闭时间。 + + +假设集群中存在以下自定义的 Pod +[优先级类](/zh/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass)。 + +| Pod 优先级类名称 | Pod 优先级类数值 | +|-------------------------|------------------------| +|`custom-class-a` | 100000 | +|`custom-class-b` | 10000 | +|`custom-class-c` | 1000 | +|`regular/unset` | 0 | + + +在 [kubelet 配置](/zh/docs/reference/config-api/kubelet-config.v1beta1/#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)中, +`shutdownGracePeriodByPodPriority` 可能看起来是这样: + +| Pod 优先级类数值 | 关闭期限 | +|------------------------|-----------| +| 100000 | 10 秒 | +| 10000 | 180 秒 | +| 1000 | 120 秒 | +| 0 | 60 秒 | + + +对应的 kubelet 配置 YAML 将会是: + +```yaml +shutdownGracePeriodByPodPriority: + - priority: 100000 + shutdownGracePeriodSeconds: 10 + - priority: 10000 + shutdownGracePeriodSeconds: 180 + - priority: 1000 + shutdownGracePeriodSeconds: 120 + - priority: 0 + shutdownGracePeriodSeconds: 60 +``` + + +上面的表格表明,所有 `priority` 值大于等于 100000 的 Pod 会得到 10 秒钟期限停止, +所有 `priority` 值介于 10000 和 100000 之间的 Pod 会得到 180 秒钟期限停止, +所有 `priority` 值介于 1000 和 10000 之间的 Pod 会得到 120 秒钟期限停止, +所有其他 Pod 将获得 60 秒的时间停止。 + +用户不需要为所有的优先级类都设置数值。例如,你也可以使用下面这种配置: + +| Pod 优先级类数值 | 关闭期限 | +|------------------------|-----------| +| 100000 | 300 秒 | +| 1000 | 120 秒 | +| 0 | 60 秒 | + + +在上面这个场景中,优先级类为 `custom-class-b` 的 Pod 会与优先级类为 `custom-class-c` +的 Pod 在关闭时按相同期限处理。 + +如果在特定的范围内不存在 Pod,则 kubelet 不会等待对应优先级范围的 Pod。 +kubelet 会直接跳到下一个优先级数值范围进行处理。 + + +如果此功能特性被启用,但没有提供配置数据,则不会出现排序操作。 + +使用此功能特性需要启用 `GracefulNodeShutdownBasedOnPodPriority` 功能特性, +并将 kubelet 配置中的 `ShutdownGracePeriodByPodPriority` 设置为期望的配置, +其中包含 Pod 的优先级类数值以及对应的关闭期限。 + + +kubelet 子系统中会生成 `graceful_shutdown_start_time_seconds` 和 +`graceful_shutdown_end_time_seconds` 度量指标以便监视节点关闭行为。 + ## 交换内存管理 {#swap-memory} {{< feature-state state="alpha" for_k8s_version="v1.22" >}} -在 Kubernetes 1.22 之前,节点不支持使用交换内存,并且 -默认情况下,如果在节点上检测到交换内存配置,kubelet 将无法启动。 在 1.22 -以后,可以在每个节点的基础上启用交换内存支持。 + +在 Kubernetes 1.22 之前,节点不支持使用交换内存,并且默认情况下, +如果在节点上检测到交换内存配置,kubelet 将无法启动。 +在 1.22 以后,可以逐个节点地启用交换内存支持。 + 要在节点上启用交换内存,必须启用kubelet 的 `NodeSwap` 特性门控, - 同时使用 `--fail-swap-on` 命令行参数或者将 `failSwapOn` +同时使用 `--fail-swap-on` 命令行参数或者将 `failSwapOn` [配置](/zh/docs/reference/config-api/kubelet-config.v1beta1/#kubelet-config-k8s-io-v1beta1-KubeletConfiguration) -设置为false。 +设置为 false。 -用户还可以选择配置 `memorySwap.swapBehavior` 以指定节点使用交换内存的方式。 例如: + +用户还可以选择配置 `memorySwap.swapBehavior` 以指定节点使用交换内存的方式。例如: ```yaml memorySwap: @@ -818,41 +1026,43 @@ The available configuration options for `swapBehavior` are: use. Workloads on the node not managed by Kubernetes can still swap. - `UnlimitedSwap`: Kubernetes workloads can use as much swap memory as they request, up to the system limit. +--> +可用的 `swapBehavior` 的配置选项有: +- `LimitedSwap`:Kubernetes 工作负载的交换内存会受限制。 + 不受 Kubernetes 管理的节点上的工作负载仍然可以交换。 +- `UnlimitedSwap`:Kubernetes 工作负载可以使用尽可能多的交换内存请求, + 一直到达到系统限制为止。 + + +如果启用了特性门控但是未指定 `memorySwap` 的配置,默认情况下 kubelet 将使用 +`LimitedSwap` 设置。 +`LimitedSwap` 这种设置的行为取决于节点运行的是 v1 还是 v2 的控制组(也就是 `cgroups`): + + +- **cgroupsv1:** Kubernetes 工作负载可以使用内存和交换,上限为 Pod 的内存限制值(如果设置了的话)。 +- **cgroupsv2:** Kubernetes 工作负载不能使用交换内存。 + -已有的 `swapBehavior` 的配置选项有: - -- `LimitedSwap`:Kubernetes 工作负载的交换内存会受限制。 - 不受 Kubernetes 管理的节点上的工作负载仍然可以交换。 -- `UnlimitedSwap`:Kubernetes 工作负载可以使用尽可能多的交换内存 - 请求,一直到系统限制。 - -如果启用了特性门控但是未指定 `memorySwap` 的配置,默认情况下 kubelet 将使用 -`LimitedSwap` 设置。 - -`LimitedSwap` 设置的行为还取决于节点运行的是 v1 还是 v2 的控制组(也就是 `cgroups`): - -- **cgroupsv1:** Kubernetes 工作负载可以使用内存和 - 交换,达到 pod 的内存限制(如果设置)。 -- **cgroupsv2:** Kubernetes 工作负载不能使用交换内存。 - -如需更多信息以及协助测试和提供反馈,请 -参见 [KEP-2400](https://github.com/kubernetes/enhancements/issues/2400) 及其 -[设计方案](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2400-node-swap/README.md)。 +如需更多信息以及协助测试和提供反馈,请参见 +[KEP-2400](https://github.com/kubernetes/enhancements/issues/2400) +及其[设计提案](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2400-node-swap/README.md)。 ## {{% heading "whatsnext" %}} @@ -863,10 +1073,10 @@ see [KEP-2400](https://github.com/kubernetes/enhancements/issues/2400) and its section of the architecture design document. * Read about [taints and tolerations](/docs/concepts/scheduling-eviction/taint-and-toleration/). --> -* 了解有关节点[组件](/zh/docs/concepts/overview/components/#node-components)。 +* 进一步了解节点[组件](/zh/docs/concepts/overview/components/#node-components)。 * 阅读 [Node 的 API 定义](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#node-v1-core)。 * 阅读架构设计文档中有关 - [节点](https://git.k8s.io/community/contributors/design-proposals/architecture/architecture.md#the-kubernetes-node) + [Node](https://git.k8s.io/community/contributors/design-proposals/architecture/architecture.md#the-kubernetes-node) 的章节。 * 了解[污点和容忍度](/zh/docs/concepts/scheduling-eviction/taint-and-toleration/)。