简介:在 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: 1
template:
metadata:
annotations:
app-config: "... config v1 ..."
spec:
containers:
- name: sidecar
env:
- name: KRUISE_CONTAINER_PRIORITY
value: "10"
- name: APP_CONFIG
valueFrom:
fieldRef:
fieldPath: metadata.annotations['app-config']
- name: main
image: main-image:v1
updateStrategy:
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: # optional
whenDeleted: Retain | Delete
whenScaled: 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 label
lifecycle:
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

原文链接

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

OpenKruise v1.1:功能增强与上游对齐,大规模场景性能优化的更多相关文章

  1. DevExpress WPF v19.1:Data Grid/Tree List等控件功能增强

    行业领先的.NET界面控件DevExpress 日前正式发布v19.1版本,本站将以连载的形式介绍各版本新增内容.在本系列文章中将为大家介绍DevExpress WPF v19.1中新增的一些控件及部 ...

  2. MWeb 1.4 新功能介绍二:静态博客功能增强

    MWeb 比较有特色的是一键生成静态博客功能,然后从 MWeb 最开始规划要做静态博客生成功能时,我就希望 MWeb 的静态博客生成功能在易用的同时,还要有很强大的扩展性. 比如说能自己增加网站公告, ...

  3. VMare中安装“功能增强工具”,实现CentOS5.5与win7host共享文件夹的创建

    读者如要转载,请标明出处和作者名,谢谢. 地址01:http://space.itpub.net/25851087 地址02:http://www.cnblogs.com/zjrodger/ 地址03 ...

  4. ps 中取消网格线的吸附功能,其实是对齐功能

    ps 中取消网格线的吸附功能,其实是对齐功能

  5. Java SE 5.0 - SE 8 的功能增强

    Table of Contents 前言 Java 5.0 Generics Enhanced for Loop Autoboxing Typesafe Enums Varargs Static Im ...

  6. jquery-7 jquery中的文档处理方法有哪些(方法的参数表示功能增强)

    jquery-7 jquery中的文档处理方法有哪些(方法的参数表示功能增强) 一.总结 一句话总结:多看参考文档,多看主干目录.一般的功能分两个方法来实现,一个对应标签,一个对应标签和事情,比如克隆 ...

  7. DevExpress WinForms v19.1新版亮点:Spreadsheet/Sunburst控件功能增强

    行业领先的.NET界面控件DevExpress v19.1终于正式发布,本站将以连载的形式介绍各版本新增内容.在本系列文章中将为大家介绍DevExpress WinForms v19.1中新增的一些控 ...

  8. Kubernetes 弹性伸缩HPA功能增强Advanced Horizontal Pod Autoscaler -介绍部署篇

    背景 WHAT(做什么) Advanced Horizontal Pod Autoscaler(简称:AHPA)是kubernetes中HPA的功能增强. 在兼容原生HPA功能基础上,增加预测.执行模 ...

  9. Tapdata Cloud 版本上新!新增TiDB等数据源支持,连接和任务功能增强,体验更优

    Tapdata Cloud cloud.tapdata.net Tapdata Cloud 是国内首家异构数据库实时同步云平台,目前支持Oracle.MySQL.PG.SQL Server.Mongo ...

  10. 【公开课】【阿里在线技术峰会】何登成:AliSQL性能优化与功能突破的演进之路

    MySQL的公开课,可能目前用不上这些,但是往往能在以后想解决方案的时候帮助到我.以下是阿里对公开课的整理 摘要: 本文根据阿里高级数据库专家何登成在首届阿里巴巴在线技术峰会上的分享整理而成.他主要介 ...

随机推荐

  1. 求给定两个排序好的数组中第k大的数

    这个问题比求两个长度相等的排序数组的上中位数难度要高一点,难就难在不是求中位数了,但是我们要学会举一反三,可以尝试通过分析将求第k大的数转化为求中位数.将数组中不可能的数排除,在剩下可能的数中求中位数 ...

  2. C#的窗体防闪烁解决方案 - 开源研究系列文章

    昨天编码的时候想到了关于无边框窗体的闪烁问题,主要是改变窗体大小的时候会闪烁,默认的窗体没这个问题.而现在无边框窗体的应用比较多,所以就找了度娘,然后结合自己的经验进行了测试,得到了这个例子,简单有效 ...

  3. 使用现代身份验证(OAuth)来连接POP、IMAP或SMTP

    我的博客园:https://www.cnblogs.com/CQman/ 转载: https://mp.weixin.qq.com/s?__biz=MzU0MzUxMzU2NA==&mid=2 ...

  4. 记录-Vue移动端日历设计与实现

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 工作中遇到一个需求是根据日历查看某一天/某一周/某一月的睡眠报告,但是找了好多日历组件都不是很符合需求,只好自己手写一个日历组件,顺便记录 ...

  5. 鸿蒙HarmonyOS实战-ArkUI组件(Row/Column)

    前言 HarmonyOS的布局组件是一组用于构建用户界面布局的组件,包括线性布局.相对布局.网格布局等.这些组件帮助开发者以简单和灵活的方式管理和组织应用程序中的视图,并支持多种不同的设备屏幕尺寸和方 ...

  6. 开发必会系列:《Java多线程编程实战》读书笔记

    如何判断是否开启超线程 一  基础 进程是程序向操作系统申请资源(如内存空间和文件句柄)的基本单位.线程是进程中可独立执行的最小单位. 在Java平台中创建一个线程就是创建一个Thread类(或其子类 ...

  7. hdfs开启回收站(废纸篓)

    1.背景 我们知道,在mac系统上删除文件,一般情况下是可以进入 废纸篓里的,如果此时我们误删除了,还可以从 废纸篓中恢复过来.那么在hdfs中是否存在类似mac上的废纸篓这个功能呢?答案是存在的. ...

  8. 聊聊ShareGPT格式的微调数据集

    转载请注明住处:https://www.cnblogs.com/zhiyong-ITNote 概述 ShareGPT格式的数据集中,一般是如下格式: [ { "conversations&q ...

  9. KingbaseES 使用sys_bulkload远程导入

    前言 sys_bulkload 常见场景是本地导入数据,也可以在远程运行 sys_bulkload ,对数据库上的CSV 文件进行导入.远程导入数据时候需要注意,csv文件和ctl文件所在服务器.以下 ...

  10. Java 实现OCR扫描/识别图片文字

    图片内容一般无法编辑,如果想要读取图片中的文本,我们需要用到OCR工具.本文将介绍如何在Java中实现OCR识别读取图片中的文字. 所需工具: IDEA Spire.OCR for Java - Ja ...