OpenKruise v0.5.0 版本发布,支持无损的流式分批发布策略

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 目前在阿里巴巴内部云原生环境中,绝大部分应用都统一使用 OpenKruise 的能力做 Pod 部署、发布管理,而不少业界公司和阿里云上客户由于 K8s 原生 Deployment 等负载不能完全满足需求,也转而采用 OpenKruise 作为应用部署载体。

image.png

目前在阿里巴巴内部云原生环境中,绝大部分应用都统一使用 OpenKruise 的能力做 Pod 部署、发布管理,而不少业界公司和阿里云上客户由于 K8s 原生 Deployment 等负载不能完全满足需求,也转而采用 OpenKruise 作为应用部署载体。

背景问题

在介绍 OpenKruise 新增能力之前,我们先来看一下原生 K8s workload 所提供的发布能力:

  • Deployment 目前支持 maxUnavailable 和 maxSurge:

image.png

  • StatefulSet 目前支持 partition:

image.png

  • 其余 workload 如 DaemonSet,也只支持了 maxUnavailable。

以上这些策略在测试环境或是小场景下尚且可行,但其实无法完全满足大规模的应用场景。比方说:

  • 首先,Deployment 不支持灰度分批发布,你想只灰度升级其中 20% 的 Pod 做验证?抱歉做不到啊,用户只能设置小一些的 maxUnavailable 等着它全部发完,或者发布出现问题紧急 pause 暂停;
  • StatefulSet 确实支持灰度分批(partition),但目前是只能一个一个 Pod 来升级。如果 replicas 总数有个几百上千的量,那么一次发布可能要等到天黑。

v0.5.0 新增功能

这里我们只针对 v0.5.0 版本 CloneSet 和 SidecarSet 的两个主要功能改动来介绍,有兴趣的同学可以在 Github changelog 上看到版本改动明细:https://github.com/openkruise/kruise/blob/master/CHANGELOG.md

CloneSet 支持 maxSurge 策略

在阿里巴巴内部的云原生环境下,绝大部分无状态应用都使用 CloneSet 管理。为了应对超大规模应用的极致部署需求,我们在其中支持:

  • 原地升级(发布前后 Pod 对象不变、IP 不变、volume 不变,只升级容器的镜像)
  • 缩小 replicas 指定 Pod 删除
  • 丰富的发布策略(流式、灰度分批、优先级、打散等)

而在今年 2 月份的 Kruise v0.4.0 版本中,我们将 CloneSet 推出到开源。CloneSet 一经发布就广受关注,目前已经有多家知名互联网公司在调研使用。

最初版本的 CloneSet 并未支持 maxSurge(先扩后缩发布),只支持了 maxUnavailable、partition 等策略。这对阿里巴巴内部的大体量应用来说不是问题,但是很多社区用户的平台上都有小规模的应用,如果不能配置先扩后缩,那么在发布阶段可能会影响到应用的可用性。

在收到社区的 issue #250 #260 反馈后,我们在 CloneSet 中新增了 maxSurge 策略的支持并于 v0.5.0 版本中提供,在此也感谢社区 fatedier shiyan2016 等成员的参与贡献和宝贵建议。至此,CloneSet 已经覆盖了 K8s 原生 workload 的所有发布策略,下图构建了 CloneSet 目前提供的发布功能:

image.png

这里暂时不对 CloneSet 的发布策略做详细说明,我们后续会有专项文章来介绍。我们只看一下新增的 maxSurge 是如何配合流式、分批发布来实现的呢?接下来我们用几个简单的例子来看一下:

  1. 设置 maxSurge + maxUnavailable + partition 发布:

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet

...

spec:

replicas: 5          # Pod 总数为 5

updateStrategy:

maxSurge: 20%      # 多扩出来 5 * 20% = 1 个 Pod (rounding up)
maxUnavailable: 0  # 保证发布过程 5 - 0 = 5 个 Pod 可用
partition: 3       # 保留 3 个旧版本 Pod (只发布 5 - 3 = 2 个 Pod)

当开始发布时,CloneSet 会先根据 maxSurge 多扩出来一个 Pod,此时 Pod 总数为 6(5 个旧版,1 个新版):

$ kubectl get clone demo
NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE
demo 5 1 0 5 6 17m
随后,CloneSet 会在保证 maxUnavailable 的前提下逐渐把 Pod 删除、新建的方式更新,直到满足 partition=3 即剩余 3 个旧版本 Pod。此时,因为已经达到了期望的终态,CloneSet 会把新版本 Pod 删除一个,此时 Pod 总数为 5(3 个旧版,2 个新版):

