架构14-资源与调度
1、资源模型
(1)概述
在 Kubernetes 中,资源模型是一个非常重要的概念,它涉及如何管理和分配集群中的资源,以确保 Pod 能够在最合适的节点上运行。
资源模型不仅包括物理资源,如处理器、内存、存储和网络资源,还包括各种抽象资源,如策略、依赖、权限等。
(2)广义资源 vs 狭义资源
**广义资源:**Kubernetes 系统中所有你能接触的方方面面,都被抽象成了资源。例如:
**工作负荷资源:**Pod、ReplicaSet、Service 等。
**存储资源:**Volume、PersistentVolume、Secret 等。
**策略资源:**SecurityContext、ResourceQuota、LimitRange 等。
**身份资源:**ServiceAccount、Role、ClusterRole 等。
**狭义资源:**特指能够与真实物理底层硬件对应起来的资源,如处理器资源、内存资源、磁盘存储资源等。
(3)物理资源
资源单位
处理器资源:
默认计量单位是"逻辑处理器的个数"。
如果不明确标注单位,直接写 0.5,默认单位是 Core,即 0.5 个处理器。
也可以明确使用 Millcores 为单位,例如 500 m,同样代表 0.5 个处理器,因为 1 Core = 1000 Millcores。
内存资源:
默认计量单位是 Bytes。
为了实际设置的方便,Kubernetes 还支持以 Ei、Pi、Ti、Gi、Mi、Ki 以及 E、P、T、G、M、K 为单位。
例如,Mi 表示 Mebibytes(1024×1024 Bytes),M 表示 Megabytes(1000×1000 Bytes)。
资源类型
**可压缩资源:**如处理器资源,当资源不足时,Pod 只会处于"饥饿状态",运行变慢,但不会被系统杀死。
**不可压缩资源:**如内存资源,当资源不足或超过容器声明的最大限度时,Pod 会被系统直接杀掉(Out-Of-Memory, OOM)。
(4)资源需求与配额
**资源需求:**通过 spec.containers[].resources.requests
字段设置,用于告诉调度器 Pod 需要多少资源。
**资源配额:**通过 spec.containers[].resources.limits
字段设置,用于告诉 cgroups Pod 最多可以使用多少资源。
2、服务质量与优先级
(1)概述
在 Kubernetes 中,为了更好地管理和分配集群资源,确保重要服务的稳定性和资源利用率的最大化,引入了服务质量(Quality of Service, QoS)和优先级(Priority)两个重要概念。
(2)服务质量(QoS)
服务质量是 Pod 的一个隐含属性,用于衡量 Kubernetes 在资源紧张时优先保障哪些 Pod 的运行。
Kubernetes 目前提供了三个级别的服务质量,由高到低分别为:
Guaranteed
**定义:**Pod 中所有容器都设置了 limits
和 requests
,且两者的值相等。
**特点:**这类 Pod 的资源需求非常明确,Kubernetes 会尽力保证它们的资源需求得到满足。除非 Pod 使用超过了它们的 limits
所描述的不可压缩资源,或者节点的内存压力大到 Kubernetes 已经杀光所有等级更低的 Pod 了,否则它们都不会被系统自动杀死。
**适用场景:**适合数据库应用等有状态的应用,或者是一些重要的、要保证不能中断的业务。
Burstable
**定义:**Pod 中有部分容器的 requests
值小于 limits
值,或者只设置了 requests
而未设置 limits
。
**特点:**这类 Pod 有一定的灵活性,可以在资源充足时使用更多的资源,但在资源紧张时可能会被系统降低优先级。
**适用场景:**适合大多数中间件服务,如缓存服务、消息队列等。
BestEffort
**定义:**Pod 中没有任何容器设置了 limits
和 requests
。
**特点:**这类 Pod 可以使用节点上所有可用的计算资源,但也是最不稳定的风险来源。在资源紧张时,它们最容易被系统杀掉。
**适用场景:**适合临时的、不那么重要的任务,如批处理任务、临时测试环境等。
(3)优先级(Priority)
优先级允许系统管理员自行决定 Pod 的优先级,通过类型为 PriorityClass
的资源来实现。优先级不仅影响 Pod 的调度顺序,还会影响 Kubernetes 的抢占机制。
调度影响
**高优先级 Pod:**在多个 Pod 同时被调度时,高优先级的 Pod 会优先被调度。
**低优先级 Pod:**越晚被调度的 Pod,越大概率地会因节点资源已被占用而不能成功。
抢占机制(Preemption)
**定义:**当一个设置了明确优先级的 Pod 调度失败时,Kubernetes 会在系统中寻找出一批牺牲者(Victims),把它们杀掉以便给更高优先级的 Pod 让出资源。
**原则:**在优先级低于待调度 Pod 的所有已调度的 Pod 里,按照优先级从低到高排序,从最低的杀起,直至腾出的资源可以满足待调度 Pod 的成功调度为止,或者已经找不到更低优先级的 Pod 为止。
3、驱逐机制
(1)概述
在 Kubernetes 中,驱逐机制是一种重要的资源管理手段,用于确保节点上的资源在紧张时能够合理分配,防止因为资源耗尽而导致整个节点或关键服务崩溃。
驱逐机制由 kubelet
负责执行,kubelet
是部署在每个节点上的集群管理程序,能够实时监控节点的资源使用情况。
(2)驱逐机制的触发条件
驱逐机制主要针对不可压缩资源,如内存、磁盘空间、文件系统 inode 数量等。当这些资源即将耗尽时,kubelet
会触发驱逐操作。具体的触发条件如下:
内存:
磁盘空间:
文件系统 inode 数量:
容器运行时镜像存储空间:
这些阈值可以通过 kubelet
的命令行参数进行调整,例如:
shell
复制代码
--eviction-hard=memory.available<100Mi,nodefs.available<10%,nodefs.inodesFree<5%,imagefs.available<15%
(3)驱逐机制的类型
软驱逐
软驱逐通常配置一个较低的警戒线,当资源使用率达到这个警戒线时,系统会进入一段观察期。如果资源在观察期内恢复正常,就不会启动驱逐操作。如果资源持续超过警戒线一段时间,系统会触发 Pod 的优雅退出(Graceful Shutdown),通知 Pod 进行必要的清理工作,然后自行结束。如果在优雅退出期结束后,Pod 仍未自行终止,系统会强制杀掉 Pod。
例如:
shell
复制代码
--eviction-soft=memory.available<200Mi
--eviction-soft-grace-period=memory.available=30s
--eviction-max-pod-grace-period=120
硬驱逐
硬驱逐通常配置一个较高的终止线,一旦资源使用率达到这个终止线,系统会立即强制杀掉 Pod,不理会优雅退出。
例如:
shell
复制代码
--eviction-hard=memory.available<100Mi
(4)驱逐机制的执行流程
资源监控: kubelet
持续监控节点的资源使用情况。
**触发条件判断:**当资源使用率达到软驱逐或硬驱逐的阈值时,触发驱逐操作。
选择驱逐目标: kubelet
会选择服务质量等级(QoS)较低的 Pod 进行驱逐。
**优雅退出:**对于软驱逐,系统会通知 Pod 进行优雅退出。
**强制终止:**如果 Pod 在优雅退出期内未自行终止,系统会强制杀掉 Pod。
**资源释放:**被驱逐的 Pod 被终止后,其占用的资源会被释放。
(5)驱逐机制的注意事项
**资源抖动:**资源使用率可能会出现短暂的波动,因此软驱逐机制可以帮助减少因资源抖动导致的频繁驱逐。
**资源预留:**驱逐机制不仅要考虑当前资源的释放,还要为新 Pod 的调度和旧 Pod 的运行预留足够的资源。
**参数配置:**合理的配置驱逐参数可以避免资源浪费和不必要的服务中断。
**特殊 Pod 处理:**对于由 DaemonSet
等管理的 Pod,需要特别注意驱逐后的重新调度问题,避免出现"阴魂不散"的情况。
4、 默认调度器
(1)概述
Kubernetes 的默认调度器是负责将新创建的 Pod 分配到合适的节点上运行的关键组件。调度器的设计旨在高效地处理大规模集群中的资源分配问题,同时确保服务的稳定性和资源的充分利用。
(2)调度流程
调度器的工作流程可以分为两个主要的控制循环:Informer Loop 和 Scheduler Loop 。
Informer Loop
**作用:**持续监视 etcd 中与调度相关资源(主要是 Pod 和 Node)的变化情况。
具体操作:
**Pod 变化:**当有新 Pod 生成时,将其入队(Enqueue)到调度队列中。
**Node 变化:**当有新的节点加入集群或已有的节点资源信息发生变动时,更新调度缓存中的信息。
**Scheduler Loop **
**作用:**从调度队列中取出 Pod,使用 Predicate 和 Priority 算法进行节点选择和评分,最终确定目标节点。
具体步骤:
**出队:**从调度队列中取出一个 Pod。
**Predicate 筛选:**使用一组节点过滤器(Filter)筛选出符合要求的节点。
**通用过滤策略:**检查节点是否满足 Pod 声明中需要的资源。
**卷过滤策略:**检查节点挂载的 Volume 是否存在冲突。
**节点过滤策略:**检查节点的污点与容忍度机制。
**Priority 评分:**对筛选出的节点进行评分,选择得分最高的节点。
**LeastRequestedPriority:**选择处理器和内存空闲资源最多的节点。
**BalancedResourceAllocation:**选择资源分配最均衡的节点。
**绑定:**更新 Pod 的 nodeName 字段为目标节点的名字,通知目标节点的 kubelet 创建 Pod。
(3)调度缓存
**作用:**作为两个控制循环的共享状态,避免调度器每次调度时主动轮询所有集群节点,提高调度器的执行效率。
**局限:**不能完全避免因节点信息同步不及时导致的资源变化情况,因此在 kubelet 创建 Pod 前还需要进行二次确认(Admit 操作)。
(4)乐观绑定
**作用:**提高调度器的效率,避免等待 kubelet 完成 Pod 创建后再宣告调度成功。
具体操作:
**同步更新:**在调度缓存中更新 Pod 的 nodeName 字段。
**异步更新:**在 etcd 中更新 Pod 的 nodeName 字段。
**失败处理:**如果调度失败,由 Informer 根据 Pod 的变动,将调度成功但未创建成功的 Pod 清空 nodeName 字段,重新同步回调度缓存中。
(5)扩展性
**Scheduler Framework:**通过暴露扩展点(如 Predicate、Priority 等),允许用户自定义调度逻辑。
**实现方式:**通过 Golang 的 Plugin 机制实现,需静态编译,属于高级的 Kubernetes 管理技能。
(6)关键概念
**服务质量(QoS):**Pod 的隐含属性,分为 Guaranteed、Burstable 和 BestEffort 三级。
**优先级(Priority):**通过 PriorityClass 资源实现,影响 Pod 的调度顺序和抢占机制。
**驱逐机制(Eviction):**当节点资源不足时,根据 QoS 和优先级选择牺牲的 Pod,以保证重要服务的稳定。