首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >别再把VPC当成"云上交换机"了:我用AWS从0搭一套生产可用网络,把云计算里的VPC彻底讲透

别再把VPC当成"云上交换机"了:我用AWS从0搭一套生产可用网络,把云计算里的VPC彻底讲透

作者头像
悠悠12138
发布2026-07-03 19:40:22
发布2026-07-03 19:40:22
110
举报

刚开始搞云计算那会儿,我也觉得VPC这玩意儿挺虚的。

控制台点进去一堆名词往脸上砸:Subnet、Route Table、Internet Gateway、NAT Gateway、Security Group、NACL、Endpoint、Peering……看着像网络,又不像传统机房那种网络。以前在机房里,交换机、路由器、防火墙、网线,摸得着看得见,排障还能去机柜边上看灯闪不闪。到了云上,啥都在页面里点来点去,概念全靠想象,理解起来总感觉隔了一层。

后来自己踩过几次坑,才慢慢把VPC这东西给整明白了。

这篇文章我就按我平时做云上网络规划的思路,拿AWS从头到尾搭一个贴近生产的小型VPC。不是那种点几下创建EC2能上网就完事的入门教程,而是把里面每个组件为什么这么配、出了问题怎么查、哪些地方容易踩坑都聊清楚。


VPC到底是什么,我的理解是这样

image-20260702220259137
image-20260702220259137

image-20260702220259137

VPC,全称Virtual Private Cloud,翻译过来就是虚拟私有云。

你可以把它理解成:AWS在它那个巨大的全球网络基础设施里面,给你圈出来的一块“逻辑上完全隔离的私有网络空间”。

这个空间里,你自己说了算:

  • • IP地址段用多大,随便选
  • • 哪些机器能访问公网,哪些只能内部互通
  • • 流量怎么走,哪些能出互联网
  • • 访问AWS其他服务走不走公网
  • • 多AZ之间怎么组网
  • • 怎么跟公司本地机房打通

它不是一台具体的物理设备,也不是一个单一的网关服务。它更像一个容器,所有EC2、RDS、EKS节点、ALB、ElastiCache,只要放进去,就都得遵守这个VPC定下的网络规则。

我之前给团队新来的同事解释VPC,喜欢打个不太严谨的比方:

image-20260702220341838
image-20260702220341838

image-20260702220341838

VPC是小区,Subnet是楼栋,Route Table是小区里的指路牌,Internet Gateway是通往外面市政道路的大门,NAT Gateway是专门帮内网机器代购外网资源的代购员,Security Group是每户人家的门禁卡,NACL是小区大门口的保安。

比喻不准确,但先建立个画面感再说。


生产环境我基本不用默认VPC

AWS每个Region创建账号之后都会自带一个default VPC,你直接在控制台Launch Instance,它默认就塞进这个VPC里,机器起来就能上网,对新手非常友好。

但生产环境我基本不用它。

原因很简单:默认VPC的IP段通常是172.31.0.0/16,子网和路由表都是AWS自动建好的,你不知道里面有啥也不知道改了对业务有啥影响。特别是当团队变大、多个人同时操作的时候,一个不留神把默认VPC的路由表改了,整组人集体断网,那场面真的挺刺激的。

所以我现在不管是搭测试环境还是生产环境,第一步永远是先Create Your Own VPC,从头规划,自己掌控。

image-20260702220434952
image-20260702220434952

image-20260702220434952


实际操作:从头搭一个生产级VPC

规划IP地址段

这是最容易被忽略但其实最关键的一步。

IP段选大了浪费,选小了以后扩容麻烦。我一般会问自己几个问题:

  • • 这个VPC要放哪些业务
  • • 预估有多少台机器
  • • 需不需要跟其他VPC打通
  • • 有没有本地IDC要互联

拿我现在给一个中小型SaaS服务搭的VPC举例,我选了10.100.0.0/16这个段。

为什么是这个段?没什么硬性要求,主要是我司IDC用的是10.50.0.0/16,云上用10.100.0.0/16,两边不打架,好记。以后要是真拉专线打通,路由也好配。

然后把这个大段拆成几个子网:

  • 10.100.1.0/24 — 公网子网,AZ1
  • 10.100.2.0/24 — 公网子网,AZ2
  • 10.100.11.0/24 — 私网子网,AZ1
  • 10.100.12.0/24 — 私网子网,AZ2
  • 10.100.21.0/24 — 数据库子网,AZ1
  • 10.100.22.0/24 — 数据库子网,AZ2

公网子网放什么?ALB、NAT Gateway、需要对外提供服务的EC2。

