开始前你需要准备
先准备一个你能正常登录的 GCP 项目,并确认账号有创建 VPC 网络、子网、防火墙规则和 VM 的权限。最省事的是让管理员给你 Compute Network Admin 和 Compute Instance Admin 两个角色。新手常卡在这一步:项目能打开,一点「创建」却提示权限不足,白折腾半天。
动手前先想清楚三件事:用哪个区域、网络干什么、内网网段填多少。本文场景是让两台 VM 内网通信,可以选 asia-east1,网段用 10.0.0.0/24。区域别乱选,两台 VM 分到不同区域,互通和延迟都会变复杂;网段也别随手填完就走,如果公司内网或已有 VPC 占了同一段,以后互联会冲突,返工很麻烦。可以先查一下已占用的网段:
gcloud compute networks subnets list --format="table(name,region,ipCidrRange)"
再准备一个最新版浏览器就够了,本文全程在控制台点鼠标完成,不装工具也能跟着做。gcloud 属于可选,想查信息再装,零基础可以先跳过。
最后提醒:测试用的 VM、防火墙规则和自定义网络都可能产生费用,VM 只要开着就一直计费。练完记得回来把 VM、规则和自定义 VPC 全删掉,别让它们躺着扣钱。
整体思路
配置VPC网络,先别急着建 VM。把它想成一座小区:VPC 是围墙和地皮,子网是楼栋片区,路由是道路牌,防火墙规则是门卫,内网 IP 是每户门牌,SSH 入口是只给管理员留的边门。本文目标很明确:同一 VPC 内两台 Linux VM 可用内网互通,并且只有指定来源才可 SSH 登录。
- 创建自定义 VPC 网络;
- 划分子网;
- 放行必要流量;
- 创建 VM;
- 测试连通。
为什么按这个顺序?先有围墙、道路和门卫,再搬机器,才不会建好才发现连不上,或把端口暴露给全网。自定义网络默认拒绝入站,防火墙像门卫登记本,只看来源、协议、端口;所以内网互通先开 ICMP 做测试,SSH 只开 tcp:22,来源写当前公网 IP/32,业务要别的端口再单独加。子网别照抄默认网段,避免以后和办公室或其它 VPC 打通时地址打架;系统路由由 GCP 自动维护,别手删。小白常踩坑:沿用 default、忘防火墙、IP 变了不更新;也千万别图省事,把所有来源都写成 0.0.0.0/0。这等于小区大门全天敞开;坚持最小权限,只开放需要的协议和端口。命令请在同一 Cloud Shell、已选好项目后复制,变量才能连续生效;每完成一步先看结果,再做下一步,出错时更容易定位,不会把网络、权限和机器问题搅在一起。
P=$(gcloud config get-value project); R=asia-east1; Z=asia-east1-b; N=vpc-demo; S=subnet-demo; IP=$(curl -fsS https://api.ipify.org)
gcloud services enable compute.googleapis.com --project "$P"
gcloud compute networks create "$N" --subnet-mode=custom --project "$P"
gcloud compute networks subnets create "$S" --network "$N" --region "$R" --range 10.10.0.0/24 --project "$P"
gcloud compute firewall-rules create "$N-ping" --network "$N" --allow icmp --source-ranges 10.10.0.0/24 --project "$P"
gcloud compute firewall-rules create "$N-ssh" --network "$N" --allow tcp:22 --source-ranges "$IP/32" --project "$P"
gcloud compute instances create vm-a vm-b --zone "$Z" --network "$N" --subnet "$S" --machine-type=e2-micro --image-family=debian-12 --image-project=debian-cloud --project "$P"
B=$(gcloud compute instances describe vm-b --zone "$Z" --project "$P" --format='get(networkInterfaces[0].networkIP)'); gcloud --quiet compute ssh vm-a --zone "$Z" --project "$P" --strict-host-key-checking=no --command "ping -c 3 $B"
详细步骤一:创建自定义 VPC 网络
控制台顶部搜索框输「VPC 网络」,进列表点「创建 VPC 网络」。
- 名称填 gcpok-vpc,别带空格和大写。
- 「子网创建模式」选 自定义,别留默认的「自动」。
- 其他不动,拉到底点「创建」。
为啥?自动模式会在每个区域预建一大堆子网,网段还被平台定死,后面按规划改都改不动;自定义刚建好是张空网,后面一条条加子网,用了哪段 IP 心里有数,也不容易跟公司内网撞车。
「高级路由」「DNS 名称解析」保持默认。这俩管动态路由和专用 DNS,现在随手一改,回头虚拟机连不上网,根本查不出哪儿坏了,等真用上再调。
顺手记三样:项目名称、网络名称、下一步子网要放的区域(如 asia-east1)。资源都挂在项目下,不少人同时开着测试和正式项目,建完发现子网跑到别处就找不到了,坑就在这。
不想点界面,右上角 Cloud Shell 里这句直接复制回车:
gcloud compute networks create gcpok-vpc --subnet-mode=custom
粘之前瞄一眼当前项目跟记的是否一致,不一致先切项目再回车。
详细步骤二:配置子网与防火墙规则
接着上一节创建的 my-vpc 配置VPC网络。控制台进“VPC 网络 → my-vpc → 添加子网”:新建子网时先选区域,区域决定 VM 位置,建好后不能改;IPv4 网段填 10.0.1.0/24。专用 Google 访问、流日志、IPv6 等其他高级选项先保持默认。这样是给 VM 划一小块私有地址,少踩路由冲突;网段别和办公室或其他子网重叠。
打开 Cloud Shell,复制执行;命令会自动取本机公网 IP,并建好子网、内网入站规则和 SSH 规则。
export VPC_NAME="my-vpc"
export REGION="asia-east1"
export SUBNET_NAME="subnet-a"
export SUBNET_RANGE="10.0.1.0/24"
export OFFICE_IP="$(curl -4 -s https://ifconfig.me)/32"
export SSH_TAG="allow-ssh"
gcloud compute networks subnets create "$SUBNET_NAME"
--network="$VPC_NAME"
--region="$REGION"
--range="$SUBNET_RANGE"
gcloud compute firewall-rules create "$VPC_NAME-allow-internal"
--network="$VPC_NAME"
--direction=INGRESS
--priority=1000
--action=ALLOW
--rules=icmp,tcp:80,tcp:443,tcp:8080
--source-ranges="$SUBNET_RANGE"
gcloud compute firewall-rules create "$VPC_NAME-allow-ssh-office"
--network="$VPC_NAME"
--direction=INGRESS
--priority=900
--action=ALLOW
--rules=tcp:22
--source-ranges="$OFFICE_IP"
--target-tags="$SSH_TAG"
第一条命令创建入站防火墙规则,来源填子网网段,允许 ICMP(方便 ping 排障)和业务需要的 TCP 端口(示例 80、443、8080,按业务改,别一次全开)。另建的 SSH 规则只让本机公网 IP 连 TCP 22;若办公室有固定出口,把 OFFICE_IP 换成该 IP 的 /32。把内网互访和远程管理分开,是为了减少暴露面。目标标记只命中带同样网络标签的 VM:创建 VM 时填 allow-ssh,或事后补上;VM 没标签会误以为规则失效。
最后:规则和 VM 必须属于同一 VPC 网络,VM 创建时也要选 my-vpc/subnet-a;入站方向、优先级和来源范围要逐项核对,优先级数字越小越先匹配,来源范围分别是 10.0.1.0/24 和自己的 /32。小白常见坑是把 22 开给 0.0.0.0/0、规则建错 VPC,或被更小数字的拒绝规则挡住。
详细步骤三:创建 VM 并测试连通
先确认右上角项目没变,别把刚做好的配置VPC网络切到别的项目。到「Compute Engine > 虚拟机实例 > 创建实例」,在同一项目、同一 VPC 的同一子网里建两台 Linux VM:vm-a、vm-b。在「网络接口」把网络选成刚建的 VPC、子网选成刚建的子网;控制台常会带回 default,一定不要让实例落回默认网络。外部 IP 按需开:要浏览器 SSH 就临时开,不需要就选「无」,测完释放。创建后记下两台「内部 IP」,后面只测内网,不用公网 IP。
- 点击 vm-a 的「SSH」,在终端整段复制下面命令,按提示填 vm-b 的内网 IP,以及已放行、且有服务监听的端口。
sudo apt-get update -qq
sudo apt-get install -y -qq iputils-ping curl
read -p "输入 vm-b 的内网 IP:" VM_B_INTERNAL_IP
ping -c 4 "$VM_B_INTERNAL_IP"
read -p "输入已放行的服务端口(如 8000):" PORT
curl -m 5 "http://$VM_B_INTERNAL_IP:$PORT"
原因与坑:ping 验证私网互通,curl 验证端口放行且服务真在监听。ping 不通先看 ICMP 规则;curl 报拒绝连接,多半是 vm-b 没起服务或端口不是 HTTP;别把外部 IP、跨项目或跨子网的 IP 填进来。关掉外部 IP 又没配 IAP/Cloud NAT 时,SSH 和装包也会失败。
gcloud 等价思路:先理解控制台字段,再把同样参数写成命令复用:项目、可用区、网络、子网、外部 IP 开关都能对应到参数。下面在 Cloud Shell 整段复制,按提示输入即可;漏掉网络或子网,命令也可能落到默认网络。
read -p "项目 ID:" PROJECT
read -p "可用区(如 asia-east1-b):" ZONE
read -p "刚建的 VPC 名:" NETWORK
read -p "刚建的子网名:" SUBNET
read -p "是否分配临时外部 IP?(y/N):" EXT_IP
if [[ "$EXT_IP" == "y" ]]; then EXT_FLAG=""; else EXT_FLAG="--no-address"; fi
gcloud compute instances create vm-a vm-b
--project="$PROJECT" --zone="$ZONE"
--machine-type=e2-micro
--image-family=debian-12 --image-project=debian-cloud
--network="$NETWORK" --subnet="$SUBNET" $EXT_FLAG
gcloud compute instances list --project="$PROJECT"
--format="table(name,zone,networkInterfaces[0].networkIP,networkInterfaces[0].subnetwork)"
验证结果
配置 VPC 网络后,先在控制台依次看 VPC 网络、子网、路由、防火墙规则,逐项确认名称、区域、网段、下一跳、来源范围和端口无误。先做这一步,是为了把云端配置和真实流量分开;别只看绿色状态就以为能用。小白常把名称对了但区域选错,或只改规则没改来源范围。
gcloud compute networks list --format='table(name)'
gcloud compute networks subnets list --format='table(name,region,ipCidrRange)'
gcloud compute routes list --format='table(name,destRange,priority,nextHopGateway,nextHopIp,nextHopInstance,nextHopVpnTunnel)'
gcloud compute firewall-rules list --format='table(name,network,direction,priority,sourceRanges:label=SOURCE_RANGES,allowed:label=ALLOWED)'
在 Cloud Shell 选对项目后复制命令:IP1/IP2 要都属于规划网段;两个方向 ping 通、nc 显示 succeeded,才算内网互通且指定 TCP 端口可访问。代码里的端口变量用 80 演示,规则也要开放 tcp:80。坑:别把外部 IP 当内网 IP,VM 没启动会让变量为空,nc 失败也可能是服务没启动。
PORT=80
ROW1=$(gcloud compute instances list --filter='status=RUNNING' --format='value(name,zone.basename(),networkInterfaces[0].networkIP)' | sed -n '1p')
ROW2=$(gcloud compute instances list --filter='status=RUNNING' --format='value(name,zone.basename(),networkInterfaces[0].networkIP)' | sed -n '2p')
VM1=$(echo "$ROW1" | awk '{print $1}')
ZONE1=$(echo "$ROW1" | awk '{print $2}')
IP1=$(echo "$ROW1" | awk '{print $3}')
VM2=$(echo "$ROW2" | awk '{print $1}')
ZONE2=$(echo "$ROW2" | awk '{print $2}')
IP2=$(echo "$ROW2" | awk '{print $3}')
echo "IP1=$IP1 IP2=$IP2"
gcloud compute ssh "$VM1" --zone="$ZONE1" --command="ping -c 3 $IP2; nc -zv $IP2 $PORT"
gcloud compute ssh "$VM2" --zone="$ZONE2" --command="ping -c 3 $IP1; nc -zv $IP1 $PORT"
在允许的公网出口执行 SSH 自检,curl 显示的地址应在来源范围内且能登录;换到不允许来源再跑一次,应无法登录或连不上 22 端口,说明规则确实生效。坑:Cloud Shell 出口 IP 不等于本机宽带 IP,/32 别漏。
ROW=$(gcloud compute instances list --filter='status=RUNNING' --format='value(name,zone.basename())' | sed -n '1p')
VM=$(echo "$ROW" | awk '{print $1}')
ZONE=$(echo "$ROW" | awk '{print $2}')
curl -s ifconfig.me; echo
gcloud compute ssh "$VM" --zone="$ZONE"
排障看连通性测试和日志,用来判断问题在 GCP 规则、路由,还是 VM 系统内部:有 DROP 查 GCP 规则/来源范围;无到达记录且跨子网失败查路由目标、优先级和下一跳;日志放行但 ss 无监听、iptables 或系统日志报错,就是 VM 系统内部。日志没开会查不到,不代表没流量。
gcloud logging read 'logName:"compute.googleapis.com%2Ffirewall" OR logName:"compute.googleapis.com%2Fvpc_flows"' --freshness=30m --limit=20 --format='table(timestamp,logName,jsonPayload)'
ROW=$(gcloud compute instances list --filter='status=RUNNING' --format='value(name,zone.basename())' | sed -n '1p')
VM=$(echo "$ROW" | awk '{print $1}')
ZONE=$(echo "$ROW" | awk '{print $2}')
gcloud compute ssh "$VM" --zone="$ZONE" --command="ip route; sudo ss -lntp; sudo iptables -L -n; sudo journalctl --since '10 minutes ago' --no-pager | tail -n 30"
常见坑与解决办法
配置VPC网络时,别急着改 IP。命令在已登录的 Cloud Shell 或本机 gcloud 里跑;第一行会让你填项目 ID。默认/自动模式会自动铺子网,网段难和内网、VPN 对齐;练习时新建自定义 VPC,并重建测试 VM,别在旧机上反复试。
- 误用默认网络。
read -p "输入 GCP 项目 ID: " PROJECT_ID gcloud config set project "$PROJECT_ID" gcloud services enable compute.googleapis.com gcloud compute instances delete test-vm --zone=asia-east1-b --quiet 2>/dev/null || true gcloud compute networks describe vpc-lab-custom >/dev/null 2>/dev/null || gcloud compute networks create vpc-lab-custom --subnet-mode=custom gcloud compute networks subnets describe subnet-asia-east1 --region=asia-east1 >/dev/null 2>/dev/null || gcloud compute networks subnets create subnet-asia-east1 --network=vpc-lab-custom --region=asia-east1 --range=10.10.0.0/24 gcloud compute instances create test-vm --zone=asia-east1-b --subnet=subnet-asia-east1 --image-family=debian-12 --image-project=debian-cloud --machine-type=e2-micro - 防火墙别图省事。0.0.0.0/0 等于全网可敲门;ping 用 ICMP,不等于 TCP:22。先查本机公网 IP,再只放行它并补 ICMP。坑:Cloud Shell 里 curl 查到的是它的出口,不是你电脑。
echo "浏览器打开 https://ipinfo.io/ip,查你电脑公网 IP" read -p "把查到的 IP 原样输入: " MY_IP if gcloud compute firewall-rules describe vpc-lab-custom-allow-ssh-icmp >/dev/null 2>/dev/null; then gcloud compute firewall-rules update vpc-lab-custom-allow-ssh-icmp --allow=tcp:22,icmp --source-ranges="$MY_IP/32" else gcloud compute firewall-rules create vpc-lab-custom-allow-ssh-icmp --network=vpc-lab-custom --allow=tcp:22,icmp --source-ranges="$MY_IP/32" fi - 区域别混。子网属于 region,VM 属于 zone;zone 必须落在子网所在 region。最省事把 VM 建在 asia-east1-b;若必须 us-central1-a,就新增该区域子网,网段别重叠。
gcloud compute networks subnets create subnet-us-central1 --network=vpc-lab-custom --region=us-central1 --range=10.10.1.0/24 2>/dev/null || true gcloud compute instances create test-vm-us --zone=us-central1-a --subnet=subnet-us-central1 --image-family=debian-12 --image-project=debian-cloud --machine-type=e2-micro 2>/dev/null || true - 只查 GCP 防火墙不够。规则只管到网卡门口,VM 里还可能有 iptables/nftables,服务也可能只听 127.0.0.1。SSH 进不去就用串口控制台,逐层看端口和进程。
sudo iptables -S 2>/dev/null || true sudo nft list ruleset 2>/dev/null || true sudo ss -lntup sudo systemctl is-active ssh - 收尾按顺序清。删了 VM 不等于规则、子网、VPC 也没了;顺序反了常被“仍在使用”挡住。按 VM、防火墙规则、子网、VPC 网络清理:
gcloud compute instances delete test-vm --zone=asia-east1-b --quiet 2>/dev/null || true gcloud compute instances delete test-vm-us --zone=us-central1-a --quiet 2>/dev/null || true gcloud compute firewall-rules delete vpc-lab-custom-allow-ssh-icmp --quiet 2>/dev/null || true gcloud compute networks subnets delete subnet-asia-east1 --region=asia-east1 --quiet 2>/dev/null || true gcloud compute networks subnets delete subnet-us-central1 --region=us-central1 --quiet 2>/dev/null || true gcloud compute networks delete vpc-lab-custom --quiet 2>/dev/null || true
常见问题(FAQ)
配置VPC网络一定要用自定义模式吗?
不一定。学习和生产规划更建议自定义模式,便于控制子网网段和区域。
不创建防火墙规则会怎样?
默认会拒绝大多数入站连接,VM 可能无法 SSH 或互相访问,需按端口放行。
同一 VPC 不同区域的子网能互通吗?
通常可以,只要路由和防火墙规则允许,并确认没有额外限制。
外部 IP 必须开启吗?
不是。仅内网互访可不分配外部 IP;需要公网 SSH 或上网时再按需配置。
用控制台还是 gcloud 更好?
新手先用控制台理解流程,熟练后用 gcloud 批量创建和复用配置。
不想自己折腾 GCP?我们提供云平台代维护、上云迁移与账单代付服务,一对一技术支持。
