vpc之玩转自定义路由

阿凡达2018-07-04 11:03

一、背景

近期网络新版本VPC上线,相较于经典网络,VPC提供了一个玩法比较丰富的新功能:自定义路由。由于自定义路由用法相较于其它功能比较复杂,本文将简单介绍一下自定义路由用法以及几种比较常见的使用场景。

二、自定义路由介绍

1、系统路由

在创建VPC时,系统会自动为VPC创建一张主路由表,路由表中的每一项是一条路由规则,路由规则定义了通向指定目标网段的网络流量的下一跳地址。路由表根据具体的路由规则的设置来转发网络流量。

主路由表中保存的都是系统路由,系统路由主要包括以下几类:

  • 内网路由local:一条典型的内网路由如下,其目的段地址为VPC的cidr,主要负责VPC内网互连路由转发,一般来说内网路由规则具有最高的优先级,当其它路由规则与内网路由cidr发生冲突时流量优先走内网路由。


| routes     | {                                                               |
|            |      "route_type": "system",                                    |
|            |      "tenant_id": "0acf3278cb134e519383fcd0ab2a47e2",           |
|            |      "destination": "10.199.0.0/16",                            |
|            |      "priority": "low",                                         |
|            |      "route_table_id": "5d8f6efb-92e7-4497-aec6-565547edc87c",  |
|            |      "nexthop_ports": [],                                       |
|            |      "id": "9977e963-5d3d-4276-9c27-391954a6fa54",              |
|            |      "nexthop_device_id": "",                                   |
|            |      "nexthop_type": "local"                                    |
|            | }                                                               |
  • floating ip路由:一条典型的floating ip的路由规则如下,如果在VPC内部创建floating ip,主路由表中会出现一条对应的路由规则,由于floating ip一般用于云主机外网连接,所以对应目的段cidr一般为0.0.0.0/0,下一跳的ports为创建floating ip时调度到网关节点的port uuid,floating ip路由优先级规则高于snat 路由和用户自定义路由,低于内网路由。

|            | {                                                                  |
|            |      "route_type": "system",                                       |
|            |      "destination": "0.0.0.0/0",                                   |
|            |      "priority": "low",                                            |
|            |      "route_table_id": "dfbd35e0-115f-4509-a082-a50a3b4e2889",     |
|            |      "nexthop_ports": [                                            |
|            |           "154be29a-e97b-40fa-bccb-33c2d2eb7da7",                  |
|            |           "d31f6afa-e292-4843-9517-0597297307da"                   |
|            |      ],                                                            |
|            |      "id": "e4befb22-09fe-41f5-8800-33ed21384b7c",                 |
|            |      "nexthop_device_id": "2177b7f4-a7d4-46a6-8461-0ff8455024ac",  |
|            |      "nexthop_type": "floating_ip"                                 |
|            | }                                                                  |
  • ephemeral ip路由:和floating ip类似,在创建ephemeral ip时,主路由表中也会新增一条ephemeral ip的路由规则,与floating ip不同的是,ephmeral ip的路由规则目的段一般是对应公共服务/管理网的cidr,具体内容由ephemeral ip的类型决定,ephemeral ip路由的优先级与floating ip一致。
  • snat 路由:一条典型的snat路由规则如下,如果在VPC中创建了snat,那么主路由表中会新增snat对应的路由规则,路由规则的目的段由snat的类型决定,如果创建internet类型的snat,那么目的段cidr一般为0.0.0.0/0,如果是service类型的snat,那么路由规则目的段则为对应的公共服务段地址,snat路由规则优先级最低。

需要注意的是,floating ip路由和ephemeral ip的作用范围仅限于其所绑定的fixed ip所对应的云主机,而snat路由作用范围是整个VPC内部所有fixed ip绑定的云主机

