OpenKruise v0.10.0 新特性 WorkloadSpread 解读

简介: 针对需求,OpenKruise 在 v0.10.0 版本中新增了 WorkloadSpread 特性。目前它支持配合 Deployment、ReplicaSet、CloneSet 这些 workload,来管理它们下属 Pod 的分区部署与弹性伸缩。下文会深入介绍 WorkloadSpread 的应用场景和实现原理,帮助用户更好的了解该特性。

背景

Workload 分布在不同 zone,不同的硬件类型,甚至是不同的集群和云厂商已经是一个非常普遍的需求。过去一般只能将一个应用拆分为多个 workload(比如 Deployment)来部署,由 SRE 团队手工管理或者对 PaaS 层深度定制,来支持对一个应用多个 workload 的精细化管理。

进一步来说,在应用部署的场景下有着多种多样的拓扑打散以及弹性的诉求。其中最常见就是按某种或多种拓扑维度打散,比如:

  • 应用部署需要按 node 维度打散,避免堆叠(提高容灾能力)。
  • 应用部署需要按 AZ(available zone)维度打散(提高容灾能力)。
  • 按 zone 打散时,需要指定在不同 zone 中部署的比例数。

随着云原生在国内外的迅速普及落地,应用对于弹性的需求也越来越多。各公有云厂商陆续推出了 Serverless 容器服务来支撑弹性部署场景,如阿里云的弹性容器服务 ECI,AWS 的 Fragate 容器服务等。以 ECI 为例,ECI 可以通过Virtual Kubelet对接 Kubernetes 系统,给予 Pod 一定的配置就可以调度到 virtual-node 背后的 ECI 集群。总结一些常见的弹性诉求,比如:

  • 应用优先部署到自有集群,资源不足时再部署到弹性集群。缩容时,优先从弹性节点缩容以节省成本。
  • 用户自己规划基础节点池和弹性节点池。应用部署时需要固定数量或比例的 Pod 部署在基础节点池,其余的都扩到弹性节点池。

针对这些需求,OpenKruise 在 v0.10.0 版本中新增了 WorkloadSpread 特性。目前它支持配合 Deployment、ReplicaSet、CloneSet 这些 workload,来管理它们下属 Pod 的分区部署与弹性伸缩。下文会深入介绍 WorkloadSpread 的应用场景和实现原理,帮助用户更好的了解该特性

WorkloadSpread介绍

官方文档(见文末相关链接一)

简而言之,WorkloadSpread 能够将 workload 所属的 Pod 按一定规则分布到不同类型的 Node 节点上,能够同时满足上述的打散与弹性场景。

现有方案对比

简单对比一些社区已有的方案。

Pod Topology Spread Constrains(见文末相关链接二)

Pod Topology Spread Constrains 是 Kubernetes 社区提供的方案,可以定义按 topology key 的水平打散。用户在定义完后,调度器会依据配置选择符合分布条件的 node。

由于 PodTopologySpread 更多的是均匀打散,无法支持自定义的分区数量以及比例配置,且缩容时会破坏分布。WorkloadSpread 可以自定义各个分区的数量,并且管理着缩容的顺序。因此在一些场景下可以避免 PodTopologySpread 的不足。

UnitedDeployment(见文末相关链接三)

UnitedDeployment 是 Kruise 社区提供的方案,通过创建和管理多个 workload 管理多个区域下的 Pod。

UnitedDeployment非常好的支持了打散与弹性的需求,不过它是一个全新的 workload,用户的使用和迁移成本会比较高。而 WorkloadSpread 是一种轻量化的方案,只需要简单的配置并关联到 workload 即可。

应用场景

下面我会列举一些 WorkloadSpread 的应用场景,给出对应的配置,帮助大家快速了解 WorkloadSpread 的能力。

1. 基础节点池至多部署 100 个副本,剩余的部署到弹性节点池

1.png

