透過Terraform在AWS上運行VPC Peering

Terraform AWS VPC Peering

前言

在現代雲端架構中,我們經常需要將不同的工作負載隔離在各自的 VPC(Virtual Private Cloud)中,以提高安全性和管理效率。然而,這些隔離的網路環境之間往往需要進行私有通訊,例如:

  • 開發與生產環境分離:開發環境需要存取生產環境的共用服務
  • 多層應用架構:前端 VPC 需要連接後端 VPC 的資料庫
  • 跨團隊協作:不同團隊管理的 VPC 需要互相存取資源
  • 混合雲整合:本地資料中心透過 VPN 連接的 VPC 需要存取其他 VPC

AWS VPC Peering 提供了一個簡單且低成本的解決方案,讓兩個 VPC 之間可以透過 AWS 內部網路進行私有 IP 通訊,就像它們在同一個網路中一樣。流量不會經過公開網際網路,確保了資料傳輸的安全性和低延遲。

VPC Peering 的特點

  • 私有連線:流量透過 AWS 骨幹網路傳輸,不經過公開網際網路
  • 低延遲:直接的網路連線,延遲比透過 NAT Gateway 或 Internet Gateway 更低
  • 無頻寬瓶頸:沒有單點頻寬限制
  • 跨帳號與跨區域支援:可以連接不同 AWS 帳號或不同區域的 VPC
  • 成本效益:相較於 Transit Gateway,VPC Peering 在少量連線時更具成本優勢

網路架構圖

本文將建立以下網路架構:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
┌─────────────────────────────────────────────────────────────────────────────┐
│                              AWS Region: us-west-2                          │
├─────────────────────────────────┬───────────────────────────────────────────┤
│                                 │                                           │
│     VPC-1 (10.0.0.0/16)         │           VPC-2 (20.0.0.0/16)             │
│                                 │                                           │
│  ┌─────────────────────────┐    │    ┌─────────────────────────┐            │
│  │   subnet-1a             │    │    │   subnet-2a             │            │
│  │   10.0.1.0/24           │    │    │   20.0.1.0/24           │            │
│  │   ┌─────────────┐       │    │    │   ┌─────────────┐       │            │
│  │   │   ec2-1a    │       │    │    │   │   ec2-2a    │       │            │
│  │   │  (t2.micro) │       │    │    │   │  (t2.micro) │       │            │
│  │   └─────────────┘       │    │    │   └─────────────┘       │            │
│  └─────────────────────────┘    │    └─────────────────────────┘            │
│                                 │                                           │
│  ┌─────────────────────────┐    │    ┌─────────────────────────┐            │
│  │   subnet-1b             │    │    │   subnet-2b             │            │
│  │   10.0.2.0/24           │    │    │   20.0.2.0/24           │            │
│  │   ┌─────────────┐       │◄───┼───►│   ┌─────────────┐       │            │
│  │   │   ec2-1b    │       │ VPC│    │   │   ec2-2b    │       │            │
│  │   │  (t2.micro) │       │Peer│    │   │  (t2.micro) │       │            │
│  │   └─────────────┘       │    │    │   └─────────────┘       │            │
│  └─────────────────────────┘    │    └─────────────────────────┘            │
│                                 │                                           │
│  ┌─────────────────────────┐    │    ┌─────────────────────────┐            │
│  │       igw-1             │    │    │       igw-2             │            │
│  │  (Internet Gateway)     │    │    │  (Internet Gateway)     │            │
│  └───────────┬─────────────┘    │    └───────────┬─────────────┘            │
│              │                  │                │                          │
└──────────────┼──────────────────┴────────────────┼──────────────────────────┘
               │                                   │
               ▼                                   ▼
         ┌─────────────────────────────────────────────┐
         │                 Internet                    │
         └─────────────────────────────────────────────┘

路由規劃

