草庐IT

也许,这样理解K8s的Pod自动化扩缩容机制更容易

翟志军 2023-03-28 原文

本文尝试以通俗的方式向读者介绍K8s的Pod的自动化横向扩缩容的领域模型。其实是以领域驱动设计(DDD)的思考方式来学习一项技术。希望能对读者帮助。

问题是什么

当要理解一个解决方案时,我们从问题域开始理解,会更容易。

比如存在一个场景:基于Pod的CPU使用率进行自动化扩容。当一个Pod的CPU使用率大于60%,并持续15秒时,我们就希望Pod的数量从10个扩到13个。

要实现这个场景,我们推断K8s应该存在一种机制方便我们实现这个场景。这种机制就是HPA(Horizontal Pod Autoscaler)。

换位思考一下,如果你是HPA机制的使用者,你会如何使用HPA呢?

你可能会配置如下:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60

(如果看不懂,也没有关系,你只需要知道,你可以通过代码来定义HPA的行为)

作为用户,你只需要通过YAML文件定义清楚你的期望就可以了。至于如何实现,是由HPA机制的实现者实现的。

就好比司机开车过程中是不需要考虑动力系统是由电机实现的,还是由柴油引擎实现的。这就是“接口是用户的”的含义了。当然,作为汽车的设计者,你就必须考虑动力系统的设计与实现。

同样的,作为K8s的设计者,就必须考虑HPA机制的设计与实现。

当用户通过kubectl apply -f hpa.yaml命令部署HPA到K8s中时,我们的K8s该做什么呢?它需要考虑以下问题:

  1. 我该如何拿到用户Pod的某一个指标的值呢?
  2. 多久拿一次指标呢?
  3. 当这个指标不是CPU,内存等资源指标,而是应用本身的自定义指标呢?如果指标数据甚至不在K8s内部呢?
  4. Pod本来已经是由控制器控制的了,我们是该控制控制器去完成工作,还是直接控制Pod去完成?
  5. 当用户需要根据多个指标的值共同决定扩容时,我们该如何权衡其中的策略?
  6. 如果Pod中有多个容器,如何根据其中一个容器的指标进行扩容?
  7. 以上说的都是扩容,如何缩容呢?
  8. 缩容太快了,怎么办?即如何保证缩容时的稳定性?

笔者对以上相对口语的表述进行抽象。当我们作为K8s的HPA的设计者与实现者时,我们需要考虑以下问题:

  1. 指标来源问题;
  2. 指标的数量问题:即不仅只支持针对一个指标的扩缩容;
  3. 指标类型支持问题:资源指标、自定义指标、外部指标;
  4. Pod扩缩的控制器实现;
  5. 自定义Pod扩缩行为:扩容行为应该可以由用户自定义。

接下来我们分别看下K8s是如何解决以上问题的。

指标来源与指标类型

HPA控制器会从Metrics API中获取指标。而Metrics API根据不同的指标类型去不同的Metrics API的实现中去获取指标。

Untitled.png

Metrics API支持三类指标:

  • 资源指标:CPU和内存的使用率指标,由Metrics Server提供。Metrics Server需要单独安装;
  • 自定义指标:比如应用的连接数大小。最终由你的Custom Metrics API的实现者提供;
  • 外部自定义指标:与K8s 对象无关的自定义指标。

自定义指标与外部自定义指标的区别是该自定义指标是否来自于与应用同处于同一个K8s集群。

虽然定义是这样,这个界线也可以被打破,如下图:

Untitled 1.png

Pod扩缩的控制器实现及自定义Pod扩缩行为

当HPA拿到指标后,在哪里,又该如何实现对Pod的数量的控制呢?

既然Pod已经存在Deployment 及其 Replicate Controller了,没有必要再重新设计一个新的控制器,在现有的控制器之上进行操作即可。

这部分逻辑是HPA的核心逻辑。具体实现在kube-controller-manager。网络上已经有很多源码分析。此处不再赘述。

Untitled 2.png

小结

本文虽说的是K8s的HPA的机制的领域模型,但是,你发现这个领域模型也适用于非K8s的部署方式。

总的来说,关于HPA你只需要记住两个问题:

  1. 指标从何而来
  2. 如何根据指标进行扩缩容

然后找到这两个问题答案。当我们想通这两个问题后,即使不在K8s中实现HPA,我们也会有思路实现。

