OpenKruise v1.1:功能增强与上游对齐,大规模场景性能优化

简介:在 v1.1 版本中,OpenKruise 对不少已有功能做了扩展与增强,并且优化了在大规模集群中的运行性能。以下对 v1.1 的部分功能做简要介绍。

作者:酒祝(王思宇)

云原生应用自动化管理套件、CNCF Sandbox 项目 -- OpenKruise,近期发布了 v1.1 版本。

OpenKruise[1] 是针对 Kubernetes 的增强能力套件,聚焦于云原生应用的部署、升级、运维、稳定性防护等领域。所有的功能都通过 CRD 等标准方式扩展,可以适用于 1.16 以上版本的任意 Kubernetes 集群。单条 helm 命令即可完成 Kruise 的一键部署,无需更多配置。

版本解析

在 v1.1 版本中,OpenKruise 对不少已有功能做了扩展与增强,并且优化了在大规模集群中的运行性能。以下对 v1.1 的部分功能做简要介绍。

值得注意的是,OpenKruise v1.1 已经将 Kubernetes 代码依赖版本升级到 v1.22,这意味着用户可以在 CloneSet 等工作负载的 pod template 模板中使用 up to v1.22 的新字段等, 但用户安装使用 OpenKruise 所兼容的 Kubernetes 集群版本仍然保持在 >= v1.16。

原地升级支持容器顺序优先级

去年底发布的 v1.0 版本,OpenKruise 引入了容器启动顺序控制[2]功能, 它支持为一个 Pod 中的多个容器定义不同的权重关系,并在 Pod 创建时按照权重来控制不同容器的启动顺序。

在 v1.0 中,这个功能仅仅能够作用于每个 Pod 的创建阶段。当创建完成后,如果对 Pod 中多个容器做原地升级,则这些容器都会被同时执行升级操作。

最近一段时间,社区与 LinkedIn 等公司做过一些交流,获得了更多用户使用场景的输入。在一些场景下,Pod 中多个容器存在关联关系,例如业务容器升级的同时,Pod 中其他一些容器也需要升级配置从而关联到这个新版本;或是多个容器避免并行升级,从而保证如日志采集类的 sidecar 容器不会丢失业务容器中的日志等。

因此,在 v1.1 版本中 OpenKruise 支持了按容器优先级顺序的原地升级。在实际使用过程中,用户无需配置任何额外参数,只要 Pod 在创建时已经带有了容器启动优先级,则不仅在 Pod 创建阶段,会保证高优先级容器先于低优先级容器启动;并且在单次原地升级中,如果同时升级了多个容器,会先升级高优先级容器,等待它升级启动完成后,再升级低优先级容器。

这里的原地升级,包括修改 image 镜像升级与修改 env from metadata 的环境变量升级,详见原地升级介绍[3]总结来说:

  • 对于不存在容器启动顺序的 Pod,在多容器原地升级时没有顺序保证。
  • 对于存在容器启动顺序的 Pod:
  • 如果本次原地升级的多个容器具有不同的启动顺序,会按启动顺序来控制原地升级的先后顺序。
  • 如果本地原地升级的多个容器的启动顺序相同,则原地升级时没有顺序保证。

例如,一个包含两个不同启动顺序容器的 CloneSet 如下:

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:...
spec:replicas: 1template:metadata:annotations:app-config: "... config v1 ..."spec:containers:- name: sidecarenv:- name: KRUISE_CONTAINER_PRIORITYvalue: "10"- name: APP_CONFIGvalueFrom:fieldRef:fieldPath: metadata.annotations['app-config']- name: mainimage: main-image:v1updateStrategy:type: InPlaceIfPossible

当我们更新 CloneSet,将其中 app-config annotation 和 main 容器的镜像修改后, 意味着 sidecar 与 main 容器都需要被更新,Kruise 会先原地升级 Pod 来将其中 sidecar 容器重建来生效新的 env from annotation。

接下来,我们可以在已升级的 Pod 中看到 apps.kruise.io/inplace-update-state annotation 和它的值:

{"revision": "{CLONESET_NAME}-{HASH}",         // 本次原地升级的目标 revision 名字"updateTimestamp": "2022-03-22T09:06:55Z",    // 整个原地升级的初次开始时间"nextContainerImages": {"main": "main-image:v2"},                // 后续批次中还需要升级的容器镜像// "nextContainerRefMetadata": {...},                            // 后续批次中还需要升级的容器 env from labels/annotations"preCheckBeforeNext": {"containersRequiredReady": ["sidecar"]},  // pre-check 检查项,符合要求后才能原地升级后续批次的容器"containerBatchesRecord":[{"timestamp":"2022-03-22T09:06:55Z","containers":["sidecar"]}  // 已更新的首个批次容器(它仅仅表明容器的 spec 已经被更新,例如 pod.spec.containers 中的 image 或是 labels/annotations,但并不代表 node 上真实的容器已经升级完成了)]
}

当 sidecar 容器升级成功之后,Kruise 会接着再升级 main 容器。最终你会在 Pod 中看到如下的 apps.kruise.io/inplace-update-state annotation:

{"revision": "{CLONESET_NAME}-{HASH}","updateTimestamp": "2022-03-22T09:06:55Z","lastContainerStatuses":{"main":{"imageID":"THE IMAGE ID OF OLD MAIN CONTAINER"}},"containerBatchesRecord":[{"timestamp":"2022-03-22T09:06:55Z","containers":["sidecar"]},{"timestamp":"2022-03-22T09:07:20Z","containers":["main"]}]
}

通常来说,用户只需要关注其中 containerBatchesRecord 来确保容器是被分为多批升级的。 如果这个 Pod 在原地升级的过程中卡住了,你可以检查 nextContainerImages/nextContainerRefMetadata 字段,以及 preCheckBeforeNext 中前一次升级的容器是否已经升级成功并 ready 了。

StatefulSetAutoDeletePVC 功能

从 Kubernetes v1.23 开始,原生的 StatefulSet 加入了 StatefulSetAutoDeletePVC 功能,即根据给定策略来选择保留或自动删除 StatefulSet 创建的 PVC 对象,参考文档[4]

因此,v1.1 版本的 Advanced StatefulSet 从上游同步了这个功能,允许用户通过 .spec.persistentVolumeClaimRetentionPolicy 字段来指定这个自动清理策略。这需要你在安装或升级 Kruise 的时候,启用 StatefulSetAutoDeletePVC feature-gate 功能。

apiVersion: apps.kruise.io/v1beta1
kind: StatefulSet
spec:...persistentVolumeClaimRetentionPolicy:  # optionalwhenDeleted: Retain | DeletewhenScaled: Retain | Delete

其中,两个策略字段包括:

  • whenDeleted:当 Advanced StatefulSet 被删除时,对 PVC 的保留/删除策略。
  • whenScaled:当 Advanced StatefulSet 发生缩容时,对缩容 Pod 关联 PVC 的保留/删除策略。

每个策略都可以配置以下两种值:

  • Retain(默认值):它的行为与过去 StatefulSet 一样,在 Pod 删除时对它关联的 PVC 做保留。
  • Delete:当 Pod 删除时,自动删除它所关联的 PVC 对象。

除此之外,还有几个注意点:

  1. StatefulSetAutoDeletePVC 功能只会清理由 volumeClaimTemplate 中定义和创建的 PVC,而不会清理用户自己创建或关联到 StatefulSet Pod 中的 PVC。
  2. 上述清理只发生在 Advanced StatefulSet 被删除或主动缩容的情况下。例如 node 故障导致的 Pod 驱逐重建等,仍然会复用已有的 PVC。

Advanced DaemonSet 重构并支持生命周期钩子

早先版本的 Advanced DaemonSet 实现与上游控制器差异较大,例如对于 not-ready 和 unschedulable 的节点需要额外配置字段来选择是否处理,这对于我们的用户来说都增加了使用成本和负担。

在 v1.1 版本中,我们对 Advanced DaemonSet 做了一次小重构,将它与上游控制器重新做了对齐。因此,Advanced DaemonSet 的所有默认行为会与原生 DaemonSet 基本一致,用户可以像使用 Advanced StatefulSet 一样,通过修改 apiVersion 就能很方便地将一个原生 DaemonSet 修改为 Advanced DaemonSet 来使用。