路由表目的地 CIDR目標說明
route-table-110.0.0.0/16localVPC-1 內部流量
route-table-120.0.0.0/16VPC Peering往 VPC-2 的流量
route-table-10.0.0.0/0igw-1往網際網路的流量
route-table-220.0.0.0/16localVPC-2 內部流量
route-table-210.0.0.0/16VPC Peering往 VPC-1 的流量
route-table-20.0.0.0/0igw-2往網際網路的流量

示意圖

Terraform 資源說明

在開始建置之前,讓我們先了解本文將使用的各項 Terraform 資源:

資源類型說明
aws_vpc建立虛擬私有雲,定義 CIDR 區塊
aws_subnet在 VPC 中建立子網路,指定可用區域
aws_internet_gateway讓 VPC 中的資源可以存取網際網路
aws_route_table定義網路流量的路由規則
aws_route_table_association將路由表與子網路關聯
aws_security_group定義進出規則,控制網路存取
aws_instance建立 EC2 執行個體
aws_eip配置彈性 IP 位址
aws_eip_association將彈性 IP 與 EC2 執行個體關聯
aws_vpc_peering_connection建立 VPC 對等連線

建置環境

1. 建立 Provider 和 Region

首先設定 AWS Provider,指定區域和認證設定檔:

1
2
3
4
provider "aws" {
  region  = "us-west-2"
  profile = "default"
}

說明

  • region:指定 AWS 區域,本範例使用 us-west-2(奧勒岡)
  • profile:使用 AWS CLI 設定的認證設定檔

2. 建立 VPC 1 環境

建立第一個 VPC 及其相關網路資源:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# 建立 VPC-1,CIDR 區塊為 10.0.0.0/16
resource "aws_vpc" "vpc-1" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true  # 啟用 DNS 主機名稱
  enable_dns_support   = true  # 啟用 DNS 解析
  tags = {
    "Name" = "vpc-1"
  }
}

# 建立子網路 1a,位於 us-west-2a 可用區域
resource "aws_subnet" "subnet-1a" {
  cidr_block        = "10.0.1.0/24"
  vpc_id            = aws_vpc.vpc-1.id
  availability_zone = "us-west-2a"
  tags = {
    "Name" = "subnet-1a"
  }
}

# 建立子網路 1b,位於 us-west-2a 可用區域
resource "aws_subnet" "subnet-1b" {
  cidr_block        = "10.0.2.0/24"
  vpc_id            = aws_vpc.vpc-1.id
  availability_zone = "us-west-2a"
  tags = {
    "Name" = "subnet-1b"
  }
}

# 建立路由表,定義往 VPC-2 和網際網路的路由
resource "aws_route_table" "route-table-1" {
  vpc_id = aws_vpc.vpc-1.id

  # 往 VPC-2 的流量透過 VPC Peering 連線
  route {
    cidr_block                = "20.0.0.0/16"
    vpc_peering_connection_id = aws_vpc_peering_connection.peer.id
  }

  # 往網際網路的流量透過 Internet Gateway
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw-1.id
  }

  tags = {
    "Name" = "route-table-1"
  }
}

# 將路由表與子網路關聯
resource "aws_route_table_association" "subnet-1a" {
  subnet_id      = aws_subnet.subnet-1a.id
  route_table_id = aws_route_table.route-table-1.id
}

resource "aws_route_table_association" "subnet-1b" {
  subnet_id      = aws_subnet.subnet-1b.id
  route_table_id = aws_route_table.route-table-1.id
}

# 建立 Internet Gateway,讓 VPC 可以存取網際網路
resource "aws_internet_gateway" "igw-1" {
  vpc_id = aws_vpc.vpc-1.id
  tags = {
    Name = "igw-1"
  }
}

# 建立安全群組,控制 EC2 的網路存取
resource "aws_security_group" "sg-1" {
  name        = "sg1"
  description = "Security group for VPC-1 instances"
  vpc_id      = aws_vpc.vpc-1.id

  # 允許 SSH 連線(建議限制來源 IP)
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # 允許 HTTP 連線
  ingress {
    from_port   = 80
    to_port     = 80
    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"]
  }

  tags = {
    Name = "sg-1"
  }
}

