单节点K8s迁移上云实战:准不停服迁移与JMeter压测验证

发布时间:2026/9/18 0:54:01
单节点K8s迁移上云实战:准不停服迁移与JMeter压测验证 制造业上云这件事听起来是个宏大的战略叙事但落在我们这些具体干活的人头上往往就是一句话的事把一套正在运行的系统从旧环境搬到云上而且老板只给了两个要求——业务尽量不停数据一条不能少。我最近就接了一个这样的活迁移对象是单节点 K8s 上的一套基于若依微服务框架搭建的工业互联网平台目标环境是阿里云 ECS。整个过程中踩了不少坑也沉淀出一些可复用的方法。这篇就掰开揉碎讲一讲从方案选型、迁移步骤到迁移后的高并发压测验证全部复盘一遍希望能给正在做类似迁移的朋友一些参考。1. 这次迁移的本质工业互联网平台为什么要“准不停服”上云1.1 先盘清楚我们到底在迁移什么我接手这套系统的时候先没急着动手而是把家底盘了一遍。这是一套典型的若依微服务架构拆分成了十几个服务包括网关、认证中心、系统管理、设备采集、报表服务等。中间件层面依赖 MySQL、Redis、Nacos还有一堆静态资源和上传文件整体跑在一台单节点的 K8s 集群上用 Kubeadm 搭建etcd 也在同一台机器上属于典型的“麻雀虽小五脏俱全”部署。说到底这套结构本身并不复杂复杂的是它承载的业务。这套系统服务的不是一个普通网站而是一个工厂车间的生产管理和设备监控平台属于工业互联网平台的典型落地场景。生产线上几十台设备的实时运行数据、报警记录、产品质量追溯、工单流转全都依赖这套系统。这意味着什么意味着不能随便停。生产车间是连续运行的哪怕停半小时工人可能还能忍受但如果数据丢了比如一批产品的追溯记录不完整那后面出质量问题都查不到源头这个责任谁都背不起。所以“准不停服、不丢数据”不是客户提的过分要求而是这个行业场景的底线。单节点 K8s 本身是有风险的机器一挂整个平台就瘫了没有高可用可言。上云的核心诉求其实是要把这份单点风险转嫁掉让平台具备横向扩展的可能同时保留历史数据不影响生产连续性。1.2 “准不停服”到底是一个什么标准很多人一听到“不停服”就非常头疼觉得怎么可能做到零停机。我做的时候跟业务方确认了一下“准不停服”的准字到底怎么量化。最后定下来的口径是切换窗口期间允许短暂停写但全程不允许影响已采集数据的完整性和连续性整个切换过程尽量控制在 20 分钟以内而且挑在车间换班或者计划性停产的间隙来做。这里要强调一点“准不停服”不等于“零停机”而是尽量缩短不可用时间同时保证数据不丢失。实际操作上我们用“整库备份 binlog 增量同步 文件增量同步 最终一致性校验”的组合把不可用窗口压缩到了分钟级。这里面最关键的不是最后的切换操作而是前面准备阶段是否把增量同步做扎实了。1.3 为什么选阿里云 ECS 而不是容器托管服务当时也有人问既然上云为什么不直接用托管的 Kubernetes 服务这里面有个现实考量原系统是自建的在单节点 K8s 上运维人员对 Kubeadm 裸集群更熟悉直接迁移到托管集群虽然省了 Master 节点维护但网络插件、存储类、负载均衡的用法都有差异反而会引入更多变量。ECS 上重建一套同样架构的 K8s 集群学习成本最低风险最可控。而且 ECS 本身就是阿里云的基础计算产品云端资源池天然具备弹性和扩展能力后续扩容也方便。我在这一步的决策原则是能用成熟工具就用成熟工具能少改就少改。目标是让迁移本身足够“无感”而不是借机上大改造。2. 迁移准备方案选型和关键决策2.1 先盘点单节点 K8s 的“家底”别凭感觉定方案很多人在迁移时容易犯一个错误上来就开始备份结果迁移到一半发现有些数据不在预期位置。我在动手之前先做了一个详细清单把系统里所有需要迁移的对象分成了几类迁移对象内容包括存放位置迁移方式Kubernetes 资源对象Deployment、Service、ConfigMap、Secret、PVC、IngressetcdYAML 导出重建容器镜像业务服务镜像、中间件镜像Registry推送/拉取关系型数据MySQL 业务库宿主机挂载的 PV 或本地盘逻辑备份 binlog 增量缓存数据Redis 缓存、Token、Session本地持久化目录RDB 快照 AOF文件数据设备图片、报表文件、上传附件对象存储或宿主机目录rsync 增量同步配置信息网关路由、微服务配置Nacos、ConfigMap配置导出导入这个清单列完后我心里就有底了。这里面最容易出问题的就是数据文件尤其是 MySQL 和 Redis因为它们有状态数据强一致性的要求高。K8s 里的 Pod 本身是无状态的重建很容易关键是这些有状态组件的数据怎么平滑搬过去。2.2 备份策略不是“做不做”而是“做几份”数据不丢这件事靠的不是运气是冗余的备份机制。我当时做了三道防线。第一道是数据库层的全量备份用 mysqldump 以单事务模式导出保证备份期间不影响线上写入同时记录 binlog 位置。第二道是操作系统的文件级快照把 MySQL 数据目录和 Redis 持久化文件直接打包。第三道是 K8s 对象资源的导出所有 Deployment、Service、Ingress 等 YAML 全部提取出来存成 Git 仓库里的文件这等于给整个环境的“定义”也做了一份版本化备份。有些同行可能会觉得直接用云平台的数据传输服务不就行了为什么还要在本地再做备份我的个人习惯是本地永远留一份完整的“兜底”。云服务再方便也不能保证数据不出问题特别是跨环境迁移时源和目标之间的差异可能会让你意想不到。多一道备份就多一条退路。2.3 为什么首选“重建目标环境 增量同步”路线迁移方案我其实评估了好几种。第一种是 Velero 整集群备份恢复这是 K8s 生态里比较标准的灾备工具但问题在于 Velero 的 Restic 备份对单节点本地 PV 的处理效率不高而且目标集群的 CSI 插件不一定对得上恢复时容易出现 PVC 绑定异常。第二种是直接把原节点整机做成系统镜像再把它迁移到云上这个方案虽然“做过”的人很多但底层的硬件驱动、内核模块变化都会引发不稳定而且它只是把原来的单点故障搬到了云上并没有真正解决架构问题。第三种就是我最终选的路线在目标 ECS 上重建一套干净的标准 K8s 集群然后用数据同步手段把业务数据迁移过去最后切换流量。这条路线的好处很明显目标环境是“干净”的可以顺便把网络、存储、安全组都按生产标准配置一遍数据同步可以通过数据库复制、文件增量同步来保证持续性切换前还可以在目标环境先做预演发现问题提前解决。坏处是工作量相对大一些但对工业互联网这种对稳定性要求很高的场景这点工作量是值得的。3. 动手迁移一套可执行的完整操作流程3.1 在阿里云 ECS 上重建 K8s 集群的要点目标环境我规划了三台 ECS一台用于运行主控节点和部分中间件另外两台作为工作节点承载微服务 Pod。选择的规格按业务负载预估CPU 内存型为主数据盘采用高效云盘并开启自动快照策略。这里特别提醒一句重建集群时K8s 的版本最好和源环境保持一致或者至少保证 APIVersion 兼容否则从旧环境导出的 YAML 可能因为 API 版本差异无法直接使用。集群搭好后第一步是把网络插件装好。我选的是 Calico因为源环境用的就是它Pod 网段和服务网段尽量保持一致这样后面积累的访问地址、网络策略基本不用改。镜像方面提前把私服上的镜像推送到阿里云容器镜像服务或者在 ECS 上直接拉取看实际情况决定。目标环境全部准备完毕后用 kubectl get nodes 检查节点状态确认所有节点 Ready再继续下一步。3.2 数据库迁移mysqldump 全量 binlog 增量MySQL 是这套系统的核心迁移难度也最大。源库和目标库之间我先做了全量基础同步。具体命令大概是这样的# 在源库执行全量逻辑备份--single-transaction 保证不锁表 mysqldump -uroot -p \ --single-transaction \ --routines \ --triggers \ --events \ --master-data2 \ --databases ruoyi_cloud /data/backup/ruoyi_full.sql # 查看备份文件中记录的 binlog 位置 grep MASTER_LOG_FILE /data/backup/ruoyi_full.sql拿到 MASTER_LOG_FILE 和 MASTER_LOG_POS 之后我把全量备份恢复到目标库mysql -uroot -p -h目标IP /data/backup/ruoyi_full.sql接下来是增量同步。这里有两种选择一种是直接配置 MySQL 主从复制在有公网互通能力的条件下把目标库配成源库的 Slave这样增量数据会持续同步另一种是手动记录 binlog 文件名和位置在切换前把这一段 binlog 应用到目标库。两种我都试过最稳妥的是直接做主从复制因为切换前可以一直观察主从延迟等到延迟归零再切换。配置主从的参考步骤-- 在源库创建复制账号 CREATE USER repl% IDENTIFIED BY StrongPass123; GRANT REPLICATION SLAVE ON *.* TO repl%; FLUSH PRIVILEGES; -- 在目标库执行 CHANGE MASTER TO MASTER_HOST源IP, MASTER_USERrepl, MASTER_PASSWORDStrongPass123, MASTER_LOG_FILEmysql-bin.000123, MASTER_LOG_POS123456789; START SLAVE;然后通过 SHOW SLAVE STATUS 查看 Seconds_Behind_Master直到它变成 0说明两个库已经基本一致。这一步完成后MySQL 的迁移就算完成了三分之一。为什么说三分之一因为后面还有业务服务和文件的切换一个环节出错都可能导致数据不一致。3.3 Redis 和文件数据怎么同步过去Redis 在业务里主要承担缓存和 Token 存储对数据一致性要求没那么高但也不能直接丢。稳妥做法是通过 RDB 快照加 AOF 追加方式同步。先在源 Redis 上执行 BGSAVE把 dump.rdb 拷贝到目标机目标 Redis 启动后加载这份快照然后打开 AOF 重放。如果需要准实时同步可以把源 Redis 配置为只读然后通过 Redis 主从复制方式持续同步但考虑到实际业务体量简单快照加切换后的缓存穿透兜底就足够了。文件数据的同步我用的是 rsync。工业互联网平台里一般会有大量设备图片、质检报告、导出文件等这些文件如果迁移不完整到了云端就会出现附件打不开的问题。我的做法是先用 rsync 做一次全量同步之后每 10 分钟执行一次增量同步保证大部分新文件都同步过去切换前再执行一次最终同步# 源服务器上执行 rsync -avz --progress \ /data/ruoyi/upload \ root目标IP:/data/whitelabel/upload/这里有个容易被忽略的点文件目录的属主和权限。K8s 里挂载的存储如果是 hostPath那么 Pod 运行时的 UID 必须能访问这些文件否则切换后会出现权限拒绝。我在这上面吃过一次亏后面单独排查了很久建议在同步文件后检查一下 owner 和 group最好用 ls -n 确认数值 UID/GID 保持一致。3.4 K8s 资源迁移把 YAML 从旧环境搬到新环境K8s 里的工作负载我并没有用备份恢复工具直接恢复而是基于之前导出的 YAML在目标环境重新 apply。这样做的好处是可以通过 Git 管理变更记录后续如果还要调整副本数、环境变量直接改 YAML 再 apply 即可整个过程是可控、可追溯的。我在导出 YAML 时用了一个技巧直接通过 kubectl 获取资源的 JSON 再用 yq 转换这样可以省去手写大量配置的工作量。比如kubectl get deploy -n ruoyi -o json | yq e .items[] | .metadata.name -然后把每一个 Deployment 的完整 YAML 导出来批量替换掉镜像仓库地址、环境变量、配置中心地址等与环境相关的字段再在目标环境逐个 apply。替换的时候尤其要注意 ConfigMap 和 Secret这些里面有些是 Base64 编码的敏感信息环境变了有些配置可能就要改。我在实际操作中把 Secret 全部重新生成了一遍而不是直接沿用旧值。3.5 切换窗口的十分钟到底在做什么所有同步工作做完、目标环境全部准备好之后就到了最关键的一步正式切换。切换时我选择了凌晨两点确认车间没有正在进行的关键生产批次然后开始按脚本操作。这个窗口期的操作顺序很重要稍微弄错一步就可能影响数据一致性甚至造成回滚困难。第一步在源端把对外服务停掉。我的做法是把入口 Nginx 或 K8s Ingress 的副本数直接缩到 0同时给接入层加一个“系统维护中”的提示页。这时用户已经进不来了但已经建立的连接可能还在传输所以我又等了几分钟让存量请求自然结束。第二步确认源业务流量已经归零停止所有微服务的定时任务避免还有后台任务在写库。第三步停止源 MySQL 的写入并确认主从同步已经追平Seconds_Behind_Master 为 0。第四步把最新的配置从源 Nacos 导出导入到目标环境的 Nacos。第五步把目标环境的 Ingress / 负载均衡流量切到新的 ECS 集群即把云上的公网 IP 或 SLB 的监听发到新集群的 NodePort / LoadBalancer 上。整个切换过程我卡了表从停止入口到新环境开始接管流量大约用了 12 分钟。原环境所有数据都还在目标环境也完整承接了新的读写请求可以说做到了“准不停服、不丢数据”。3.6 回滚预案出了问题怎么退回去所有生产变更都不能没有回滚方案哪怕你信心再足。我在切换前把回滚预案也写好了核心逻辑是源环境在切换过程中不销毁、不关停保留原样只把入口流量切走。如果新环境在观察期出现严重问题就直接把入口 Nginx 的流量切回源环境源环境的数据仍然完整业务可以继续在旧环境运行。这个方案听起来简单但实施时有两个前提。第一切换前必须停止源环境的写入否则源和目标的数据会分叉回滚后两边数据对不上。第二回滚后需要把切换期间产生的增量数据也就是目标环境接管期间写入的数据反向同步回源环境。这个反向同步过程比较麻烦实际中很少触发但预案里必须写清楚一旦真发生能按照既定步骤执行而不是临时拍脑袋。4. 迁移后的高并发压测用 JMeter 验证云端环境4.1 压测脚本从哪里来迁移完成后压测人员使用配套的 JMeter 脚本对整个云上环境做了高并发测试。这套脚本是从源环境“顺”过来的所谓顺不是直接拷过来就能用而是把脚本里的服务器地址、端口、请求路径等全部替换成新环境的参数再把关联的 CSV 数据文件、JAR 插件、断言规则都检查一遍。为什么强调这点因为很多 JMeter 脚本从低版本环境拷到高版本后插件路径和断言习惯都不一样直接打开运行很容易因为版本问题报错白白浪费时间。我在配合压测时做的事情比较简单先把目标环境的对外地址、微服务网关地址、登录认证接口梳理成一份接口清单然后帮压测人员确认压力机与目标 ECS 之间的网络连接是否通畅安全组是否放行了 JMeter 发送压力的端口。这些基础检查做完压测脚本才能真正跑起来。4.2 压测参数怎么定线程数、Ramp-Up 和循环次数压测不能上来就一股脑把线程数拉到很高否则压力机本身可能先成了瓶颈。我们这次按层级逐步加压第一步先测单接口稳定性比如登录接口、获取设备实时数据的接口设定线程数 100、Ramp-Up 60 秒、循环 10 次先看基础响应时间。第二步再按典型业务链路测比如用户登录、查询设备列表、查看设备详情、导出报表这条链路线程数逐渐加到 500。第三步才是极限测试把线程数拉到 2000观察系统在峰值压力下是否出现雪崩。关于 Ramp-Up 时间之前有同事问过是不是直接设成 0 就是最大压力其实不是。Ramp-Up 设为 0 会让所有线程在同一瞬间出发容易出现瞬时尖峰反而把压力机自身搞挂而且不符合真实用户的到达节奏。一般来说Ramp-Up 时长和线程数的比例大约控制在 1 线程 / 每秒到 2 线程 / 每秒左右比较平稳。压测场景线程数Ramp-Up秒循环次数预期观察指标轻量冒烟50305接口成功率 100%响应时间 500ms常规压力50030020TPS 稳定错误率 0.1%极限压力200060050吞吐量达到阈值确认瓶颈所在4.3 从压测结果里能看到什么压测最终目的是验证云上环境能否支撑业务承载。我们重点关注四个指标TPS、响应时间、错误率、资源利用率。第一轮常规压力测试时发现有个报表导出接口响应时间直接飙到了 5 秒以上TP99 比较难看。后来定位到是报表服务没有开启分页查询一次拉出全部数据再内存聚合数据库压力瞬间升高。这个在旧环境因为访问量少没暴露出来到了云上并发一上来就现了原形。后来对这个接口做了优化加上分页和异步导出响应时间降到 800 毫秒以内同时调整了服务副本数通过 HorizontalPodAutoscaler 根据 CPU 使用率自动扩容。压测第二轮的 TPS 明显提升说明云上的弹性伸缩机制是生效的。这里也想提醒大家一句压测不只是为了看数字更是为了在真实上云后暴露架构上的短板。一个系统平时单机跑得很顺不代表并发 2000 时还能撑住这恰恰是做压测的价值所在。5. 复盘与避坑这次迁移我学到的几件事5.1 最容易翻车的几个细节第一K8s 版本和容器镜像的兼容性。如果旧环境里很久没升级镜像新环境用的容器运行时版本可能无法直接运行老的镜像层尤其是涉及底层 glibc 或 kernel 依赖的镜像建议迁移前先在目标环境拉起来做一次 smoke test。第二ConfigMap 和 Secret 的配置差异。很多微服务在多个环境间切换时配置中心地址、数据库地址、Redis 地址都会变如果忘了同步修改服务虽然能启动但连不上依赖组件排查起来很浪费时间。第三hostPath 和 PV 的访问权限问题。前面说过 UID/GID 不一致会导致文件读不到实际排查时你会发现报错日志有时候只在 Pod 内部显示外部很难直接定位。另外线程池和数据库连接池的参数也值得留意。旧环境可能配置的连接池大小偏小比如 20 个连接到了云上并发上来后连接池瞬间被打满请求排队。我在迁移时顺势把 Druid 连接池的最大连接数和超时时间调大了同时检查了各个微服务的 JVM 堆内存设置避免默认参数下出现频繁 GC。5.2 如果重来一次我会在哪里做得更好这次迁移整体算顺利但复盘时还是有几个地方可以优化。第一个是预演次数不够。虽然我在正式切换前做过一次模拟演练但当时只验证了数据同步没有完整模拟“停入口、追增量、切流量”三个步骤同时执行。如果再来一次我一定会找一台临时的 Pre-production 环境完整预演至少两遍把所有步骤的耗时和风险点都摸清楚再动正式环境。第二个是同步环节缺少自动化。全量备份、增量同步、最后的切流量很多步骤都是靠人盯着执行虽然每一步都有脚本但脚本与脚本之间的衔接没有自动化全靠手动触发。下次可以顺带搭建一套简单的任务编排比如在切换窗口前自动执行最后一次增量同步并校验延迟是否归零把人为操作失误的可能性降到最低。第三个是压测的时间可以更充分。这次压测只安排了两个小时很多极限场景没有来得及细测。如果时间允许应该把压测过程拉长到半天甚至一天做一次持续 30 分钟的稳定性压测确认 JVM 内存平稳、GC 频率正常、数据库连接池没有缓慢泄漏。根据我个人的经验迁移上云最难的不是技术而是“在保证业务连续性的前提下把数据完整搬过去”这个过程中每一个环节都不能有侥幸心理。你准备的备份越多切换时的底气就越足。希望这篇复盘能帮正在做工业互联网平台上云的各位少踩几个坑尤其是单节点 K8s 迁云城的场景把方案和步骤都提前想清楚后面就会顺畅很多。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询