從零開始理解 VPC、AZ 與 Subnet 的架構設計

Published November 18, 2025 by 徐培鈞
架構

你是不是曾經看過 AWS 架構圖,然後心裡想:「為什麼要把東西分散在不同的 AZ(可用區)?這樣不是很麻煩嗎?」

或者你可能遇過這樣的情況:主管說要做「高可用架構」,但你不太確定這到底是什麼意思,更不知道該怎麼做。

別擔心,這篇文章就是要用最白話的方式,帶你搞懂這些問題:

核心概念解析

什麼是 AZ(Availability Zone)?

想像一下,你開了一家電商網站,所有伺服器都放在同一個機房裡。某天突然停電,或是機房淹水了,會發生什麼事?

沒錯,整個網站直接掛掉,所有客戶都無法下單,損失慘重。

這就是為什麼 AWS 設計了 AZ(Availability Zone,可用區) 的概念。

簡單來說:AZ 就是獨立的機房

每個 AZ 都是一個完全獨立的資料中心,就像是在不同地點開設的分店,各自有:

  • 獨立的電力供應: 有自己的發電機和備用電源,不會互相影響
  • 獨立的網路線路: 有自己的網路骨幹,一條線斷了不影響其他條
  • 獨立的機房位置: 實體距離夠遠(通常數公里到數十公里),天災不會同時影響
  • 獨特的名稱:ap-northeast-1aap-northeast-1bap-northeast-1c(分別代表東京區域的三個機房)

最重要的特性:互不影響

假設 ap-northeast-1a 這個機房突然停電,甚至整個機房失火了(當然這種情況極少發生),部署在 ap-northeast-1bap-northeast-1c 的資源還是能正常運作,你的網站不會掛掉!

這就像是你在台北、台中、高雄都開了分店,台北店停電了,台中和高雄的店還是照常營業。

Public Subnet vs Private Subnet

知道了 AZ 是什麼之後,接下來要了解另一個重要概念:Subnet(子網路)

先說個實際情境

你的網站需要一個「門面」讓客戶可以訪問,但你不希望把資料庫直接暴露在網路上讓任何人都能連線,對吧?這時候就需要區分「對外開放的區域」和「內部專用的區域」。

在 AWS 的 VPC(虛擬私有雲)架構中,Subnet 就是用來做這種區分的。

兩種 Subnet 的差別

用途對外服務的「門面」
能不能連外網?✅ 可以(有 Internet Gateway)
通常放什麼?負載平衡器 (ALB)、堡壘機 (Bastion Host)
用途內部核心服務的「後台」
能不能連外網?❌ 不行(沒有 Internet Gateway)
通常放什麼?應用程式伺服器 (EC2)、資料庫 (RDS)、快取 (Redis)

用餐廳來比喻:

  • Public Subnet 就像餐廳的「外場」:客人可以進來點餐、用餐,服務生在這裡接待客人
  • Private Subnet 就像餐廳的「廚房」:只有員工能進去,客人看不到也進不來,但這裡才是真正做菜的地方

為什麼要這樣設計?

  1. 安全性: 資料庫、應用程式邏輯放在 Private Subnet,駭客無法從網路直接攻擊
  2. 控制性: 所有對外的流量都必須經過 Public Subnet 的負載平衡器,方便管理和監控
  3. 最佳實踐: 這是業界公認的安全架構設計原則

為什麼要將 Subnet 分散到不同 AZ?

好,現在你已經知道:

  • AZ 是獨立的機房,一個掛掉不會影響其他個
  • Subnet 分成 Public(對外)和 Private(內部)兩種

接下來最重要的概念來了:

每個 AZ 都應該同時部署 Public Subnet 和 Private Subnet,形成一個完整的架構單元。

讓我用圖來說明:

graph TB
    subgraph AZ-a["AZ-a (ap-northeast-1a)"]
        PubA["Public Subnet<br/>10.0.1.0/24"]
        ALB-A["ALB"]
        PrivA["Private Subnet<br/>10.0.2.0/24"]
        EC2-A["EC2 App"]
        RDS-A["RDS 主要"]

        PubA --> ALB-A
        ALB-A --> PrivA
        PrivA --> EC2-A
        PrivA --> RDS-A
    end

    subgraph AZ-b["AZ-b (ap-northeast-1b)"]
        PubB["Public Subnet<br/>10.0.3.0/24"]
        ALB-B["ALB"]
        PrivB["Private Subnet<br/>10.0.4.0/24"]
        EC2-B["EC2 App"]
        RDS-B["RDS 備用"]

        PubB --> ALB-B
        ALB-B --> PrivB
        PrivB --> EC2-B
        PrivB --> RDS-B
    end

    Internet["網際網路"] --> ALB-A
    Internet --> ALB-B

    style AZ-a fill:#e1f5ff
    style AZ-b fill:#fff4e1
    style Internet fill:#ffcccb

為什麼要這樣設計?

每個 AZ 都是一個「獨立作戰單位」

想像你開了一家連鎖便利商店,你會怎麼設計分店?

❌ 錯誤做法:

  • 店A 只有收銀台(Public Subnet)
  • 店B 只有倉庫(Private Subnet)
  • 客人要在店A結帳,然後商品從店B送過來

這樣的問題是:如果店A停電了,客人連結帳都不行。如果店B淹水了,所有分店都沒貨可賣。

✅ 正確做法:

  • 每家分店都有收銀台(Public Subnet)
  • 每家分店都有自己的倉庫(Private Subnet)
  • 任何一家店出問題,其他店照常營業

AWS 的跨 AZ 架構就是這個概念!

每個 AZ 都部署完整的「Public + Private Subnet」組合,這樣任何一個 AZ 掛掉,其他 AZ 還能獨立運作。

具體來說有什麼好處?

好處 1:單一 AZ 故障不影響服務

情境: AZ-1a 整個機房停電了 ⚡

graph TB
    Event["⚡ 故障發生:AZ-1a 停電"]

    Event --> Path1["情況 1️⃣<br/>只有單一 AZ 架構"]
    Event --> Path2["情況 2️⃣<br/>多個 AZ 架構"]

    Path1 --> Check1{"能切換到<br/>其他 AZ 嗎?"}
    Check1 -->|❌ 不能<br/>沒有其他 AZ| Fail["❌ 服務完全中斷<br/>所有資源都在 1a<br/>只能等 AWS 修復"]

    Path2 --> Check2{"能切換到<br/>其他 AZ 嗎?"}
    Check2 -->|✅ 能!<br/>有 AZ-1b 可用| Switch["🔄 自動切換"]
    Switch --> Success["✅ 切換到 AZ-1b<br/>ALB → EC2 → RDS<br/>服務繼續運作"]

    style Event fill:#ffd700,stroke:#ff6b6b,stroke-width:3px
    style Path1 fill:#ffe6e6
    style Path2 fill:#e6f7e6
    style Check1 fill:#fff
    style Check2 fill:#fff
    style Fail fill:#ff9999,stroke:#ff0000,stroke-width:2px
    style Switch fill:#fff9c4
    style Success fill:#a5d6a7,stroke:#00aa00,stroke-width:2px

核心差異就在:能不能切換!

  • ❌ 單一 AZ → 無處可切 → 服務中斷
  • ✅ 多 AZ → 自動切換 → 服務不中斷

這個切換是自動的! 你不需要半夜爬起來手動處理。

好處 2:流量可以均勻分散

當你在每個 AZ 都部署 Public + Private Subnet 後:

ALB 的智能分流:

  1. 使用者請求進來
  2. ALB 自動判斷哪個 AZ 比較不忙
  3. 把請求送到負載較低的 AZ 處理
  4. 同一個 AZ 內的 Public Subnet (ALB) 直接連到 Private Subnet (EC2),速度最快

好處:

  • 沒有特定 AZ 會過載
  • 同 AZ 內通訊更快(延遲更低)
  • 系統整體效能更好

好處 3:維護時可以逐一升級,不用停機

假設你要更新應用程式:

單一 AZ 的做法:

1. 關閉服務
2. 更新程式
3. 重啟服務
 停機時間 30 分鐘,使用者無法使用

多 AZ 的做法(滾動更新):

1. 先更新 AZ-a  EC2,ALB 把流量都送到 AZ-b
2. AZ-a 更新完成後,再更新 AZ-b,流量回到 AZ-a
3. 全程服務不中斷!
 零停機時間

跨 AZ 資源如何相互溝通?

看到這裡,你應該已經理解為什麼要把資源分散到不同 AZ 了:當某個 AZ 掛掉時,其他 AZ 可以接手,服務就不會中斷。

聽起來很棒,對吧?

但是…你可能開始想:

「AZ-a 在東京某個機房,AZ-b 在另一個機房,它們距離可能有好幾公里遠。」

「那 AZ-a 的 ALB 要怎麼把請求送到 AZ-b 的 EC2?」

「而且 AZ-a 掛掉的時候,系統怎麼知道要切到 AZ-b?它們之間到底能不能溝通?」

這個問題超重要!因為如果不同 AZ 之間不能溝通,那前面講的「自動切換」根本不可能發生

所以這一章,我們就來解答這個關鍵問題。

答案很簡單:可以通訊!

在同一個 VPC 裡,不同 AZ 的資源可以直接互相溝通,就像在同一個區域網路一樣!

是不是覺得有點神奇?讓我解釋給你聽。

為什麼不同 AZ 可以互通?

想像一下這個情境:

你的公司在台北、台中、高雄都有辦公室(就像不同的 AZ)。雖然辦公室在不同城市,但是:

  • 每個辦公室都連到公司的內部網路(這就是 VPC)
  • 台北的同事可以直接訪問台中辦公室的檔案伺服器
  • 高雄的同事可以用公司內部 Email 跟台北的人溝通

AWS 的 AZ 就是這樣運作的!

技術上是怎麼做到的?

1. VPC 本身就是一個大內網

當你建立一個 VPC(例如 10.0.0.0/16),這個 IP 範圍內的所有資源都在「同一個網路」裡。

VPC: 10.0.0.0/16
├── AZ-a  Subnet: 10.0.1.0/24  ◄─┐
├── AZ-b  Subnet: 10.0.2.0/24  ◄─┼─ 都在同一個 VPC 內網
└── AZ-c  Subnet: 10.0.3.0/24  ◄─┘

只要在同一個 VPC,預設就可以互通!

2. Route Table 的 Local 路由

每個 VPC 都有一條神奇的路由規則:

目的地: 10.0.0.0/16 (你的 VPC)
目標: local (本地網路)

這條規則的意思是:「所有要去 VPC 內部 IP 的流量,直接走內部網路就好,不用出去外面繞。」

3. AWS 的高速骨幹網路

不同 AZ 之間不是用普通網路線連接,而是 AWS 自己建的高速光纖骨幹

  • 延遲超低(通常 1-2 毫秒)
  • 頻寬超大(不用擔心塞車)
  • 比你家的網路快多了

哪些資源可以跨 AZ 溝通?

簡單來說:幾乎所有資源都可以!

可以嗎?✅ 可以
說明同 VPC 就能通
可以嗎?✅ 可以
說明RDS Multi-AZ 就是這樣設計的
可以嗎?✅ 可以
說明ALB 本來就是用來跨 AZ 分流的
可以嗎?✅ 可以
說明設定好 Security Group 就行

前提條件:

  1. 所有資源在同一個 VPC
  2. Security Group 有開放對應的 Port
  3. Route Table 沒有被亂改(通常不會)

實際例子:一個請求怎麼跑

讓我們看一個真實的流程,假設使用者要查詢商品資料:

graph TD
    User["👤 使用者<br/>查詢商品資料"] --> Internet["🌐 網際網路"]
    Internet --> ALB["ALB<br/>(在 AZ-a 的 Public Subnet)"]
    ALB -->|跨 AZ 通訊<br/>延遲 1-2ms| EC2["EC2 應用伺服器<br/>(在 AZ-b 的 Private Subnet)"]
    EC2 -->|1. 查詢商品資料| RDS["RDS 資料庫<br/>(在 AZ-b 的 Private Subnet)"]
    EC2 -->|2. 查詢快取| Redis["Redis 快取<br/>(在 AZ-c 的 Private Subnet)"]
    RDS -->|回傳資料| EC2
    Redis -->|回傳快取| EC2
    EC2 -->|組裝回應| ALB
    ALB --> Internet
    Internet --> User

    style User fill:#e3f2fd
    style ALB fill:#fff9c4
    style EC2 fill:#c8e6c9
    style RDS fill:#bbdefb
    style Redis fill:#ffccbc

流程說明:

  1. 使用者的請求進來,先到 AZ-a 的 ALB
  2. ALB 決定把請求送給 AZ-b 的 EC2(跨 AZ 通訊,但超快!)
  3. EC2 需要查資料,連到 AZ-b 的 RDS(同 AZ,更快)
  4. EC2 也查一下 AZ-c 的 Redis 快取(跨 AZ,但也很快)
  5. EC2 把結果組裝好,回傳給 ALB
  6. ALB 把回應送回給使用者

重點:整個過程都在 VPC 內部,安全又快速!

但是要注意 Security Group!

雖然不同 AZ 可以通訊,但你還是要設定 Security Group(安全群組) 來控制誰可以連誰。

簡單比喻:

  • VPC 讓大家「可以」互相溝通(網路是通的)
  • Security Group 控制「允許」誰溝通(防火牆)

實際配置範例

ALB 的 Security Group:

規則✅ 允許:來自任何地方的 HTTP (Port 80) 和 HTTPS (Port 443)
規則✅ 允許:到 EC2 Security Group 的所有流量

EC2 的 Security Group:

規則✅ 允許:來自 ALB Security Group 的 Port 8080;來自 RDS Security Group 的 Port 3306
規則✅ 允許:到 RDS Security Group 的 Port 3306;到 Redis Security Group 的 Port 6379

RDS 的 Security Group:

規則✅ 允許:來自 EC2 Security Group 的 Port 3306
規則通常不用設定(RDS 只接收請求,不主動對外連線)

關鍵技巧:用 Security Group ID 當來源

注意到了嗎?我們不是寫「允許 10.0.2.5 這個 IP」,而是寫「允許 ALB Security Group」。

好處:

  • EC2 的 IP 可能會變,但 Security Group 不會變
  • 更容易管理(不用記一堆 IP)
  • 更安全(只有特定群組的資源能連)

總結一下

跨 AZ 通訊的關鍵觀念:

  1. 同一個 VPC = 同一個內網,不同 AZ 也能互通
  2. AWS 骨幹網路超快,跨 AZ 延遲只有 1-2 毫秒
  3. 幾乎所有服務都支援跨 AZ 通訊
  4. ⚠️ 但要設定 Security Group,控制誰可以連誰
  5. ⚠️ 跨 AZ 流量有成本(每 GB 約 $0.01,不過通常不多)

最重要的一句話:

把不同 AZ 想成「同一個公司在不同城市的辦公室」,它們都連在同一個公司內網,可以互相溝通,只是距離遠一點而已!

完整架構設計實戰範例

場景描述

需求: 建立一個電商網站的後端系統,要求高可用、高安全性

技術堆疊:

  • 前端:透過 CloudFront CDN 提供靜態資源
  • 負載平衡:Application Load Balancer
  • 應用層:EC2 執行 Node.js 應用程式
  • 資料層:RDS MySQL 資料庫、ElastiCache Redis

架構設計圖

