Tổng quan
Networking là nền tảng của mọi kiến trúc cloud. Hiểu rõ VNet, subnetting, NSG, và Private Endpoints giúp bạn xây dựng hệ thống vừa bảo mật vừa hiệu quả.
VNet Design Patterns
Hub-Spoke Topology
Pattern phổ biến nhất cho enterprise - tách biệt shared services (hub) khỏi workloads (spokes).
Subnet Planning Best Practices
| Subnet | CIDR | Mục đích | NSG |
|---|---|---|---|
snet-gateway | /27 | VPN/ExpressRoute Gateway | Không cần |
AzureFirewallSubnet | /26 | Azure Firewall (bắt buộc tên này) | Không cần |
AzureBastionSubnet | /26 | Azure Bastion (bắt buộc tên này) | Không cần |
snet-app | /24 | Application tier | Strict inbound |
snet-data | /24 | Database tier | Chỉ cho app subnet |
snet-pe | /24 | Private Endpoints | Default deny |
NSG Rules Best Practices
bash# Tạo NSG cho application subnet
az network nsg create \
--resource-group rg-network \
--name nsg-app-tier
# Cho phép HTTPS từ Application Gateway
az network nsg rule create \
--resource-group rg-network \
--nsg-name nsg-app-tier \
--name Allow-HTTPS-From-AGW \
--priority 100 \
--direction Inbound \
--access Allow \
--protocol Tcp \
--source-address-prefixes 10.0.4.0/24 \
--destination-port-ranges 443
# Deny tất cả inbound khác
az network nsg rule create \
--resource-group rg-network \
--nsg-name nsg-app-tier \
--name Deny-All-Inbound \
--priority 4096 \
--direction Inbound \
--access Deny \
--protocol '*' \
--source-address-prefixes '*' \
--destination-port-ranges '*'
NSG Rules - Nguyên tắc:
- Default deny all, explicit allow từng port/source
- Dùng Application Security Groups (ASG) thay vì IP ranges khi có thể
- Log NSG flow logs vào Log Analytics để audit
- Tránh dùng
*cho source hoặc destination
Private Link vs Service Endpoint
| Tiêu chí | Private Endpoint (Private Link) | Service Endpoint |
|---|---|---|
| Traffic path | Qua private IP trong VNet | Qua Microsoft backbone nhưng từ public IP range |
| DNS resolution | Private DNS zone cần thiết | Không thay đổi DNS |
| On-premises access | Có - qua VPN/ExpressRoute | Không - chỉ từ VNet |
| Cross-region | Có | Không |
| Chi phí | Có phí (data processing + endpoint) | Miễn phí |
| Granularity | Resource-level (1 storage account cụ thể) | Service-level (toàn bộ Azure Storage) |
| Security | Cao - completely private | Trung bình - vẫn dùng public endpoint |
Khuyến nghị: Ưu tiên Private Endpoint cho production workloads. Service Endpoint chỉ phù hợp khi cần tiết kiệm chi phí ở dev/test.
Private Endpoint Setup - Playbook
Step 1: Tạo VNet và Subnet cho Private Endpoints
bash# Tạo VNet
az network vnet create \
--resource-group rg-app \
--name vnet-app \
--address-prefix 10.1.0.0/16 \
--subnet-name snet-pe \
--subnet-prefix 10.1.100.0/24
# Disable private endpoint network policies trên subnet
az network vnet subnet update \
--resource-group rg-app \
--vnet-name vnet-app \
--name snet-pe \
--disable-private-endpoint-network-policies true
Step 2: Tạo Private Endpoint cho Azure SQL
bash# Lấy resource ID của SQL Server
SQL_ID=$(az sql server show \
--resource-group rg-app \
--name sql-myapp-prod \
--query id --output tsv)
# Tạo Private Endpoint
az network private-endpoint create \
--resource-group rg-app \
--name pe-sql-myapp \
--vnet-name vnet-app \
--subnet snet-pe \
--private-connection-resource-id $SQL_ID \
--group-ids sqlServer \
--connection-name pe-conn-sql
Step 3: Cấu hình Private DNS Zone
bash# Tạo Private DNS Zone
az network private-dns zone create \
--resource-group rg-app \
--name privatelink.database.windows.net
# Link DNS Zone vào VNet
az network private-dns link vnet create \
--resource-group rg-app \
--zone-name privatelink.database.windows.net \
--name link-vnet-app \
--virtual-network vnet-app \
--registration-enabled false
# Tạo DNS record tự động từ Private Endpoint
az network private-endpoint dns-zone-group create \
--resource-group rg-app \
--endpoint-name pe-sql-myapp \
--name default \
--private-dns-zone privatelink.database.windows.net \
--zone-name privatelink-database
Step 4: Disable Public Access
bash# Tắt public access trên SQL Server
az sql server update \
--resource-group rg-app \
--name sql-myapp-prod \
--enable-public-network false
DNS Resolution Flow với Private DNS Zones
Network Peering
bash# Peering từ Hub → Spoke
az network vnet peering create \
--resource-group rg-hub \
--name hub-to-spoke1 \
--vnet-name vnet-hub \
--remote-vnet /subscriptions/{sub-id}/resourceGroups/rg-spoke1/providers/Microsoft.Network/virtualNetworks/vnet-spoke1 \
--allow-vnet-access true \
--allow-forwarded-traffic true \
--allow-gateway-transit true
# Peering từ Spoke → Hub
az network vnet peering create \
--resource-group rg-spoke1 \
--name spoke1-to-hub \
--vnet-name vnet-spoke1 \
--remote-vnet /subscriptions/{sub-id}/resourceGroups/rg-hub/providers/Microsoft.Network/virtualNetworks/vnet-hub \
--allow-vnet-access true \
--allow-forwarded-traffic true \
--use-remote-gateways true
Lưu ý quan trọng:
- Peering là non-transitive - Spoke 1 không tự động nói chuyện được với Spoke 2
- Cần Azure Firewall hoặc NVA ở Hub để route traffic giữa spokes
allow-gateway-transit+use-remote-gatewayscho phép spokes dùng VPN Gateway của hub
Bicep - Hub-Spoke Foundation
bicepparam location string = 'southeastasia' resource hubVnet 'Microsoft.Network/virtualNetworks@2023-09-01' = { name: 'vnet-hub' location: location properties: { addressSpace: { addressPrefixes: ['10.0.0.0/16'] } subnets: [ { name: 'AzureFirewallSubnet' properties: { addressPrefix: '10.0.1.0/26' } } { name: 'GatewaySubnet' properties: { addressPrefix: '10.0.2.0/27' } } ] } } resource spokeVnet 'Microsoft.Network/virtualNetworks@2023-09-01' = { name: 'vnet-spoke1' location: location properties: { addressSpace: { addressPrefixes: ['10.1.0.0/16'] } subnets: [ { name: 'snet-app' properties: { addressPrefix: '10.1.1.0/24' networkSecurityGroup: { id: nsgApp.id } } } { name: 'snet-pe' properties: { addressPrefix: '10.1.100.0/24' privateEndpointNetworkPolicies: 'Disabled' } } ] } } resource nsgApp 'Microsoft.Network/networkSecurityGroups@2023-09-01' = { name: 'nsg-app-tier' location: location properties: { securityRules: [ { name: 'Allow-HTTPS' properties: { priority: 100 direction: 'Inbound' access: 'Allow' protocol: 'Tcp' sourceAddressPrefix: '10.0.4.0/24' destinationPortRange: '443' sourcePortRange: '*' destinationAddressPrefix: '*' } } ] } }
Trade-off Analysis
| Quyết định | Option A | Option B | Khuyến nghị |
|---|---|---|---|
| Private Endpoint vs Service Endpoint | Bảo mật cao, tốn phí | Miễn phí, bảo mật vừa | PE cho prod, SE cho dev |
| Hub-Spoke vs Flat VNet | Quản lý tốt, phức tạp hơn | Đơn giản, khó scale | Hub-Spoke cho > 3 workloads |
| Azure Firewall vs NVA | Managed, tích hợp tốt, đắt | Linh hoạt, rẻ hơn, tự quản lý | Azure Firewall cho enterprise |
| ExpressRoute vs VPN | Bandwidth cao, SLA tốt, đắt | Rẻ, dễ setup, SLA thấp hơn | ExpressRoute cho production |