|            | {                                                                  |
|            |      "route_type": "system",                                       |
|            |      "destination": "10.187.12.0/22",                              |
|            |      "priority": "low",                                            |
|            |      "route_table_id": "dfbd35e0-115f-4509-a082-a50a3b4e2889",     |
|            |      "nexthop_ports": [                                            |
|            |           "bb54a65a-365a-44c4-a24d-a132725548bd",                  |
|            |           "bca5f3b5-a302-42a1-bb75-52cd49bd9fd7"                   |
|            |      ],                                                            |
|            |      "id": "fb7e34ac-5797-476d-a96b-6a6e151f3e44",                 |
|            |      "nexthop_device_id": "d0840916-cf18-47d6-a2e3-7f225be4a5b7",  |
|            |      "nexthop_type": "snat"                                        |
|            | }                                                                  |

2、自定义路由

VPC中将用户自行创建的路由定义为自定义路由,路由规则类型为user,在创建自定义路由规则时,下一跳地址必须是VPC内的某个port uuid,自定义路由规则优先级高于snat路由,但低于内网路由和floating ip/ephemeral ip路由。

如果需要使用自定义路由功能,一般需要创建一张新路由表,将自定义路由规则创建在新创建的路由表中。当新建路由表时,这张路由表会继承主路由表中的所有系统路由。

注意:当路由表与subnet关联时不能直接删除,需要更新subnet的路由表方可删除,此外,当一个VPC被删除时,系统会清空路由表和路由规则

需要注意的是,自定义路由表作用范围是subnet,要想自定义路由生效,需要update对应subnet的路由表为新创建的路由表,具体流程为:

1、创建一张新路由表
(dev-env)hzhezhongwei@pubbeta2-nova10:~/vpc_test_shell_stable$ proton route-table-create ab2e5529-e790-43b5-97b4-3bd0ba7e5945 --name test_route_table
Created a new route_table:
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field      | Value                                                                                                                                                                                             |
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| default    | False                                                                                                                                                                                             |
| id         | 71bcb8b6-a52c-4fbd-a91e-c6b20e6516d5                                                                                                                                                              |
| name       | test_route_table                                                                                                                                                                                  |
| network_id | ab2e5529-e790-43b5-97b4-3bd0ba7e5945                                                                                                                                                              |
| routes     | {"route_type": "system", "tenant_id": "00e63c1e4e4c43bd800597c557d5c3e7", "destination": "10.182.8.0/22", "priority": "low", "route_table_id": "dfbd35e0-115f-4509-a082-a50a3b4e2889",            |
|            | "nexthop_ports": ["bb54a65a-365a-44c4-a24d-a132725548bd", "bca5f3b5-a302-42a1-bb75-52cd49bd9fd7"], "id": "013db824-5650-4054-992a-0c85dc6752c6", "nexthop_device_id":                             |
|            | "d0840916-cf18-47d6-a2e3-7f225be4a5b7", "nexthop_type": "snat"}                                                                                                                                   |
|            | {"route_type": "system", "tenant_id": "00e63c1e4e4c43bd800597c557d5c3e7", "destination": "0.0.0.0/0", "priority": "low", "route_table_id": "dfbd35e0-115f-4509-a082-a50a3b4e2889",                |
|            | "nexthop_ports": ["154be29a-e97b-40fa-bccb-33c2d2eb7da7", "d31f6afa-e292-4843-9517-0597297307da"], "id": "e4befb22-09fe-41f5-8800-33ed21384b7c", "nexthop_device_id":                             |
|            | "2177b7f4-a7d4-46a6-8461-0ff8455024ac", "nexthop_type": "floating_ip"}                                                                                                                            |
|            | {"route_type": "system", "tenant_id": "00e63c1e4e4c43bd800597c557d5c3e7", "destination": "0.0.0.0/0", "priority": "low", "route_table_id": "dfbd35e0-115f-4509-a082-a50a3b4e2889",                |
|            | "nexthop_ports": ["154be29a-e97b-40fa-bccb-33c2d2eb7da7", "d31f6afa-e292-4843-9517-0597297307da"], "id": "87abca6b-c86d-4a97-953e-1a1cd5affb78", "nexthop_device_id":                             |
|            | "a7d3b318-15a2-40b1-bce5-5013869643fa", "nexthop_type": "snat"}                                                                                                                                   |
|            | {"route_type": "system", "tenant_id": "00e63c1e4e4c43bd800597c557d5c3e7", "destination": "172.16.220.0/24", "priority": "low", "route_table_id": "dfbd35e0-115f-4509-a082-a50a3b4e2889",          |
|            | "nexthop_ports": [], "id": "e816b42f-94a2-4980-ab45-9bf8f800a043", "nexthop_device_id": "", "nexthop_type": "local"}                                                                              |
|            | {"route_type": "system", "tenant_id": "00e63c1e4e4c43bd800597c557d5c3e7", "destination": "10.187.12.0/22", "priority": "low", "route_table_id": "dfbd35e0-115f-4509-a082-a50a3b4e2889",           |
|            | "nexthop_ports": ["bb54a65a-365a-44c4-a24d-a132725548bd", "bca5f3b5-a302-42a1-bb75-52cd49bd9fd7"], "id": "fb7e34ac-5797-476d-a96b-6a6e151f3e44", "nexthop_device_id":                             |
|            | "d0840916-cf18-47d6-a2e3-7f225be4a5b7", "nexthop_type": "snat"}                                                                                                                                   |
| tenant_id  | 00e63c1e4e4c43bd800597c557d5c3e7                                                                                                                                                                  |
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2、在新路由表中创建自定义路由规则,这里创建了一条目的段为0.0.0.0/0,下一跳port地址为9f736b33-09fa-48f2-ad05-468bce9b919d的自定义路由规则
(dev-env)hzhezhongwei@pubbeta2-nova10:~/vpc_test_shell_stable$ proton route-create 71bcb8b6-a52c-4fbd-a91e-c6b20e6516d5 9f736b33-09fa-48f2-ad05-468bce9b919d 0.0.0.0/0
Created a new route:
+-------------------+--------------------------------------+
| Field             | Value                                |
+-------------------+--------------------------------------+
| destination       | 0.0.0.0/0                            |
| id                | dd9c3f4b-6980-43ad-be57-0842b67d2721 |
| nexthop_device_id | 9f736b33-09fa-48f2-ad05-468bce9b919d |
| nexthop_ports     | 9f736b33-09fa-48f2-ad05-468bce9b919d |
| nexthop_type      | port                                 |
| priority          | low                                  |
| route_table_id    | 71bcb8b6-a52c-4fbd-a91e-c6b20e6516d5 |
| route_type        | user                                 |
| tenant_id         | 00e63c1e4e4c43bd800597c557d5c3e7     |
+-------------------+--------------------------------------+
3、更新对应subnet的路由表为新创建的路由表:
(dev-env)hzhezhongwei@pubbeta2-nova10:~/vpc_test_shell_stable$ proton subnet-update 9efaf875-05b1-428a-95b9-41070e1127ca --route-table 71bcb8b6-a52c-4fbd-a91e-c6b20e6516d5
Updated subnet: 9efaf875-05b1-428a-95b9-41070e1127ca

3、选路规则

就优先级而言,内网路由 > flaoting ip路由 = epehemral ip路由 > 用户自定义路由 > snat路由,但是flaoting ip和ephemeral ip作用范围仅为单个fixed ip。 例如一个VPC的路由表如下所示:

目标网段 下一跳地址类型 下一跳 路由规则类型
0.0.0.0/0 port-1111 snat
0.0.0.0/0 port-2222 floating ip
172.16.0.0/16 local
10.176.1.0/24 instance port-3333 user
10.176.2.0/24 instance port-4444 user

前三行分别为snat路由,flaoting ip路由和内网路由,后两行为用户自定义路由。