# 配置彈性 IP
resource "aws_eip" "eip-1a" {
  domain = "vpc"
}

resource "aws_eip" "eip-1b" {
  domain = "vpc"
}

# 將彈性 IP 與 EC2 執行個體關聯
resource "aws_eip_association" "eipa-1a" {
  instance_id   = aws_instance.ec2-1a.id
  allocation_id = aws_eip.eip-1a.id
}

resource "aws_eip_association" "eipa-1b" {
  instance_id   = aws_instance.ec2-1b.id
  allocation_id = aws_eip.eip-1b.id
}

# 建立 EC2 執行個體
resource "aws_instance" "ec2-1a" {
  ami                    = "ami-0747e613a2a1ff483"
  instance_type          = "t2.micro"
  key_name               = "demo-key-us-west-2"
  availability_zone      = "us-west-2a"
  subnet_id              = aws_subnet.subnet-1a.id
  vpc_security_group_ids = [aws_security_group.sg-1.id]
  tags = {
    Name = "ec2-1a"
  }
}

resource "aws_instance" "ec2-1b" {
  ami                    = "ami-0747e613a2a1ff483"
  instance_type          = "t2.micro"
  key_name               = "demo-key-us-west-2"
  availability_zone      = "us-west-2a"
  subnet_id              = aws_subnet.subnet-1b.id
  vpc_security_group_ids = [aws_security_group.sg-1.id]
  tags = {
    Name = "ec2-1b"
  }
}

3. 建立 VPC 2 環境

建立第二個 VPC,架構與 VPC-1 相似,但使用不同的 CIDR 區塊:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# 建立 VPC-2,CIDR 區塊為 20.0.0.0/16
resource "aws_vpc" "vpc-2" {
  cidr_block           = "20.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = {
    "Name" = "vpc-2"
  }
}

# 建立子網路 2a,位於 us-west-2b 可用區域
resource "aws_subnet" "subnet-2a" {
  cidr_block        = "20.0.1.0/24"
  vpc_id            = aws_vpc.vpc-2.id
  availability_zone = "us-west-2b"
  tags = {
    "Name" = "subnet-2a"
  }
}

# 建立子網路 2b
resource "aws_subnet" "subnet-2b" {
  cidr_block        = "20.0.2.0/24"
  vpc_id            = aws_vpc.vpc-2.id
  availability_zone = "us-west-2b"
  tags = {
    "Name" = "subnet-2b"
  }
}

# 建立路由表,定義往 VPC-1 和網際網路的路由
resource "aws_route_table" "route-table-2" {
  vpc_id = aws_vpc.vpc-2.id

  # 往 VPC-1 的流量透過 VPC Peering 連線
  route {
    cidr_block                = "10.0.0.0/16"
    vpc_peering_connection_id = aws_vpc_peering_connection.peer.id
  }

  # 往網際網路的流量透過 Internet Gateway
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw-2.id
  }

  tags = {
    "Name" = "route-table-2"
  }
}

# 將路由表與子網路關聯
resource "aws_route_table_association" "subnet-2a" {
  subnet_id      = aws_subnet.subnet-2a.id
  route_table_id = aws_route_table.route-table-2.id
}

resource "aws_route_table_association" "subnet-2b" {
  subnet_id      = aws_subnet.subnet-2b.id
  route_table_id = aws_route_table.route-table-2.id
}

# 建立 Internet Gateway
resource "aws_internet_gateway" "igw-2" {
  vpc_id = aws_vpc.vpc-2.id
  tags = {
    Name = "igw-2"
  }
}

# 建立安全群組
resource "aws_security_group" "sg-2" {
  name        = "sg2"
  description = "Security group for VPC-2 instances"
  vpc_id      = aws_vpc.vpc-2.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 80
    to_port     = 80
    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"]
  }

  tags = {
    Name = "sg-2"
  }
}