有关也许,这样理解K8s的Pod自动化扩缩容机制更容易的更多相关文章

  1. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  2. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  3. ruby-on-rails - 没有这样的文件或目录 - 用 Mini Magick 识别 - 2

    在我让另一个人重做我的前端UI之前,我的Rails应用程序运行平稳。我已经尝试解决此错误3天了。这是错误:Nosuchfileordirectory-identifyExtractedsource(aroundline#59):575859606162@post=Post.find(params[:id])authorize@postif@post.update_attributes(post_params)flash[:notice]="Postwasupdated."redirect_to[@topic,@post]else{"utf8"=>"✓","_method"=>"patc

  4. ruby - 易于初学者理解的 Ruby 库 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭3年前。Improvethisquestion我正处于学习Ruby的阶段,我想查看一些小型库的源代码以了解它们是如何构建的。我不知道什么是小型图书馆,但希望SO能推荐一些易于理解的图书馆来学习。因此,如果有人知道一两个非常小的库,这是新手Rubyists学习的好例子,请推荐!我想使用Manveru'sInnatelib,因为它试图保持在2000LOC以下,但我还不熟悉其中经常使用的Ruby速记。也许大约100-5

  5. ruby - 无法理解 `puts{}.class` 和 `puts({}.class)` 之间的区别 - 2

    由于匿名block和散列block看起来大致相同。我正在玩它。我做了一些严肃的观察,如下所示:{}.class#=>Hash好的,这很酷。空block被视为Hash。print{}.class#=>NilClassputs{}.class#=>NilClass为什么上面的代码和NilClass一样,下面的代码又显示了Hash?puts({}.class)#Hash#=>nilprint({}.class)#Hash=>nil谁能帮我理解上面发生了什么?我完全不同意@Lindydancer的观点你如何解释下面几行:print{}.class#NilClassprint[].class#A

  6. ruby - 如何理解 Ruby 中的发送者和接收者? - 2

    我很难理解Ruby中sender和receiver的实际含义。它们一般是什么意思?到目前为止,我只是将它们理解为方法调用和获取其返回值的调用。但是,我知道我的理解还远远不够。谁能给我一个Ruby中发送者和接收者的具体解释? 最佳答案 面向对象中的一个核心概念是消息传递和早期概念化,这在很大程度上借鉴了计算的Actor模型。艾伦·凯(AlanKay)创造了面向对象一词并发明了最早的OO语言之一SmallTalk,他拥有voicedregretatusingatermwhichputthefocusonobjectsinsteadofo

  7. ruby-on-rails - 像 "has_one"这样的 Rails 方法调用是如何工作的? - 2

    我是PHP开发人员,目前我正在学习Rails(3),当然还有Ruby。Idon'twanttobelieveinmagic因此,我尽可能多地了解Rails“背后”发生的事情。我发现有趣的是ActiveRecord模型中的方法调用,如has_one或belongs_to。我试图重现它,并提供了一个天真的例子:#has_one_test_1.rbmoduleFooclassBasedefself.has_oneputs'Willitwork?'endendendclassModel2如我所料,只要运行这个文件就会输出“Willitwork?”。在搜索Rails源代码时,我找到了负责的函数:

  8. ruby-on-rails - Rails - 理解 application.js 和 application.css - 2

    rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:

  9. ruby - 奇怪的 ruby​​ for 循环行为(为什么这样做有效) - 2

    defreverse(ary)result=[]forresult[0,0]inaryendresultendassert_equal["baz","bar","foo"],reverse(["foo","bar","baz"])这行得通,我想了解原因。有什么解释吗? 最佳答案 如果我使用each而不是for/in重写它,它看起来像这样:defreverse(ary)result=[]#forresult[0,0]inaryary.eachdo|item|result[0,0]=itemendresultendforainb基本上就

  10. ruby-on-rails - 为什么 Rails 使用像 link_to 这样的辅助方法而不是 <a href...>? - 2

    我正在学习Rails,我注意到Rails不断地使用诸如link_to之类的辅助方法,而不是仅仅使用普通的html。现在我可以理解为什么他们会使用他们会使用一些辅助方法,但我不明白为什么他们更喜欢辅助方法而不是直接编码html。为什么Rails更喜欢辅助方法而不是您必须手动编写html?为什么Rails团队做出这样的设计选择? 最佳答案 在Rails应用程序中,通常使用URL方法和内容方法生成链接,例如这绝对比将它们放入中更易于管理手动标记。">(您正在使用路由器生成这些URL,对吗?如果您硬编码/users/1并决定稍后将其设为/u

随机推荐