OpenKruise v1.0:云原生应用自动化达到新的高峰
云原生应用自动化管理套件、CNCF Sandbox 项目 -- OpenKruise,近期发布了 v1.0 大版本。
OpenKruise [1] 是针对 Kubernetes 的增强能力套件,聚焦于云原生应用的部署、升级、运维、稳定性防护等领域。所有的功能都通过 CRD 等标准方式扩展,可以适用于 1.16 以上版本的任意 Kubernetes 集群。单条 helm 命令即可完成 Kruise 的一键部署,无需更多配置。
总得来看,目前 OpenKruise 提供的能力分为几个领域:
应用工作负载: 面向无状态、有状态、daemon 等多种类型应用的高级部署发布策略,例如原地升级、灰度流式发布等。
Sidecar 容器管理: 支持独立定义 sidecar 容器,完成动态注入、独立原地升级、热升级等功能。
增强运维能力: 包括容器原地重启、镜像预拉取、容器启动顺序保障等。
应用分区管理: 管理应用在多个分区(可用区、不同机型等)上的部署比例、顺序、优先级等。
应用安全防护: 帮助应用在 Kubernetes 之上获得更高的安全性保障与可用性防护。
版本解析
在 v1.0 大版本中,OpenKruise 带来了多种新的特性,同时也对不少已有功能做了增强与优化。
首先要说的是,从 v1.0 开始 OpenKruise 将 CRD/WehhookConfiguration 等资源配置的版本从 v1beta1 升级到 v1 ,因此可以支持 Kubernetes v1.22 及以上版本的集群,但同时也要求 Kubernetes 的版本不能低于 v1.16。
以下对 v1.0 的部分功能做简要介绍,详细的 ChangeLog 列表请查看 OpenKruise Github 上的 release 说明以及官网文档。
支持环境变量原地升级
Author: @FillZpp [2]
OpenKruise 从早期版本开始就支持了 “原地升级” 功能,主要应用于 CloneSet 与 Advanced StatefulSet 两种工作负载上。简单来说,原地升级使得应用在升级的过程中,不需要删除、新建 Pod 对象,而是通过对 Pod 中容器配置的修改来达到升级的目的。
如上图所示,原地升级过程中只修改了 Pod 中的字段,因此:
可以避免如调度、分配 IP、分配、挂载盘等额外的操作和代价。
更快的镜像拉取,因为开源复用已有旧镜像的大部分 layer 层,只需要拉取新镜像变化的一些 layer。
当一个容器在原地升级时,Pod 的网络、挂载盘、以及 Pod 中的其他容器不会受到影响,仍然维持运行。
然而,OpenKruise 过去只能对 Pod 中 image 字段的更新做原地升级,对于其他字段仍然只能采用与 Deployment 相似的重建升级。一直以来,我们收到很多用户反馈,希望支持对 env 等更多字段的原地升级 -- 由于受到 kube-apiserver 的限制,这是很难做到的。
经过我们的不懈努力,OpenKruise 终于在 v1.0 版本中,支持了通过 Downward API 的方式支持了 env 环境变量的原地升级。例如对以下 CloneSet YAML,用户将配置定义在 annotation 中并关联到对应 env 中。后续在修改配置时,只需要更新 annotation value 中的值,Kruise 就会对 Pod 中所有 env 里引用了这个 annotation 的容器触发原地重建,从而生效这个新的 value 配置。
与此同时,我们在这个版本中也去除了过去对镜像原地升级的 imageID 限制,即支持相同 imageID 的两个镜像替换升级。
具体使用方式请参考文档 [3] 。
配置跨命名空间分发
Author: @veophi [4]
在对 Secret、ConfigMap 等 namespace-scoped 资源进行跨 namespace 分发及同步的场景中,原生 kubernetes 目前只支持用户 one-by-one 地进行手动分发与同步,十分地不方便。
典型的案例有:
当用户需要使用 SidecarSet 的 imagePullSecrets 能力时,要先重复地在相关 namespaces 中创建对应的 Secret,并且需要确保这些 Secret 配置的正确性和一致性。
当用户想要采用 ConfigMap 来配置一些通用的环境变量时,往往需要在多个 namespaces 做 ConfigMap 的下发,并且后续的修改往往也要求多 namespaces 之间保持同步。
因此,面对这些需要跨 namespaces 进行资源分发和多次同步的场景,我们期望一种更便捷的分发和同步工具来自动化地去做这件事,为此我们设计并实现了一个新的 CRD --- ResourceDistribution。
ResourceDistribution 目前支持 Secret 和 ConfigMap 两类资源的分发和同步。
如上述 YAML 所示,ResourceDistribution 是一类 cluster-scoped 的 CRD,其主要由 resource 和 targets 两个字段构成,其中 resource 字段用于描述用户所要分发的资源,targets 字段用于描述用户所要分发的目标命名空间。
具体使用方式请参考文档 [5] 。
容器启动顺序控制
Author: @Concurrensee [6]
对于 Kubernetes 的一个 Pod,其中的多个容器可能存在依赖关系,比如 容器 B 中应用进程的运行依赖于 容器 A 中的应用。因此,多个容器之间存在顺序关系的需求:
容器 A 先启动,启动成功后才可以启动 容器 B
容器 B 先退出,退出完成后才可以停止 容器 A
通常来说 Pod 容器的启动和退出顺序是由 Kubelet 管理的。Kubernetes 曾经有一个 KEP 计划在 container 中增加一个 type 字段来标识不同类型容器的启停优先级。但是由于 sig-node 考虑到对现有代码架构的改动太大,目前这个 KEP 已经被拒绝了。
因此,OpenKruise 在 v1.0 中提供了名为 Container Launch Priority 的功能,用于控制一个 Pod 中多个容器的强制启动顺序:
对于任意一个 Pod 对象,只需要在 annotations 中定义 apps.kruise.io/container-launch-priority: Ordered,则 Kruise 会按照 Pod 中 containers 容器列表的顺序来保证其中容器的串行启动。
如果要自定义 containers 中多个容器的启动顺序,则在容器 env 中添加 KRUISE_CONTAINER_PRIORITY 环境变量,value 值是范围在 [-2147483647, 2147483647] 的整数。一个容器的 priority 值越大,会保证越先启动。
具体使用方式请参考文档 [7] 。
kubectl-kruise 命令行工具
Author: @hantmac [8]
过去 OpenKruise 是通过 kruise-api、client-java 等仓库提供了 Go、Java 等语言的 Kruise API 定义以及客户端封装,可供用户在自己的应用程序中引入使用。但仍然有不少用户在测试环境下需要灵活地用命令行操作 workload 资源。
然而原生 kubectl 工具提供的 rollout、set image 等命令只能适用于原生的 workload 类型,如 Deployment、StatefulSet,并不能识别 OpenKruise 中扩展的 workload 类型。
因此,OpenKruise 最新提供了 kubectl-kruise 命令行工具,它是 kubectl 的标准插件,提供了许多适用于 OpenKruise workload 的功能。
具体使用方式请参考文档 [9] 。
其余部分功能改进与优化
CloneSet:
通过 scaleStrategy.maxUnavailable 策略支持流式扩容
Stable revision 判断逻辑变化,当所有 Pod 版本与 updateRevision 一致时则标记为 currentRevision
WorkloadSpread:
支持接管存量 Pod 到匹配的 subset 分组中
优化 webhook 在 Pod 注入时的更新与重试逻辑
Advanced DaemonSet:
支持对 Daemon Pod 做原地升级
引入 progressive annotation 来选择是否按 partition 限制 Pod 创建
SidecarSet:
解决 SidecarSet 过滤屏蔽 inactive Pod
在 transferenv 中新增 SourceContainerNameFrom 和 EnvNames 字段,来解决 container name 不一致与大量 env 情况下的冗余问题
PodUnavailableBudget:
新增 “跳过保护” 标识
PodUnavailableBudget controller 关注 workload 工作负载的 replicas 变化
NodeImage:
加入 --nodeimage-creation-delay 参数,并默认等待新增 Node ready 一段时间后同步创建 NodeImage
UnitedDeployment:
解决 NodeSelectorTerms 为 nil 情况下 Pod NodeSelectorTerms 长度为 0 的问题
Other optimization:
kruise-daemon 采用 protobuf 协议操作 Pod 资源
暴露 cache resync 为命令行参数,并在 chart 中设置默认值为 0
解决 certs 更新时的 http checker 刷新问题
去除对 forked controller-tools 的依赖,改为使用原生 controller-tools 配合 markers 注解
社区参与
非常欢迎你通过 Github/Slack/钉钉/微信 等方式加入我们来参与 OpenKruise 开源社区。你是否已经有一些希望与我们社区交流的内容呢?可以在我们的社区双周会 [10] 上分享你的声音,或通过以下渠道参与讨论:
加入社区 Slack channel [11] (English)
加入社区钉钉群:搜索群号 23330762 (Chinese)
加入社区微信群:添加用户 openkruise 并让机器人拉你入群 (Chinese)
参考资料
[1] OpenKruise:
[2] @FillZpp:
https://github.com/FillZpp
[3] 文档:
/docs/core-concepts/inplace-update
[4] @veophi:
[5] 文档:
/docs/user-manuals/resourcedistribution
[6] @Concurrensee:
https://github.com/Concurrensee
[7] 文档:
/docs/user-manuals/containerlaunchpriority
[8] @hantmac:
https://github.com/hantmac
[9] 文档:
/docs/cli-tool/kubectl-plugin
[10] 社区双周会:
https://shimo.im/docs/gXqmeQOYBehZ4vqo
[11] Slack channel:
https://kubernetes.slack.com/channels/openkruise
戳原文,查看 OpenKruise 项目官方主页与文档!
版权声明: 本文为 InfoQ 作者【阿里巴巴云原生】的原创文章。
原文链接:【http://xie.infoq.cn/article/2e3d32e55b34451c839e03040】。文章转载请联系作者。
评论