另外,我们还为 Advanced DaemonSet 增加了生命周期钩子,首先支持 preDelete hook,来允许用户在 daemon Pod 被删除前执行一些自定义的逻辑。

apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
spec:...# define with labellifecycle:preDelete:labelsHandler:example.io/block-deleting: "true"

当 DaemonSet 删除一个 Pod 时(包括缩容和重建升级):

  • 如果没有定义 lifecycle hook 或者 Pod 不符合 preDelete 条件,则直接删除。
  • 否则,会先将 Pod 更新为 PreparingDelete 状态,并等待用户自定义的 controller 将 Pod 中关联的 label/finalizer 去除,再执行 Pod 删除。

Disable DeepCopy 性能优化

默认情况下,我们在使用 controller-runtime 来编写 Operator/Controller 时, 使用其中 sigs.k8s.io/controller-runtime/pkg/client Client 客户端来 get/list 查询对象(typed),都是从内存 Informer 中获取并返回,这是大部分人都知道的。

但很多人不知道的是,在这些 get/list 操作背后,controller-runtime 会将从 Informer 中查到的所有对象做一次 deep copy 深拷贝后再返回。

这个设计的初衷,是避免开发者错误地将 Informer 中的对象直接篡改。在深拷贝之后,无论开发者对 get/list 返回的对象做了任何修改,都不会影响到 Informer 中的对象,后者只会从 kube-apiserver 的 ListWatch 请求中同步。

但是在一些很大规模的集群中,OpenKruise 中各个控制器同时在运行,同时每个控制器还存在多个 worker 执行 Reconcile,可能会带来大量的 deep copy 操作。例如集群中有大量应用的 CloneSet,而其中一些 CloneSet 下管理的 Pod 数量非常多,则每个 worker 在 Reconcile 的时候都会 list 查询一个 CloneSet 下的所有 Pod 对象,再加上多个 worker 并行操作, 可能造成 kruise-manager 瞬时的 CPU 和 Memory 压力陡增,甚至在内存配额不足的情况下有发生 OOM 的风险。

在上游的 controller-runtime 中,我在去年已经提交合并了 DisableDeepCopy 功能[5],包含在 controller-runtime v0.10 及以上的版本。它允许开发者指定某些特定的资源类型,在做 get/list 查询时不执行深拷贝,而是直接返回 Informer 中的对象指针。

例如下述代码,在 main.go 中初始化 Manager 时,为 cache 加入参数即可配置 Pod 等资源类型不做深拷贝。

  mgr, err := ctrl.NewManager(cfg, ctrl.Options{...NewCache: cache.BuilderWithOptions(cache.Options{UnsafeDisableDeepCopyByObject: map[client.Object]bool{&v1.Pod{}: true,},}),})

但在 Kruise v1.1 版本中,我们没有选择直接使用这个功能,而是将 Delegating Client[6] 重新做了封装, 从而使得开发者可以在任意做 list 查询的地方通过 DisableDeepCopy ListOption 来指定单次的 list 操作不做深拷贝。

 if err := r.List(context.TODO(), &podList, client.InNamespace("default"), utilclient.DisableDeepCopy); err != nil {return nil, nil, err}

这样做的好处是使用上更加灵活,避免为整个资源类型关闭深拷贝后,众多社区贡献者在参与开发的过程中如果没有注意到则可能会错误修改 Informer 中的对象。

其他改动

你可以通过 Github release[7] 页面,来查看更多的改动以及它们的作者与提交记录。

社区参与

非常欢迎你通过 Github/Slack/钉钉/微信 等方式加入我们来参与 OpenKruise 开源社区。你是否已经有一些希望与我们社区交流的内容呢?可以在我们的社区双周会[8]上分享你的声音,或通过以下渠道参与讨论:

  • 加入社区 Slack channel [9](English)
  • 加入社区钉钉群:搜索群号 23330762 (Chinese)
  • 加入社区微信群(新):添加用户 openkruise 并让机器人拉你入群 (Chinese)

相关链接

[1]OpenKruise

https://openkruise.io/

[2]容器启动顺序控制

Container Launch Priority | OpenKruise

[3]原地升级介绍

