OpenKruise:解放 DaemonSet 运维之路

简介: # 前言 [OpenKruise](https://github.com/openkruise/kruise) 是阿里云开源的大规模应用自动化管理引擎,在功能上对标了 Kubernetes 原生的 Deployment/StatefulSet 等控制器,但 OpenKruise 提供了更多的增强功能如 优雅原地升级、发布优先级/打散策略、多可用区workload抽象管理、统一 sidecar

前言


OpenKruise 是阿里云开源的大规模应用自动化管理引擎,在功能上对标了 Kubernetes 原生的 Deployment/StatefulSet 等控制器,但 OpenKruise 提供了更多的增强功能如 优雅原地升级、发布优先级/打散策略、多可用区workload抽象管理、统一 sidecar 容器注入管理等,都是经历了阿里巴巴超大规模应用场景打磨出的核心能力。这些 feature 帮助我们应对更加多样化的部署环境和需求、为集群维护者和应用开发者带来更加灵活的部署发布组合策略。


目前在阿里巴巴内部云原生环境中,应用全部统一使用 OpenKruise 的能力做 Pod 部署、发布管理,而不少业界公司和阿里云上客户由于K8s原生 Deployment 等负载不能完全满足需求,也转而采用 OpenKruise 作为应用部署载体。我们希望 OpenKruise 能让每一位 Kubernetes 开发者和阿里云上的用户都能便捷地使用上阿里巴巴内部云原生应用所统一使用的部署发布能力!


背景


如何在 Kubernetes 集群中部署节点组件呢?相信大家对 DaemonSet 并不陌生,它能够帮助我们将定义好的 Pod 部署到所有符合条件的 Node 上,这大大解放了过去我们维护节点上各类守护进程的痛苦。


在阿里巴巴内部的云原生环境中,存在不少网络、存储、GPU、监控等等相关的节点组件都是通过 DaemonSet 部署管理的。但是随着近两年 Kubernetes 集群规模越来越大,所有核心业务逐渐全量上云原生之后,我们越发感受到原生 DaemonSet 很难满足大规模、高可用的复杂场景需求。


大家可以理解为原生的 DaemonSet 确实解决了 0 -> 1 的问题,避免了直接管理 Node 上各类软件包和守护进程的难题,能做到用一致化的 Pod 来部署节点组件。但是在部署之后呢,我们面临的是 1 -> N 的不断迭代升级的问题了,而在升级能力方面,原生 DaemonSet 做的实在有些敷衍了事的感觉。


apiVersion: apps/v1
kind: DaemonSet
spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
  maxUnavailable: 2

# ...


apiVersion: apps/v1
kind: DaemonSet
spec:
updateStrategy:
type: OnDelete

# ...


以上是原生 DaemonSet 支持的两种升级方式。相信多数人使用 DaemonSet 基本都是默认的 RollingUpdate 滚动升级,这本身是没问题的,问题就在于滚动升级时只支持了 maxUnavailable 一个策略,这就让我们很难接受了。目前阿里巴巴内的 Kubernetes 不少已经做到单集群上万节点,这些节点可能有不同的机型、拓扑、核心程度、内核版本等等,而 DaemonSet 升级也覆盖到这上万节点上的 daemon Pod、涉及所有节点上的应用 Pod。


面对如此复杂和规模化的环境,原生 DaemonSet 没有灰度、没有分批、没有暂停、没有优先级,仅仅用一个 maxUnavailable 策略显然是无法满足的。要知道 daemon Pod 即使配置了 readinessProbe 往往也只能检查容器内进程是否启动运行,而对于进程的运行情况很难考量。
因此,即使 DaemonSet 发布了一个代码有bug的版本,只要进程能正常启动则 maxUnavailable 策略就无法保护,DaemonSet 会一直发布下去;如果升级开始了一段时间后才发现到问题,那此时很可能故障范围就已经覆盖到整个集群了。


为了避免这个问题,我们曾经一度改为使用 OnDelete 策略、在发布平台上控制发布顺序和分批,但终态上我们还是希望将 workload 的能力下沉归还到 workload,形成闭环,避免将完整的能力分散到多个模块。因此随着 OpenKruise 的成熟和在阿里内外的铺开,我们总结了内部对 DaemonSet 的通用化发布需求、将其沉淀到 OpenKruise 中,我们称之为 Advanced DaemonSet。


