探路
前篇列出的都是缓兵之计, 大部分问题还是存在, 在前几个月懵逼和饱受白名单问题煎熬后, 慢慢打起了vpc迁移的算盘.
这个迁移很大的一个问题就是, 如何将VPC和经典资源打通呢?
VPC经典互通的第一次尝试
在16年底, 风控准备上第一版服务, 将服务放在了vpc内. 以此为契机尝试打通vpc和经典的服务,但是这个时候阿里云vpc刚上没多久, 基本没有任何对这方面的支持.
第一次尝试方案如下
- 在vpc内创建了一个openvpn server把端口暴露给经典网络
- 在经典环境以一台空闲节点作为client保持和openvpn server的连接
- vpn server给经典client下发vpc网段路由下一跳指向vpn server
- 在vpn server上对vpn和经典网段分别进行SNAT
- vpc路由器上将经典网段的10路由下一跳指向vpn server
- 经典节点上对vpc和vpn网段SNAT
其他的经典节点由于路由不可控无法主动访问vpc, 经典client节点可以openvpn server的身份访问其他vpc所有节点.这样经典client的节点相当于和vpc完全互通了.
而vpc内的节点则可以通过vpn client访问所有经典节点, 由于是在路由器上加的路由这个访问是对于vpc节点来说是无需配置, 无感知的.
不过由于阿里云有一个神奇的100.64.0.0/10网段(RDS,DRDS,redis,部分SLB), 这个路由是无法控制的, 为了让vpc能访问到阿里云的这些资源, 只能不停在将各种不同的资源在经典的vpn client做DNAT.
DNAT规则大致如下.
firewall { '100 snat for vpn':
chain => 'POSTROUTING',
jump => 'SNAT',
proto => 'all',
source => '192.168.0.0/24',
table => 'nat',
tosource => '10.165.69.144',
}
firewall { '101 snat for vpn':
chain => 'POSTROUTING',
jump => 'SNAT',
proto => 'all',
source => '172.31.255.0/24',
table => 'nat',
tosource => '10.165.69.144',
}
firewall { '102 dnat for drds xxx':
chain => 'PREROUTING',
table => 'nat',
jump => 'DNAT',
source => '!10.0.0.0/8',
destination => '10.165.69.144',
proto => 'tcp',
dport => '3306',
todest => '100.98.69.136',
}
firewall { '103 dnat for rds xxx.mysql.rds.aliyuncs.com':
chain => 'PREROUTING',
table => 'nat',
jump => 'DNAT',
source => '!10.0.0.0/8',
destination => '10.165.69.144',
dport => '3307',
proto => 'tcp',
todest => '100.114.46.162:3306',
}
firewall { '104 dnat for redis xxxx.m.cnbja.kvstore.aliyuncs.com':
chain => 'PREROUTING',
table => 'nat',
jump => 'DNAT',
source => '!10.0.0.0/8',
destination => '10.165.69.144',
proto => 'tcp',
dport => '6379',
todest => '100.99.94.201',
}
firewall { '105 dnat for slb xxx':
chain => 'PREROUTING',
table => 'nat',
jump => 'DNAT',
source => '!10.0.0.0/8',
destination => '10.165.69.144',
proto => 'tcp',
dport => '80',
todest => '100.114.31.148',
}
整个结构的简单图示:
这样勉强达到了互通的要求, 但是问题也很明显, vpn client和vpn server都是单点的. 期间分别准备好了备机以防止意外随时切换, 这种状态跑了半年, 除了有时经典节点公网带宽跑满, 并未出现过其他问题, 升级过带宽后也好了. iptables的转发还是很给力的, 不过现在阿里云在互通方面做了很多支持,没必要这样做了.
正式上路
阿里云推出经典与vpc互联支持后
阿里云文档: https://help.aliyun.com/document_detail/55051.html
主要支持了 ClassicLink
, 混访混挂
, 单ECS迁移
, 既有的java应用也是在推出上述实际支持后开始的.
迁移问题
提前规划
- 迁移到vpc后, 自然不希望再和以前一样看着经典ip一脸懵逼. 希望看到ip就能知道是哪个集群里的, 策略可以直接根据预先设定的网段来设置. 下面是之前规划时整理的部分文档(2017年4月写的, 具体请以阿里云最新文档为准)
限制:
注意事项:
- VPC 的交换机是一个 3 层交换机,不支持 2 层广播和组播。
- 每个交换机的第1个和最后3个 IP 地址为系统保留地址。以 192.168.1.0/24 为例,192.168.1.0、 192.168.1.253、 192.168.1.254 和 192.168.1.255 这些地址是系统保留地址。
- 专有网络内的 ECS 使用安全组防火墙进行三层网络访问控制。
划分原则
- 每个分组对应至少一个或多个(可用区)交换机, 每个交换机绑定至少一个分组命名的安全组.
- 每个分组对应至少一个分组命名的容器集群.
- 每个分组对应单独的SNAT表或者SNAT IP POOL.
- 每个分组之间默认完全隔离. 由安全组控制访问.访问
- 每个分组保证至少2个可用区,核心业务三个可用区. 以可用区字母结尾, 例如 common-a 表示common分组, A可用区
- 生产和测试vpc独立, 完全隔离
其实不太建议用 192.168.0.0/16
网段, 可用ip相对会少一些, 而且后续如果办公网或者经典互联容易出现问题.
路由问题
这里需要注意2个问题
- 默认情况路由表条目是有限制的, 默认是48, 如果后续容器化(阿里云为了打通容器网段, 会在路由表上自动添加路由条目, 容器网段下一跳指向对应宿主机节点), 很容易达到限制配额. 可以手动控台申请配额, 或者工单申请.
- 正常情况classiclink后, 经典网络节点可以直接访问vpc节点, 但是如果vpc网段是
192.168.0.0/16
就比较特殊了, 需要手动在经典节点上加下路由. 脚本参考这里 添加路由
新老服务交互
我们应用主要是dubbo + http方式来进行应用间的互相访问, 涉及数十个应用, 不会是一波进去, 就会存在一段时间需要vpc和经典互访的情况.
dubbo服务
- 利用classic将zk集群和provider端链入vpc
- vpc内新建一个zk集群
- consumer端先迁入, 同时注册新老zk集群, 因为后续使用的容器化, 直接在启动entrypoint的脚本里做一些处理即可, 应用无需改动.
# add dubbo vpc registry
# find /data/ -name "*.xml" -exec grep -Hn 'registry' {} \; | awk -F: '{print $1}' | xargs -i -t sed -i -r '/zookeeper.vpc.cluster/d' {}
# find /data/ -name "*.xml" -exec grep -Hn 'registry' {} \; | awk -F: '{print $1}' | xargs -i -t sed -i -r '/registry/{h;s/dubbo:registry/& id="vpc"/;s/(address=")(.*)(")/\1${zookeeper.vpc.cluster}\3/;G}' {}
- 后续provider迁入, 同理. 直至相关服务迁移完成后将主zk直接指向vpc的zk集群, 老zk集群下线.
http服务
这个比较简单了, 因为我们内部服务也通过slb暴露, 这里主要通过slb混挂来做.
- vpc内起一个新的服务, 将相关节点挂入原有的经典内网slb.
- 调整权重, 观察服务正常逐渐替换老的节点即可.
- 一般会在vpc内也再开一个vpc内网slb提供vpc内调用, 后续迁移完成后确认老的经典slb无流量后释放即可.
公网slb其实同理. 不过由于在迁移vpc同时进行了容器化, 这里稍微有些处理(下篇专门介绍容器化会说到)
阿里云相关资源调用
后续迁移过程中阿里云其实都已经提供了相当方便的支持, 在这之前我们都是使用的相当粗暴的走公网链接方式(很不推荐, 受公网带宽限制, 而且有一定风险, 虽然traceroute测试下来公网路径貌似都是经过的阿里云节点,但终究心里没底)
- oss, ots, ons等等直接换成vpc的endpoint即可
- drds,rds, redis稍微麻烦一点, 需要迁移vpc后选择
保留经典链接
, 最多可以同时维持vpc,经典内网,公网三个链接地址, 而且经典地址保留时间可以工单延长. vpc内的应用直接使用vpc内网地址即可.
基本上在阿里云实际提供支持后, vpc和经典网络这块并没有太多的障碍, 主要根据应用状态, 逐个迁移观察, 就是一些细心的活了. 更多踩到的坑还是在容器化中, 下篇继续介绍vpc迁移同时容器化踩到的一些坑.