subsets:
- name: subset-normalmaxReplicas: 100requiredNodeSelectorTerm:matchExpressions:- key: app.deploy/zoneoperator: Invalues:- normal
- name: subset-elastic #副本数量不限requiredNodeSelectorTerm:matchExpressions:- key: app.deploy/zoneoperator: Invalues:- elastic

当 workload 少于 100 副本时,全部部署到 normal 节点池,超过 100 个部署到 elastic 节点池。缩容时会优先删除 elastic 节点上的 Pod。

由于 WorkloadSpread 不侵入 workload,只是限制住了 workload 的分布,我们还可以通过结合 HPA 根据资源负载动态调整副本数,这样当业务高峰时会自动调度到 elastic 节点上去,业务低峰时会优先释放 elastic 节点池上的资源。

2. 优先部署到基础节点池,资源不足再部署到弹性资源池

2.png

scheduleStrategy:type: Adaptiveadaptive:rescheduleCriticalSeconds: 30disableSimulationSchedule: false
subsets:
- name: subset-normal #副本数量不限requiredNodeSelectorTerm:matchExpressions:- key: app.deploy/zoneoperator: Invalues:- normal
- name: subset-elastic #副本数量不限requiredNodeSelectorTerm:matchExpressions:- key: app.deploy/zoneoperator: Invalues:- elastic

两个 subset 都没有副本数量限制,且启用 Adptive 调度策略的模拟调度和 Reschedule 能力。部署效果是优先部署到 normal 节点池,normal 资源不足时,webhook 会通过模拟调度选择 elastic 节点。当 normal 节点池中的 Pod 处于 pending 状态超过 30s 阈值, WorkloadSpread controller 会删除该 Pod 以触发重建,新的 Pod 会被调度到 elastic 节点池。缩容时还是优先缩容 elastic 节点上的 Pod,为用户节省成本。

3. 打散到3个zone,比例分别为1:1:3

3.png

subsets:
- name: subset-amaxReplicas: 20%requiredNodeSelectorTerm:matchExpressions:- key: topology.kubernetes.io/zoneoperator: Invalues:- zone-a
- name: subset-bmaxReplicas: 20%requiredNodeSelectorTerm:matchExpressions:- key: topology.kubernetes.io/zoneoperator: Invalues:- zone-b
- name: subset-cmaxReplicas: 60%requiredNodeSelectorTerm:matchExpressions:- key: topology.kubernetes.io/zoneoperator: Invalues:- zone-c

按照不同 zone 的实际情况,将 workload 按照 1:1:3 的比例打散。WorkloadSpread 会确保 workload 扩缩容时按照定义的比例分布。

4. workload在不同CPU Arch上配置不同的资源配额

workload 分布的 Node 可能有不同的硬件配置,CPU 架构等,这就可能需要为不同的 subset 分别制定 Pod 配置。这些配置可以是 label 和 annotation 等元数据也可以是 Pod 内部容器的资源配额,环境变量等。

4.png

subsets:
- name: subset-x86-arch# maxReplicas...# requiredNodeSelectorTerm...patch:metadata:labels:resource.cpu/arch: x86spec: containers:- name: mainresources:limits:cpu: "500m"memory: "800Mi"
- name: subset-arm-arch# maxReplicas...# requiredNodeSelectorTerm...patch:metadata:labels:resource.cpu/arch: armspec: containers:- name: mainresources:limits:cpu: "300m"memory: "600Mi"

从上面的样例中我们为两个 subset 的 Pod 分别 patch 了不同的 label, container resources,方便我们对 Pod 做更精细化的管理。当 workload 的 Pod 分布在不同的 CPU 架构的节点上,配置不同的资源配额以更好的利用硬件资源。

实现原理

WorkloadSpread 是一个纯旁路的弹性/拓扑管控方案。用户只需要针对自己的 Deployment/CloneSet/Job 对象创建对应的 WorkloadSpread 即可,无需对 workload 做改动,也不会对用户使用 workload 造成额外成本。