目前阿里巴巴和蚂蚁集团内部的大部分 DaemonSet 都已经统一到 Advanced DaemonSet 部署管理,并且随着 OpenKruise v0.6.0 版本的推出之后,外部一些公司如位于以色列的 Bringg 都已经开始对接使用。


能力解析


目前 Advanced DaemonSet 中主要增加的 API 字段如下:


const (
// StandardRollingUpdateType replace the old daemons by new ones using rolling update i.e replace them on each node one after the other.// this is the default type for RollingUpdate.StandardRollingUpdateType RollingUpdateType = "Standard"// SurgingRollingUpdateType replaces the old daemons by new ones using rolling update i.e replace them on each node one// after the other, creating the new pod and then killing the old one.SurgingRollingUpdateType RollingUpdateType = "Surging"
)

// Spec to control the desired behavior of daemon set rolling update.
type RollingUpdateDaemonSet struct {

// Type is to specify which kind of rollingUpdate.

Type RollingUpdateType json:"rollingUpdateType,omitempty" protobuf:"bytes,1,opt,name=rollingUpdateType"

// ...
MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,2,opt,name=maxUnavailable"`
// A label query over nodes that are managed by the daemon set RollingUpdate.// Must match in order to be controlled.// It must match the node's labels.Selector *metav1.LabelSelector json:"selector,omitempty" protobuf:"bytes,3,opt,name=selector"// The number of DaemonSet pods remained to be old version.// Default value is 0.// Maximum value is status.DesiredNumberScheduled, which means no pod will be updated.// +optionalPartition *int32 json:"partition,omitempty" protobuf:"varint,4,opt,name=partition"// Indicates that the daemon set is paused and will not be processed by the// daemon set controller.// +optionalPaused *bool json:"paused,omitempty" protobuf:"varint,5,opt,name=paused"// Only when type=SurgingRollingUpdateType, it works.// The maximum number of DaemonSet pods that can be scheduled above the desired number of pods// during the update. Value can be an absolute number (ex: 5) or a percentage of the total number// of DaemonSet pods at the start of the update (ex: 10%). The absolute number is calculated from// the percentage by rounding up. This cannot be 0. The default value is 1. Example: when this is// set to 30%, at most 30% of the total number of nodes that should be running the daemon pod// (i.e. status.desiredNumberScheduled) can have 2 pods running at any given time. The update// starts by starting replacements for at most 30% of those DaemonSet pods. Once the new pods are// available it then stops the existing pods before proceeding onto other DaemonSet pods, thus// ensuring that at most 130% of the desired final number of DaemonSet pods are running at all// times during the update.// +optionalMaxSurge *intstr.IntOrString json:"maxSurge,omitempty" protobuf:"bytes,7,opt,name=maxSurge"
}

type DaemonSetSpec struct {

// ...
// BurstReplicas is a rate limiter for booting pods on a lot of pods.// The default value is 250BurstReplicas *intstr.IntOrString json:"burstReplicas,omitempty" protobuf:"bytes,5,opt,name=burstReplicas"
}

按节点灰度


在一个大规模 Kubernetes 集群中往往存在很多种差异化的节点类型,比如机型、拓扑、核心程度、内核版本等,因此在 DaemonSet 发布的时候我们支持根据 Node 的标签来匹配发布哪些 Node 上的 Pod。


apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
spec:
# ...
updateStrategy:
type: RollingUpdate
rollingUpdate:
  selector:
    matchLabels:
      nodeType: canary</code></pre>

比如上述配置了滚动升级下的 selector 策略,则 DaemonSet 只会在符合 selector 条件的 Node 上把 Pod 做滚动升级。如果 selector 改变,则 DaemonSet 会按照新的 selector 做升级,对已经是最新版本的 Pod 不会做变动。


因此,用户可以通过多次修改 selector,来实现不同类型 Node 的前后发布顺序。这个优先顺序可以是特定一批用于灰度的非核心节点,也可以是一些逻辑资源池等。


按数量灰度


如果说你不关心节点类型,Advanced DaemonSet 同样提供了按数量灰度的能力:


apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
spec:
# ...
updateStrategy:
type: RollingUpdate
rollingUpdate:
  partition: 100</code></pre>