私网子网放什么?应用服务器,Web服务器那些跑业务代码的。

数据库子网放什么?RDS、ElastiCache,那些不放公网、只允许应用层访问的。

子网划分没有标准答案,但有个原则要记住:公网和私网一定要分开,别为了省事把数据库直接塞公网子网里。


创建VPC和子网

拥有位于 2 个可用区的子网、3 个路由表、互联网网关和网关端点的 VPC
拥有位于 2 个可用区的子网、3 个路由表、互联网网关和网关端点的 VPC

拥有位于 2 个可用区的子网、3 个路由表、互联网网关和网关端点的 VPC

好了,规划完了,开始动手。

在AWS控制台顶部搜索VPC,进入VPC控制台:

点击 Create VPC,弹窗里这样填:

代码语言:javascript
复制
IPv4 CIDR block: 10.100.0.0/16
IPv6 CIDR block: No IPv6 CIDR Block
Tenancy: Default

Name tag写 saas-prod-vpc,点 Create。

VPC创建好了,现在建子网。

点击左侧 SubnetsCreate subnet

先建AZ1的公网子网:

代码语言:javascript
复制
VPC: saas-prod-vpc
Subnet name: public-subnet-az1
Availability Zone: us-east-1a(你选你自己的AZ)
IPv4 CIDR block: 10.100.1.0/24

点 Add new subnet,继续建AZ1的私网子网:

代码语言:javascript
复制
Subnet name: private-subnet-az1
Availability Zone: us-east-1a
IPv4 CIDR block: 10.100.11.0/24

然后是数据库子网、AZ2的子网,都按规划填进去。六个子网全部建好之后,大概是这么个布局:

  • • public-subnet-az1:10.100.1.0/24
  • • public-subnet-az2:10.100.2.0/24
  • • private-subnet-az1:10.100.11.0/24
  • • private-subnet-az2:10.100.12.0/24
  • • db-subnet-az1:10.100.21.0/24
  • • db-subnet-az2:10.100.22.0/24

这里有个小细节我要说一下:AWS的子网必须关联到一个AZ,不能跨AZ。所以每个AZ都要单独建子网。另外,如果你想在里面Launch实例的时候自动分配公有IP,记得把子网的"Auto-assign public IPv4 address"那个选项打开。


路由表——流量怎么走全看它

拥有位于 2 个可用区的子网、3 个路由表、互联网网关和网关端点的 VPC
拥有位于 2 个可用区的子网、3 个路由表、互联网网关和网关端点的 VPC

拥有位于 2 个可用区的子网、3 个路由表、互联网网关和网关端点的 VPC

路由表是VPC的核心,理解透了VPC就理解了一大半。

每个VPC默认会带一张主路由表,但我一般会新建两张独立的路由表:公网路由表私网路由表,职责分离,清晰明了。

先建公网路由表:

VPC控制台左侧点 Route TablesCreate route table

代码语言:javascript
复制
Name: public-rt
VPC: saas-prod-vpc

建好之后点进去,在 Routes tab 点 Edit routes

需要加两条路由:

第一条是本地流量,10.100.0.0/16 的流量都local,这个VPC创建时就带上了,不用动。

第二条是关键:

代码语言:javascript
复制
Destination: 0.0.0.0/0
Target: igw-xxxxxxx(IGW的ID,下面马上创建)

这条的意思是:所有发往VPC外部的流量,全部扔给Internet Gateway处理。

然后Subnet associations tab里,把 public-subnet-az1public-subnet-az2 关联进来。

公网路由表搞定。

现在建私网路由表:

同样 Create route table,Name写 private-rt,VPC选 saas-prod-vpc。

私网机器要访问外网,但它没有公有IP,不能直接走IGW。怎么办?靠NAT Gateway。

路由这样配:

代码语言:javascript
复制
Destination: 10.100.0.0/16 → Target: local
Destination: 0.0.0.0/0 → Target: nat-xxxxxxx(NAT Gateway的ID)

private-subnet-az1private-subnet-az2db-subnet-az1db-subnet-az2 都关联到这个路由表。


Internet Gateway——VPC通往外界的门

带有互联网网关的 VPC
带有互联网网关的 VPC

带有互联网网关的 VPC

Internet Gateway,简称IGW,是VPC连接公网的出口。没有它,VPC里的机器就算有公有IP也上不了网。

建起来很简单:

左侧点 Internet GatewaysCreate internet gateway

代码语言:javascript
复制
Name tag: prod-igw

点 Create。

刚建好的IGW是 Detached 状态,需要手动 attach 到VPC上。选中这个IGW,点 ActionsAttach to VPC,选 saas-prod-vpc,点 Attach。