5.png

1. subset优先级与副本数量控制

WorkloadSpread 中定义了多个 subset,每个 subset 代表一个逻辑域。用户可以自由的根据节点配置,硬件类型,zone 等来划分 subset。特别的,我们规定了 subset 的优先级:

  1. 按定义从前往后的顺序,优先级从高到低。
  2. 优先级越高,越先扩容;优先级越低,越先缩容。

2. 如何控制缩容优先级

理论上,WorkloadSpread 这种旁路方案是无法干涉到 workload 控制器里的缩容顺序逻辑的。

不过,这个问题在近期得以解决—— 经过一代代用户的不懈努力(反馈),K8s 从 1.21 版本开始为 ReplicaSet(Deployment)支持了通过设置 controller.kubernetes.io/pod-deletion-cost 这个 annotation 来指定 Pod 的 “删除代价”:deletion-cost 越高的 Pod,删除的优先级越低。

而 Kruise 从 v0.9.0 版本开始,就在 CloneSet 中支持了 deletion-cost 特性。

因此,WorkloadSpread controller通过调整各个 subset 下属 Pod 的 deletion-cost,来控制workload的缩容顺序。

举个例子:对于以下 WorkloadSpread,以及它关联的 CloneSet 有 10 个副本:

  subsets:- name: subset-amaxReplicas: 8- name: subset-b # 副本数量不限

则 deletion-cost 数值以及删除顺序为:

  • 2 个在 subset-b上的 Pod,deletion-cost 为 100(优先缩容)
  • 8 个在 subset-a上的 Pod,deletion-cost 为 200(最后缩容)

然后,如果用户修改了 WorkloadSpread 为:

  subsets:- name: subset-amaxReplicas: 5 # 8-3, - name: subset-b

则 workloadspread controller 会将其中 3 个在 susbet-a 上 Pod 的 deletion-cost 值由 200 改为 -100

  • 3 个在 subset-a 上的 Pod,deletion-cost 为 -100(优先缩容)
  • 2 个在 subset-b 上的 Pod,deletion-cost 为 100(其次缩容)
  • 5 个在 subset-a 上的 Pod,deletion-cost 为 200(最后缩容)

这样就能够优先缩容那些超过 subset 副本限制的 Pod 了,当然总体还是按照 subset 定义的顺序从后向前缩容。

3. 数量控制

如何确保 webhook 严格按照 subset 优先级顺序、maxReplicas 数量来注入 Pod 规则是 WorkloadSpread 实现层面的重点难题。

3.1 解决并发一致性问题

在 workloadspread 的 status 中有对应每个 subset 的 status,其中 missingReplicas 字段表示了这个 subset 需要的 Pod 数量,-1 表示没有数量限制(subset 没有配置 maxReplicas)。

spec:subsets:- name: subset-amaxReplicas: 1- name: subset-b# ...
status:subsetStatuses:- name: subset-amissingReplicas: 1- name: subset-bmissingReplicas: -1# ...

当 webhook 收到 Pod create请求时:

  1. 根据 subsetStatuses 顺序依次找 missingReplicas 大于 0 或为 -1 的 suitable subset。
  2. 找到suitable subset后,如果 missingReplicas 大于 0,则先减 1 并尝试更新 workloadspread status。
  3. 如果更新成功,则将该 subset定义的规则注入到 pod 中。
  4. 如果更新失败,则重新 get 这个 workloadspread以获取最新的 status,并回到步骤 1(有一定重试次数限制)。

同样,当 webhook 收到 Pod delete/eviction 请求时,则将 missingReplicas 加 1 并更新。

