拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从Rancher迁移到Sealos:Kubernetes私有化部署的完整复盘

从Rancher迁移到Sealos:Kubernetes私有化部署的完整复盘

最近刚把公司内网一批业务从 Rancher 管理的 Kubernetes 集群迁移到了 Sealos 私有化集群上。原本以为只是换一个管理面板,没想到牵扯出资源梳理、存储卷处理、中间件数据搬迁和流量切换一整套活。整个过程比预想中琐碎,但落地之后回头看,这笔账是算得过来的。这篇东西就当一次复盘,把从 Rancher 迁到 Sealos 的完整思路、关键步骤和踩过的坑都整理出来,给正在评估或者已经准备动手做私有化迁移的同行一个参考。

先说结论:如果你手里只有一两套 K8s 集群,Rancher 的集群管理能力其实够用,但如果你要做的是面向公司内部或者交付客户的私有化平台,需要的是一个自带镜像仓库、应用编排和中间件管理能力的整体底座,这时候 Sealos 这种“云操作系统”形态的私有化方案会更顺手。迁移的核心工作不是把 YAML 复制过去,而是把资源依赖、数据存储、网络策略这些隐性资产一起搬过去。

1. 为什么选择从 Rancher 迁移到 Sealos

1.1 Rancher 用着不差,但痛点很真实

Rancher 在 Kubernetes 圈子里名气很大,它解决的是“多个集群集中管理”的问题。一个控制平面可以接入几十个下游集群,统一做 RBAC、项目管理、应用目录和监控告警,这在多集群规模下确实方便。我之前的团队从单集群起步,慢慢扩展到开发、测试、预发三套环境,Rancher 帮我们省了不少心。

但随着做私有化交付的需求变多,Rancher 的一些问题开始冒头。首先是它本身是一套比较重的控制系统,Rancher Server 部署在集群里,有自己的 CRD、Controller、Agent,升级的时候要考虑版本匹配问题,一旦控制面出问题,下游集群的日常管理也会跟着受影响。其次是 Rancher 的管理面和应用交付面是分离的,部署一个业务应用你仍然需要先写 Dockerfile、构建镜像、再写 Deployment/Service/Ingress,然后还要配一套 CI 流程,说白了它还是一个“Kubernetes 管理器”,不是“应用交付平台”。

另一个让我下定决心迁移的原因是资源利用率。Rancher 默认会在每个下游集群安装一组 agent,加上 logging、monitoring、catalog 等一堆组件,一台 8C16G 的机器跑控制面加组件后剩下的资源明显缩水。对于中小规模团队来说,这个开销不小。

1.2 Sealos 私有化的定位正好不一样

Sealos 的定位是“云操作系统”,底层依然是 Kubernetes,但它在 K8s 之上做了一层应用交付和资源管理抽象。部署完 Sealos 之后,你得到的不只是一个容器编排平台,而是一个自带镜像仓库、应用商店、可观测面板和数据库中间件一键部署能力的底座。

私有化场景里最看重的就是“开箱即用”和“离线交付”。Sealos 的集群安装本身支持离线包,把镜像包导入内置 registry 后,整个环境完全脱离公网也能正常工作,这对内网部署和客户环境交付是刚需。另一个让我觉得差异明显的是应用商店,里面对齐了很多常用中间件,比如 MySQL、PostgreSQL、Redis、MinIO、Nginx,通过图形化界面或者命令行就能拉起,这对 Rancher 里的 catalog 来说,操作体验根本不在一个层级。

还有一个比较关键的对比点:Rancher 为了方便多集群纳管,会往命名空间、工作负载里注入自己的一堆注解和 CRD 引用,你导出 YAML 再往别的集群导,经常因为字段不兼容要逐个清洗。而 Sealos 本身就是直接操作原生 Kubernetes 对象,资源声明更干净,迁移成本天然就低一些。

1.3 选型对比:不只看功能,还要看迁移后的运维模型

