云企业网支持在地域内定义灵活的互通、隔离、引流策略。本文为您介绍如何通过云企业网实现相互隔离的VPC同时访问同一个共享服务。
本教程所含示例代码支持一键运行,您可以直接运行代码。一键运行
背景信息
本文以下图场景为例。某企业在阿里云华东1(杭州)地域已经部署有三个VPC,其中VPC3为部署共享服务的VPC。企业希望VPC1和VPC2均能访问VPC3使用共享服务,而VPC1和VPC2之间不互通。
网络规划
为实现上述需求,结合云企业网自定义路由表、关联转发、路由学习等功能,对企业网段和路由规划如下:
将VPC3连接到转发路由器时,开启自动关联至转发路由器的默认路由表和自动传播系统路由至转发路由器的默认路由表高级功能。
开启后,转发路由器默认路由表能自动学习到VPC3的系统路由,并且VPC3通过查询转发路由器的默认路由表进行流量转发。
将VPC1和VPC2连接到转发路由器时,均只开启自动传播系统路由至转发路由器的默认路由表一个高级配置,然后将VPC1和VPC2关联到转发路由器的自定义路由表,且在自定义路由表中,添加去往VPC3的自定义路由条目。
完成后,转发路由器默认路由表能学习到VPC1和VPC2的全部系统路由。VPC1和VPC2通过查询自定义路由表将流量转发到VPC3。此时,VPC1和VPC2之间不互通。
分别在VPC1、VPC2、VPC3的路由表中添加0.0.0.0/0,下一跳指向转发路由器的路由。
在华东1(杭州)地域创建三个VPC,并在指定可用区中创建交换机。VPC中的网段规划,如下表所示。
重要在您进行网段规划时,请确保VPC之间的网段没有重叠。
专有网络VPC
交换机
交换机可用区
网段规划
云服务器ECS
VPC1
主网段:192.168.0.0/16
交换机1
可用区A
192.168.0.0/24
ECS1地址:
192.168.0.224
交换机2
可用区B
192.168.1.0/24
VPC2
主网段:172.16.0.0/16
交换机3
可用区A
172.16.0.0/24
ECS2地址:
172.16.0.222
交换机4
可用区B
172.16.1.0/24
VPC3
主网段:10.0.0.0/16
交换机5
可用区A
10.0.0.0/24
ECS3地址:
10.0.0.112
交换机6
可用区B
10.0.1.0/24
操作步骤
本文提供控制台和Terraform两种配置方式,请按需选择。
控制台
步骤一:创建云企业网实例
在您连接网络实例前,您需要先创建一个云企业网实例。
- 登录云企业网管理控制台。
在云企业网实例页面,单击创建云企业网实例。
在创建云企业网实例对话框,根据以下信息配置云企业网实例,然后单击确认。
名称:云企业网实例的名称。
描述:云企业网实例的描述。
步骤二:创建VPC连接
在云企业网实例页面,单击目标实例ID。
在云企业网实例详情页面的基本信息页签,单击VPC下的图标。
在连接网络实例页面,根据以下信息进行配置,然后单击确定创建。
实例类型:系统默认选择专有网络(VPC)。
地域:选择要连接的网络实例所在的地域。本示例选择华东1(杭州)。
转发路由器:系统自动为您在该地域创建转发路由器。
资源归属UID:选择要连接的网络实例所归属的账号类型。本示例使用默认值同账号。
付费方式:使用默认值按量付费。
连接名称:输入连接名称。
网络实例:选择要连接的VPC网络实例ID。本示例选择VPC3。
交换机:在转发路由器支持的可用区选择交换机实例。
如果企业版转发路由器在当前地域仅支持一个可用区,则您需要在当前可用区选择一个交换机实例。
如果企业版转发路由器在当前地域支持多个可用区,则您需要在至少2个可用区中各选择一个交换机实例。在VPC和企业版转发路由器流量互通的过程中,这2个交换机实例可以实现可用区级别的容灾。
推荐您在每个可用区中都选择一个交换机实例,以减少流量绕行,体验更低传输时延以及更高性能。
高级配置:系统默认帮您选中以下三种高级功能。本示例中VPC3只开启自动关联至转发路由器的默认路由表和自动传播系统路由至转发路由器的默认路由表高级功能。
自动关联至转发路由器的默认路由表
开启本功能后,VPC连接会自动关联至转发路由器的默认路由表,转发路由器通过查询默认路由表转发VPC实例的流量。
自动传播系统路由至转发路由器的默认路由表
开启本功能后,VPC实例会将自身的系统路由传播至转发路由器的默认路由表中,用于网络实例的互通。
自动为VPC的所有路由表配置指向转发路由器的路由
开启本功能后,系统将在VPC实例的所有路由表内自动配置10.0.0.0/8、172.16.0.0/12、192.168.0.0/16三条路由条目,其下一跳均指向VPC连接,用于引导VPC实例的IPv4流量进入转发路由器。转发路由器默认不向VPC实例传播路由。
VPC3连接创建完成后,单击继续创建连接。
VPC连接创建完成后,单击返回列表,返回到云企业网实例详情页面。
步骤三:VPC1和VPC2关联自定义路由表
在云企业网实例详情页面,找到已创建的转发路由器,单击其实例ID。
在转发路由器详情页面,单击转发路由器路由表页签。
在页签左侧区域,单击创建路由表。
在创建路由表对话框,根据以下信息进行配置,然后单击确定。
转发路由器:系统自动选择当前地域的转发路由器。
路由表名称:输入路由表名称。
路由表描述:输入路由表描述。
多地域等价路由:保持默认值。
单击返回路由表详情,返回到转发路由器路由表页签下。
在转发路由器路由表页签下,选择刚刚创建的自定义路由表,单击关联转发页签,然后单击创建关联转发。
在添加关联转发对话框,选择要关联至该自定义路由表的网络实例连接,然后单击确定。
本文示例中,分别将VPC1和VPC2关联至该自定义路由表。关联后,VPC1和VPC2将通过查询该路由表进行流量转发。
在自定义路由表详情页面,单击路由条目页签,然后单击创建路由条目。
在添加路由条目对话框,根据以下信息进行配置,然后单击确定。
路由表:系统默认选择当前自定义路由表。
所属转发路由器:系统默认选择当前地域的转发路由器。
路由条目名称:输入路由条目名称。
目的地址CIDR:输入要添加的路由目标网段。本示例输入10.0.0.0/16。
是否为黑洞路由:如果选择路由为黑洞路由后,所有去往该路由的流量均会被丢弃。本示例选择否。
下一跳连接:选择路由的下一跳连接。本示例选择VPC3连接。
路由条目描述:路由条目描述。
步骤四:为VPC添加默认路由条目
您需要在VPC控制台分别为VPC1、VPC2、VPC3添加网段为0.0.0.0/0,下一跳指向转发路由器的路由。
- 登录专有网络管理控制台。
在左侧导航栏,单击路由表。
在顶部菜单栏,选择路由表所属的地域。
在路由表页面,找到目标路由表,单击路由表的ID。
本示例选择VPC3的路由表。
在路由表实例详情页面,单击路由条目列表页签下的自定义路由条目,然后单击添加路由条目。
在添加路由条目面板,根据以下信息配置路由条目,然后单击确定。
名称:输入路由条目的名称。
目标网段:输入要添加的目标网段。本示例输入0.0.0.0/0。
下一跳类型:选择下一跳类型。本示例选择转发路由器。
转发路由器:选择网络实例连接。本示例选择VPC3连接。
更多参数说明,请参见使用自定义路由表进行网络流量管理。
请重复步骤4到步骤6,分别为VPC1、VPC2添加网段为0.0.0.0/0,下一跳指向转发路由器的路由。
在您完成配置后,您可以在云企业网控制台转发路由器详情页面查看VPC1、VPC2、VPC3以及转发路由器路由表的路由信息。
在转发路由器详情页面,单击网络实例路由信息,分别查看VPC1、VPC2和VPC3的路由。
在转发路由器详情页面,单击网络实例路由信息。
在网络实例后面,选择VPC1、VPC2或VPC3的实例ID,查看路由。
您可以在转发路由器路由表页签下,查看转发路由器系统路由表已学习到的VPC1、VPC2、VPC3的路由。
在转发路由器详情页面,单击转发路由器路由表。
在转发路由器路由表页签下,查看路由表路由条目。
步骤五:验证测试
完成上述配置后,您可以通过以下步骤,测试VPC1、VP2、VPC3之间的连通性。
在您执行以下步骤前,请您先了解您VPC1、VPC2、VPC3中的ECS实例所应用的安全组规则,确保安全组规则允许三个VPC中的ECS实例之间可以互通。具体操作,请参见查询安全组规则。
登录VPC1的ECS实例。具体操作,请参见ECS远程连接方式概述。
通过ping命令,ping VPC3下的ECS实例的IP地址,测试VPC1和VPC3之间的连通性。
经验证,VPC1和VPC3之间可以正常通信。
登录VPC2的ECS实例,通过ping命令,ping VPC3下的ECS实例的IP地址,测试VPC2和VPC3之间的连通性。
经验证,VPC2和VPC3之间可以正常通信。
登录VPC1的ECS实例,通过ping命令,ping VPC2下的ECS实例的IP地址,测试VPC1和VPC2之间的连通性。
经验证,VPC1和VPC2之间不能通信。
Terraform
您可以使用Terraform搭建本文示例环境,关于Terraform的安装和配置,请参考Provider 使用。
下面步骤以Linux主机运行Terraform v1.9.8为例进行介绍,操作前请确保您已经完成Terraform 身份认证。
本教程示例包含的部分资源会产生一定费用,请在不需要时及时进行释放或退订。
第一步:创建资源
为本文的实践场景创建一个目录,并进入该目录。
mkdir tf-CenSharedVpc && cd tf-CenSharedVpc
创建一个
main.tf
文件,用于定义资源信息。touch main.tf
打开
main.tf
文件,复制如下代码,粘贴到文件中并保存。此文件包含了本文实践场景中需要用到的资源和对应配置。variable "pname" { description = "The prefix name for the resources" type = string default = "tf-CenSharedVpc" } variable "default_region" { description = "Default region" type = string default = "cn-hangzhou" } variable "az_list" { description = "List of availability zones to use" type = list(string) default = ["cn-hangzhou-j", "cn-hangzhou-k"] } variable "vpc_cidr_list" { description = "List of VPC CIDR block" type = list(string) default = ["192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/16"] } variable "vsw_cidr_list" { description = "List of VSW CIDR block" type = list(string) default = [ "192.168.0.0/24", "192.168.1.0/24", "172.16.0.0/24", "172.16.1.0/24", "10.0.0.0/24", "10.0.1.0/24" ] } variable "ecs_ip_list" { description = "List of ECS ip" type = list(string) default = ["192.168.0.124", "172.16.0.222", "10.0.0.112"] } provider "alicloud" { region = var.default_region } # --- 3vpc 6vsw 3ecs resource "alicloud_vpc" "vpc" { count = length(var.vpc_cidr_list) vpc_name = "${var.pname}-vpc${count.index + 1}" cidr_block = var.vpc_cidr_list[count.index] } resource "alicloud_vswitch" "vsw" { count = length(var.vsw_cidr_list) vpc_id = alicloud_vpc.vpc[floor(count.index / length(var.az_list))].id cidr_block = var.vsw_cidr_list[count.index] zone_id = var.az_list[count.index % length(var.az_list)] vswitch_name = "${var.pname}-vsw${count.index + 1}" } resource "alicloud_instance" "ecs" { count = length(var.vpc_cidr_list) instance_name = "${var.pname}-ecs${count.index + 1}" instance_type = "ecs.e-c1m1.large" security_groups = [alicloud_security_group.sg[count.index].id] vswitch_id = alicloud_vswitch.vsw[count.index * length(var.az_list)].id image_id = "aliyun_3_x64_20G_qboot_alibase_20230727.vhd" system_disk_category = "cloud_essd" private_ip = var.ecs_ip_list[count.index] instance_charge_type = "PostPaid" } # --- 3 sg resource "alicloud_security_group" "sg" { count = length(var.vpc_cidr_list) name = "${var.pname}-${count.index + 1}" vpc_id = alicloud_vpc.vpc[count.index].id } resource "alicloud_security_group_rule" "allow_inbound_ssh" { count = length(var.vpc_cidr_list) type = "ingress" ip_protocol = "tcp" nic_type = "intranet" policy = "accept" port_range = "22/22" priority = 1 security_group_id = alicloud_security_group.sg[count.index].id cidr_ip = "0.0.0.0/0" } resource "alicloud_security_group_rule" "allow_inbound_icmp" { count = length(var.vpc_cidr_list) type = "ingress" ip_protocol = "icmp" nic_type = "intranet" policy = "accept" port_range = "-1/-1" priority = 1 security_group_id = alicloud_security_group.sg[count.index].id cidr_ip = "0.0.0.0/0" } # --- cen and tr resource "alicloud_cen_instance" "cen" { cen_instance_name = "${var.pname}-cen1" } resource "alicloud_cen_transit_router" "tr" { transit_router_name = "${var.pname}-tr" cen_id = alicloud_cen_instance.cen.id } data "alicloud_cen_transit_router_route_tables" "tr" { # get tr sys table transit_router_id = alicloud_cen_transit_router.tr.transit_router_id transit_router_route_table_type = "System" } # 3 attach resource "alicloud_cen_transit_router_vpc_attachment" "attach" { count = length(var.vpc_cidr_list) cen_id = alicloud_cen_instance.cen.id transit_router_id = alicloud_cen_transit_router.tr.transit_router_id vpc_id = alicloud_vpc.vpc[count.index].id zone_mappings { zone_id = var.az_list[0] vswitch_id = alicloud_vswitch.vsw[count.index * length(var.az_list)].id } zone_mappings { zone_id = var.az_list[1] vswitch_id = alicloud_vswitch.vsw[count.index * length(var.az_list) + 1].id } transit_router_vpc_attachment_name = "attach${count.index + 1}" } # 3 propa resource "alicloud_cen_transit_router_route_table_propagation" "propa" { count = length(var.vpc_cidr_list) transit_router_route_table_id = data.alicloud_cen_transit_router_route_tables.tr.tables[0].id transit_router_attachment_id = alicloud_cen_transit_router_vpc_attachment.attach[count.index].transit_router_attachment_id } # 1 custom_table resource "alicloud_cen_transit_router_route_table" "custom_table" { # create tr custom_table transit_router_id = alicloud_cen_transit_router.tr.transit_router_id transit_router_route_table_name = "custom_table" } resource "alicloud_cen_transit_router_route_entry" "tr_entry" { transit_router_route_table_id = alicloud_cen_transit_router_route_table.custom_table.transit_router_route_table_id transit_router_route_entry_destination_cidr_block = "10.0.0.0/16" transit_router_route_entry_next_hop_type = "Attachment" transit_router_route_entry_name = "entry1_name" transit_router_route_entry_description = "entry1_desc" transit_router_route_entry_next_hop_id = alicloud_cen_transit_router_vpc_attachment.attach[2].transit_router_attachment_id } # associate attach1\2 custom_table resource "alicloud_cen_transit_router_route_table_association" "ass1" { transit_router_route_table_id = alicloud_cen_transit_router_route_table.custom_table.transit_router_route_table_id transit_router_attachment_id = alicloud_cen_transit_router_vpc_attachment.attach[0].transit_router_attachment_id } resource "alicloud_cen_transit_router_route_table_association" "ass2" { transit_router_route_table_id = alicloud_cen_transit_router_route_table.custom_table.transit_router_route_table_id transit_router_attachment_id = alicloud_cen_transit_router_vpc_attachment.attach[1].transit_router_attachment_id } # ass attach3 sys_table resource "alicloud_cen_transit_router_route_table_association" "ass3" { transit_router_route_table_id = data.alicloud_cen_transit_router_route_tables.tr.tables[0].id transit_router_attachment_id = alicloud_cen_transit_router_vpc_attachment.attach[2].transit_router_attachment_id } # vpc entry resource "alicloud_route_entry" "vpc_entry" { count = length(var.vpc_cidr_list) route_table_id = alicloud_vpc.vpc[count.index].route_table_id destination_cidrblock = "0.0.0.0/0" nexthop_type = "Attachment" nexthop_id = alicloud_cen_transit_router_vpc_attachment.attach[count.index].transit_router_attachment_id } output "ecs1_login_address" { value = "https://ecs-workbench.aliyun.com/?from=EcsConsole&instanceType=ecs®ionId=${var.default_region}&instanceId=${alicloud_instance.ecs[0].id}" } output "ecs2_login_address" { value = "https://ecs-workbench.aliyun.com/?from=EcsConsole&instanceType=ecs®ionId=${var.default_region}&instanceId=${alicloud_instance.ecs[1].id}" } output "ecs3_login_address" { value = "https://ecs-workbench.aliyun.com/?from=EcsConsole&instanceType=ecs®ionId=${var.default_region}&instanceId=${alicloud_instance.ecs[2].id}" }
初始化目录,完成Terraform的初始化配置。
terraform init
创建资源。执行后Terraform会先预览将要创建的资源,确认无误后,输入
yes
正式开始创建。terraform apply
第二步:验证测试
您可以通过以下步骤,测试VPC1、VPC2、VPC3之间的连通性。
登录VPC1下的ECS1实例(实例名称为
tf-CenSharedVpc-ecs1
)。您可以在Terraform的Outputs输出中,找到ECS1的登录地址并复制到浏览器打开,登录时注意认证方式选择临时SSH密钥认证。
通过ping命令,ping VPC3下的ECS3实例的IP地址,测试VPC1和VPC3之间的连通性。
ping 10.0.0.112
经验证,VPC1和VPC3之间可以正常通信。
登录VPC2下的ECS2实例(实例名称为
tf-CenSharedVpc-ecs2
),通过ping命令,ping VPC3下的ECS3实例的IP地址,测试VPC2和VPC3之间的连通性。ping 10.0.0.112
经验证,VPC2和VPC3之间可以正常通信。
登录VPC1下的ECS1实例(实例名称为
tf-CenSharedVpc-ecs1
),通过ping命令,ping VPC2下的ECS2实例的IP地址,测试VPC1和VPC2之间的连通性。ping 172.16.0.222
经验证,VPC1和VPC2之间不能通信。
第三步:释放资源
验证完毕后,如果您不再使用资源,请执行以下命令释放资源,防止继续计费。
terraform destroy --auto-approve