毫无疑问,我们在使用乐观锁来解决更新冲突。但是仅使用乐观锁是不合适的,因为 workload 在创建 Pod 时会并行创建大量的 Pod,apiserver 会在一瞬间发送很多 Pod create 请求到 webhook,并行处理会产生非常多的冲突。大家都知道,冲突太多就不适合使用乐观锁了,因为它解决冲突的重试成本非常高。为此我们还加入了 workloadspread 级别的互斥锁,将并行处理限制为串行处理。加入互斥锁还有新的问题,即当前 groutine 获取锁后,极有可能从 infromer 中拿的 workloadspread 不是最新的,还是会冲突。所以 groutine 在更新完 workloadspread 之后,先将最新的 workloadspread 对象缓存起来再释放锁,这样新的 groutine 获取锁后就可以直接从缓存中拿到最新的 workloadspread。当然,多个 webhook 的情况下还是需要结合乐观锁机制来解决冲突。

3.2 解决数据一致性问题

那么,missingReplicas 数值是否交由 webhook 控制即可呢?答案是不行,因为:

  1. webhook 收到的 Pod create 请求,最终不一定真的能成功(比如 Pod 不合法,或在后续 quota 等校验环节失败了)。
  2. webhook 收到的 Pod delete/eviction 请求,最终也不一定真的能成功(比如后续被 PDB、PUB 等拦截了)。
  3. K8s 里总有种种的可能性,导致 Pod 没有经过 webhook 就结束或没了(比如 phase 进入 Succeeded/Failed,或是 etcd 数据丢了等等)。
  4. 同时,这也不符合面向终态的设计理念。

因此,workloadspread status 是由 webhook 与 controller 协作来控制的:

  • webhook 在 Pod create/delete/eviction 请求链路拦截,修改 missingReplicas 数值。
  • 同时 controller 的 reconcile 中也会拿到当前 workload 下的所有 Pod,根据 subset 分类,并将 missingReplicas 更新为当前实际缺少的数量。
  • 从上面的分析中,controller 从 informer 中获取 Pod 很可能存在延时,所以我们还在status中增加了 creatingPods map, webook 注入的时候会记录 key 为pod.name, value 为时间戳的一条 entry 到 map,controller 再结合 map 维护真实的 missingReplicas。同理还有一个 deletingPods map 来记录 Pod 的delete/eviction 事件。

4. 自适应调度能力

在 WorkloadSpread 中支持配置 scheduleStrategy。默认情况下,type 为 Fixed,即固定按照各个 subset 的前后顺序、maxReplicas 限制来将 Pod 调度到对应的 subset 中。

但真实的场景下,很多时候 subset 分区或拓扑的资源,不一定能完全满足 maxReplicas 数量。用户需要按照实际的资源情况,来为 Pod 选择有资源的分区扩容。这就需要用 Adaptive 这种自适应的调度分配。

WorkloadSpread 提供的 Adaptive 能力,逻辑上分为两种:

  1. SimulationSchedule:在 Kruise webhook 中根据 informer 里已有的 nodes/pods 数据,组装出调度账本,对 Pod 进行模拟调度。即通过 nodeSelector/affinity、tolerations、以及基本的 resources 资源,做一次简单的过滤。(对于 vk 这种节点不太适用)
  2. Reschedule:在将 Pod 调度到一个 subset 后,如果调度失败超过 rescheduleCriticalSeconds 时间,则将该 subset 暂时标记为 unschedulable,并删除 Pod 触发重建。默认情况下,unschedulable 会保留 5min,即在 5min 内的 Pod 创建会跳过这个 subset。

小结

WorkloadSpread 通过结合一些 kubernetes 现有的特性以一种旁路的形式赋予 workload 弹性部署与多域部署的能力。我们希望用户通过使用 WorkloadSpread 降低 workload 部署复杂度,利用其弹性伸缩能力切实降低成本。

