雲端網路架構(Cloud Networking)

是什麼?

雲端網路架構定義了雲端資源之間以及和外部的通訊方式。VNet 提供隔離的網路環境、Subnet 劃分區域、NSG 控制流量、Load Balancer 分散請求。正確的網路設計是安全和效能的基礎。

ℹ️零信任架構

現代雲端網路設計遵循零信任原則(Zero Trust)— 不信任任何人(包括內網),每次存取都驗證身份和權限。不是「進了內網就安全」,而是「每一步都要驗證」。

核心觀念

常見誤區

⚠️常見誤區

  • 把資料庫放在 Public Subnet:資料庫必須放在 Private Subnet,只允許 App Subnet 存取。直接暴露在公網是重大安全漏洞
  • NSG 設定太寬鬆0.0.0.0/0 允許所有 IP 存取是偷懶做法。Production 環境必須限制來源 IP 或 Subnet
  • 忽略 VNet Peering 的傳遞性:VNet A 對 B 建立 Peering,B 對 C 建立 Peering,A 和 C 之間不會自動通。需要另外建立 A-C 的 Peering

流程/步驟

1

規劃 IP 位址空間

為 VNet 和 Subnet 規劃不重疊的 CIDR 範圍

2

建立 VNet 和 Subnet

依功能分區:Web Subnet、App Subnet、DB Subnet

3

設定 NSG 規則

最小權限原則 — 只開放必要的 Port 和來源

4

設定 Load Balancer

Web 層前面加 L7 LB,分散流量到多個實例

5

設定 Private Endpoint

PaaS 服務(DB、Storage)走私有網路存取

6

設定監控和日誌

開啟 NSG Flow Logs、Network Watcher 監控流量

流程解讀:從 IP 規劃開始,避免 Subnet 之間的 IP 衝突。依功能分區後,每個 Subnet 附加 NSG 控制存取權限。Web 層前加 Load Balancer 分散流量。PaaS 服務用 Private Endpoint 確保流量走私有網路。

程式碼範例

C# 版本

csharp
// Bicep — 定義 VNet + Subnet + NSG
bicep
// network.bicep
param location string = resourceGroup().location
 
// NSG — Web 層只開放 443
resource webNsg 'Microsoft.Network/networkSecurityGroups@2023-05-01' = {
  name: 'web-nsg'
  location: location
  properties: {
    securityRules: [
      {
        name: 'AllowHTTPS'
        properties: {
          priority: 100
          direction: 'Inbound'
          access: 'Allow'
          protocol: 'Tcp'
          sourceAddressPrefix: '*'
          destinationPortRange: '443'
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
        }
      }
      {
        name: 'DenyAllInbound'
        properties: {
          priority: 4096
          direction: 'Inbound'
          access: 'Deny'
          protocol: '*'
          sourceAddressPrefix: '*'
          destinationPortRange: '*'
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
        }
      }
    ]
  }
}
 
// VNet + Subnets
resource vnet 'Microsoft.Network/virtualNetworks@2023-05-01' = {
  name: 'main-vnet'
  location: location
  properties: {
    addressSpace: { addressPrefixes: ['10.0.0.0/16'] }
    subnets: [
      { name: 'web-subnet', properties: { addressPrefix: '10.0.1.0/24', networkSecurityGroup: { id: webNsg.id } } }
      { name: 'app-subnet', properties: { addressPrefix: '10.0.2.0/24' } }
      { name: 'db-subnet',  properties: { addressPrefix: '10.0.3.0/24' } }
    ]
  }
}

TypeScript 版本

hcl
# Terraform — AWS VPC + Subnet + Security Group
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags       = { Name = "main-vpc" }
}
 
resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "us-east-1a"
  tags              = { Name = "public-subnet" }
}
 
resource "aws_subnet" "private" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "us-east-1a"
  tags              = { Name = "private-subnet" }
}
 
# Security Group — 只開放 443
resource "aws_security_group" "web" {
  vpc_id = aws_vpc.main.id
 
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
 
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
 
# ALB — Application Load Balancer
resource "aws_lb" "web" {
  name               = "web-alb"
  load_balancer_type = "application"
  subnets            = [aws_subnet.public.id]
  security_groups    = [aws_security_group.web.id]
}

Python 版本

python
# Pulumi — Azure VNet
import pulumi_azure_native as azure
 
# VNet
vnet = azure.network.VirtualNetwork(
    "main-vnet",
    resource_group_name=rg.name,
    address_space=azure.network.AddressSpaceArgs(
        address_prefixes=["10.0.0.0/16"]
    ),
)
 
# Web Subnet
web_subnet = azure.network.Subnet(
    "web-subnet",
    resource_group_name=rg.name,
    virtual_network_name=vnet.name,
    address_prefix="10.0.1.0/24",
    network_security_group=azure.network.NetworkSecurityGroupArgs(id=web_nsg.id),
)
 
# Private Endpoint for SQL Database
private_endpoint = azure.network.PrivateEndpoint(
    "sql-private-endpoint",
    resource_group_name=rg.name,
    subnet=azure.network.SubnetArgs(id=db_subnet.id),
    private_link_service_connections=[
        azure.network.PrivateLinkServiceConnectionArgs(
            name="sql-connection",
            private_link_service_id=sql_server.id,
            group_ids=["sqlServer"],
        )
    ],
)

架構圖/概念圖

Internet
HTTPS only
Load Balancer
port 443
Web Subnet (10.0.1.0/24)
port 8080
App Subnet (10.0.2.0/24)
port 5432
DB Subnet (10.0.3.0/24)
NSG Rules

流量從 Internet 經過 Load Balancer 進入 Web Subnet。Web 和 App 之間透過內部 Port 通訊。DB Subnet 只允許 App Subnet 存取。NSG 在每個 Subnet 層級控制流量進出規則。

實戰補充

Q: IP 位址空間怎麼規劃?

A: VNet 用 /16(65,536 個 IP),每個 Subnet 用 /24(256 個 IP)。預留空間給未來擴展。避免用 10.0.0.0/24(太容易和其他 VNet 衝突)。多個 VNet 之間的 CIDR 不能重疊。

Q: L4 和 L7 Load Balancer 怎麼選?

A: L4:基於 TCP/UDP 轉發,不解析 HTTP 內容,效能最高。適合非 HTTP 服務。L7:解析 HTTP 內容,支援 Path-based Routing、SSL Termination、WAF。Web API 幾乎都用 L7。

Q: 什麼時候需要 Private Endpoint?

A: 所有 Production 環境的 PaaS 服務都建議用 Private Endpoint。讓 SQL Database、Storage、Key Vault 等服務只能從你的 VNet 內存取,流量不經過公共網路。

理解測驗

🤔 為什麼資料庫不應該放在 Public Subnet?

🤔 NSG 的 Deny All Inbound 規則的優先級應該設為多少?

🤔 VNet Peering 有傳遞性嗎?

重點整理

💡一句話記住

VNet 隔離環境、Subnet 分區、NSG 管進出、LB 分流量。 口訣:「Public 放前端、Private 藏後端、NSG 顧門口」

| 元件 | 功能 | 類比 | |------|------|------| | VNet | 私有網路空間 | 社區圍牆 | | Subnet | 網路區域劃分 | 社區分區 | | NSG | 流量進出控制 | 區域保全 | | Load Balancer | 流量分配 | 接待員 | | Private Endpoint | PaaS 私有存取 | 內部通道 |

你可能也想看

儲存服務身份與存取管理

按 ← → 鍵切換課程