节点是 Kubernetes 中的作业机器,先前被称为 minion
。节点可以是 VM 或物理机,具体取决于集群。每个节点都包含运行 Pod(敬请期待~~) 所需的服务,并由主组件管理。节点上的服务包括容器运行时,kubelet 和 kube-proxy。有关更多详细信息,请参见体系结构设计文档中的 Kubernetes 节点部分。
节点状态
节点的状态包含以下信息:
可以使用以下命令显示节点状态和有关节点的其他详细信息:
kubectl describe node <insert-node-name-here>
每个部分将在下面详细说明。
地址
这些字段的用户因我们的云提供商或裸机配置而异。
- HostName;节点内核报告的主机名。可以通过 kubectl 的
--hostname-override
参数覆盖; - ExternalIP:通常是可外部路由的节点的 IP 地址(可从集群外部获得);
- InternalIP:通常仅在集群内可路由的节点的 IP 地址。
条件
conditions
字段描述所有 Running
的节点的状态。条件的示例包括:
节点条件 | 描述 |
---|---|
Ready | 如果节点运行状态良好并准备好接受 Pod,则为 True ;如果节点运行状况不佳且不接受 Pod,则为 False ;如果在最后一个 node-monitor-grace-period 中未从节点听到节点控制器的消息,则为 Unknown (默认值为 40 秒)。 |
MemoryPressure | 如果节点内存上存在压力(即节点内存不足),则为 True ;否则为 False 。 |
PIDPressure | 如果进程上存在压力,即节点上的进程太多,则为 True ;否则为 False 。 |
DiskPressure | 如果磁盘大小受到压力(即磁盘容量低),则为 True ;否则为 False 。 |
NetworkUnavailable | 如果未正确配置节点的网络,则为 True ;否则为 False 。 |
节点条件表示为 JSON 对象。例如,以下响应描述了一个健康的节点。
"conditions": [
{
"type": "Ready",
"status": "True",
"reason": "KubeletReady",
"message": "kubelet is posting ready status",
"lastHeartbeatTime": "2019-06-05T18:38:35Z",
"lastTransitionTime": "2019-06-05T11:41:27Z"
}
]
如果 “就绪” 状态的状态保持 Unknown
或 False
的时间超过 pod-eviction-timeout
(传递给 kube-controller-manager(敬请期待~~) 的参数)的时间,则节点上的所有 Pod 都将由 Node Controller 安排删除。默认逐出超时持续时间为五分钟。在某些情况下,当节点不可访问时,apiserver 无法与节点上的 kubelet 通信。在重新建立与 apiserver 的通信之前,无法将删除 pod 的决定传达给 kubelet。同时,计划删除的 Pod 可能会继续在分区节点上运行。
在 1.5 之前的 Kubernetes 版本中,节点控制器将从 apiserver 中强制删除(敬请期待~~)这些无法访问的 Pod。但是,在 1.5 及高版本中,节点控制器在确认已停止在集群中运行之前不会强制删除它们。我们可以看到处于不可触及节点上的 Pod 处于 Terminating
或 Unknown
状态。如果 Kubernetes 无法从基础架构推断出某个节点永久离开集群的情况,则集群管理员可能需要手动删除该节点对象。从 Kubernetes 中删除节点对象会导致节点上运行的所有 Pod 对象从 apiserver 中删除,并释放它们的名称。
节点生命周期控制器会自动创建代表条件的污点(敬请期待~~)。在将 Pod 分配给节点时,调度程序会考虑节点的污点。Pod 还可以具有一定的容忍度,从而可以容热节点的污点。
容量及可分配块
描述节点上可用的资源:CPU、内存和可调度到节点上的 Pod 的最大数量。
容量块中的字段指示节点拥有的资源总数。可分配块指示节点上可供普通 Pod 消耗的资源量。
在学习如何在节点上保留计算资源(敬请期待~~)的同时,我们可以阅读有关容量和可分配资源的更多信息。
信息
描述有关节点的常规信息,例如内核版本、Kubernetes 版本(kubelet 和 kube-proxy 版本)、Docker 版本(如果使用的话)和操作系统名称。该信息由 Kubelet 从节点收集。
管理
与 Pod 和 Service 不同,节点不是 Kubernetes 固有创建的:它是由 Google Compute Engine 等云提供商在外部创建的,或者它存在于我们的物理机或虚拟机池中。因此,当 Kubernetes 创建一个节点时,它将创建一个代表该节点的对象。创建后,Kubernetes 将检查该节点是否有效。例如,如果尝试从以下内容创建节点:
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "10.240.79.157",
"labels": {
"name": "my-first-k8s-node"
}
}
}
Kubernetes 在内部创建一个节点对象(表示形式),并基于 metadata.name
字段通过运行状况检查来验证该节点。如果节点有效(即,如果所有必需的服务都在运行),则可以运行 Pod。否则,任何集群活动都将忽略它,知道它变为有效。Node 对象的名称必须是有效的 DNS 子域名。
注意:Kubernetes 将对象保留为无效节点,并继续检查以查看其是否有效。我们必须显式删除 Node 对象才能停止该过程。
目前,有三个与 Kubernetes 节点接口交互的组件:节点控制器、kubelet 及 kubectl。
节点控制器
节点控制器是 Kubernetes 主组件,它管理节点的各个方面。
节点控制器在节点的生命中扮演者多种角色。第一个是在注册节点时将 CIDR 块分配给节点(如果 CIDR 分配已开启)。
第二个是使节点控制器的内部节点列表与云提供商的可用计算机列表保持最新。在云环境中运行时,只要节点运行状况不佳,节点控制器就会询问云提供商,该节点的 VM 是否仍然可用。如果不是,则节点控制器从其节点列表中删除该节点。
第三是监控节点的运行状况。节点控制器负责在节点变得不可访问时将 NodeStatus 的 NodeReady 条件更新为 ConditionUnknown(即,由于某些原因,例如由于节点关闭,节点控制器停止接收心跳信号),并且随后将其中的所有 Pod 逐出。节点(使用正常终止)如果该节点继续无法触及。(默认超时为 40 秒,开始报告 ConditionUnknown,之后为 5m,开始逐出 Pod。)节点控制器每隔 --node-monitor-period
秒检查一次每个节点的状态。
心跳检测
Kubernetes 节点发送的心跳有助于确定节点的可用性。心跳有两种形式:更新 NodeStatus
和 Lease 对象。每个节点在 kube-node-lease
命名空间中都有一个关联的 Lease 对象。租用是一种轻量级的资源,可在集群扩展时提高节点心跳的性能。
kubelet 负责创建和更新 NodeStatus
和 Lease 对象。
- 当状态发生更改或在配置的时间间隔内没有更新时,kubelet 会更新
NodeStatus
。NodeStatus
更新的默认间隔为 5 分钟(比无法访问的节点的 40 秒默认超时长得多); - Kubelet 会每 10 秒(默认更新间隔)创建并更新其 Lease 对象。租约更新独立于
NodeStatus
更新发生。如果 Lease 更新失败,则 kubelet 将以 200 毫秒开始的指数补偿重试,并以 7 秒为上限。
可靠性
在 Kubernetes 1.4 中,我们更新了节点控制器的逻辑以更好地处理大量节点无法连接到主节点的情况(例如,由于主节点存在网络问题)。从 1.4 开始,节点控制器在做出关于 Pod 逐出的决定时会查看集群中所有节点的状态。
在大多数情况下,节点控制器将逐出速率限制为 --node.eviction-rate
(默认为 0.1)每秒,这意味着每 10 秒不会从超过 1 个节点上逐出 Pod。
当给定可用性区域中的节点不正常时,节点驱逐行为会更改。节点控制器同时检查区域中有多少百分比的节点不正常(NodeReady 条件为 ConditionUnknown 或 ConditionFalse)。如果不健康节点的比例至少为 --unhealthy-zone-threshold
(默认值为 0.55),则逐出速率会降低:如果集群较小,即,集群的大小小于或等于 --large-cluster-size-threshold
节点(默认为 50),然后停止逐出,否则逐出速率降低为 --secondary-node-eviction-rate
(默认为 0.01)每秒。对每个可用区实施这些策略的原因是,一个可用区可能会与主分区分开,而其他可用区仍保持连接。如果我们的集群没有跨越多个云提供商可用性区域,则只有一个可用性区域(整个集群)。
将节点分布在各个可用区域上的一个关键原因是,当整个区域出现故障时,可以将工作负载转移到正常区域。因此,如果区域中的所有节点都不正常,则节点控制器将以 --node-eviction-rate
的正常速率逐出。当所有区域都完全不健康时(即集群中没有健康的节点)。便是最极端的情况。在这种情况下,节点控制器会认为主连接存在问题,并停止所有逐出,直到恢复某些连接为止。
从 Kubernetes 1.6 开始,Node Pod 不容忍污点时,NodeController 还负责驱逐在具有 NoExecute
污点的节点上运行的 Pod。另外,作为默认情况下禁用的 Alpha 功能,NodeController 负责添加与节点问题(例如,节点不可达或未就绪)相对应的污点。有关 NoExecute
污点和 alpha 功能的详细信息,请参考该文档(敬请期待~~)。
从版本 1.8 开始,可以使节点控制器负责创建代表节点条件的污点。这是 1.8 版本的 Alpha 功能。
节点自注册
当 kubelet 标志 --register-node
为 true
(默认值)时,kubelet 将尝试向 API 服务器注册自身。这是大多数发行版使用的首选模式。
对于自我注册,kubelet 使用以下选项启动:
--kubeconfig
- 用于向 apiserver 进行身份验证的凭据的路径;--cloud-provider
- 如何与云提供商通讯以获取有关其自身的元数据;--register-node
- 自动向 API 服务器注册;--register-with-taints
- 使用给定的污点列表(用逗号分隔的<key>=<value>:<effect>
)注册节点。如果register-node
为 false,则不进行操作;- ```node-ip` - 节点的 IP 地址;
--node-labels
- 在集群中注册节点时要添加的标签(请参阅 1.13+ 中由 NodeRestriction 准许插件(敬请期待~~)实施的标签限制);--node-status-update-frequency
- 指定 kubelet 多久将节点状态发布到主节点。
启用节点授权模式(敬请期待~~)和 NodeRestriction 准许插件(敬请期待~~)时,仅授权 kubelet 创建/修改其自己的 Node 资源。
手工管理节点
集群管理员可以创建和修改节点对象。
如果管理员希望手动创建节点对象,请设置 kubelet 标志 --register-node=false
。
管理员可以修改节点资源(无论 --register-node
的设置如何)。修改包括在节点上设置标签并将其标记为不可计划。
节点上的标签可以与 Pod 上的节点选择器结合使用,以控制调度,例如限制 Pod 仅能在节点的子集上运行。
将节点标记为不可调度可防止将新 Pod 调度到该节点,但不会影响该节点上的任何现有 Pod。这对于节点重新启动等之前的准备步骤很有用。例如,要将节点标记为不可调度,请运行以下命令:
kubectl cordon $NODENAME
注意:由 DaemonSet 控制器创建的 Pod 绕过 Kubernetes 调度程序,并且不遵守节点上的 unschedulable 属性。这假定即使在准备重新引导时耗尽了应用,守护进程也属于该计算机。
警告:
kubectl cordon
将节点标记为 “不可调度”,其副作用是服务控制器从先前符合条件的任何 LoadBalancer 节点目标列表中删除该节点,从而有效地从警戒节点中删除了传入的负载均衡器流量。
节点容量
节点的容量(CPU 数量和内存量)是节点对象的一部分。通常,节点在创建节点对象时会注册自己并报告其容量。如果要执行手动节点管理,则在添加节点时会注册自己并报告其容量。如果要执行手动节点管理,则在添加节点时需要设置节点容量。
Kubernetes 调度程序可确为节点上的所有 Pod 提供足够的资源。它检查节点上容器请求的总和不大于节点容量。它包括由 kubelet 启动的所有容器,但不包括由容器运行时直接启动的容器,也不包括在容器外部运行的任何进程。
如果要为非 Pod 进程显式保留资源,请按照该教程为系统守护进程保留资源(敬请期待~~)。
节点拓扑
功能状态
:Kubernetes v1.18
alpha
如果启用了 TopologyManager
特性之门(敬请期待~~),则 kubelet 可以在做出资源分配决策时使用拓扑提示。
API 对象
节点是 Kubernetes REST API 中的顶级资源。有关 API 对象的更多详细信息,请参见:节点 API 对象。
下一步是什么
- 了解节点组件
- 阅读有关节点级拓扑的信息:控制节点上的拓扑管理策略(敬请期待~~)