我整理了一张对比表,能比较直观地看出两者在私有化交付场景下的侧重差异:

对比维度RancherSealos
核心定位Kubernetes 多集群管理平台基于 K8s 的应用交付底座
私有化离线交付需要额外搭建内网镜像仓库并处理组件依赖自带镜像仓库和离线包机制
应用部署模式写 YAML + Helm,依赖外部工具链应用商店 + 封装格式,开箱即用
中间件管理需要自己维护 operator 和存储一键部署常见数据库和消息队列
资源开销控制面组件占比较高轻量,资源集中在业务 Pod
对原生 K8s 资源的侵入性注入大量 cattle 相关字段保持原生对象,几乎无侵入

选型的逻辑很简单:如果团队的核心诉求是“管 K8s 集群”,Rancher 依然是很好的选择;如果诉求是“搭建一套可持续交付的私有化平台”,Sealos 的架构形态更对路。我们迁移的根本原因,就是要把平台能力从“K8s 管理”上升到“应用交付和运维一体化”。

2. 迁移前准备工作:盘点资产和确定策略

2.1 先把 Rancher 里的家底全部摸清楚

迁移前最怕漏掉东西,第一步就是把 Rancher 管理的所有业务资产完整盘点一遍。我会按以下几个维度来梳理:

  • 工作负载:所有 Deployment、StatefulSet、DaemonSet,记录命名空间、副本数、镜像地址、资源 request/limit。
  • 服务暴露:Service、Ingress、ServiceEntry 和证书配置,特别是 HTTPS 证书的签发方式(Rancher 里常用 cert-manager 还是自定义 Secret)。
  • 配置数据:ConfigMap、Secret,这部分最容易迁移,也最容易被忽略。
  • 存储资源:PVC、StorageClass,记录每块存储的容量、访问模式、底层存储类型(local-path、NFS、云盘)。
  • 基础组件:DNS、网关、日志收集、监控告警,确认这些是 Rancher 自带的还是独立部署的。
  • 中间件:数据库、缓存、队列,确认连接地址是否已经写在业务配置里,还是通过服务名解析。

我这次迁移的规模大概是 30 个命名空间、120 多个服务,其中包括三套 PostgreSQL、两套 MySQL、一个 Redis 集群、一个 MinIO 对象存储,以及一批无状态 Java 和 Go 服务。盘点之后才发现,很多服务之间存在隐式依赖,比如业务服务直接通过 PVC 挂载共享目录,或者某个 ConfigMap 里硬编码了另一个服务的 IP。

2.2 规划目标集群资源,避免迁到一半资源不够

Sealos 私有化集群的节点规划,不能拍脑袋。迁移时要保留一定的扩容余量,建议按原集群资源的 1.2 到 1.5 倍来准备。比如原来 120 个服务加起来要 80 核 160G 内存,新集群至少准备 100 核 200G 内存。

节点划分也建议明确角色:Master 节点跑控制面组件,承担调度和 API 服务;Worker 节点跑业务负载。如果业务里有数据库这类有状态服务,建议单独挂一块 SSD 数据盘,存储类单独定义,避免和日志型应用抢 I/O。另外节点之间注意网络互通,私有化环境通常要提前规划好网段,避免 Docker 网段和业务网段冲突。

存储这块要提前想清楚。原 Rancher 集群如果用的是 local-path-provisioner,数据落在各节点本地目录上,迁移后要把这些磁盘数据转移过去,或者直接把旧磁盘挂载到新机器上;如果用 NFS,搭建新环境的 NFS 要做好权限映射。总之存储改造是迁移里最容易翻车的点,我会在后面单独展开。

2.3 设计迁移批次和回退方案

一般建议分批迁移,而不是一次性全量切换。我采用的策略是三个批次:

第一批迁无状态应用,比如前端静态资源、网关接口、定时任务,验证新集群的网络和 Ingress 是否正常。 第二批迁有状态中间件,比如数据库、Redis、对象存储,这部分涉及数据同步,需要预留充足时间窗口。 第三批迁对稳定性要求最高的核心链路,确认前两批没有问题之后再做最后切换。

每一批迁移都要有回退方案。比如数据库迁移前保留原集群数据,并同时开启增量同步,万一导入出问题可以切回去。业务层通过负载均衡或者 DNS 权重逐步切流量,观察日志和监控指标没有异常再完全切干净。

3. Sealos 私有化部署的实操记录

3.1 节点环境准备和离线包下载

Sealos 的私有化部署在离线环境里非常顺,但前提是提前准备好安装介质。我实际用到的核心组件是labring/kubernetes、labring/helm、labring/cert-manager、labring/sealos自带的内置 registry,以及应用商店相关的镜像包。在有网的环境下先把这些镜像通过sealos pull拉到本地,然后打成人sealos load导入目标机器。

我准备了三台机器:一台 Master,两台 Worker,操作系统是 CentOS 7.9,内核版本需要确认支持 Kubernetes 的网络要求。所有节点关闭 swap,配置好主机名和 hosts 解析,然后安装容器运行时。Sealos 支持 containerd 作为运行时,配置比较简单,只需要确认sandbox_image可以正常拉取。

这一步有一个很关键的注意点:所有节点的时钟必须同步,建议搭一个内网 NTP 服务,否则节点之间证书校验会报错,排查起来非常耗时。

3.2 用 Clusterfile 声明集群并一键安装

Sealos 部署集群可以通过命令行直接指定节点,也可以写一个 Clusterfile。我用的是 Clusterfile 的方式,好处是配置可以保存下来,后续扩容就基于这个文件改一改再执行。

下面是我实际使用的 Clusterfile 核心内容,Hosts 部分定义节点角色和地址,后面接 SSH 认证信息。

apiVersion: v1beta1 kind: Cluster metadata: name: my-private-cluster spec: hosts: - name: master01 role: master address: 192.168.10.21 user: root passwd: "YourStrongPassword" arch: amd64 - name: worker01 role: node address: 192.168.10.22 user: root passwd: "YourStrongPassword" arch: amd64 - name: worker02 role: node address: 192.168.10.23 user: root passwd: "YourStrongPassword" arch: amd64 ssh: passwd: "YourStrongPassword" port: 22

然后执行安装命令,指定要装的 Kubernetes 版本和辅助组件:

sealos run labring/kubernetes:v1.31.4 \ labring/helm:v3.14.4 \ labring/cert-manager:v1.15.0 \ --cluster my-private-cluster

整个过程大概十分钟左右,日志会输出每个节点的执行情况。安装完成之后,kubectl get node应该能看到所有节点 Ready。

3.3 内置镜像仓库和应用商店的启用

Sealos 自带镜像仓库这一点在私有化场景里太省心了。部署完成后,集群内部会有一个 registry 服务,可以手动上传镜像包。日常发布流程里,构建机把镜像推到 Sealos 的 registry,业务节点拉镜像时走的就是没网也能拉取的内网地址,不会再因为公网拉取受限而失败。

应用商店是一大亮点。私有化平台经常要部署 Redis、MySQL 这类基础组件,如果靠手写 operator 和 YAML,工作量大还容易出错。Sealos 的应用商店里提供了一键部署的入口,我这边直接通过商店拉起了一套 Redis 和一个 MinIO,耗时比从 Rancher 的 catalog 里装快很多,状态管理也更直观。

不过有一点要注意:在离线环境里要用应用商店,需要先把商店对应的应用镜像导入内置 registry,否则页面客户端会提示找不到镜像。这个步骤我一开始没注意,导致后面点安装老是卡在拉镜像,后来手动导入镜像包才恢复正常。

3.4 存储类和证书的提前配置