$ kubectl get clone demo
NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE
demo 5 2 2 5 5 17m
这里可以观察一段时间,当需要继续往下发布时,再次修改 partition 为 0。然后,CloneSet 会再次根据 maxSurge 多扩出来一个 Pod,此时 Pod 总数为 6(3 个旧版,3 个新版):

$ kubectl get clone demo
NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE
demo 5 3 2 5 6 17m
随后,CloneSet 会在保证 maxUnavailable 的前提下逐渐把 Pod 删除、新建的方式更新,直到满足 partition=0 即所有 Pod 都升级到新版本。最后,CloneSet 会把新版本 Pod 删除一个,此时 Pod 总数为 5(5 个新版):

$ kubectl get clone demo
NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE
demo 5 5 5 5 5 17m

  1. maxSurge 配合原地升级:

CloneSet 提供了 Pod 原地升级和重建升级两种升级方式,都可以配合 maxSurge / maxUnavailable / partition 等策略来发布。

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet

...

spec:
updateStrategy:

  type: InPlaceIfPossible
maxSurge: 20%

如果在原地升级方式下配置了 maxSurge,CloneSet 会先扩出来 maxSurge 数量的 Pod,然后对旧版本 Pod 采用 in-place 的方式来升级(更新 Pod spec 中的 image 镜像),最后在满足 partition 终态之后再清理删掉 maxSurge 数量的 Pod。

通过这种方式,既保证了发布过程的业务可用性,也尽量使 Pod 发布过程中 IP、volume 等信息不变。

SidecarSet 支持 volume 注入合并

SidecarSet 是 Kruise 提供的另一个重磅功能,不同于 CloneSet/StatefulSet 这些管理业务 Pod 的 workload,SidecarSet 是负责统一管理集群中的 sidecar 容器版本和注入。

而 v0.5.0 版本中新增的功能,就是在 sidecar 容器注入的时候,解决了 SidecarSet 和 Pod 中 volume 重复定义的冲突问题。这也是来自于一个社区 issue #254 反馈,他们使用 SidecarSet 做日志采集 sidecar 的管理,并期望以旁路的方式注入到所有 Pod 中。

举个例子,我们需要往集群中每个 Pod 都注入一个日志采集 sidecar 容器。但是一来我们无法让每个应用开发者都在自己的 CloneSet/Deployment 中增加这个容器的定义,二来即使在所有应用的 workload 中都加了,如果我们想要升级这个日志采集容器的镜像版本,还得更新所有应用的 workload,这样做的成本实在太高了!

而 OpenKruise 提供的 SidcarSet 正是为了解决上述这个问题。我们只需要将 sidecar 定义写到一个全局的 SidcarSet 中,不管用户用 CloneSet、Deployment、StatefulSet 等任何方式部署,扩出来的 Pod 中都会注入我们定义好的 sidecar 容器。

image.png

以日志采集为例,我们可以先定义一个 SidecarSet:

apiVersion: apps.kruise.io/v1alpha1
kind: SidecarSet
metadata:
name: log-sidecar
spec:
selector:

matchLabels:
  app-type: long-term  # 往所有带 long-term 标签的 Pod 中注入

containers:

  • name: log-collector
    image: xxx:latest
    volumeMounts:

    • name: log-volume
      mountPath: /var/log # 将 log-volume 的卷挂到 /var/log 目录,采集这个目录下的日志

    volumes:

  • name: log-volume # 定义一个名为 log-volume 的卷
    emptyDir: {}
    这里大家可能会问,如果每个应用打出日志的目录路径不同,怎么办?不要急,这就是本次 volume merge 的功能所在。

这个时候,比如有一个应用 A 扩容的原始 Pod 如下:

apiVersion: v1
kind: Pod
metadata:
labels:

app-type: long-term

spec:
containers:

  • name: app
    image: xxx:latest
    volumeMounts:

    • name: log-volume
      mountPath: /app/logs # 应用自己的日志目录

    volumes:

  • name: log-volume # 定义一个名为 log-volume 的卷
    persistentVolumeClaim:

    claimName: pvc-xxx

    那么 kruise webhook 就会将 SidecarSet 中定义的 log sidecar 容器注入到 Pod 中:

apiVersion: v1
kind: Pod
metadata:
labels:

app-type: long-term

