EMQX 在 Kubernetes 中如何进行优雅升级
背景
为了降低 EMQX 在 Kubernetes 上的部署、运维成本,我们将一些日常运维能力进行总结、抽象并整合到代码中,以 EMQX Kubernetes Operator 的方式帮助用户实现 EMQX 的自动化部署和运维。
此前,EMQX Kubernetes Operator v1beta1、v1beta2、v1beta3 的升级策略均为滚动升级,相关升级流程如下:

问题分析
滚动升级在生产环境中可能会面临以下问题:
- 升级过程中会逐个销毁旧的节点再创建新的节点,因此可能导致客户端多次断连(最糟糕的情况下断连次数与节点数量一致),从而影响用户体验。
- 当集群处于较高连接的情况下,一个节点被销毁,那么该节点上面的连接会在瞬间断开,由客户端重试逻辑来进行重连;当单节点连接数较大时,如果大量客户端进行重连,则可能会给服务端造成压力导致过载。
- 升级完成后,各节点间的负载不均衡(如上图:emqx-ee-0 在升级过程中,客户端可能会进行重连,此时由于 emqx-ee-0 还未就绪,因此可能连接到 emqx-ee-1 或者 emqx-ee-2,升级完成后 emqx-ee-0 上可能只有较少负载或者无负载),从而打破业务容量模型的规划,可能影响到服务。
- 由于使用 StatefulSets 进行部署,在升级过程中提供服务的节点会比实际节点要少一个(影响到用户的业务模型),这可能会增加服务端的一些压力。
如果上面几个步骤的问题叠加(多次断连与大量断连的客户端不停的重试连接),则可能会放大客户端重连的规模,从而造成服务端过载或雪崩。
下图是在现有升级模式下连接数的监控图(在不同的业务中会存在差异,比如后端依赖的不同资源、服务器配置、客户端重连或重试策略等,均会带来一些不同的影响)。其中:
- sum:总的连接数,图中最上面的一条线
- emqx-ee-a:前缀表示的是升级前 3 个 EMQX 节点
- emqx-ee-b:前缀表示的是升级后 3 个 EMQX 节点

在上图中,当我们开始执行滚动升级时,首先 emqx-ee-a-emqx-ee-2 进行销毁,并创建新的 emqx-ee-b-emqx-ee-2,此时仅有 emqx-ee-a-emqx-ee-1、emqx-ee-a-emqx-ee-0 能够提供服务,当客户端进行重连时,LB 会将流量转移到 emqx-ee-a-emqx-ee-0、emqx-ee-a-emqx-ee-1 上面,因此我们能够看到 emqx-ee-a-emqx-ee-1、emqx-ee-a-emqx-ee-0 有明显的流量上升,当后面更新这两个 pod 时,意味着客户端可能多次断连。由于新 pod 建立的过程存在着时间差,以上图为例,emqx-ee-a-emqx-ee-0 最后升级,当升级完成后,可能客户端已经完成重试、重连,此时主要连接已经被另两个 pod 接纳,因此会导致 pod 之间流量不均衡,从而影响到用户业务模型的评估,或者影响到服务。
为了方便展示,我们未压测大量连接模拟重连、导致服务端过载的场景(在实际生产环境中可能遇到,TPS 超过云端规划的容量模型),但从连接数监控图上,我们依然看到一个大缺口,说明对业务产生了较大影响。因此我们需制定一种方案来规避以上几个问题,保障升级过程中的平滑稳定。
问题解决
目标
- 升级过程中实现连接数可控迁移(可根据服务端处理能力设置相应的迁移速率)。
- 升级过程中减少连接断开的次数(一次断连)。
- 在整个升级的过程中始终保持预期的节点来提供服务。
- 升级完成后,不需要集群负载重平衡,各节点间的连接相对均衡(与 LB 调度策略有一定关系)。
方案设计
蓝绿发布是一种同时运行两个版本应用的发布策略。EMQX Kubernetes Operator 近日在 2.1.0 版本中实现了 EMQX Enterprise 的蓝绿发布,即从现有的 EMQX Enterprise 集群开始,创建一套新版本的 EMQX Enterprise 集群,在这一过程中不停止掉老版本,等新版本集群运行起来后,再将流量逐步平滑切换到新版本上。
从 4.4.12 版本开始,EMQX 企业版本支持节点疏散功能。节点疏散功能允许用户在关闭节点之前强制将连接和会话以一定速率迁移到其他节点,以避免节点关闭带来的会话数据丢失。
关于节点疏散更多信息请参考相关文档
在 Kubernetes 上我们通过模拟蓝绿发布以及结合节点疏散功能,实现了连接可控迁移,极大减少了断连的次数(仅断连一次)。相关升级流程图如下:

整个升级流程大致可分为以下几步:
- 升级时(镜像、Pod 相关资源修改调整)我们会先创建一个同规格的节点加入到现有集群中。
- 当新节点全部就绪后,我们将 service 全部指向新创建的节点,此时新节点开始接受新的连接请求。
- 将旧节点从 service 中摘出,此时旧节点不再接收新的连接请求。
- 通过 EMQX 节点疏散功能,逐个对节点上的连接进行可控迁移,直至连接全部完成迁移,再对节点进行销毁。
操作流程
节点疏散是 EMQX Enterprise 4.4.12 开始支持的新特性,EMQX Kubernetes Operator 在 2.1 版本中对该能力进行适配,如需使用该能力,请将 EMQX 升级到企业版 v4.4.12,EMQX Kubernetes Operator 升级到 v2.1。
- 配置蓝绿升级
apiVersion: apps.emqx.io/v1beta4
...
spec:
blueGreenUpdate:
initialDelaySeconds: 60
evacuationStrategy:
waitTakeover: 5
connEvictRate: 200
sessEvictRate: 200
...
initialDelaySeconds :所有的节点就绪后(蓝绿节点),开始节点疏散前的等待时间 (由于切换 Service 后,LoadBalancer 需要时间来处理 service 与 pod 的关系)(单位:秒)
waitTakeover :所有连接断开后,等待客户端重连以接管会话的时间(单位:秒)
connEvictRate :客户端每秒断开连接速度
sessEvictRate:waitTakeover 之后每秒会话疏散速度
详情可参考:Operator 文档
升级过程中连接数监控图如下(本次测试以 10 万连接进行):