# 配置彈性 IP
resource "aws_eip" "eip-2a" {
  domain = "vpc"
}

resource "aws_eip" "eip-2b" {
  domain = "vpc"
}

# 將彈性 IP 與 EC2 執行個體關聯
resource "aws_eip_association" "eipa-2a" {
  instance_id   = aws_instance.ec2-2a.id
  allocation_id = aws_eip.eip-2a.id
}

resource "aws_eip_association" "eipa-2b" {
  instance_id   = aws_instance.ec2-2b.id
  allocation_id = aws_eip.eip-2b.id
}

# 建立 EC2 執行個體
resource "aws_instance" "ec2-2a" {
  ami                    = "ami-0747e613a2a1ff483"
  instance_type          = "t2.micro"
  key_name               = "demo-key-us-west-2"
  availability_zone      = "us-west-2b"
  subnet_id              = aws_subnet.subnet-2a.id
  vpc_security_group_ids = [aws_security_group.sg-2.id]
  tags = {
    Name = "ec2-2a"
  }
}

resource "aws_instance" "ec2-2b" {
  ami                    = "ami-0747e613a2a1ff483"
  instance_type          = "t2.micro"
  key_name               = "demo-key-us-west-2"
  availability_zone      = "us-west-2b"
  subnet_id              = aws_subnet.subnet-2b.id
  vpc_security_group_ids = [aws_security_group.sg-2.id]
  tags = {
    Name = "ec2-2b"
  }
}

4. 建立 VPC Peering

建立 VPC Peering 連線,讓兩個 VPC 可以互相通訊:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 建立 VPC Peering 連線
resource "aws_vpc_peering_connection" "peer" {
  vpc_id      = aws_vpc.vpc-1.id      # 請求者 VPC
  peer_vpc_id = aws_vpc.vpc-2.id      # 接受者 VPC
  auto_accept = true                   # 自動接受(僅適用於同帳號同區域)

  # 啟用 DNS 解析支援
  accepter {
    allow_remote_vpc_dns_resolution = true
  }

  requester {
    allow_remote_vpc_dns_resolution = true
  }

  tags = {
    "Name" = "vpc-1-to-vpc-2-peer"
  }
}

重要說明

  • auto_accept = true 只有在兩個 VPC 屬於同一個 AWS 帳號且在同一個區域時才能使用
  • 跨帳號或跨區域的 Peering 需要手動接受或使用 aws_vpc_peering_connection_accepter 資源

進階設定:安全群組最佳實踐

在生產環境中,建議更精細地控制安全群組規則,只允許必要的流量通過:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# VPC-1 的安全群組,允許來自 VPC-2 的特定流量
resource "aws_security_group" "sg-1-peering" {
  name        = "sg1-peering"
  description = "Security group for VPC Peering traffic from VPC-2"
  vpc_id      = aws_vpc.vpc-1.id

  # 允許來自 VPC-2 的 ICMP(ping)
  ingress {
    from_port   = -1
    to_port     = -1
    protocol    = "icmp"
    cidr_blocks = ["20.0.0.0/16"]
    description = "Allow ICMP from VPC-2"
  }

  # 允許來自 VPC-2 的 SSH
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["20.0.0.0/16"]
    description = "Allow SSH from VPC-2"
  }

  # 允許來自 VPC-2 的應用程式連接埠
  ingress {
    from_port   = 8080
    to_port     = 8080
    protocol    = "tcp"
    cidr_blocks = ["20.0.0.0/16"]
    description = "Allow application traffic from VPC-2"
  }

  # 允許往 VPC-2 的出站流量
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["20.0.0.0/16"]
    description = "Allow all outbound to VPC-2"
  }

  tags = {
    Name = "sg-1-peering"
  }
}

