1. 背景
2013年贝聊正式成立,为了加快项目研发节奏,服务器使用了阿里云经典网络ECS服务器,4年后,随着贝聊业务高速发展,阿里云经典网络弊端逐渐展示出来。
经典网络服务器分配的IP地址不是连续的,没有固定的规则,运维人员需要人工维护繁琐的安全策略组,存在安全隐患;经典网络ECS默认分配1M的公网IP地址,费用会比VPC网络服务器贵,而这1M带宽是个鸡肋,满足不了生产环境业务间调用;经典网络给业务带来扩展性问题,跨机房部署在经典网络模式下变得复杂,服务的发现和注册均需适配解决,且不支持阿里云高速通道等高级功能。
阿里云专有网络,简称VPC网络,可以很好解决上述的问题,经过技术团队详细的评估后,我们决定尽快迁移服务为VPC网络。
2. 目标
1. 迁移的方案尽可能简单,业务需要改动工作量少
2. 迁移过程服务停机时间尽可能短。
3. 迁移后存储数据必须保证一致性。
4. 迁移方案必须支持迅速回滚。
3. 技术方案
3.1. 现况
贝聊业务框架大致划分4层,分别为接入层、Web层、Service层、存储层,如下图:
接入层使用阿里云SLB处理负载均衡,贝聊自建Nginx分发服务;Service层使用开源社区Dubbo框架治理服务;存储层使用阿里云RDS数据库和自建Redis分布式缓存。
3.2. 迁移方案
3.2.1. 域名梳理
贝聊使用DNSPod管理域名,历史因素影响,服务器存在很多未知用途的域名,迁移会可能会造成部分功能不可用。
这种历史问题确实没有非常好的解决方案,只能让运维导出所有的域名列表,各部门小组认领,认领后负责人需要登记业务和相关人员信息。运维对未认领的域名采取Nginx日志监控告警,避免梳理错误业务访问出错。
3.2.2. 第三方服务
贝聊部分功能依赖第三方供应商服务(如短信发送服务、支付宝),服务迁移需要考虑新环境对第三方服务兼容性,要对所有依赖第三方服务进行梳理,并测试第三方服务在新VPC环境是否正确工作。
有点大家要注意,VPC网络下ECS服务器获取公网IP地址不太一样,不能通过ifconfig获取了,如下
Dubbo服务注册在Zookeeper只会暴露内网ip地址,获取当前服务器公网IP地址可以curl ipinfo.io网络请求方式获取。
3.2.3. IP地址变更
迁移后所有服务重新部署,IP地址均发生变更,而目前大部分工程代码配置是硬IP地址,如下:
硬IP配置的方式会给我们项目迁移带来很大的风险,如果配置漏修改,会导致迁移后服务不可用。
针对上述问题,本次迁移把所有的硬IP地址替换为域名,让运维管理工作变得更方便,如果后续服务器出现硬件故障,不需要修改代码配置,运维进行域名变更即可。
3.2.4. 数据迁移
贝聊存储层保存了用户的资料交易等核心数据,不允许出现错误,存储层由阿里云RDS数据库和Redis分布式缓存集群组成,阿里云RDS支持“一键切换VPC网络”,非常完美帮助本次的VPC迁移工作。
Redis是我们自己搭建的集群,涉及很多业务,数据量非常庞大,部分缓存数据丢失可能会影响用户正常使用,迁移难度较大。
我们在GitHub发现了唯品会开源了一个好用数据迁移工具redis-migrate-tool,地址:
10G迁移数据在可以在几分钟内完成传输(网络带宽资源要充足),同时redis-migrate-tool支持增量同步数据。
3.2.5. 测试验证
服务部署、启动、测试验证都是非常耗时过程,我们无法保证迁移当天短时间完成所有服务部署验证操作,况且迁移新环境存在很多未知因素。
为了规避风险,我们采取使用“提前部署和测试”方案,即提前在VPC服务器部署所有的服务,并对该服务进行测试验证,由于服务只对贝聊内部请求白名单开放,不会影响线上用户的使用。
阿里云RDS支持同时公网和内网连接操作数据库,VPC新环境临时使用公网访问经典网络RDS,保证“提前部署和测试”测试过程数据是一致性的,等其他迁移工作完成后,RDS执行“一键切换VPC网络”,快速完成数据库转换。
上图的VPC服务部署后,只能通过接口调用测试验证,操作非常麻烦,需准备详细的接口测试用例,办公电脑Host挟持可以完美解决我们问题,如下
“Host代理”即在我们办公电脑安装Charles、Fiddler抓包工具代理,本地电脑配置/etc/hosts,利用hosts解析转发请求到测试SLB,完美解决APP环境的切换。
3.2.6. Host控制
“IP地址变更”统一采用域名方式解决,“域名化”是本次迁移工作非常重要的变更,涉及Zookeeper、Elastic-job、Redis、Memcached等基础服务,Host控制管理非常重要。阿里云RDS也是基于域名地址提供服务的,提供了两个不一样的公网地址和内网地址。
VPC提前部署服务测试,通过公网连接经典网络RDS,在迁移完成后,RDS“一键切换为VPC网络”。数据网络切换为VPC后,需要修改工程代码指向VPC内网地址,并重新发布部署,工作非常繁杂,容易出错。
基于上述问题考虑,在迁移过程中,我们在每台服务器/etc/hosts采取域名绑定控制。
假设数据库ibl_test地址信息如下
内网:rm-bp14jsmqx123456.mysql.rds.aliyuncs.com公网:rm-bp14jsmqx123456o.mysql.rds.aliyuncs.com复制代码
步骤一、工程代码统一配置了内网地址
jdbc.driver=com.mysql.jdbc.Driverjdbc.host = rm-bp14jsmqx123456.mysql.rds.aliyuncs.com/ibl_test复制代码
步骤二、VPC服务器配置/etc/hosts指向经典网络RDS地址
#RDS地址指向公网IP 10.118.xxx.xx rm-bp14jsmqx123456.mysql.rds.aliyuncs.com复制代码
步骤三、迁移完成后,执行 “一键切换VPC网络”,把/etc/hosts配置移除,重启服务。
#RDS地址指向公网IP (注释)#10.118.xxx.xx rm-bp14jsmqx123456.mysql.rds.aliyuncs.com复制代码
贝聊在阿里云100多台服务器,域名的切换要支持同时批量操作,ansible工具可以很好解决我们的需求。
Host控制给我们迁移工作带来了便利,但是也存在缺陷,如Java进程默认会对DNS有缓存,运维修改了/ect/hosts,可能无法立刻生效,对此为所有的Java进程配置了JVM参数networkaddress.cache.ttl合理值。
3.2.7. 风险控制
VPC迁移涉及所有贝聊服务器,风险非常大,本次迁移工作大概风险点:
1. 人工操作错误
2. 依赖第三方服务故障
3. 漏覆盖迁移服务
为了规避人工操作错误,我们在wiki制定了迁移过程所有人都必须遵循的操作步骤,如下
wiki上的操作步骤必须命令行、脚本化,不允许迁移当天再去输入Linux命令,这样会浪费大量时间和出现人工操作失误风险。
wiki虽然制定了操作步骤,每个人对文字步骤理解存在偏差,为此我们在测试环境组织了模拟线上的演练工作,要求每个操作人员都要理解wiki执行步骤,在一定程度规避了人工操作的风险。
如果在新环境出现严重的故障,迁移方案必须支持快速回滚,我们准备了一份回滚详细操作步骤,步骤从反方向执行迁移,完成回滚,下图
4. 迁移实施
4.1. 准备工作
迁移准备工作是非常繁琐的事情,涉及贝聊内部多个部门,我们把VPC迁移作为一个项目进行推进,每周同步各个团队的工作进度,使用wiki记录各团队执行的内容项。
4.2. 迁移演练
演练过程,所有关键人员必须就位,由一个负责人指挥协调所有的迁移工作,尽可能模拟线上的迁移。测试环境演练结束后,我们发现了很多问题,整个过程沟通不顺畅,人工操作错误,系统多次出现异常问题一下子暴露出来,导致迁移演练耗时4个小时,超过了我们的预期。
针对演练碰到的问题,所有负责人聚在进行技术复盘,重新又一次review所有的操作步骤,把不合理的步骤再一次完善。
4.3. 线上迁移
为了减少对用户的影响,线上迁移我们选择了凌晨执行,并提前了发客服公告,准了相对应的应急方案。
迁移当天,所有后台技术人员准时在工位就绪,我们按照wiki准备步骤有条不紊地展开迁移工作,短短的25分钟过后,我们成功完成了VPC迁移,共涉及100多台服务器,300多个Dubbo接口,30多项功能业务,约20G容量Redis内存数据迁移。
迁移完成后,所有人员须测试验证完业务功能,检查所有的服务运行情况,确保监控正常工作,交接好第二天值班人员事项。
5. 总结
VPC迁移看起来困难很大,但是认真执行后,其实没有想象中困难,这次迁移工作,我们总结出几点经验:
1. 要做详细迁移技术方案设计,针对关键步骤做技术调研,测试。
2. 使用类似wiki的项目管理工具制定统一操作步骤,避免人工误操作。
3. 迁移演练和步骤review方式避免人工误操作。
4. 面对面沟通会议,避免理解偏差。