vericut搭建好机床怎么保存(全网无感知迁移生产环境到VPC)

本文作者:成都瑞小博科技有限公司的rippletek

背景

今年年初,我们将预发布环境迁移至VPC,测试了平滑迁移服务到VPC的可行性。当时的结论是:要达到用户无感知,迁移过程非常繁琐,除非阿里云在基础设施一层提供支持,否则很难应用到生产环境。详见《如何将服务从经典网络迁移到VPC》。

但在今年年中,阿里云推出了一系列有利于VPC迁移的功能,我们认为将整个生产环境迁移至VPC的条件已经成熟。

迁移

迁移难点

在《如何将服务从经典网络迁移到VPC》结尾提到,将服务迁移平滑迁移至VPC最大的障碍在于:

  • 迁移数据源到VPC

使用DTS可以很方便地同步数据源至VPC实例,但需要创建VPN使VPC服务能够访问到经典网络的数据源,且在最终切换时仍需要短暂停服。

  • 切换流量到VPC

由于SLB后端不能同时接入经典网络和VPC ECS,以至于只能移除经典网络节点再挂入VPC节点。这个过程中会造成分钟级的停服,且无法实现灰度引流。

  • 数据源混访

  • 一键迁移经典网络数据源到VPC,且保留经典网络地址不变。数据源迁移到VPC后,依然可以被经典网络服务访问,业务配置不需要修改。相当于阿里云帮我们创建VPN且配置了地址映射,对已有服务完全透明,非常方便。

    • SLB混挂

    VPC和经典网络的ECS可以添加到同一个SLB。这是最重要的一个改进,避免了分钟级的停服,又方便实现灰度测试。

    • ClassicLink

    使经典网络的ECS可以和VPC中的云资源通过私网互通,避免自行搭建VPN网络来连通两个网络。

    这三项功能,尤其是数据源混访和SLB混挂,能很好地解决以往迁移中遇到的两个难点。由于业务模型中不存在ECS之间的访问,实际迁移中我们几乎没有使用ClassicLink。

    要说明的是,如果业务模型比较简单且没有平滑迁移的需求,则无需应用本文后面描述的高级策略,可直接使用阿里云的提供的“ECS迁移”功能,在控制台将ECS停机后一键迁移至VPC。

    迁移方案

    我们的业务模型如图1,nginx和service都是以docker容器的形式运行在ECS上。

    vericut搭建好机床怎么保存(全网无感知迁移生产环境到VPC)(1)

    在迁移顺序上有两种选择:

    • 自底向上迁移

    先数据源切换至VPC,再迁移service,测试正常后最后迁移nginx到VPC。这种方式先迁移了底层服务,由于没有上层nginx引流,无法判断服务是否正常,所以需要做好测试。而且首先迁移数据源的风险也很高,数据源切换到VPC,所有服务通过经典网络地址访问数据源,需要先确认阿里云提供的这种跨网络访问的性能是否满足要求。

    • 自上而下迁移

    先迁移ngix到VPC,该nginx访问经典网络service。确认正常后再迁移service到VPC,最后迁移数据源。这种方式的问题在于,nginx迁移到VPC后,是无法访问经典网络SLB的,必须创建一个VPC SLB,将经典网络service挂载到这个SLB上,然后再修改VPC nginx指向VPC SLB。

    我们的业务调用比较复杂,上图是简化后模型,实际上service-1可能还调用了service-2,而service-2可能还调用了service-3甚至service-4,所以我们的迁移主要以第1种方式为主。

    数据源跨区访问性能

    对于上面第1种方式中提到风险,我们新开了rds和redis实例以测试数据源切换到VPC后的访问性能。

    RDS

    迁移RDS到VPC后,从VPC节点测试RDS性能:

    sysbench --test=oltp --oltp-table-size=1000000 --mysql-host=vpc-id.mysql.rds.aliyuncs.com --mysql-db=dbtest --mysql-user=service --mysql-password=password prepare sysbench --test=oltp --oltp-table-size=1000000 --oltp-test-mode=complex --oltp-read-only=off --num-threads=6 --max-time=60 --max-requests=0 --mysql-host=vpc-id.mysql.rds.aliyuncs.com --mysql-db=dbtest --mysql-user=service --mysql-password=password run OLTP test statistics: queries performed: read: 112476 write: 40170 other: 16068 total: 168714 transactions: 8034 (133.80 per sec.) deadlocks: 0 (0.00 per sec.) read/write requests: 152646 (2542.13 per sec.) other operations: 16068 (267.59 per sec.) Test execution summary: total time: 60.0464s total number of events: 8034 total time taken by event execution: 360.1141 per-request statistics: min: 35.28ms avg: 44.82ms max: 100.08ms approx. 95 percentile: 54.56ms Threads fairness: events (avg/stddev): 1339.0000/123.78 execution time (avg/stddev): 60.0190/0.01

    迁移RDS到VPC后,从经典网络节点测试RDS性能:

    sysbench --test=oltp --oltp-table-size=1000000 --mysql-host=classic-id.mysql.rds.aliyuncs.com --mysql-db=dbtest --mysql-user=service --mysql-password=password prepare sysbench --test=oltp --oltp-table-size=1000000 --oltp-test-mode=complex --oltp-read-only=off --num-threads=6 --max-time=60 --max-requests=0 --mysql-host=classic-id.mysql.rds.aliyuncs.com --mysql-db=dbtest --mysql-user=service --mysql-password=password run OLTP test statistics: queries performed: read: 116620 write: 41650 other: 16660 total: 174930 transactions: 8330 (138.75 per sec.) deadlocks: 0 (0.00 per sec.) read/write requests: 158270 (2636.16 per sec.) other operations: 16660 (277.49 per sec.) Test execution summary: total time: 60.0381s total number of events: 8330 total time taken by event execution: 360.0424 per-request statistics: min: 34.20ms avg: 43.22ms max: 193.89ms approx. 95 percentile: 52.10ms Threads fairness: events (avg/stddev): 1388.3333/97.04 execution time (avg/stddev): 60.0071/0.01

    Redis

    迁移Redis到VPC后,从VPC节点测试Redis性能:

    redis-benchmark -n 10000 -q -h vpc-id.redis.rds.aliyuncs.com -a password SET: 43103.45 requests per second GET: 42735.04 requests per second INCR: 40000.00 requests per second LPUSH: 39215.69 requests per second RPUSH: 27654.01 requests per second

    迁移Redis到VPC后,从经典网络节点测试Redis性能:

    redis-benchmark -n 10000 -q -h classic-id.redis.rds.aliyuncs.com -a password SET: 38610.04 requests per second GET: 40485.83 requests per second INCR: 41841.00 requests per second LPUSH: 37593.98 requests per second RPUSH: 25839.79 requests per second

    测试数据显示,从经典网络访问VPC的数据源,其网络延迟几乎可以忽略不计。后来我们实际迁移的体验也证实了这一点。

    自动化运维工具

    一个服务迁移要到VPC,其对应的容器需要build两个镜像,经典网络镜像和VPC镜像,分别推送到经典网络和VPC各自的docker registry。两个镜像中配置不同,配置包括数据源地址和其他服务API接口地址,VPC镜像中使用VPC数据源地址和VPC私网SLB地址。我们很早就将代码与配置解耦,代码在git仓库,而配置则由运维平台统一管理。这种做法给迁移提供了很多便利,整个过程对开发是透明的。否则开发需要两个分支来维护不同的镜像,将大大增加开发成本。

    绑定API地址

    当在一个服务中调用其他API服务时,应避免将API服务的IP(私网SLB地址)直接写入配置文件,否则非常难以维护。例如要替换一个SLB,则需修改所有调用该SLB的服务配置,而且还很难知道这个SLB究竟被哪些服务调用。

    我们的做法是,在配置文件中只填写API服务的域名(自定义“.lan”内网域名),由运维平台在服务部署时通过运维数据库为服务绑定所需IP(通过dokcer的add-host参数实现)。

    数据源地址渲染

    我们使用模板来渲染数据源地址,在service的配置文件中只需要填写抽象的键值。

    production: database: test host: #host# username: #username# password: #password#

    在docker build之前,运维平台会使用运维数据库将这些键值渲染成实际的值。迁移VPC时只需要将配置文件渲染两次,分别推送到不同的docker registry。和绑定API地址一样,最终我们只需维护两套运维配置数据即可。

    调用关系图

    由于采用微服务架构,我们服务很多,调用关系也错综复杂。所前所述,服务所依赖的数据源和API服务都记录在运维数据库中,那么我们通过分析数据库就可以绘制出类似于图2的服务调用关系图。

    vericut搭建好机床怎么保存(全网无感知迁移生产环境到VPC)(2)

    有了服务调用关系图,在VPC迁移时我们才能知道应该先迁移哪些服务、迁移某个服务时需要先解决哪些依赖。例如我们采用自底向上迁移的顺序,那么就应该先迁移最靠近数据源且依赖其他API服务最少的服务。图2是service-1的调用关系图,service-1依赖两个redis实例和两个rds实例,同时也依赖服务service-2和service-3。如果要迁移service-1,除了准备好相应的数据源,还必须先迁移service-2和service3。

    流量资费

    最后,自建VPN打通经典网络和VPC的方案会产生额外的流量资费,而我们在迁移中采用的以下三种跨网访问方式:

    • SLB混挂

    • 数据源混访

    • 经典网络通过ClassicLink接入VPC网络

    经工单确认,都不会产生流量资费。

    ,

    免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

      分享
      投诉
      首页