极致成本优化背景下,如何通过优化k8s调度器实现计算资源的按需付费(四)

原创 吴就业 174 0 2024-02-04

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/c754705b30434b4ebeeec4504ee4a492

作者:吴就业
链接:https://wujiuye.com/article/c754705b30434b4ebeeec4504ee4a492
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

之四:GKE节点自动扩缩容实验

实验目的

验证gce的自动缩容时机以及扩容需要的时长:扩容一个节点需要等待多长时间,一个节点在没有Pod的情况下多久后会回收。结合scheduler-plugins框架验证。由于scheduler-plugins只是在Score阶段对节点打分,并未在其它阶段阻止Pod调度到分数为0的Node上,例如基于目标负载感知调度,当所有Node的负载都达到目标负载后,即便节点的requests满足Pod所需,是否能走扩容节点,而不是硬塞到现有节点上。

实施步骤

集群配置:

一、验证扩容

demo配置requests让每个pod只能部署到一个节点上。

requests:
   cpu: 600m
   memory: 1000Mi

先3个副本把固定节点占满。 扩容节点耗时:

扩展第1个节点 扩展第2个节点 扩展第3个节点 扩展第3个节点
耗时(秒) 58 57 74 达到上限,无法扩
平均耗时(秒) 63秒(1分钟)

二、验证缩容

每缩容1个副本,观察节点多久后回收。

缩容第1个节点 缩容第2个节点 缩容第3个节点
延迟 10分40秒 10分50秒 10分50秒
平均延迟 10分50秒 (因为是用计时器算的,秒数部分不精准)

缩容一个节点的时间几乎是固定的,大概11分钟。根据官方文档的描述:https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#how-does-scale-down-work,这个应该是可以在Node资源配置的。

cluster-autoscaler缩容时间配置

另外有一个坑,缩容如果Pod不是在弹性节点上的,弹性节点就无法被回收,而固定节点又会空置。可能需要考虑怎么控制Demployment控制器在缩容的时候优先缩弹性节点上的Pod。

三、requests未超,目标负载已超,是否能扩

demo配置requests。

requests:
   cpu: 100m
   memory: 100Mi

初始副本数15,Pod调度到三个固定节点的分布如下:

节点1(ncck) 节点2(71zk) 节点3(r408)
Pod数 6 7 2

集群真实负载情况:

wujiuye@wujiuyedeMacBook-Pro cloud_native % kubectl top node
NAME                                                 CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
gke-nebula-test-cluster-default-pool-521b9803-71zk   78m          8%     1024Mi          36%       
gke-nebula-test-cluster-default-pool-521b9803-ncck   55m          5%     1066Mi          37%       
gke-nebula-test-cluster-default-pool-521b9803-r408   66m          7%     1338Mi          47% 

每个节点抽取一个demo Pod,把节点的总负载调超30%。

wujiuye@wujiuyedeMacBook-Pro cloud_native % kubectl top node
NAME                                                 CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
gke-nebula-test-cluster-default-pool-521b9803-71zk   377m         40%    1027Mi          36%       
gke-nebula-test-cluster-default-pool-521b9803-ncck   355m         37%    1064Mi          37%       
gke-nebula-test-cluster-default-pool-521b9803-r408   366m         38%    1350Mi          48%   

增加副本数,看新的Pod是否触发扩容。

结果:否,未触发节点扩容。节点得分虽然很低,但没有插件阻止调度。

原因是,只有Pod的状态为Pending才会走节点自动扩缩容。

Pod一开始也是Pending状态,什么条件下才会触发Node扩容?

根据文档的描述,Pod只有处理Pending状态,并且处理Pending状态的原因是Unschedulable,那么才会触发节点扩容,例如:

status:
  phase: Pending
  conditions:
    - type: PodScheduled
      status: 'False'
      lastProbeTime: null
      lastTransitionTime: '2024-01-25T06:47:58Z'
      reason: Unschedulable
      message: >-
        0/3 nodes are available: 3 Insufficient cpu. preemption: 0/3 nodes are
        available: 3 No preemption victims found for incoming pod..
  qosClass: Burstable

结论

#云原生

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

我开源了一款k8s命令行工具,提供命令输入提示和自动补全功能

kubectlx是一款基于go-prompt库开发的k8s命令行工具,目的是简化kubectl工具的一些常用命令的使用, 并提供命令输入提示、自动补全。

Serverless服务日记收集,你们采用哪种方案?

Serverless帮助我们实现了自动扩缩容,但要实现真正的按需付费,就要使用弹性的物理节点,例如AWS的Fargate,使用EKS将Pod调度到Fargate上。这也注定了不会有固定的Node去运行Pod,因此在Node上以DaemonSet部署日记收集容器的方案就走不通了。

为什么java不适合云原生

云原生的优势在于利用Serverless技术优化基础设施成本,要求应用启动速度快且内存占用低。然而,Java应用在自动弹性扩缩容和内存消耗方面存在问题。文章以部署个人项目的视角,通过比较小明使用Go语言和小聪使用Java语言开发的博客系统的部署情况,展示了Java的启动速度慢和内存占用大的不适应性。

极致成本优化背景下,如何通过优化k8s调度器实现计算资源的按需付费(三)

本篇介绍的内容是scheduler-plugins框架的TargetLoadPacking插件,这是一个k8s调度框架的评分插件。TargetLoadPacking即目标负载调度器,用于控制节点的CPU利用率不超过目标值x%(例如65%),通过打分让所有cpu利用率超过x%的都不被选中。目标负载调度器只支持CPU。

极致成本优化背景下,如何通过优化k8s调度器实现计算资源的按需付费(二)

本篇介绍的内容是scheduler-plugins框架的LoadVariationRiskBalancing插件,这是一个k8s调度框架的评分插件,基于request、均值和标准差的K8s负载感知调度器。 我们通过实验去理解和验证该插件实现的负载感知均衡调度算法。

极致成本优化背景下,如何通过优化k8s调度器实现计算资源的按需付费(一)

在降低增笑的大背景下,如何在保证稳定性的前提下,做到极致压缩k8s资源的使用,实现基础设施真正的按需付费,是我们云原生项目的目标之一。要实现如Railway这种产品的基础设施按实际使用付费,不能简单的使用云Serverless产品,因为这些产品都有最低限额的要求,例如阿里云最低限制要求Pod至少0.25cpu+0.5g内存,但其实大多数应用这个配额都用不到,大量的时间cpu负载几乎为0,内存消耗可能也就几十M(Java应用除外),大量的低使用率的Pod会造成资源的浪费。