graph TB
    Internet["🌐 網際網路"]
    CDN["CloudFront CDN"]

    Internet --> CDN

    subgraph VPC["VPC (10.0.0.0/16)"]
        subgraph AZ-a["AZ a (ap-northeast-1a)"]
            PubA["Public Subnet<br/>10.0.1.0/24"]
            ALB-A["ALB (主要)"]
            PrivA["Private Subnet<br/>10.0.2.0/24"]
            EC2-A["EC2 App x2"]
            RDS-A["RDS (主要)"]

            PubA --> ALB-A
            ALB-A --> PrivA
            PrivA --> EC2-A
            PrivA --> RDS-A
        end

        subgraph AZ-b["AZ b (ap-northeast-1b)"]
            PubB["Public Subnet<br/>10.0.3.0/24"]
            ALB-B["ALB (備援)"]
            PrivB["Private Subnet<br/>10.0.4.0/24"]
            EC2-B["EC2 App x2"]
            RDS-B["RDS (備用)"]

            PubB --> ALB-B
            ALB-B --> PrivB
            PrivB --> EC2-B
            PrivB --> RDS-B
        end

        subgraph AZ-c["AZ c (ap-northeast-1c)"]
            PrivC["Private Subnet<br/>10.0.5.0/24"]
            Redis["Redis Cluster"]
            EC2-C["備用 EC2"]

            PrivC --> Redis
            PrivC --> EC2-C
        end
    end

    CDN --> ALB-A
    CDN --> ALB-B

    style Internet fill:#ffcccb
    style CDN fill:#fff9c4
    style VPC fill:#f0f0f0
    style AZ-a fill:#e1f5ff
    style AZ-b fill:#fff4e1
    style AZ-c fill:#e8f5e9
    style ALB-A fill:#90caf9
    style ALB-B fill:#90caf9
    style EC2-A fill:#a5d6a7
    style EC2-B fill:#a5d6a7
    style EC2-C fill:#a5d6a7
    style RDS-A fill:#ce93d8
    style RDS-B fill:#ce93d8
    style Redis fill:#ffab91

讓我們拆解這個架構

看完上面的圖,你可能覺得有點複雜。別擔心,我們一層一層來看。

第一層:門面(Public Subnet)

想像這是你店面的「櫃台」,客人進來第一個看到的地方。

我們在 AZ-a 和 AZ-b 都放了 ALB(負載平衡器):

  • 就像在兩個城市都開店,任何一家店關門,客人還能去另一家
  • ALB 會自動判斷:「欸,AZ-a 的櫃檯人太多了,把客人引導到 AZ-b 吧」
  • 這就是為什麼 ALB 必須至少在兩個 AZ,AWS 的硬性規定

為什麼要這樣?
假設 AZ-a 的 ALB 掛了,網站不會掛掉,因為 AZ-b 的 ALB 馬上接手。DNS 會自動把流量導過去,使用者根本不會發現。

第二層:工作區(Private Subnet – 應用層)

這是你的「辦公室」,員工在這裡處理訂單、查資料。客人看不到,但這裡才是做事的地方。

我們在 AZ-a 和 AZ-b 各放 2 台 EC2 伺服器:

  • 為什麼要 2 台?因為 1 台掛了,另 1 台還能撐著
  • 為什麼要兩個 AZ?因為整個 AZ 掛了,另一個 AZ 的伺服器繼續跑

Auto Scaling 的魔法:

想像你開餐廳,平日只需要 4 個廚師,但週末客人暴增,系統會自動叫更多廚師來幫忙:

  • 平常: 4 台 EC2(每個 AZ 各 2 台)
  • 開始忙: 自動擴展到 6 台
  • 超級忙: 最多可以擴展到 12 台
  • 人少了: 自動縮減回 4 台,省成本

更新程式時怎麼辦?

這是最酷的部分!我們用「滾動更新」:

  1. 先更新 AZ-a 的第 1 台 EC2,ALB 把流量都導到其他台
  2. 更新完成後,再更新第 2 台
  3. 接著更新 AZ-b 的伺服器
  4. 全程網站不停機!

第三層:金庫(Private Subnet – 資料層)

這是最重要的地方:資料庫和快取,就像公司的金庫和檔案室。

RDS 資料庫(跨 AZ-a 和 AZ-b):