sum:总的连接数,图中最上面的一条线
emqx-ee-86d7758868:前缀表示的是升级前的 3 个 EMQX 节点
emqx-ee-745858464d:前缀表示升级后的 3 个 EMQX 节点
如上图,我们通过 EMQX Kubernetes Operator 的蓝绿发布在 Kubernetes 中实现了优雅升级,通过该方案升级,总连接数未出现较大抖动(取决于迁移速率、服务端能够接收的速率、客户端重连策略等),能够极大程度保障升级过程的平滑,有效防止服务端过载,减少业务感知,从而提升服务的稳定性。
注:由于升级后的集群,三个节点负载较平均,因此上图三条线重叠在了一起。
结语
通过采用节点疏散功能结合模拟蓝绿发布,本文所提供的方案解决了普通升级导致的多次断连和可能的服务过载与负载不均问题,实现了在 Kubernetes 上优雅的升级。
作为一个自动化管理工具,EMQX Kubernetes Operator 旨在帮助用户轻松创建和管理 EMQX 集群,充分享受 EMQX 的强大产品能力。通过本文方案完成 EMQX 的升级,用户可以进一步体验 EMQX 的最新特性,构建创新物联网应用。
版权声明: 本文为 EMQ 原创,转载请注明出处。
原文链接:https://www.emqx.com/zh/blog/how-to-upgrade-emqx-in-kubernetes
EMQX 在 Kubernetes 中如何进行优雅升级的更多相关文章
- 如何将云原生工作负载映射到 Kubernetes 中的控制器
作者:Janakiram MSV 译者:殷龙飞 原文地址:https://thenewstack.io/how-to-map-cloud-native-workloads-to-kubernetes- ...
- Kubernetes 中的核心组件与基本对象概述
Kubernetes 是 Google 基于 Borg 开源的容器编排调度,用于管理容器集群自动化部署.扩容以及运维的开源平台.作为云原生计算基金会 CNCF(Cloud Native Computi ...
- StatefulSet: Kubernetes 中对有状态应用的运行和伸缩
在最新发布的 Kubernetes 1.5 我们将过去的 PetSet 功能升级到了 Beta 版本,并重新命名为StatefulSet.除了依照社区民意改了名字之外,这一 API 对象并没有太大变化 ...
- [转帖]Kubernetes中安装Helm及使用
Kubernetes中安装Helm及使用 2018年07月02日 17:41:09 灬勿忘丶心安 阅读数 3699更多 分类专栏: K8S 版权声明:本文为博主原创文章,遵循CC 4.0 BY-S ...
- Helm, 在Kubernetes中部署应用的利器
一.背景 Kubernetes(k8s)是一个基于容器技术的分布式架构领先方案.它在Docker技术的基础上,为容器化的应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,提高了大规模容器 ...
- Kubernetes中Service的使用
目录 简介 1. Service资源定义 1.1 Service Type ClusterIP 无头service NodePort sessionAffinity实现源地址session绑定 简介 ...
- Kubernetes中予许及限制(PodSecurityPolicy)使用宿主机资源
1.在pod中使用宿主机命名空间.端口等资源 pod中的容器通常在分开的Linux命名空间中运行.这些命名空间将容器中的进程与其他容器中,或者宿主机默认命名空间中的进程隔离开来. 例如,每一个pod有 ...
- 如何发现 Kubernetes 中服务和工作负载的异常
大家好,我是来自阿里云的李煌东,今天由我为大家分享 Kubernetes 监控公开课的第二节内容:如何发现 Kubernetes 中服务和工作负载的异常. 本次分享由三个部分组成: 一.Kuberne ...
- Kubernetes 中部署 NFS-Subdir-External-Provisioner 为 NFS 提供动态分配卷
文章转载自:http://www.mydlq.club/article/109/ 系统环境: 操作系统: CentOS 7.9 Docker 版本: 19.03.13 Kubernetes 版本: 1 ...
- 在C#中实现软件自动升级
在C#中实现软件自动升级 winform程序相对web程序而言,功能更强大,编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,本文结合实际情况,通过软件实现自动升级,弥补了这一缺陷,有较好的 ...
随机推荐
- P4525 【模板】自适应辛普森法 1
\(\text{Solution}\) 题目 \(\text{Simpson}\) 公式: \[\int_l^r f(x) {\mathrm d}x = \frac{(r-l)(f(l)+f(r)+4 ...
- layui 手机端时间不能滑动问题
// 滑动问题 .laydate-time-list ol{overflow-x: hidden !important ;overflow-y: auto !important ;} //去除秒的显示 ...
- .net 中的几种事务
在一个MIS系统中,没有用事务那就绝对是有问题的,要么就只有一种情况:你的系统实在是太小了,业务业务逻辑有只要一步执行就可以完成了.因此掌握事务处理的方法是很重要,进我的归类在.net中大致有以下4种 ...
- yarn的基础语法:yarn安装完vue cli3后提示不是内部命令
: 第一步:安装nodejs: 第二步:全局安装vue-cli 解决方案: 全局搜索vue.cmd 将vue.cmd所在的路径添加到环境变量Path后面.再执行vue -V即可.
- django我学习的第一个web框架
第一个APP----------联通后台管理系统 第二个APP----------baby商场
- 【树莓派】在vscode中连接树莓派并编写代码
在树莓派里编写代码的话会比较麻烦因此可以在vscode中通过ssh连接树莓派并且编辑代码 参考: vscode通过ssh连接树莓派实现远程开发 VSCODE 远程开发树莓派 使用vscode打造pyt ...
- 关于fetch请求中非表单模式(form)转化为form格式请求成功问题
首先证实一下接口请求可以成功,postman掉通 2.证实接口可以掉通之后,来发现问题 发现根本不是form表单格式3.去操作实现form表单格式 发现form格式貌似已经转换,但是请求还是不对 最后 ...
- web实践学习3
web实践学习3 20201303张奕博 2023.1.26 创建树 从预览动图和页面可以看到,浮岛上共有两种树 ,绿色的高树和粉红色的矮树,树的实现也非常简单,是使用了两个 BoxBufferGeo ...
- 前端日期控件,在设置了readonly的情况,还能选择日期的解决办法
去掉只读和增加onclick属性: $("#date").removeAttr("readonly"); $("#date").attr(& ...
- git remote prune origin删除本地有但在远程库已经不存在的分支
先调用git remote show origin 该命令能够获取远端分支信息,你可以看到和本地和远端不同步的地方: 过时的就是和本地不同步的分支,本地已过时的表示你需要移除这个分支了. 这个时候你需 ...