这里的 partition 和 OpenKruise 中其他 CloneSet、Advanced StatefulSet 类似,都表示了维持旧版本的数量,也就是说 Kruise 控制器会选择 status.DesiredNumberScheduled - partition 数量的 Pod 滚动升级为新版本。


比如当前集群中 DaemonSet 部署的节点数量是 120 个,当滚动升级时如果设置了 partition 为 100,则 DaemonSet 只会选择 20 个 Pod 滚动到新版本。只有当用户再次下调 partition,DaemonSet 才会继续按要求数量来继续升级。


多维度灰度


上述两种灰度策略相信都不难理解,那么如果同时配置了按节点和按数量两种灰度策略,会怎么样呢?


apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
spec:
# ...
updateStrategy:
type: RollingUpdate
rollingUpdate:
  maxUnavailable: 5
  partition: 100
  selector:
    matchLabels:
      nodeType: canary</code></pre>

想搞清楚这个问题,其实看懂 Advanced DaemonSet 的发布策略计算逻辑就很好理解了,有兴趣的同学可以跳去看一下:https://github.com/openkruise/kruise/blob/master/pkg/controller/daemonset/update.go#L459


参考上面这个 YAML,如果用户同时配置了 partition 和 selector,那么控制器在发布的时候会先按照 selector 匹配符合条件的 Node,再按照 partition 计算其中能够发布的数量。当然,如果你还配置了原生 DaemonSet 就支持的 maxUnavailable,那么最后还会按照 unavailable 的数量再次限制实际能滚动升级的数量。


简单来说,最终真正执行滚动升级的 Pod,一定是要同时满足所有配置的灰度策略。


热升级


标准的 DaemonSet 滚动升级过程,是通过先删除旧 Pod、再创建新 Pod 的方式来做的。在绝大部分场景下这样的方式都是可以满足的,然而如果这个 daemon Pod 的作用还需要对外提供服务,那么滚动的时候可能对应 Node 上的服务就不可用了。


为了提供高可用能力,我们对 DaemonSet 也提供了 surging 发布策略。(回顾一下原生 Deployment 或者 OpenKruise 的 CloneSet,在这些面向无状态服务的 workload 中如果配置了 maxSurging,则发布时会先多扩出来 maxSurging 数量的 Pod,再逐渐删掉旧版本的 Pod)


apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
spec:
# ...
updateStrategy:
rollingUpdate:
  type: Surging  # defaults to Standard
  maxSurge: 30%</code></pre>

首先,在滚动升级中配置 type: Surging,这个类型默认是 Standard -- 也就是先删再扩,而一旦设置为 Surging 则变为先扩再缩。也就是在滚动升级时,DaemonSet 会先在要发布的 Node 上新建一个 Pod,等这个新版本 Pod 变为 ready 之后再把旧版本 Pod 删除掉。


另外在流式的策略上,maxUnavailable 是用于 Standard 类型的,对应了在滚动升级时最多在多少个 Node 上删除 Pod。而 maxSurge 策略是用于 Surging 类型的,对应了在滚动升级时最多在多少个 Node 上多扩出一个 Pod。


发布暂停


此外,Advanced DaemonSet 还支持了 paused 一键暂停发布。这个比较好理解,就不细表述了。


apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
spec:
# ...
updateStrategy:
rollingUpdate: paused: true</code></pre>

总结


总的来看,OpenKruise 在原生 DaemonSet 基础上增加了一系列面向生产场景的发布策略,让 DaemonSet 的升级过程更加安全、可控、自动化。


Advanced DaemonSet 发布能力.png