原地升级 | OpenKruise

[4]参考文档StatefulSets | Kubernetes

[5]DisableDeepCopy 功能

 Add UnsafeDisableDeepCopy into cache option to avoid deep copy during get/list by FillZpp · Pull Request #1274 · kubernetes-sigs/controller-runtime · GitHub

[6]Delegating Client

kruise/delegating_client.go at master · openkruise/kruise · GitHub

[7]Github release

Releases · openkruise/kruise · GitHub

[8]社区双周会

石墨文档

[9]Slack channel

https://kubernetes.slack.com/?redir=%2Farchives%2Fopenkruise

原文链接

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

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

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

相关文章

贼喊捉贼?“盗版”软件开发者向 GitHub 投诉被侵权

整理 | 于轩 出品 | CSDN(ID:CSDNnews)拥有超过2亿个代码存储库,由8000多万用户共享,GitHub已然成为世界上最大和最先进的开发平台。 与其他托管用户生成内容的平台一样,这个庞大的代码库经常会接到版权…

基于 Serverless 架构的头像漫画风处理小程序

简介: 当一个程序员想要个漫画风的头像时... 前言 我一直都想要有一个漫画版的头像,奈何手太笨,用了很多软件 “捏不出来”,所以就在想着,是否可以基于 AI 实现这样一个功能,并部署到 Serverless 架构上让…

异动分析技术解决方案—异动归因之指标拆解

简介:归因的方法有多种,这篇文章的重点是指标拆解,也是我们做业务分析时最常用到的方法。我们的目的是解放人力,将指标拆解实现自动化,一方面可以加快业务迭代速度,快速定位问题;另一方面可以对…

阿里巴巴云原生混部系统 Koordinator 正式开源

简介: 脱胎于阿里巴巴内部,经过多年双 11 打磨,每年为公司节省数十亿的混部系统 Koordinator 今天宣布正式开源。通过开源,我们希望将更好的混部能力、调度能力开放到整个行业,帮助企业客户改进云原生工作负载运行的效…

足不出户,确保交付——独家交付秘籍(第二回)

简介:在后疫情时代,遇到无法出差、无法访客时,如何保障交付按时保质的进行,做好运维质量的保障,从而不影响企业整体营收,已成为我们生死攸关的难题。小锤在遇到无法只通过远程就完成项目交付验收&#xff0…

react中类组件this指向

