背景
云原生这个词想必大家应该不生疏了,容器是云原生的重要基石,而 Kubernetes 通过这几年的疾速迭代倒退曾经成为容器编排的事实标准了。越来越多的公司不论是大公司还是中小公司曾经在他们的生产环境中开始应用 Kubernetes, 原生 Kubernetes 尽管曾经提供了一套十分残缺的资源调度及治理计划然而在理论应用过程中还是会碰到很多问题:
- 集群节点负载不平衡的问题
- 业务创立 Pod 资源申请不合理的问题
- 业务如何更疾速的扩容问题
- 多租户资源抢占问题
这些问题可能是大家在应用 Kubernetes 的过程中应该会常常遇到的几个比拟典型的资源问题,接下来咱们将别离介绍在腾讯外部是如果解决和优化这些问题的。
集群节点负载不平衡的问题
咱们晓得 Kubernetes 原生的调度器多是基于 Pod Request 的资源来进行调度的,没有依据 Node 以后和过来一段时间的实在负载状况进行相干调度的决策。这样就会导致一个问题在集群内有些节点的残余可调度资源比拟多然而实在负载却比拟高,而另一些节点的残余可调度资源比拟少然而实在负载却比拟低, 然而这时候 Kube-scheduler 会优先将 Pod 调度到残余资源比拟多的节点上(依据 LeastRequestedPriority 策略)。
如上图,很显然调度到 Node1 是一个更优的抉择。为了将 Node 的实在负载状况加到调度策略里,防止将 Pod 调度到高负载的 Node 上,同时保障集群中各 Node 的实在负载尽量平衡,咱们扩大了 Kube-scheduler 实现了一个基于 Node 实在负载进行预选和优选的动静调度器(Dynamic-scheduler)。
Dynamic-scheduler 在调度的时候须要各 Node 上的负载数据,为了不阻塞动静调度器的调度这些负载数据,须要有模块定期去收集和记录。如下图所示 node-annotator 会定期收集各节点过来 5 分钟,1 小时,24 小时等相干负载数据并记录到 Node 的 annotation 里,这样 Dynamic-scheduler 在调度的时候只须要查看 Node 的 annotation 便能很快获取该节点的历史负载数据。
为了防止 Pod 调度到高负载的 Node 上,须要先通过预选把一些高负载的 Node 过滤掉,如下图所示(其中的过滤策略和比例是能够动静配置的,能够依据集群的理论状况进行调整)Node2 过来 5 分钟的负载,Node3 过来 1 小时的负载多超过了对应的域值所以不会参加接下来的优选阶段。
同时为了使集群各节点的负载尽量平衡,Dynamic-scheduler 会依据 Node 负载数据进行打分, 负载越低打分越高。如下图所示 Node1 的打分最高将会被优先调度(这些打分策略和权重也是能够动静配置的)。
Dynamic-scheduler 只能保障在调度的那个时刻会将 Pod 调度到低负载的 Node 上,然而随着业务的高峰期不同 Pod 在调度之后这个 Node 可能会呈现高负载。为了防止因为 Node 的高负载对业务产生影响咱们在 Dynamic-scheduler 之外还实现了一个 Descheduler,它会监控 Node 的高负载状况将一些配置了高负载迁徙的 Pod 迁徙到负载比拟低的 Node 上。
业务如何更疾速的扩容问题
业务上云的一个重要劣势就是在云上能实现更好的弹性伸缩,Kubernetes 原生也提供了这种横向扩容的弹性伸缩能力(HPA)。然而官网的这个 HPA Controller 在实现的时候用的是一个 Gorountine 来解决整个集群的所有 HPA 的计算和同步问题,在集群配置的 HPA 比拟多的时候可能会导致业务扩容不及时的问题,其次官网 HPA Controller 不反对为每个 HPA 进行独自的个性化配置。
为了优化 HPA Controller 的性能和个性化配置问题,咱们把 HPA Controller 独自抽离进去独自部署。同时为每一个 HPA 独自配置一个 Gorountine,并且每一个 HPA 多能够依据业务的须要进行独自的配置。
其实仅仅优化 HPA Controller 还是不能满足一些业务在业务顶峰时候的一些需要,比方在业务做流动的时候心愿在流量高峰期之前就可能把业务扩容好。这个时候咱们就须要一个定时 HPA 的性能,为此咱们定义了一个 CronHPA 的 CRD 和 CronHPA Operator。CronHPA 会在业务定义的工夫进行扩容和缩容,同时还能和 HPA 一起配合工作。
业务创立 Pod 资源申请不合理的问题
通过 Dynamic-scheduler 和 Descheduler 来保障集群各节点的负载平衡问题。然而我可能会面临另一个比拟头疼的问题就是集群的整体负载比拟低然而可调度资源曾经没有了,从而导致 Pod Pending。这个往往是因为 Pod 资源申请不合理或者业务顶峰时段不同所导致的,那咱们是否能够依据 Node 负载状况对 Node 资源进行肯定比例的超卖呢。于是咱们通过 Kubernetes 的 MutatingWebhook 来截获并批改 Node 的可调度资源量的形式来对 Node 资源进行超卖。
这里须要留神的是节点的超卖管制须要比拟灵便不能一概而论,比方负载高的 Node 超卖比例应该要设置比拟小或者不能设置超卖。
多租户资源抢占问题
当平台用户增多的时候,如果对资源不做任何管制那么各租户之间资源抢占是不可避免的。Kubernetes 原生提供的 ResourceQuota 能够提供 Namespace 级别对资源配额限度。然而腾讯外部资源估算治理通常是按产品维度,而一个产品可能会包含很多 Namespace 的显然 ResourceQuota 不太适宜这种场景。其次 ResourceQuota 只有资源限度性能不能做资源预留,当业务要做流动的时候不能保障流动期间有足够的资源能够应用。
为了实现一个产品维度且有资源预留性能的配额治理性能,咱们设计了一个 DynamicQuota 的 CRD 来治理产品在各集群的配额。如下图所示产品 2 在各集群所占的配额资源其它产品多无奈应用。
如果一个产品占用配额始终不应用就可能会导致平台资源的节约,因而咱们在产品配额预留的根底上提供了在不同产品间配额借调的性能。如下图所示产品 1 临时不必的配额能够借调给产品 2 长期应用。
当平台有多集群的时候,产品配额须要如何调配。为了简化配下发操作,如下图所示管理员在下发产品配额的时候只需配置一个该产品的配额总量,配额下发模块会依据产品目前在各集群的应用状况按比例调配到各个集群。
产品在各集群的资源应用状况是会时刻变动的,所以产品在各集群配额也须要依据业务的应用状况进行动静的调整。如下图所示产品在集群 2 中的配额曾经快用完的时候,配额调整模块会动静的把配额从应用不多的集群 1 和集群 3 调到集群 2。
在线业务和离线业务混合部署是云平台的发展趋势,所以咱们在设计配额治理的时候也把在离线配额管制思考进去了。如下图所示咱们在集群维度加了一个离线配额管制,一个集群的离线业务资源应用不能超过该集群总资源的 30%(这个比例能够依据理论状况进行调整)。其次一个产品的在线业务和离线业务配额之和又不能超过产品在该集群的总配额。
总结
下面提到的计划只是简略说了一下咱们的一些解决问题的思路,其实在真正运作的过程中还有很多细节须要思考和优化。比方:下面提到的产品配额治理如果一个产品的配额有余了,这时候业务有顶峰须要进行 HPA 扩容,这时候配额治理模块须要对这种扩容优化并放行。
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!