目前阿里云内部正在积极的落地,落地过程中的调整会及时反馈社区。未来 WorkloadSpread 还有一些新能力计划,比如让 WorkloadSpread 支持 workload 的存量 Pod 接管,支持批量的 workload 约束,甚至是跨过 workload 层级使用 label 来匹配 Pod。其中一些能力需要实际考量社区用户的需求场景。希望大家多多参与到 Kruise 社区,多提 issue 和 pr,帮助用户解决更多云原生部署方面的难题,构建一个更好的社区。

  • Github:https://github.com/openkruise/kruise
  • Official:https://openkruise.io/
  • Slack: Channel in Kubernetes Slack

原文链接
本文为阿里云原创内容,未经允许不得转载。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/512343.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS 状态管理,玩出花样了!

作者 | 零一来源 | 前端印象CSS用于交互的方式无非就那么几种:伪类::hover、:link、:active ...动画:animation过渡动画:transition这些交互方式组合起来,真的可以玩出一些花样,例如我们本文的主题&#xf…

告别Kafka Stream,让轻量级流处理更加简单

简介: 还在花精力去选型Kafka组件去做清洗转化?来试试Kafka ETL任务功能! 一说到数据孤岛,所有技术人都不陌生。在 IT 发展过程中,企业不可避免地搭建了各种业务系统,这些系统独立运行且所产生的数据彼此独…

元宇宙“性骚扰”现象频出,Meta推出“个人结界”能保护好女玩家吗?

作者 | 小码君来源 | 抓码青年元宇宙,可以说是最近最炙手可热的概念了。各大厂纷纷入局元宇宙,Faceebook甚至将总公司名字都改名为Meta。不过盯上元宇宙的可不止资本大鳄,还有一些不怀好意的色狼。据外媒报道称,在Meta的Oculus设备…

【CDS技术揭秘系列 01】阿里云CDS-OSS容灾大揭秘

简介: 本文主要阐述 CDS 产品中 OSS 服务在容灾方面的部署形态以及实现的其本原理。 容灾功能可以保证用户一份数据在多个地方存在冗余备份,当某个机房出现极端异常(比如物理损毁)情况下,数据也不会出现丢失&#xff1…

如何促合作共赢?技术人的一点经验分享

简介: 本文作者将通过与詹韦团队一起合作的《树懒平台》,分享在工作过程中,我们什么情况下会有合作诉求?有了合作诉求之后,如何寻找对的人?锁定候选人之后,如何打动对方促成合作?合作…

不记得 Git 命令? 懒人版 Git 值得拥有!

作者 | Eason来源 | 程序员巴士Git的强大是所有开发者都心知肚明的事情,但是其多样的命令令人很是难受。不过在Github上有着这么一个开源项目lazygit[1]。Lazygit是由Jesseduffield开发并维护的项目,其代码托管在Github。通过使用Lazygit,我们…

Dubbo3.0|阿里巴巴服务框架三位一体的选择与实践

简介: 服务框架就像铁路的铁轨一样,是互通的基础,只有解决了服务框架的互通,才有可能完成更高层的业务互通,所以用相同的标准统一,合二为一并共建新一代的服务框架是必然趋势。Dubbo3.0 是 Dubbo2.0 与 HSF…

全球首款乘云而来的存储产品CDS诞生!

9月22日,阿里云发布全球首款“云定义存储”(Cloud Defined Storage,CDS)产品。作为一款本地部署的分布式存储产品,阿里云CDS拥有与公共云存储相同的技术架构,让企业客户在本地也能部署和使用与公共云一致的…

性能提升3倍、时延降低70%,阿里云企业级存储ESSD云盘再升级!

9月22日,阿里云存储年度新品发布会上,阿里云基础产品资深产品总监陈起鲲发布了其全球领先的旗舰级块存储产品ESSD的两款新规格(ESSD Auto PL、ESSD PL-X),并宣布了新增的多项企业级能力。 据了解,ESSD是阿…

一图看懂,什么是“云定义存储”