attach成功之后,它会显示关联的VPC ID。

这就是之前路由表里引用的那个 igw-xxxxxxx


NAT Gateway——让没有公IP的机器也能上网

两个可用区中的区域 NAT 网关与跨区的区域 NAT 网关的比较。

Internet Gateway只接受有公网IP的实例主动发起流量,私网里的EC2没有公有IP,它想访问外网(比如拉镜像、更新系统包)怎么办?

靠NAT Gateway。

NAT Gateway是AWS托管的服务,你不用自己维护EC2当NAT用,它自己高可用,按流量和小时数收费,贵是贵点但省心。

怎么建?

左侧菜单找 NAT GatewaysCreate NAT Gateway

代码语言:javascript
复制
Subnet: public-subnet-az1(注意,是公网子网!)
Elastic IP allocation ID: 点Allocate Elastic IP让AWS给你分配一个

点 Create。

NAT Gateway创建完之后,记得去公网路由表 public-rt 里确认一下,0.0.0.0/0 是不是指向了这个NAT Gateway——我在实际操作中就犯过把NAT Gateway建到私网子网的错误,结果私网流量根本出不去。

NAT Gateway建好之后会有一个从 initializing 到 available 的过程,大概一两分钟。状态变成 available 之后,私网子网的EC2就能通过它访问外网了,但只允许从内向外发起连接,外面的流量想主动进来?门都没有。这就是NAT的意思,Network Address Translation,网络地址转换,它会把自己的公有IP替换掉私网机器的内网IP去访问外网,然后回来的流量再转换回去。


安全组Security Group——实例级别的门禁卡

具有 2 个子网、2 个安全组的 VPC,子网中的服务器关联了不同的安全组
具有 2 个子网、2 个安全组的 VPC,子网中的服务器关联了不同的安全组

具有 2 个子网、2 个安全组的 VPC,子网中的服务器关联了不同的安全组

路由表控制的是“能不能出这个VPC”,到了具体某个实例层面,谁能和它通信,就要靠Security Group。

我见过太多人把Security Group当成防火墙来理解,这也没大错,但有个关键区别要记住:Security Group是有状态的,NACL是无状态的

有状态的意思是:只要入方向允许了一条规则,出方向会自动放行,不需要手动配置。比如你允许了22端口入,那22端口出的流量自动是通的。

怎么理解这个"有状态"?就像你进小区门的时候保安让你进去了,你出来的时候保安不会再拦你。

但NACL不一样,它是小区大门保安,你出去也要看它脸色。

好,先建一个Web层的安全组:

Network & SecuritySecurity GroupsCreate security group

代码语言:javascript
复制
Name: web-sg
VPC: saas-prod-vpc
Description: Security group for web servers

入方向规则这样配:

代码语言:javascript
复制
Type: SSH | Source: 10.100.0.0/16(只允许内网SSH)
Type: HTTP | Source: 0.0.0.0/0
Type: HTTPS | Source: 0.0.0.0/0

出方向默认全放行,一般不用改。

再建一个App层的安全组:

代码语言:javascript
复制
Name: app-sg
VPC: saas-prod-vpc

入方向:

代码语言:javascript
复制
Type: SSH | Source: 10.100.0.0/16
Type: Custom TCP | Port: 8080 | Source: web-sg的安全组ID(允许来自Web层的访问)

这里有个细节:Source那里可以直接引用另一个安全组ID,而不是写死IP地址。这意味着只要属于web-sg的实例,不管IP怎么变,都能访问app层的8080端口。这比写死IP灵活太多了,生产里强烈建议用这种方式。

再建一个DB层的安全组:

代码语言:javascript
复制
Name: db-sg
VPC: saas-prod-vpc

入方向:

代码语言:javascript
复制
Type: MySQL/Aurora | Port: 3306 | Source: app-sg的安全组ID

这样只有App层的机器能连数据库,其他地方一概拒绝。


NACL——子网级别的守门员

具有两个子网的 VPC 和每个子网的网络 ACL。
具有两个子网的 VPC 和每个子网的网络 ACL。

具有两个子网的 VPC 和每个子网的网络 ACL。

NACL,网络访问控制列表,它是子网级别的防护。每个子网必须关联一个NACL,默认NACL允许所有流量进和出。

NACL和Security Group的主要区别:

  • • SG是实例级别的,NACL是子网级别的
  • • SG有状态,NACL无状态
  • • SG只支持允许规则,NACL支持允许和拒绝

