节点池
节点池是集群中一个或一组节点的逻辑集合,一个集群中可以创建多个不同配置和类型的节点池。节点池的配置包含节点的属性,例如节点规格、可用区、标签、污点等。这些属性可以在创建节点池时指定,也可以在创建完成后进行编辑修改。 通过节点池,您可以在同一个集群中实现不同类型的节点混合部署管理。
- 同一个集群中,允许创建不同操作系统镜像(ContainerOS、Alibaba Cloud Linux、Windows等)的节点池。
- 同一个集群中,允许创建不同容器运行时(containerd、Docker、安全沙箱)的节点池。
- 同一个集群中,允许创建不同计费类型(按量付费、包年包月、抢占式实例)的节点池。
- 同一个集群中,允许创建多个开启自动弹性伸缩的节点池。
k8s通过将容器放入在节点(Node)上运行的 Pod 中来执行你的工作负载。 节点可以是一个虚拟机或者物理机器,取决于所在的集群配置。 每个节点包含运行Pod负责管理。
Kubernetes 会在内部创建一个 Node 对象作为节点的表示。Kubernetes 检查 kubelet 向 API 服务器注册节点时使用的 metadata.name 字段是否匹配。 如果节点是健康的(即所有必要的服务都在运行中),则该节点可以用来运行 Pod。 否则,直到该节点变为健康之前,所有的集群活动都会忽略该节点。
节点状态
一个节点的状态包含以下信息:
- 地址(Addresses)
- 状况(Condition)
- 容量与可分配(Capacity)
- 信息(Info)
地址
- HostName:由节点的内核报告。可以通过 kubelet 的
--hostname-override参数覆盖。 - ExternalIP:通常是节点的可外部路由(从集群外可访问)的 IP 地址。
- InternalIP:通常是节点的仅可在集群内部路由的 IP 地址。
状况
conditions 字段描述了所有 Running 节点的状况。状况的示例包括:
| 节点状况 | 描述 |
|---|---|
Ready | 如节点是健康的并已经准备好接收 Pod 则为 True;False 表示节点不健康而且不能接收 Pod;Unknown 表示节点控制器在最近 node-monitor-grace-period 期间(默认 40 秒)没有收到节点的消息 |
DiskPressure | True 表示节点存在磁盘空间压力,即磁盘可用量低, 否则为 False |
MemoryPressure | True 表示节点存在内存压力,即节点内存可用量低,否则为 False |
PIDPressure | True 表示节点存在进程压力,即节点上进程过多;否则为 False |
NetworkUnavailable | True 表示节点网络配置不正确;否则为 False |
容量(Capacity)与可分配(Allocatable)
这两个值描述节点上的可用资源:CPU、内存和可以调度到节点上的 Pod 的个数上限。
capacity 块中的字段标示节点拥有的资源总量。 allocatable 块指示节点上可供普通 Pod 消耗的资源量。
信息(Info)
Info 指的是节点的一般信息,如内核版本、Kubernetes 版本(kubelet 和 kube-proxy 版本)、 容器运行时详细信息,以及节点使用的操作系统。 kubelet 从节点收集这些信息并将其发布到 Kubernetes API。
心跳
Kubernetes 节点发送的心跳帮助你的集群确定每个节点的可用性,并在检测到故障时采取行动。
对于节点,有两种形式的心跳:
- 更新节点的
.status kube-node-lease名字空间中的Lease(租约)对象。 每个节点都有一个关联的 Lease 对象。 与 Node 的.status更新相比,Lease 是一种轻量级资源。 使用 Lease 来表达心跳在大型集群中可以减少这些更新对性能的影响。
kubelet 负责创建和更新节点的 .status,以及更新它们对应的 Lease。
- 当节点状态发生变化时,或者在配置的时间间隔内没有更新事件 时,kubelet 会更新
.status。.status更新的默认间隔为 5 分钟(比节点不可达事件的 40 秒默认超时时间长很多)。 kubelet会创建并每 10 秒(默认更新间隔时间)更新 Lease 对象。 Lease 的更新独立于 Node 的.status更新而发生。 如果 Lease 的更新操作失败,kubelet 会采用指数回退机制,从 200 毫秒开始重试, 最长重试间隔为 7 秒钟。
节点控制器
节点控制器在节点的生命周期中扮演多个角色。 第一个是当节点注册时为它分配一个 CIDR 区段(如果启用了 CIDR 分配)。
第二个是保持节点控制器内的节点列表与云服务商所提供的可用机器列表同步。 如果在云环境下运行,只要某节点不健康,节点控制器就会询问云服务是否节点的虚拟机仍可用。 如果不可用,节点控制器会将该节点从它的节点列表删除。
第三个是监控节点的健康状况。节点控制器负责:
- 在节点不可达的情况下,在 Node 的
.status中更新Ready状况。 在这种情况下,节点控制器将 NodeReady 状况更新为Unknown。 - 如果节点仍然无法访问:对于不可达节点上的所有 Pod 触发API 发起的逐出操作。 默认情况下,节点控制器在将节点标记为
Unknown后等待 5 分钟提交第一个驱逐请求。
默认情况下,节点控制器每 5 秒检查一次节点状态,可以使用 kube-controller-manager 组件上的 --node-monitor-period 参数来配置周期。
资源容量跟踪
Node 对象会跟踪节点上资源的容量(例如可用内存和 CPU 数量)。 通过自注册机制生成的 Node 对象会在注册期间报告自身容量。 如果手动添加了 Node, 你就需要在添加节点时手动设置节点容量。
Kubernetes调度器保证节点上有足够的资源供其上的所有 Pod 使用。 它会检查节点上所有容器的请求的总和不会超过节点的容量。 总的请求包括由 kubelet 启动的所有容器,但不包括由容器运行时直接启动的容器, 也不包括不受 kubelet 控制的其他进程。
查看节点资源请求量和使用量
- CPU请求量 = SUM(当前节点上所有Pod的CPU请求值)/ 节点可分配的CPU
- CPU使用量 = SUM(当前节点上所有Pod的CPU实际使用量)/ 节点可分配的CPU
- 内存请求量= SUM(当前节点上所有Pod的内存请求值)/ 节点可分配的内存
- 内存使用量 = SUM(当前节点上所有Pod的内存实际使用量)/ 节点可分配的内存
- 节点可分配资源(Allocatable) = 总资源(Capacity)-预留资源(Reserved)-驱逐阈值(Eviction-Threshold)
- 根据可分配资源,您可以为业务Pod设置所需资源(request),节点上所有业务Pod所需资源之和不应该大于节点的可分配资源,否则业务Pod会因节点容量不足而调度失败。
- 当节点的请求量达到100%时,新的Pod不会被调度到当前节点上。
节点伸缩
节点池扩容顺序策略
-
随机策略:存在多个可扩容节点池时,从中任意选择一个节点池进行扩容。
-
默认策略:存在多个可扩容节点池时,从中选择一个资源浪费最少的节点池进行扩容。
-
优先级策略:存在多个可扩容节点池时,会按照您自定义的顺序选择优先级高的节点池进行扩容。
有跨可用区节点的集群发生故障时,集群会如何决定节点驱逐策略?
通常情况下,当节点发生故障时,节点Controller会驱逐不健康的节点,驱逐速率--node-eviction-rate默认为0.1个/秒,即每10秒钟内至多从一个节点驱逐Pod。
而一个存在多个可用区节点的ACK集群发生故障时,节点Controller会根据可用区的状态以及集群大小来决定如何驱逐。
可用区故障分为三种情况。
- FullDisruption:该可用区不存在正常节点,且至少有1个异常节点。
- PartialDisruption:该可用区至少有2个异常节点,并且异常节点的比例,即
(异常节点/(异常节点+正常节点)),大于0.55。 - Normal:除FullDisruption和PartialDisruption两种情况外,其余均为Normal状态。
在此场景下,集群大小分为两种情况:
- 大集群:大于50个节点的集群。
- 小集群:小于等于50个节点的集群。
在三种故障状态下,节点Controller的驱逐速率计算方式如下:
-
如果所有可用区都处于FullDisruption状态时,则关闭系统所有可用区的驱逐功能。
-
如果不是所有可用区都处于FullDisruption状态,驱逐速率通过以下方式确定。
- 如果某个可用区处于FullDisruption状态,那么驱逐速率设定为正常值(0.1),不受集群大小影响。
- 如果某个可用区处于PartialDisruption状态,那么驱逐速率受集群大小因素影响。在大集群中,该可用区的驱逐速率为0.01;在小集群中,该可用区的驱逐速率为0,即不进行驱逐。
- 如果某个可用区处于Normal状态,那么驱逐速率设定为正常值(0.1),不受集群大小因素影响。