这是一个标准的类组件 import React,{Component} from react; class View extends Component{constructor(props){super(props)}state{} //写在这里跟写在constructor中一样&#xff0c;都可以起到初始化的效果,并且可以省去thisfn(){}fn1(){}render(){return(<div><…

如何使用 PTS 快速发起微服务压测

简介&#xff1a;本文讲阐述什么是微服务架构、微服务架构对系统稳定性带来的影响&#xff0c;以及用性能测试验证稳定性的必要性、用户进行微服务压测的痛点和 PTS 的独特优势、云上使用 PTS 快速发起微服务压测的步骤&#xff0c;以及压测完成后排查分析相关问题的 Tips。 作…

一首让计算机崩溃的歌曲!

大家好&#xff0c;我是轩辕。想象一个场景&#xff1a;手机里播放一首音乐&#xff0c;然后你带着手机从一台电脑旁经过&#xff0c;电脑就被你弄崩溃死机了。这是不是有点像电影里的桥段&#xff1f;一年前&#xff0c;我写过一篇文章&#xff1a;电脑关机了&#xff0c;黑客…

OpenYurt 之 Yurthub 数据过滤框架解析

简介&#xff1a;OpenYurt 是业界首个非侵入的边缘计算云原生开源项目&#xff0c;通过边缘自治&#xff0c;云边协同&#xff0c;边缘单元化&#xff0c;边缘流量闭环等能力为用户提供云边一体化的使用体验。在 Openyurt 里边缘网络可以使用数据过滤框架在不同节点池里实现边缘…

react中规范类型接口的使用

安装 yarn add prop-types 使用 // 注意大小写 import PropTypes from prop-types {name:小红,age:13,sex:"女"} //场景 name String类型&#xff0c;必传 // age Nuber类型&#xff0c;默认值18 // sex String类型&#xff0c;默认值男//类型的限制 Per…

金融核心系统云原生转型的三个挑战、六个误区和四个步骤

嘉宾 | 马振雄出品 | CSDN云原生近年来&#xff0c;云原生技术发展如火如荼&#xff0c;IT系统云原生转型已成共识&#xff0c;留给各行各业的只是何时云原生、怎样云原生的时间和方式问题。金融行业作为各类转型历来的排头兵&#xff0c;在推进云原生转型上同样不逞多让。金融…

KubeVela v1.3 多集群初体验,轻松管理应用分发和差异化配置

简介&#xff1a;KubeVela v1.3 在之前的多集群功能上进行了迭代&#xff0c;本文将为你揭示&#xff0c;如何使用 KubeVela 进行多集群应用的部署与管理&#xff0c;实现以上的业务需求。 作者&#xff1a;段威&#xff08;段少&#xff09; 在当今的多集群业务场景下&#…

Java 定时任务技术趋势

简介&#xff1a;定时任务是每个业务常见的需求&#xff0c;比如每分钟扫描超时支付的订单&#xff0c;每小时清理一次数据库历史数据&#xff0c;每天统计前一天的数据并生成报表等等。 作者&#xff1a;黄晓萌&#xff08;学仁&#xff09; Java 中自带的解决方案 使用 Ti…

ajax,jsonp,axios面试题

什么是前后端联调&#xff1f; react中axios跨域的配置 const { createProxyMiddleware } require(http-proxy-middleware); module.exports function (app) {app.use(// https://home-api.pinduoduo.com/home/mediareports?page_number1&page_size20/home, createPro…

从再造到赋能——360数科举办第二届技术开放日

8月31日&#xff0c;360数科在北京举办“从再造到赋能——2022年技术开放日”。这是360数科的第二届开放日&#xff0c;全面展示了公司在金融科技业务全环节的精细化运营成果&#xff0c;呈现了360数科从市场连接者到流程再造者的技术演化历程&#xff0c;展望了其成为行业赋能…

EventBridge 特性介绍|以 IaC 的方式使用 EventBridge

简介&#xff1a;本文将重点介绍 EventBridge 和 IaC 的重点概念和特性&#xff0c;然后演示如何应用 IaC 理念自动化部署 EventBridge 来使用这些概念和特性。 作者&#xff1a;王川&#xff08;弗丁&#xff09; 引言 EventBridge 作为构建 EDA 架构的基础设施&#xff0c…

关于项目经验的

页面常用的尺寸 PC&#xff1a;内容区宽度&#xff1a; 早期&#xff1a;60 980 1000 1200 1380 字体大小&#xff1a; 12px 14px 16px 18px 常用字体&#xff1a;“微软雅黑” Arial&#xff08;针对英文&#xff09; H5&#xff1a; 750(大多设计稿的宽度) 暂时保留页面状态…

如何使用 Serverless Devs 部署静态网站到函数计算(上)

简介&#xff1a;部署个静态网站到函数计算~ 前言 公司经常有一些网站需要发布上线&#xff0c;对比了几款不同的产品后&#xff0c;决定使用阿里云的函数计算&#xff08;FC)来托管构建出来的静态网站。 FC 弹性实例自带的500 Mb 存储空间对静态网站来说简直是太充足了 。 函…

盛邦安全创始人权晓文入选IDC中国CSO名人堂十大人物

在近日举办的IDC 2022 CSO全球网络安全峰会&#xff08;中国站&#xff09;上&#xff0c;盛邦安全入选API领域推荐厂商&#xff0c;盛邦安全创始人权晓文入选“中国CSO名人堂&#xff08;十大人物&#xff09;”&#xff0c;展现了盛邦安全在网络安全创新方面的不断进取和突出…

硬核调试实操 | 手把手带你实现 Serverless 断点调试

简介&#xff1a;本文将借助 Serverless Devs 工具&#xff0c;对函数计算 (FC&#xff09;应用的断点调试步骤进行详细指导&#xff0c;手把手带你实现 Serverless 的断点调试&#xff0c;并从以下四个方面为你厘清“硬核调试”的脉络步骤&#xff0c;干货满满。 导读&#x…