spec:
containers:

  • name: app
    image: xxx:latest
    volumeMounts:

    • name: log-volume
      mountPath: /app/logs # 应用自己的日志目录
  • name: log-collector
    image: xxx:latest
    volumeMounts:

    • name: log-volume
      mountPath: /var/log

    volumes:

  • name: log-volume # 定义一个名为 log-volume 的卷
    persistentVolumeClaim:

    claimName: pvc-xxx

    可以看到,因为 SidecarSet 和 Pod 中定义的日志 volume 名字都叫 log-volume,那么在注入的时候就会以 Pod 中定义的 volume 为准。比如这里 Pod 中的 volume 采用了 pvc 的方式来挂载 pv,那么注入 sidecar 后,同样会把这个卷挂到 sidecar 容器中的 /var/log 目录下,然后执行日志采集即可。

这样以 SidecarSet 的方式管理 sidecar 容器,既和应用部署发布做了解耦,也同样可以和应用容器共享 volume 卷,来实现日志采集、监控等相关 sidecar 功能。

总结

本次 v0.5.0 版本的升级,主要带来了应用无损发布和 sidecar 容器管理上更加便捷的能力。

后续 OpenKruise 还会持续在应用部署/发布能力上做出更深的优化,我们也欢迎更多的同学参与到 OpenKruise 社区来,共同建设一个场景更加丰富、完善的 K8s 应用管理、交付扩展能力,能够面向更加规模化、复杂化、极致性能的场景。

本文转自<阿里巴巴云原生技术圈>——阿里巴巴云原生小助手

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
10月前
|
云安全 存储 监控
云计算安全:AWS与Azure的安全策略与实践比较
【10月更文挑战第26天】本文详细比较了AWS和Azure在安全性方面的策略和实践,涵盖身份与访问管理、数据加密与保护以及安全监控与响应。通过代码示例展示了两家云服务提供商在实际应用中的具体操作,帮助企业在选择云服务时做出明智决策。
237 0
|
9月前
|
运维 Cloud Native 持续交付
深入理解云原生架构及其在现代企业中的应用
随着数字化转型的浪潮席卷全球,企业正面临着前所未有的挑战与机遇。云计算技术的迅猛发展,特别是云原生架构的兴起,正在重塑企业的IT基础设施和软件开发模式。本文将深入探讨云原生的核心概念、关键技术以及如何在企业中实施云原生策略,以实现更高效的资源利用和更快的市场响应速度。通过分析云原生架构的优势和面临的挑战,我们将揭示它如何助力企业在激烈的市场竞争中保持领先地位。
218 13
|
4月前
|
人工智能 运维 监控
兄弟,你还在翻日志看故障?AI都快替你写日报了!
兄弟,你还在翻日志看故障?AI都快替你写日报了!
261 7
|
5月前
|
SQL 存储 关系型数据库
MySQL选错索引了怎么办?
本文探讨了MySQL中因索引选择不当导致查询性能下降的问题。通过创建包含10万行数据的表并插入数据,分析了一条简单SQL语句在不同场景下的执行情况。实验表明,当数据频繁更新时,MySQL可能因统计信息不准确而选错索引,导致全表扫描。文章深入解析了优化器判断扫描行数的机制,指出基数统计误差是主要原因,并提供了通过`analyze table`重新统计索引信息的解决方法。
137 3
|
前端开发 JavaScript
前端 JS 经典:箭头函数的意义
前端 JS 经典:箭头函数的意义
249 0
|
数据可视化 BI 定位技术
数据可视化系列-02各类图表的综合使用介绍及实践-下篇
数据可视化系列-02各类图表的综合使用介绍及实践-下篇
|
数据安全/隐私保护
BUUCTF [SWPU2019]伟大的侦探 1
BUUCTF [SWPU2019]伟大的侦探 1
347 0
|
自然语言处理 算法
Prompt for Extraction? PAIE: Prompting Argument Interaction for Event Argument Extraction 论文解读
在本文中,我们提出了一个既有效又高效的模型PAIE,用于句子级和文档级的事件论元抽取(EAE),即使在缺乏训练数据的情况下也能很好地泛化。
272 0
|
Java API Spring
在SockJS+Spring Websocket中convertAndSendToUser中的“用户”来自哪里?
我们知道可以使用客户端订阅的主题前缀从 stomp 服务器向客户端发送消息,例如 /topic/hello。我们还知道我们可以向特定用户发送消息,因为 spring 提供了convertAndSendToUser(username, destination, message)API。它接受一个字符串用户名,这意味着如果我们以某种方式为每个连接都有一个唯一的用户名,我们能够向订阅某个主题的特定用户发送消息。 那么,这个用户名来自哪里?或者说它是如何用这个用户名确定对应连接的?
337 0