世界的诞生是从盘古开天辟地开始 而数据的存储 则由在龟甲上刻下的第一个字开始 经过数千年发展 数据存储也从最初的 龟壳、竹简等材料逐步进化到磁带、硬盘甚至云上 在之前几千年里 人们对于数据存储的需求并没那么高 仅仅通过纸张就能将所有数据记录下来 随着第一台计算机面…

Android 13 第一个开发者版本来了,网友直呼:Android 12 还没玩透!

整理 | 苏宓出品 | CSDN(ID:CSDNnews)2 月 10 日,Google 宣布 Android 13 首个预览版面向开发者开放,此版本重点聚焦隐私和安全、提供开发者生产力、应用兼容性,并保持与 OpenJDK 11 更新一致、提供主题图标…

「技术人生」第6篇:技术同学应该如何理解业务?

简介: 本文以大量理论论述解析业务,并提供多种基于不同场景的实操方法,帮助技术同学以科学、合理的方式开展日常工作、指导团队开展业务建设,保障顶层设计的落地执行。 一. 背景 目前已经发布《技术一号位的方法论》系列文章其实…

参数设置_变频器基本参数设置

工业设备的使用如何达到最大效能以及最佳效果,需要使用人员充分了解设备性能以及工艺要求,所以变频器参数设置或者优化是非常重要的环节,古人云失之毫厘差之千里就是这个道理。一、变频器基本参数设置参数设置可以是手持编程器操作&#xff0…

Morphling:云原生部署 AI , 如何把降本做到极致?

简介: Morphling 本意是游戏 Dota 中的英雄“水人”,他可以根据环境要求,通过灵活改变自身形态,优化战斗表现。我们希望通过 Morphling 项目,实现针对机器学习推理作业的灵活、智能的部署配置改变,优化服务…

datax参数设置_DataX Web数据增量同步配置说明

一、根据日期进行增量数据抽取1.页面任务配置打开菜单任务管理页面,选择添加任务按下图中5个步骤进行配置1.任务类型选DataX任务2.辅助参数选择时间自增3.增量开始时间选择,即sql中查询时间的开始时间,用户使用此选项方便第一次的全量同步。第…

Node18 即将支持 import HTTP资源!

作者 | 零一来源 | 前端印象最近看到Node官方提交了一条commit ,并且已经合入 master分支 ,如下图所示:node master commit由此可见,Node18可能会支持一个非常 nice 的功能,那就是 支持 import 远程HTTPS资源和本地的H…

MYSQL深潜 - 剖析Performance Schema内存管理

简介: 本文主要是通过对PFS引擎的内存管理的源码的阅读,解读PFS内存分配及释放原理,深入剖析其中存在的一些问题,以及一些改进思路。本文源代码分析基于Mysql-8.0.24版本。 作者 | 之枢 来源 | 阿里技术公众号 一 引言 MYSQL Pe…

基于MaxCompute SQL 的半结构化数据处理实践

简介: MaxCompute作为企业级数据仓库服务,集中存储和管理企业数据资产、面向数据应用处理和分析数据,将数据转换为业务洞察。通过与阿里云内、外部服务灵活组合,可构建丰富的数据应用。全托管的数据与分析解决方案,可简…

file_get_contents请求失败处理_SpringCloud Gateway网关处理请求过程中遇到400Bad Request问题解决方案...

大家在使用springcloud自己的gateway作为网关服务时,可能会不小心遇到自定义的Filter处理请求Request报文时出现400的错误,而且这个错误还不是每次请求都必现,额什么意思?难不成你是说请求还时好时坏?bingo&#xff01…

CSDN企业数字化之路 ——「低代码」发展研讨会北京站现场实录大放送

作者 | 千鸟 出品 | CSDN云计算(ID:CSDNcloud) 2021年底,CSDN面向行业开发者和高校学生开发者,展开了关于“低代码”的开发者调研活动。基于调研数据,CSDN提出了对低代码发展趋势的五大方向。在随后举行的 …