后续 OpenKruise 还会持续在应用部署/发布能力上做出更深的优化,我们也欢迎每一位云原生爱好者来共同参与 OpenKruise 的建设。与其他一些开源项目不同,OpenKruise 并不是阿里内部代码的复刻;恰恰相反,OpenKruise Github 仓库是阿里内部代码库的 upstream。因此,每一行你贡献的代码,都将运行在阿里内部的所有 Kubernetes 集群中、都将共同支撑了阿里巴巴全球顶尖规模的云原生应用场景!

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3月前
|
人工智能 运维 自然语言处理
对话蚂蚁开源蒋炜:让 Agent 把运维人员从 24 小时的待命中解放出来
当整个行业的智慧都集中在一件事情上时,比起闭门造车,开源一定能带来更好的技术迭代和发展。CodeFuse 「编码挑战季」活动火热进行中,诚邀广大开发者们参与编码挑战
140 3
对话蚂蚁开源蒋炜:让 Agent 把运维人员从 24 小时的待命中解放出来
|
7月前
|
运维 监控 安全
自动化运维:解放双手,提升效率
【6月更文挑战第19天】本文将深入探讨自动化运维的重要性和优势,以及如何实现自动化运维。我们将从自动化运维的定义开始,然后讨论它的优势,包括提高效率、减少错误、节省成本等。接下来,我们将详细介绍如何实现自动化运维,包括选择合适的工具和技术、设计自动化流程、测试和优化等步骤。最后,我们将通过一个实际案例来展示自动化运维的实施过程和效果。
|
7月前
|
运维 监控
自动化运维:解放双手,提升效率
【6月更文挑战第18天】在数字化时代,运维工作的复杂性和重要性日益凸显。传统的人工运维方式已经难以满足现代企业的需求。自动化运维作为一种新兴的运维模式,通过引入自动化工具和技术,实现对IT资源的高效管理。本文将介绍自动化运维的概念、优势以及实施步骤,帮助读者更好地理解和应用自动化运维。
|
运维 数据挖掘 BI
【Dataphin运维】解放双手,支持补数据任务定时调度和手动运行,轻松实现回刷历史数据
Datatphin V3.11版本全新上线补数据任务功能,支持将单次补数据保存为补数据任务,保存补数据节点范围及运行规则;支持补数据任务定时调度,自动定期回刷历史数据;支持手动运行补数据任务。满足企业复杂多样的回刷历史数据的需求,减少人工操作成本。
259 0
|
JSON Kubernetes Cloud Native
OpenKruise:解放 DaemonSet 运维之路
我们希望 OpenKruise 让每一位 Kubernetes 开发者和阿里云上的用户都能便捷地使用上阿里巴巴内部云原生应用所统一使用的部署发布能力!
10328 0
OpenKruise:解放 DaemonSet 运维之路
|
弹性计算 运维 Java
【流水线入门】解放运维,一键部署
阿里云云效流水线,降低运维工作量,让运维解放出来做更有意义的事
611 0
【流水线入门】解放运维,一键部署
|
3月前
|
运维 Linux Apache
,自动化运维成为现代IT基础设施的关键部分。Puppet是一款强大的自动化运维工具
【10月更文挑战第7天】随着云计算和容器化技术的发展,自动化运维成为现代IT基础设施的关键部分。Puppet是一款强大的自动化运维工具,通过定义资源状态和关系,确保系统始终处于期望配置状态。本文介绍Puppet的基本概念、安装配置及使用示例,帮助读者快速掌握Puppet,实现高效自动化运维。
73 4
|
6天前
|
人工智能 运维 监控
AI辅助的运维流程自动化:实现智能化管理的新篇章
AI辅助的运维流程自动化:实现智能化管理的新篇章
295 22
|
2月前
|
机器学习/深度学习 运维 监控
智能化运维:从自动化到AIOps的演进之路####
本文深入探讨了IT运维领域如何由传统手工操作逐步迈向高度自动化,并进一步向智能化运维(AIOps)转型的过程。不同于常规摘要仅概述内容要点,本摘要将直接引入一个核心观点:随着云计算、大数据及人工智能技术的飞速发展,智能化运维已成为提升企业IT系统稳定性与效率的关键驱动力。文章详细阐述了自动化工具的应用现状、面临的挑战以及AIOps如何通过预测性分析和智能决策支持,实现运维工作的质变,引领读者思考未来运维模式的发展趋势。 ####
|
2月前
|
机器学习/深度学习 数据采集 人工智能
智能化运维:从自动化到AIOps的演进与实践####
本文探讨了智能运维(AIOps)的崛起背景,深入分析了其核心概念、关键技术、应用场景及面临的挑战,并对比了传统IT运维模式,揭示了AIOps如何引领运维管理向更高效、智能的方向迈进。通过实际案例分析,展示了AIOps在不同行业中的应用成效,为读者提供了对未来智能运维趋势的洞察与思考。 ####
105 1

热门文章

最新文章

下一篇
开通oss服务