這裡有個超酷的機制叫「Multi-AZ」:

  1. 平常: 主要資料庫在 AZ-a 處理所有讀寫
  2. 背後: AWS 偷偷把資料同步複製到 AZ-b 的備用資料庫
  3. 災難發生: AZ-a 掛了?沒關係,1-2 分鐘內自動切換到 AZ-b
  4. 神奇的地方: 你的程式連接的網址(DNS endpoint)不用改,自動指向新的資料庫

就像你的銀行帳戶,不管你去哪個分行,看到的都是同一個帳戶餘額。

Redis 快取(在 AZ-c):

為什麼把快取獨立放在第三個 AZ?

  • 快取掛了不會影響主要功能,只是變慢一點
  • 這樣可以省點成本(不用在每個 AZ 都放快取)

實戰演練:如果真的出事了會怎樣?

讓我們模擬兩個真實場景,看看系統怎麼反應。

情境 1:整個 AZ-a 停電了 ⚡

凌晨 3 點,AZ-a 機房突然停電…

會受影響的:

  • AZ-a 的 ALB 掛了
  • AZ-a 的 2 台 EC2 掛了
  • AZ-a 的主要 RDS 資料庫掛了

系統自動做的事(你不用做任何事):

0-30 秒:

  • DNS 偵測到 AZ-a 的 ALB 沒回應
  • 立刻把所有流量導向 AZ-b 的 ALB

30 秒 – 2 分鐘:

  • AZ-b 的 2 台 EC2 開始承接所有流量
  • Auto Scaling 偵測到負載變高,開始啟動新的 EC2 實例
  • RDS 自動故障轉移到 AZ-b 的備用資料庫

2 分鐘後:

  • 新的 EC2 實例上線,流量分散開來
  • AZ-c 的 Redis 快取完全不受影響
  • 服務恢復正常

用戶體驗:

  • 前 1-2 分鐘可能有點慢,或是少數請求失敗
  • 之後完全正常
  • 大部分人可能根本沒發現出事了

情境 2:某台 EC2 當機了 💥

下午 2 點,AZ-a 的其中一台 EC2 突然當機…

影響: 就一台 EC2 掛了

系統自動反應:

30 秒內:

  • ALB 健康檢查發現這台 EC2 沒回應
  • 立刻停止送請求給這台

2-5 分鐘內:

  • Auto Scaling 發現實例數量不足
  • 自動啟動一台新的 EC2
  • 新 EC2 準備好後,ALB 開始送流量給它

用戶體驗:

  • 幾乎無感!因為還有其他 3 台 EC2 在正常服務
  • 可能只有極少數正在處理中的請求會失敗

總結

核心要點回顧

  1. 高可用架構的基石
  • 將 Public Subnet 和 Private Subnet 分散到不同 AZ,是實現高可用性的關鍵策略
  • 這不僅是技術最佳實踐,更是業務連續性的保障
  1. 跨 AZ 通訊的本質
  • 同一 VPC 內的不同 AZ 資源可以無縫通訊
  • 透過 AWS 內部高速網路,延遲極低,無需擔心效能問題
  • 正確配置 Security Group 和 Route Table 是關鍵
  1. 架構設計的平衡
  • 在高可用性、成本和複雜度之間找到平衡點
  • 至少 2 個 AZ 是底線,3 個 AZ 是生產環境的理想配置
  • 根據業務重要性決定哪些資源需要跨 AZ 部署
  1. 持續優化與演練
  • 架構設計不是一次性的工作,需要持續監控和優化
  • 定期進行災難復原演練,確保團隊熟悉應對流程
  • 關注 AWS 的新服務和最佳實踐更新

最後的話

雲端架構設計是一門藝術,也是一門科學。高可用性不是一蹴而就的,而是透過精心設計、持續優化和實戰演練逐步建立起來的。

記住這句話:「希望不是策略,但準備是。」 當故障發生時(而不是如果),你的架構設計將決定服務是繼續運作還是完全停擺。

從今天開始,將跨 AZ 高可用架構作為你設計系統的預設選擇,而不是可選項。你的使用者會感謝你,你的老闆會感謝你,你的團隊也會感謝你。

祝你在 AWS 的學習旅程中一切順利!