# VPC-2 的安全群組,允許來自 VPC-1 的特定流量
resource "aws_security_group" "sg-2-peering" {
  name        = "sg2-peering"
  description = "Security group for VPC Peering traffic from VPC-1"
  vpc_id      = aws_vpc.vpc-2.id

  # 允許來自 VPC-1 的 ICMP(ping)
  ingress {
    from_port   = -1
    to_port     = -1
    protocol    = "icmp"
    cidr_blocks = ["10.0.0.0/16"]
    description = "Allow ICMP from VPC-1"
  }

  # 允許來自 VPC-1 的 MySQL 連線
  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"]
    description = "Allow MySQL from VPC-1"
  }

  # 允許往 VPC-1 的出站流量
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["10.0.0.0/16"]
    description = "Allow all outbound to VPC-1"
  }

  tags = {
    Name = "sg-2-peering"
  }
}

跨帳號 VPC Peering 設定

當需要連接不同 AWS 帳號的 VPC 時,需要使用兩個 Provider 並手動處理接受流程:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# 定義兩個 Provider,分別代表不同的 AWS 帳號
provider "aws" {
  alias   = "requester"
  region  = "us-west-2"
  profile = "account-a"  # 請求者帳號
}

provider "aws" {
  alias   = "accepter"
  region  = "us-west-2"
  profile = "account-b"  # 接受者帳號
}

# 取得接受者帳號的資訊
data "aws_caller_identity" "accepter" {
  provider = aws.accepter
}

# 在請求者帳號建立 VPC Peering 連線請求
resource "aws_vpc_peering_connection" "cross_account_peer" {
  provider = aws.requester

  vpc_id        = aws_vpc.vpc-requester.id
  peer_vpc_id   = aws_vpc.vpc-accepter.id
  peer_owner_id = data.aws_caller_identity.accepter.account_id  # 接受者帳號 ID
  peer_region   = "us-west-2"

  auto_accept = false  # 跨帳號不能自動接受

  tags = {
    Name = "cross-account-peer-requester"
    Side = "Requester"
  }
}

# 在接受者帳號接受 VPC Peering 連線
resource "aws_vpc_peering_connection_accepter" "cross_account_peer" {
  provider = aws.accepter

  vpc_peering_connection_id = aws_vpc_peering_connection.cross_account_peer.id
  auto_accept               = true

  tags = {
    Name = "cross-account-peer-accepter"
    Side = "Accepter"
  }
}

# 在請求者帳號設定 Peering 選項
resource "aws_vpc_peering_connection_options" "requester" {
  provider = aws.requester

  vpc_peering_connection_id = aws_vpc_peering_connection.cross_account_peer.id

  requester {
    allow_remote_vpc_dns_resolution = true
  }

  depends_on = [aws_vpc_peering_connection_accepter.cross_account_peer]
}

# 在接受者帳號設定 Peering 選項
resource "aws_vpc_peering_connection_options" "accepter" {
  provider = aws.accepter

  vpc_peering_connection_id = aws_vpc_peering_connection.cross_account_peer.id

  accepter {
    allow_remote_vpc_dns_resolution = true
  }

  depends_on = [aws_vpc_peering_connection_accepter.cross_account_peer]
}

跨區域 VPC Peering 設定

跨區域(Inter-Region)VPC Peering 讓位於不同 AWS 區域的 VPC 可以互相通訊:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 定義兩個區域的 Provider
provider "aws" {
  alias   = "us-west-2"
  region  = "us-west-2"
  profile = "default"
}

provider "aws" {
  alias   = "ap-northeast-1"
  region  = "ap-northeast-1"
  profile = "default"
}

# 在 us-west-2 建立 VPC
resource "aws_vpc" "vpc-us-west" {
  provider   = aws.us-west-2
  cidr_block = "10.0.0.0/16"

  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "vpc-us-west-2"
  }
}

# 在 ap-northeast-1 建立 VPC
resource "aws_vpc" "vpc-ap-northeast" {
  provider   = aws.ap-northeast-1
  cidr_block = "172.16.0.0/16"

  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "vpc-ap-northeast-1"
  }
}