存储是迁移成功与否的关键。我在 Sealos 集群上提前定义了两个 StorageClass:一个用本地盘做默认存储,给无状态服务配 PVC;一个用 NFS 给有状态中间件提供共享存储,比如 MinIO 的持久化目录。

NFS 的配置过程中,我踩过一个坑:新机器上挂载 NFS 时权限锁死,容器进程运行用户是 nobody 或者 65534,写不进去数据目录。解决办法是设置 NFS 服务端导出目录时指定no_root_squash,同时把目录属主改成容器运行用户 UID,然后在 StorageClass 里挂载时不要强制改属主。

证书这边,我直接复用 cert-manager 的流程。Sealos 集群里部署好 cert-manager,然后创建 ClusterIssuer,内部域名签发用自签名 CA,外部域名则对接已有的内网 CA。这样可以保证 HTTPS 证书在迁移后无缝衔接。

4. 从 Rancher 导出资源并迁入 Sealos 集群

4.1 清洗 Rancher 注入的 CRD 字段和注解

Rancher 在命名空间上会打上field.cattle.io/projectId这类注解,工作负载里也会出现cattle.io/timestamp或者 ownerReferences 指向 Rancher 管理的 CRD。这些字段在目标集群中大多无效,直接 apply 虽然不一定报错,但会干扰后续的资源管理和回收。

我在每个命名空间执行一次完整导出:

kubectl get deploy,sts,ds,svc,cm,secret,pvc,ingress -n app-namespace -o yaml > app-namespace-backup.yaml

然后写了一个简单的 Python 脚本来做字段清理,重点删除以下内容:

  • metadata.uid、metadata.resourceVersion、metadata.generation、metadata.creationTimestamp
  • metadata.managedFields这整个数组
  • metadata.annotations里所有以field.cattle.io和cattle.io开头的键
  • metadata.ownerReferences指向非原生资源的引用
  • Deployment 里status整个段,这个只是运行时状态,导入时会自动重新生成

清洗的时候要留意:有些注解虽然带 cattle 前缀,但业务可能依赖,比如某些灰度发布配置。稳妥的做法是保留名单机制,先拉一个常见删除清单,确认无副作用后再批量执行。

4.2 适配目标集群的镜像地址和存储类

清洗完字段之后,第二步是全局替换镜像地址。原 Rancher 集群的镜像放在公网仓库或者公司旧的内网 registry,迁移后统一指向 Sealos 内置 registry。替换方法不复杂,用 sed 批量处理 YAML 中的镜像前缀:

sed -i 's#old-registry.example.com#registry.sealos.svc.cluster.local:5000#g' app-namespace-backup.yaml

但有一点要注意,不同命名空间拉取镜像的 Secret 可能不同。如果是私有镜像,要将原 registry 的 docker-registry Secret 重新创建到 Sealos 集群对应命名空间,否则 Pod 启动会报 ImagePullBackOff。

存储类的替换更直接,把 PVC 定义里的storageClassName从原来的local-path改成目标集群实际存在的存储类名,比如nfs-storage。如果原 PVC 容量比较大,需要确认目标存储类支持动态扩容,否则只能预先按规格创建 PV,再通过 label 匹配绑定。

4.3 处理 Ingress 和 Service 的访问关系

Rancher 的 Ingress 依赖它自己实现的 nginx-ingress 或 Traefik,而 Sealos 默认的网关层可能不同,因此 IngressClass 要重新指定。我把 PYC 里所有 Ingress 的:

  • 删除kubernetes.io/ingress.class注解中的旧值
  • 在spec.ingressClassName字段填上 Sealos 集群的platform-navigation-ingress或默认网关类

Service 本身的 ClusterIP 会变化,但集群内通过服务名访问不受影响,因为 DNS 解析走的是服务名。要重点检查的是跨集群调用有没有硬编码 IP 的地方,比如某些业务配置里写了192.168.10.5:3306这类地址,这类地址必须改成新集群中对应服务的对外地址或者集群内服务名。

4.4 批量 apply 和资源校验

清洗完的 YAML 文件放在一个目录里,然后逐个命名空间进行校验和应用:

kubectl create --dry-run=client -f app-namespace-cleaned.yaml kubectl apply -f app-namespace-cleaned.yaml

先跑 dry-run 的目的是尽早在客户端侧发现字段非法或不兼容的问题。批量 apply 之后,等 Pod 拉起来,检查 PVC 是否 Binding、Service 的 Endpoints 是否正常、Ingress 是否得到地址。

我实际导入之后,发现部分 Deployment 的 imagePullPolicy 被 Rancher 改写成了 Always,导致在离线环境里每次启动都要检查镜像是否存在心跳。这个改为 IfNotPresent 能显著降低拉取延迟,也避免网络抖动引起的拉取失败。

5. 数据迁移:数据库、对象存储和共享目录

5.1 数据库迁移要用逻辑导出导入,而不是直接搬文件

数据库迁移是整个项目里风险最高的环节。我处理了三套 PostgreSQL 和两套 MySQL,统一采用逻辑导出导入的方式,而不是直接拷贝数据文件,这样避免版本兼容性和文件权限问题。

MySQL 迁移流程:

mysqldump -h old-mysql -u root -p --single-transaction --routines --triggers --events --databases db1 db2 > db-backup.sql mysql -h new-mysql -u root -p < db-backup.sql

PostgreSQL 迁移流程:

pg_dump -h old-pg -U postgres -d dbname --no-owner -F c > dbname.dump pg_restore -h new-pg -U postgres -d dbname --no-owner dbname.dump

注意几个细节:一是--single-transaction保证 MySQL 导出时的一致性视图,避免出现数据中途修改导致备份不一致;二是--no-owner解决新旧环境数据库用户名不一致导致的权限问题;三是大表一定要分库分表导出,不要一把梭全库一次性 dump,否则恢复时间太长,还会因为某个表出问题被迫从头再来。

数据导入完成之后,要立刻做表结构和行数对比,我写了一个对比脚本遍历每张表统计COUNT(*),与原库做差值。另外跑几个关键业务查询,确认索引和存储过程都正常。

5.2 Redis 和对象存储的快速迁移

Redis 迁移用redis-cli --pipe做全量填充。源库是集群模式下就用redis-cli -c,导出格式用MIGRATE脚本或者直接RDB再导入。小数据集下直接取 RDB 文件复制过去再重启最省事,但要注意版本,Redis 6 和 7 的 RDB 格式多数不通用。安全起见我用dump.rdb的方式时会先匹配版本号。

MinIO 这类对象存储,我用的是mc mirror命令做同步:

mc mirror --overwrite --remove source-bucket/ minio-target/bucket/

同步完成之后记得做一次抽查,对比几个大文件的 ETag 是否一致,避免传输中损坏。

5.3 共享目录和 PVC 数据怎么处理

无状态服务的 PVC 数据量不大,可以直接重建空 PVC 再复制数据。但如果是共享目录,比如多个服务共用一个 NFS 挂载的目录,迁移时要注意保持目录结构和属主一致。

我先在旧节点上打包共享目录:

tar czvf shared-data.tar.gz -C /data shared

然后在目标节点上解压,并将目录属主改成容器运行的 UID。如果是 NFS,先确认目标 NFS 服务端的目录挂载属性,避免权限拒绝。

还有一类比较特殊的情况:服务在启动时对临时目录有大量写入,旧集群里用hostPath挂载。我迁移时改成新集群里统一的 StorageClass 动态分配 PVC,避免节点重启后数据丢失,也不用再和具体节点绑定。

6. 流量切换、灰度验证与原集群下线

6.1 低风险流量切换到新集群的方式

内部服务切流量的方式我做了两种:有域名入口的,通过 DNS 解析把权重逐步调向新集群的负载均衡 IP;没有域名只有集群内访问的,直接改动上游调用方配置指向新服务名,然后滚动重启上游服务。

为了豁免 DNS 缓存对灰度验证的干扰,我在切换前先在本地/etc/hosts里把域名指向新集群,验证核心链路。之后再改 DNS 的 A 记录权重,先切 10%,观察告警和接口错误率,稳定后切到 50%,最后全部切过去。

6.2 数据校验必需的清单

切换完成后一定要按清单逐项验证,而不是简单看 Pod 状态。我用的是下面这个表:

检查项检查方法
Pod 状态所有业务容器 Running,无 CrashLoopBackOff
服务发现kubectl get endpoints确认对应 Pod IP 已注册
PVC 挂载kubectl get pvc状态为 Bound,Pod 可读写测试
数据库连接业务日志无 connection refused 报错
定时任务到点后检查任务执行记录和输出日志
监控告警基础监控无新增 P1/P2 告警

6.3 回退方案和原集群下线时机

灰度期间保留原 Rancher 集群不关停,数据库有新数据写入时通过增量同步或者业务双向写入过渡。等新集群稳定跑一周以上,再把数据库的写流量切过去,旧库改成只读模式,业务侧验证无异常后才彻底下线。

下线前要把旧集群里的 PVC 数据做一次最终备份,以防后续审计或追查需要。Rancher 控制面本身不急于删除,建议保留到所有业务验证通过,并且旧集群的证书、监控、日志等附属系统不再被依赖以后再清理。

7. 迁移之后常见问题速查表

把这次迁移中实际遇到的几个典型问题整理成一张速查表,很多问题都是迁移到新 K8s 环境都会遇到的,供参考:

现象可能原因解决办法
Pod 一直 PendingPVC 未绑定或存储类不存在检查 StorageClass 名称,重提 PVC 或预建 PV
ImagePullBackOff镜像在 registry 中不存在导入镜像或者修改镜像标签地址为内置 registry
服务间访问超时DNS 解析失败或集群网络策略拦截检查 CoreDNS 配置,确认没有残留旧的 hosts 记录
Ingress 404IngressClass 不匹配或证书 Secret 没同步删除旧注解,设置新的ingressClassName
数据库写入权限报错迁移时丢失用户权限授权重新执行GRANT授权,更新业务账号密码
容器写入目录无权限NFS 导出目录是 root squash调整 NFS 配置no_root_squash,或修改属主 UID

还有一个容易被忽略的地方:Rancher 的命名空间默认带项目隔离策略,迁移到 Sealos 后如果不做 NetworkPolicy 限制,所有服务之间默认全通。从安全视角看,建议对照原 Rancher 项目空间的隔离关系,把核心业务命名空间之间用 NetworkPolicy 显式约束好,避免新环境网络面被放大。

8. 一点个人体会

这次迁移让我印象最深的一点是:真正花时间的不是安装和部署,而是对存量系统的梳理。Rancher 这种平台管理能力很强,但长期使用下来,工作负载、存储、配置之间的隐式依赖会慢慢沉淀成一个“黑箱”,你不做迁移,永远不知道里面有多少隐式关联。

如果你也在准备从 Rancher 迁到 Sealos 或者其他私有化底座,我建议先花两周时间把资产盘点做扎实,再启动扑腾。过程中多留后路,宁可批次拆碎一点,也不要追求一次切换的“英雄主义”。Sealos 在私有化场景里的交付效率确实高,但再好的工具也替代不了严谨的迁移规划和数据验证。

最后再分享一个小技巧:迁移完成后,别急着把旧集群删掉,在旧集群旁边保留一份核心服务的运行快照,比如备份关键 Deployment 和 ConfigMap 到一个 Git 仓库里。后续如果新环境有配置需要比对,随时可以拉出来对照,这个习惯在长时间运维里非常有用。

返回列表