1. 前言

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

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

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

1.1. VPC 简介

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

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

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

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

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

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

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

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

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

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

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

2. 实操:从头搭一个生产级 VPC

2.1. 规划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 和子网

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

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

IPv4 CIDR block: 10.100.0.0/16
IPv6 CIDR block: No IPv6 CIDR Block
Tenancy: Default

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

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

点击左侧 Subnets → Create subnet:

先建AZ1的公网子网

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的私网子网:

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.2. 路由表-流量怎么走全看它

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

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

先建公网路由表:

VPC控制台左侧点 Route Tables → Create route table:

Name: public-rt
VPC: saas-prod-vpc

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

需要加两条路由:

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

第二条是关键:

Destination: 0.0.0.0/0
Target: igw-xxxxxxx(IGW的ID,下面马上创建)

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

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

公网路由表搞定。

现在建私网路由表:

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

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

路由这样配:

Destination: 10.100.0.0/16 → Target: local
Destination: 0.0.0.0/0 → Target: nat-xxxxxxx(NAT Gateway的ID)

把 private-subnet-az1、private-subnet-az2、db-subnet-az1、db-subnet-az2 都关联到这个路由表。

2.3. Internet Gateway-VPC 通往外界的门

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

建起来很简单:

左侧点 Internet Gateways → Create internet gateway:

Name tag: prod-igw

点 Create。

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

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

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

2.4. NAT Gateway-让没有公IP的机器也能上网

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

靠NAT Gateway。

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

怎么建?

左侧菜单找 NAT Gateways → Create NAT Gateway:

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去访问外网,然后回来的流量再转换回去。

2.5. 安全组Security Group-实例级别的门禁卡

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

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

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

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

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

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

Network & Security → Security Groups → Create security group:

Name: web-sg
VPC: saas-prod-vpc
Description: Security group for web servers

入方向规则这样配:

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层的安全组:

Name: app-sg
VPC: saas-prod-vpc

入方向:

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层的安全组:

Name: db-sg
VPC: saas-prod-vpc

入方向:

Type: MySQL/Aurora | Port: 3306 | Source: app-sg的安全组ID

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

2.6. NACL-子网级别的守门员

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

NACL和Security Group的主要区别:

• SG是实例级别的,NACL是子网级别的
• SG有状态,NACL无状态
• SG只支持允许规则,NACL支持允许和拒绝
什么场景下用NACL?比如你想拒绝某个特定IP段访问某个子网,SG做不到拒绝,只能允许。但NACL可以。

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

Name: strict-nacl
VPC: saas-prod-vpc

入方向规则:

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已经够用了。

2.7. 把 EC2 放进 VPC 测试一下

现在我们把各层组件串起来测试。在EC2控制台Launch Instance:

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,终端里:

ssh -i your-key.pem ec2-user@54.xxx.xxx.xxx

能连上说明这台机器网络通了。然后在这台机器上测试:

curl https://aws.amazon.com

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

现在Launch一台App层的EC2:

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

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

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

# 先连上公网的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。

aws ssm start-session --target i-xxxxxxxxxx

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

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

curl https://aws.amazon.com

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

再看一个:

ping -c 3 10.100.1.10

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

2.8. 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左侧菜单点 Endpoints → Create Endpoint:

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的路由表里会多一条:

Destination: pl-xxxxxxxxx(S3的VPC Endpoint前缀) → Target: vpce-xxxxxxxxx

现在从app-server测试:

aws s3 ls

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

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

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

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

2.9. VPC Peering-打通两个VPC的网络

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

VPC Peering就是干这个的。

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

在生产VPC这端操作:

左侧点 Peering Connections → Create peering connection:

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 里加一条:

Destination: 10.200.0.0/16 → Target: pcx-xxxxxxx(Peering Connection ID)

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

Destination: 10.100.0.0/16 → Target: pcx-xxxxxxx

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

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


  • 无标签

0 评论

你还没有登录。你所做的任何更改会将作者标记为匿名用户。 如果你已经拥有帐户,请登录