对于没有绑定floating ip的云主机而言,其访问0.0.0.0/0地址段的流量转发至ID为port-1111的port,而绑定了flaoting ip的云主机访问访问0.0.0.0/0地址段的流量将转发至ID为port-2222的port。此外,根据最长cidr匹配原则,所有虚拟机访问10.176.1.0/24的流量都将转发到port-3333。

三、典型应用场景

将floating ip作为外网网关

当一个VPC中的部分主机没有flaoting ip但需要访问外网时,可以通过配置一台带有flaoting ip的云主机作为公网网关来给这些主机提供外网访问。公网网关主机将对出网流量进行源地址转换,所有其它云主机访问外网的流量经过公网网关后,源IP都被转换为公网网关主机的IP地址,如下图:

想要完成上述架构,需要进行以下几个步骤:

  • 创建网关子网
  • 在网关子网中创建网关云主机,同时为网关云主机绑定flaoting ip,网关云主机需要配置iptables的nat规则,以及打开kernel的ip_forward,具体流程为:
    开启ip_forward:
    vim  /etc/sysctl.conf
    修改net.ipv4.ip_forward = 1
    开启nat:
    iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    
  • 为普通子网创建路由表和路由规则:

创建路由表
(dev-env)hzhezhongwei@pubbeta2-nova10:~/vpc_test_shell_stable$ proton route-table-create 70caf334-ff87-4cd1-9059-3e7a3284df49 --name test_route_table
Created a new route_table:
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field      | Value                                                                                                                                                                                             |
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| default    | False                                                                                                                                                                                             |
| id         | d0a3f433-5fb8-4b7d-ba2e-373749d16a3e                                                                                                                                                              |
| name       | test_route_table                                                                                                                                                                                  |
| network_id | 70caf334-ff87-4cd1-9059-3e7a3284df49                                                                                                                                                              |
| routes     | {"route_type": "system", "tenant_id": "00e63c1e4e4c43bd800597c557d5c3e7", "destination": "172.16.0.0/16", "priority": "low", "route_table_id": "bf9b3cb2-90cd-48ce-83ca-90ca40b9103e",            |
|            | "nexthop_ports": [], "id": "73f487d1-9b62-434d-a180-66c0187cd737", "nexthop_device_id": "", "nexthop_type": "local"}                                                                              |
| tenant_id  | 00e63c1e4e4c43bd800597c557d5c3e7                                                                                                                                                                  |
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
创建路由
(dev-env)hzhezhongwei@pubbeta2-nova10:~/vpc_test_shell_stable$ proton route-create d0a3f433-5fb8-4b7d-ba2e-373749d16a3e  c8d273e7-830d-455c-a1a8-6f3d16a9c837  0.0.0.0/0
Created a new route:
+-------------------+--------------------------------------+
| Field             | Value                                |
+-------------------+--------------------------------------+
| destination       | 0.0.0.0/0                            |
| id                | 855fe7d2-0940-4ed4-a475-2d89da34b389 |
| nexthop_device_id | c8d273e7-830d-455c-a1a8-6f3d16a9c837 |
| nexthop_ports     | c8d273e7-830d-455c-a1a8-6f3d16a9c837 |
| nexthop_type      | port                                 |
| priority          | low                                  |
| route_table_id    | d0a3f433-5fb8-4b7d-ba2e-373749d16a3e |
| route_type        | user                                 |
| tenant_id         | 00e63c1e4e4c43bd800597c557d5c3e7     |
+-------------------+--------------------------------------+

至此,就可以让普通子网中的云主机通过网关云主机访问外网

总结

自定义路由的玩法非常丰富,并不局限于文中介绍的场景,你甚至可以在两个子网中通过自定义路由构建环路,自建ECMP路由等,后续VPC将推出更多更强大的功能,欢迎大家多多实践,多谢!

本文来自网易实践者社区,经作者何中威授权发布。