什么场景下用NACL?比如你想拒绝某个特定IP段访问某个子网,SG做不到拒绝,只能允许。但NACL可以。

我一般会建一个严格的NACL:

代码语言:javascript
复制
Name: strict-nacl
VPC: saas-prod-vpc

入方向规则:

代码语言:javascript
复制
Rule #: 100 | Type: All Traffic | Source: 10.100.0.0/16 | Allow
Rule #: 200 | Type: All Traffic | Source: 0.0.0.0/0 | Deny(拒绝其他所有)

出方向同理,放行内网和必要的端口出去。

然后把私网子网和数据库子网关联到这个NACL。公网子网可以保持默认的允许所有NACL,因为Security Group已经够用了。


把EC2放进VPC测试一下

现在我们把各层组件串起来测试。

在EC2控制台Launch Instance:

代码语言:javascript
复制
Name: web-server-01
Network: saas-prod-vpc
Subnet: public-subnet-az1
Auto-assign public IP: Enable(这台要能被外网访问)
Security Group: web-sg
Key Pair: 选你的密钥对

创建完成后,AWS会给你分配一个公有IP。复制这个IP,终端里:

代码语言:javascript
复制
ssh -i your-key.pem ec2-user@54.xxx.xxx.xxx

能连上说明这台机器网络通了。

然后在这台机器上测试:

代码语言:javascript
复制
curl https://aws.amazon.com

能返回HTML,说明从公网子网访问外网没问题,IGW工作正常。

现在Launch一台App层的EC2:

代码语言:javascript
复制
Name: app-server-01
Network: saas-prod-vpc
Subnet: private-subnet-az1(注意是私网子网)
Auto-assign public IP: Disable
Security Group: app-sg

这台机器没有公有IP,你怎么SSH进去?有两个办法:

方法一:通过公网EC2跳板机跳转

代码语言:javascript
复制
# 先连上公网的web-server
ssh -i your-key.pem ec2-user@54.xxx.xxx.xxx

# 然后从web-server连app-server(内网IP互访)
ssh -i your-key.pem ec2-user@10.100.11.xxx

前提是web-server能访问app-server的22端口——也就是说web-sg要允许到app-sg的SSH,或者干脆让web-server和app-server用同一个安全组。

方法二:用SSM Session Manager

AWS Systems Manager的Session Manager可以直接管理EC2,不需要开放SSH端口,也不需要机器有公网IP。只要EC2装了SSM Agent,IAM角色有相应权限,从浏览器里就能开一个终端会话连到私网EC2。

代码语言:javascript
复制
aws ssm start-session --target i-xxxxxxxxxx

这个方式安全很多,生产环境我建议用SSM。

好,app-server起来了。在上面测试:

代码语言:javascript
复制
curl https://aws.amazon.com

能通,说明NAT Gateway在正常工作,私网机器通过NAT代理访问了外网。

再看一个:

代码语言:javascript
复制
ping -c 3 10.100.1.10

这是web-server的内网IP,能ping通说明VPC内部的私有通信没问题。


VPC Endpoint——访问AWS服务不再绕公网

EC2访问S3、DynamoDB、Secrets Manager这些AWS服务,默认会走公网。不光是流量成本的问题,数据出公网还有安全合规的风险,尤其是金融、医疗这类行业。

VPC Endpoint就是来解决这个问题的。

它让你的EC2在访问AWS服务时,走AWS内部网络,不经过公网,有两种类型:

  • Gateway Endpoint:用于S3和DynamoDB,免费,在路由表里配置
  • Interface Endpoint:用于其他服务(Secrets Manager、SSM、CloudWatch等),按连接小时数收费

先看Gateway Endpoint:

VPC左侧菜单点 EndpointsCreate Endpoint

代码语言:javascript
复制
Service category: AWS services
Service: com.amazonaws.us-east-1.s3(选你的Region)
VPC: saas-prod-vpc
Route Table: private-rt(把私网路由表关联上)
Policy: Full Access(先用全访问,后续可以细化)

创建完成之后,在private-rt的路由表里会多一条:

代码语言:javascript
复制
Destination: pl-xxxxxxxxx(S3的VPC Endpoint前缀) → Target: vpce-xxxxxxxxx

现在从app-server测试:

代码语言:javascript
复制
aws s3 ls

能列出S3桶,说明访问走的是内网。

然后是Interface Endpoint。拿Secrets Manager举例:

Create Endpoint,服务选 com.amazonaws.us-east-1.secretsmanager,Subnet那里选 private-subnet-az1private-subnet-az2(多AZ部署),安全组选 app-sg