# 從 us-west-2 發起跨區域 Peering 請求
resource "aws_vpc_peering_connection" "inter_region_peer" {
  provider = aws.us-west-2

  vpc_id      = aws_vpc.vpc-us-west.id
  peer_vpc_id = aws_vpc.vpc-ap-northeast.id
  peer_region = "ap-northeast-1"  # 指定對等方的區域

  auto_accept = false  # 跨區域不能自動接受

  tags = {
    Name = "us-west-2-to-ap-northeast-1"
  }
}

# 在 ap-northeast-1 接受 Peering 請求
resource "aws_vpc_peering_connection_accepter" "inter_region_peer" {
  provider = aws.ap-northeast-1

  vpc_peering_connection_id = aws_vpc_peering_connection.inter_region_peer.id
  auto_accept               = true

  tags = {
    Name = "ap-northeast-1-accept-us-west-2"
  }
}

# 在 us-west-2 新增路由指向 ap-northeast-1
resource "aws_route" "us-west-to-ap" {
  provider = aws.us-west-2

  route_table_id            = aws_route_table.us-west-rt.id
  destination_cidr_block    = "172.16.0.0/16"
  vpc_peering_connection_id = aws_vpc_peering_connection.inter_region_peer.id
}

# 在 ap-northeast-1 新增路由指向 us-west-2
resource "aws_route" "ap-to-us-west" {
  provider = aws.ap-northeast-1

  route_table_id            = aws_route_table.ap-northeast-rt.id
  destination_cidr_block    = "10.0.0.0/16"
  vpc_peering_connection_id = aws_vpc_peering_connection.inter_region_peer.id

  depends_on = [aws_vpc_peering_connection_accepter.inter_region_peer]
}

VPC Peering vs Transit Gateway 比較

在選擇網路連接方案時,VPC Peering 和 Transit Gateway 各有優缺點:

特性VPC PeeringTransit Gateway
連線拓撲點對點(一對一)中心輻射型(一對多)
最大連線數每個 VPC 最多 125 個 Peering每個 TGW 最多 5,000 個 VPC
可擴展性N*(N-1)/2 個連線(完全網狀)N 個連線(星狀)
路由管理每個 VPC 獨立管理路由表集中式路由管理
跨區域支援支援(Inter-Region Peering)支援(TGW Peering)
跨帳號支援支援支援
頻寬限制無額外限制每個 VPC 連線 50 Gbps
延遲較低略高(經過 TGW)
成本僅資料傳輸費連線費 + 資料處理費
VPN/Direct Connect 整合不支援支援

選擇建議

適合使用 VPC Peering 的情況

  • VPC 數量較少(3-5 個以內)
  • 需要最低延遲的點對點連線
  • 成本敏感的環境
  • 簡單的網路拓撲

適合使用 Transit Gateway 的情況

  • VPC 數量眾多
  • 需要與 VPN 或 Direct Connect 整合
  • 需要集中管理路由
  • 複雜的網路拓撲
  • 需要網路分段和安全控制

成本比較範例

假設每月傳輸 100 GB 資料,連接 5 個 VPC:

VPC Peering

  • 需要 10 個 Peering 連線(完全網狀)
  • 費用:僅資料傳輸費(同區域免費,跨區域 $0.01/GB)

Transit Gateway

  • 需要 5 個 TGW 連線
  • 連線費:$0.05/小時 x 5 x 720 小時 = $180/月
  • 資料處理費:$0.02/GB x 100 GB = $2/月
  • 總計約 $182/月

故障排除指南

常見問題與解決方案

1. VPC Peering 連線狀態為 “pending-acceptance”

原因:跨帳號或跨區域的 Peering 需要手動接受

解決方案

  • 確認已使用 aws_vpc_peering_connection_accepter 資源
  • 檢查接受者帳號是否有足夠的 IAM 權限
  • 確認 peer_owner_idpeer_region 設定正確
