Kubernetes集群子网迁移实战:RKE2/K3s安全迁移方案
1. 项目概述
最近在帮客户做Kubernetes集群网络改造时,遇到一个典型场景:原先部署在AWS VPC子网A中的RKE2集群,由于网络规划调整需要整体迁移到子网B。这个看似简单的需求背后其实暗藏玄机,今天就来详细聊聊如何安全地将RKE2/K3s下游集群迁移到新子网。
作为Rancher的老用户,我深知直接修改现有节点的网络配置会导致各种诡异问题。去年就有一个惨痛教训:某生产环境因为IP变更导致etcd集群脑裂,最后不得不重建整个集群。经过多次实践,我总结出一套稳妥的迁移方案,核心思路是"新旧子网并行,节点逐步替换"。
2. 迁移方案设计原理
2.1 为什么不能直接修改现有节点网络?
RKE2/K3s集群的网络配置是深度耦合的,主要体现在三个层面:
节点注册层面:通过Rancher节点驱动创建的实例,其网络配置(安全组、子网、IP分配方式等)是固化在Cloud-Init模板中的。我曾在测试环境尝试直接修改EC2实例的子网,结果kubelet启动后无法加入原有集群。
Kubernetes网络层面:每个Node对象的status.addresses字段会记录节点的InternalIP和ExternalIP。当底层网络变更时,这些IP信息不会自动更新,导致kube-proxy、CNI插件等组件无法正常工作。
etcd集群层面:etcd成员列表中使用的是节点的固定IP。通过抓包分析发现,当某节点IP变更后,其他etcd节点仍会向旧IP发送心跳检测,最终导致quorum丢失。
2.2 新旧子网并行迁移的优势
基于上述问题,我们采用的迁移方案具有以下特点:
- 无单点故障:始终保持etcd quorum和control-plane可用性
- 可回滚:旧节点保留至最终验证阶段
- 最小影响:工作负载逐步迁移,避免批量重启
3. 详细迁移步骤
3.1 迁移前准备
3.1.1 网络连通性检查
在新子网创建测试实例,验证与以下组件的连通性:
# 测试控制平面通信 telnet <原API Server IP> 6443 # 测试节点间通信(以Canal CNI为例) nc -zv <原节点IP> 8472 # VXLAN端口 nc -zv <原节点IP> 9099 # Canal健康检查端口3.1.2 关键备份操作
- etcd快照(RKE2特有命令):
sudo rke2 etcd-snapshot \ --name pre-migration \ --s3 \ --s3-bucket=<your-bucket> \ --s3-region=us-west-1- 集群状态备份:
kubectl get nodes -o wide > node-status.txt kubectl get pods -A -o wide > pod-status.txt3.2 创建新机器池
在Rancher UI中操作时,有几个关键配置项需要注意:
角色分配策略:
- 先迁移worker节点,再迁移control-plane
- 每个etcd节点迁移前确保新etcd节点已加入quorum
高级网络配置:
# 在cloud-config中显式指定新子网配置 network: interfaces: eth0: addresses: - 10.1.2.100/24 gateway: 10.1.2.1重要提示:建议开启"节点自动替换"功能,这样当排空旧节点时,Rancher会自动补充新节点
3.3 节点迁移实战技巧
3.3.1 Worker节点迁移
采用"增-删"循环策略:
- 新worker节点就绪后:
kubectl cordon <old-node> kubectl drain <old-node> --ignore-daemonsets --delete-emptydir-data- 观察工作负载迁移状态:
watch kubectl get pods -o wide | grep <old-node>3.3.2 Control Plane节点迁移
特殊处理步骤:
- 先添加新control-plane节点:
# 检查新节点加入情况 sudo journalctl -u rke2-server -f | grep "successfully established"- 确认etcd成员状态:
sudo ETCDCTL_API=3 etcdctl \ --endpoints=https://127.0.0.1:2379 \ --cacert=/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt \ --cert=/var/lib/rancher/rke2/server/tls/etcd/server-client.crt \ --key=/var/lib/rancher/rke2/server/tls/etcd/server-client.key \ member list- 移除旧节点前确保:
# 检查quorum健康状态 sudo ETCDCTL_API=3 etcdctl endpoint health3.4 迁移后验证
3.4.1 网络连通性测试
# 跨节点Pod通信测试 kubectl run test-pod --image=busybox -- sleep 3600 kubectl exec test-pod -- ping <其他节点PodIP> # 服务发现测试 nslookup kubernetes.default.svc.cluster.local3.4.2 存储卷验证
特别关注使用Local PV或节点绑定的存储:
kubectl get pv -o yaml | grep -A 3 nodeAffinity4. 常见问题排查
4.1 新节点无法加入集群
典型表现:kubelet日志中出现"x509 certificate signed by unknown authority"
解决方案:
- 检查新节点是否使用与原集群相同的RKE2版本
- 验证
/etc/rancher/rke2/config.yaml中的server URL配置 - 确保新子网可以访问Rancher的TCP/443端口
4.2 etcd成员列表不一致
错误现象:etcdctl member list显示旧节点仍存在
修复步骤:
# 强制移除故障成员 sudo ETCDCTL_API=3 etcdctl member remove <旧成员ID> # 清理旧数据(在新节点上) sudo rm -rf /var/lib/rancher/rke2/server/db/etcd4.3 CNI网络异常
典型症状:Pod间网络不通,但节点间网络正常
处理方案:
- 检查CNI插件Pod状态:
kubectl get pods -n kube-system -l app=cni-plugin- 必要时重置CNI配置:
sudo rm /etc/cni/net.d/* sudo systemctl restart kubelet5. 经验总结
经过多次迁移实践,我总结了几个关键要点:
迁移顺序很重要:先worker后control-plane,且etcd节点要逐个替换。有次同时迁移两个etcd节点导致quorum丢失,不得不从快照恢复。
监控关键指标:迁移过程中要密切观察:
- etcd leader变更次数(prometheus指标
etcd_server_leader_changes_seen_total) - API Server响应延迟(
apiserver_request_duration_seconds)
- etcd leader变更次数(prometheus指标
DNS缓存问题:迁移完成后曾遇到CoreDNS继续解析旧节点IP的情况,通过重启coredns Pod解决:
kubectl rollout restart deployment coredns -n kube-system- 客户端配置更新:别忘了更新以下客户端的kubeconfig:
- CI/CD系统的集群配置
- 开发者的本地kubectl配置
- 监控系统的抓取配置