建好之后,EC2访问Secrets Manager的地址会从公网DNS变成VPC内网DNS:secretsmanager.us-east-1.amazonaws.com 自动解析到 vpce-xxx 这个地址。


第十步:VPC Peering——打通两个VPC的网络

有时候业务需要,两个不同的VPC之间要互相访问。比如测试环境VPC和生产环境VPC要互通,或者集团子公司各自有VPC要内网互联。

VPC Peering就是干这个的。

假设你现在有个测试VPC:10.200.0.0/16,想和刚才的生产VPC 10.100.0.0/16 打通。

在生产VPC这端操作:

左侧点 Peering ConnectionsCreate peering connection

代码语言:javascript
复制
Name: prod-to-test-peering
VPC Requester: saas-prod-vpc
VPC Accepter: test-vpc(需要另一个VPC的ID或者账号授权)

点 Create Peering Connection。

然后去测试VPC那端,Accept这个Peering请求。

接下来两边都要配置路由表:

在生产VPC的 private-rt 里加一条:

代码语言:javascript
复制
Destination: 10.200.0.0/16 → Target: pcx-xxxxxxx(Peering Connection ID)

在测试VPC的路由表里加一条:

代码语言:javascript
复制
Destination: 10.100.0.0/16 → Target: pcx-xxxxxxx

加完之后,两边的EC2就能通过内网IP互相访问了。

有一点要提醒:VPC Peering不支持传递路由。什么意思?假设A和B打通,B和C打通,A和C还是不通,必须单独建立A和C的Peering。


常见踩坑点,列几个我经历过的

坑1:子网配错了路由表。 刚建VPC的时候经常把公网子网绑到了私网路由表,然后公网EC2死活出不去。一查路由表,发现0.0.0.0/0指向的是NAT Gateway而不是IGW,改过来就好了。

坑2:安全组引用了自己。 想让同一安全组的机器之间互访,写规则时Source填了自己的安全组ID,结果发现根本不通。这是因为SG引用自己的时候只对入方向生效,出方向流量会被同组的另一条规则拦截。这个问题比较隐蔽,要特别注意。

坑3:NAT Gateway放错子网。 有一次图省事把NAT Gateway塞进了私网子网,然后私网机器配置0.0.0.0/0指向它,结果全部断网。NAT Gateway必须放在公网子网,它自己是需要能访问公网才能代理流量的。

坑4:修改了默认VPC的路由表。 前面说过我不爱用默认VPC,就是因为大家共用一套路由表,你改了我就得遭殃。某次团队有人不小心把默认VPC路由表里指向IGW那条规则删了,十几台测试机集体上不了网,排障排查了两个小时才定位到。

坑5:跨AZ通信以为走了专线。 在一个AZ里的EC2发流量到另一个AZ的EC2,误以为走了内网专线所以很快。实际上AZ间的流量走的是AWS骨干网,延迟会比同AZ高一些,而且是有流量费用的。别把跨AZ当同AZ用。


总结一下

VPC这东西,说难不难,说简单也不简单。核心就那么几个组件:VPC本身、子网、路由表、IGW、NAT Gateway、Security Group、NACL、Endpoint、Peering。但怎么组合、怎么规划、出了问题怎么排查,需要实际操练才能有感觉。

建议你真的动手搭一遍,别光看文章。看十篇教程不如踩一次坑,踩过坑你才能真正理解流量是怎么走的、安全边界是怎么划的、高可用是怎么实现的。

搭完之后,可以试试这样验证网络连通性:

代码语言:javascript
复制
# 在私网EC2上
curl ifconfig.me  # 看返回的IP是不是NAT Gateway的IP
traceroute aws.amazon.com  # 看路径有没有经过NAT Gateway

# 在公网EC2上
curl ifconfig.me  # 看返回的是不是自己的公有IP
traceroute aws.amazon.com  # 看路径有没有经过IGW

搞懂这些,你对VPC的理解就上了一个台阶。


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维躬行录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • VPC到底是什么,我的理解是这样
  • 生产环境我基本不用默认VPC
  • 实际操作:从头搭一个生产级VPC
    • 规划IP地址段
    • 创建VPC和子网
    • 路由表——流量怎么走全看它
    • Internet Gateway——VPC通往外界的门
    • NAT Gateway——让没有公IP的机器也能上网
    • 安全组Security Group——实例级别的门禁卡
    • NACL——子网级别的守门员
    • 把EC2放进VPC测试一下
    • VPC Endpoint——访问AWS服务不再绕公网
    • 第十步:VPC Peering——打通两个VPC的网络
  • 常见踩坑点,列几个我经历过的
  • 总结一下
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档