1
2
3
# 使用 AWS CLI 檢查 Peering 狀態
aws ec2 describe-vpc-peering-connections \
  --vpc-peering-connection-ids pcx-xxxxxxxxx

2. 無法透過 Peering 連線 ping 到對方 VPC

檢查清單

  1. 確認安全群組允許 ICMP 流量
  2. 確認路由表有正確的路由規則
  3. 確認 NACL(Network ACL)沒有阻擋流量
  4. 確認 CIDR 區塊沒有重疊
1
2
3
4
5
# 檢查路由表
aws ec2 describe-route-tables --route-table-ids rtb-xxxxxxxxx

# 檢查安全群組規則
aws ec2 describe-security-groups --group-ids sg-xxxxxxxxx

3. CIDR 區塊重疊錯誤

原因:兩個 VPC 的 CIDR 區塊有重疊

解決方案

  • 規劃不重疊的 IP 位址空間
  • 使用 Secondary CIDR 區塊
  • 考慮使用 PrivateLink 作為替代方案
1
2
3
4
5
# 為 VPC 新增 Secondary CIDR
resource "aws_vpc_ipv4_cidr_block_association" "secondary_cidr" {
  vpc_id     = aws_vpc.vpc-1.id
  cidr_block = "100.64.0.0/16"
}

4. DNS 解析問題

原因:未啟用跨 VPC 的 DNS 解析

解決方案

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
resource "aws_vpc_peering_connection_options" "peer_options" {
  vpc_peering_connection_id = aws_vpc_peering_connection.peer.id

  accepter {
    allow_remote_vpc_dns_resolution = true
  }

  requester {
    allow_remote_vpc_dns_resolution = true
  }
}

5. 連線超時

檢查步驟

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 1. 確認 Peering 連線狀態
aws ec2 describe-vpc-peering-connections \
  --filters "Name=status-code,Values=active"

# 2. 追蹤路由
traceroute <target-private-ip>

# 3. 檢查 VPC Flow Logs(如果已啟用)
aws logs filter-log-events \
  --log-group-name vpc-flow-logs \
  --filter-pattern "REJECT"

監控與日誌

建議啟用 VPC Flow Logs 來監控和偵錯網路流量:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 建立 CloudWatch Log Group
resource "aws_cloudwatch_log_group" "vpc_flow_logs" {
  name              = "/aws/vpc/flow-logs"
  retention_in_days = 30
}

# 建立 IAM Role
resource "aws_iam_role" "vpc_flow_logs_role" {
  name = "vpc-flow-logs-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "vpc-flow-logs.amazonaws.com"
      }
    }]
  })
}

# 啟用 VPC Flow Logs
resource "aws_flow_log" "vpc_flow_log" {
  iam_role_arn    = aws_iam_role.vpc_flow_logs_role.arn
  log_destination = aws_cloudwatch_log_group.vpc_flow_logs.arn
  traffic_type    = "ALL"
  vpc_id          = aws_vpc.vpc-1.id
}

後記:小提醒

  • 記得手動去申請 Key Pairs,這裡我使用的是名稱為 demo-key-us-west-2Key Pairs

其他注意事項

  1. CIDR 規劃:在建立 VPC 之前,務必先規劃好 CIDR 區塊,避免日後需要 Peering 時發生重疊問題

  2. 成本管理:VPC Peering 本身不收費,但跨區域的資料傳輸會產生費用

  3. 限制

    • 每個 VPC 最多可以有 125 個 active 的 Peering 連線
    • VPC Peering 不支援傳遞路由(Transitive Routing)
    • 無法透過 VPC-A 存取 VPC-B Peering 到的 VPC-C
  4. 安全性

    • 使用安全群組限制只允許必要的流量
    • 定期審查 Peering 連線和路由規則
    • 考慮使用 VPC Flow Logs 進行監控
  5. 命名規範:建議使用有意義的標籤和名稱,便於管理和識別

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy