↓メインコンテンツへスキップ
  1. Blogs/

TerraformでGoogle CloudのVPCとSubnetとFirewallを作成してみた

3 分
Terraform GoogleCloud
0222-nnn
著者
0222-nnn
猫が好き
目次
Terraform-GoogleCloud - この記事は連載の一部です
パート 3: この記事

概要
#

Google CloudでVMやGKEなどを利用するには、まずVPCネットワークが必要です。自動モードVPCで済ませると、意図しないRegionにSubnetができていても把握できません。Firewallの範囲が広すぎることにも気づきにくくなります。

Terraformなら、Subnet範囲やFirewallの許可範囲をコードとして明示できます。ここでは自動Subnetを持たないカスタムモードVPCと、東京RegionのSubnetを作成します。内部通信用とIAP SSH用のFirewall Ruleも用意します。

Terraformの基本操作は前提としています。VPCの基本用語(Subnet、Firewall)に触れたことがある方向けです。

VMやCloud NAT、外部IPは作成しません。基本的なネットワークリソースだけを扱います。

VMやCloud NAT、外部IPは作成せず、基本的なネットワークリソースだけを検証します。

検証すること
#

  • カスタムモードVPCを作成できること
  • Regionを指定したSubnetを作成できること
  • VPC内部通信用のFirewall Ruleを作成できること
  • IAP経由のSSHだけを許可するFirewall Ruleを作成できること
  • 作成したネットワークをgcloudで確認できること

今回の構成
#

カスタムモードのVPCを作り、その中にSubnetを1つ置きます。Firewallはネットワーク単位の設定なのでVPC直下です。

flowchart TB
    subgraph GCP["Google Cloud"]
        IAP["Identity-Aware Proxy
(VPC外・Google管理)"] subgraph Project["Project"] subgraph Region["asia-northeast1"] subgraph VPC["VPC(カスタムモード)"] FWIAP["Firewall: allow-iap-ssh
src 35.235.240.0/20 / TCP:22"] FWInt["Firewall: allow-internal
src 10.10.0.0/24 / tcp,udp,icmp"] subgraph Subnet["Subnet 10.10.0.0/24"] VM["VM など
(本記事では作らない)"] end end end end end IAP -->|"TCP:22"| FWIAP FWIAP --> VM VM <-->|"内部通信"| FWInt

自動モードのVPCだと全Regionにサブネットが作られます。カスタムモードでは、必要なRegionだけを自分で決めます。

VPCはGlobalリソース、SubnetはRegionリソースです。Firewall RuleはVPCへ関連付けます。

前提環境
#

  • Google Cloud CLI
  • Terraform 1.10.0以上、2.0.0未満
  • ADCで認証済み
  • 検証用Google Cloud Project
  • Compute Network Admin相当の権限
  • Service Usageを操作できる権限
  • 検証時のバージョン:Terraform 1.14.3、google 7.43.0

Compute Engine APIはTerraformコード内で有効化します。

使用するTerraformコード
#

前回はAPIの有効化を確認しました。

ファイル構成
#

02-network/
├── README.md
├── versions.tf
├── provider.tf
├── variables.tf
├── network.tf
├── outputs.tf
└── terraform.tfvars.example

ネットワーク自体が今回の検証対象なので、リソースはmain.tfではなくnetwork.tfへまとめています。

今回重要なTerraformコード
#

Compute Engine API
#

VPCなどを操作するため、Compute Engine APIを有効化します。

resource "google_project_service" "compute" {
  project = var.project_id
  service = "compute.googleapis.com"

  disable_on_destroy = false
}

destroy後も他のシステムへ影響させないよう、APIは有効なまま残します。

カスタムモードVPC
#

resource "google_compute_network" "vpc" {
  name                    = var.network_name
  auto_create_subnetworks = false
  routing_mode            = "REGIONAL"

  depends_on = [google_project_service.compute]
}

auto_create_subnetworks = falseにすることで、自動モードではなくカスタムモードVPCを作成します。必要なSubnetだけを明示的に管理できる構成です。

depends_onにより、Compute Engine APIの有効化後にVPCを作成します。

Subnet
#

resource "google_compute_subnetwork" "primary" {
  name                     = var.subnet_name
  ip_cidr_range            = var.subnet_cidr
  region                   = var.region
  network                  = google_compute_network.vpc.id
  private_ip_google_access = true
}

デフォルトではasia-northeast1に10.10.0.0/24のSubnetを作成します。

private_ip_google_access = trueにより、外部IPを持たないVMからGoogle APIやサービスへ到達できるようにします。ただし、一般のインターネット宛て通信を提供する設定ではありません。

VPC内部通信用Firewall Rule
#

resource "google_compute_firewall" "allow_internal" {
  name    = "${var.network_name}-allow-internal"
  network = google_compute_network.vpc.name

  allow {
    protocol = "tcp"
  }

  allow {
    protocol = "udp"
  }

  allow {
    protocol = "icmp"
  }

  source_ranges = [var.subnet_cidr]
  priority      = 1000
}

送信元をSubnetのCIDRに限定し、TCP、UDP、ICMPを許可します。0.0.0.0/0からの内部通信許可にはしていません。

IAP SSH用Firewall Rule
#

resource "google_compute_firewall" "allow_iap_ssh" {
  name    = "${var.network_name}-allow-iap-ssh"
  network = google_compute_network.vpc.name

  allow {
    protocol = "tcp"
    ports    = ["22"]
  }

  source_ranges = ["35.235.240.0/20"]
  priority      = 1000
}

SSHをインターネット全体へ公開せず、IAP TCP forwardingで使用される送信元範囲からのTCP 22番だけを許可します。

Firewall RuleだけでIAP SSHの認可が完了するわけではありません。実際に接続するユーザーにはIAPやVMログインに必要なIAM権限も必要です。

入力値を設定する
#

cd Basic-Examples/02-network
cp terraform.tfvars.example terraform.tfvars
project_id = "your-project-id"
region     = "asia-northeast1"

デフォルト値を変更する場合は、次の値も設定できます。

network_name = "tf-example-vpc"
subnet_name  = "tf-example-subnet"
subnet_cidr  = "10.10.0.0/24"

既存ネットワークとCIDRが重複しないように確認します。

Terraformを実行する
#

terraform init
terraform fmt -check
terraform validate
terraform plan
terraform apply

デフォルト構成では、API設定、VPC、Subnet、2つのFirewall RuleがPlanへ表示されます。

applyが完了すると、5つのResourceが作成されOutputが表示されます。

google_compute_firewall.allow_iap_ssh: Creation complete after 11s [id=projects/YOUR_PROJECT_ID/global/firewalls/tf-example-vpc-allow-iap-ssh]
google_compute_subnetwork.primary: Creation complete after 25s [id=projects/YOUR_PROJECT_ID/regions/asia-northeast1/subnetworks/tf-example-subnet]

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

Outputs:

firewall_names = [
  "tf-example-vpc-allow-internal",
  "tf-example-vpc-allow-iap-ssh",
]
network_id = "projects/YOUR_PROJECT_ID/global/networks/tf-example-vpc"
network_name = "tf-example-vpc"
subnet_cidr = "10.10.0.0/24"
subnet_name = "tf-example-subnet"

GCP側で確認する
#

VPCを確認します。

gcloud compute networks describe \
  "$(terraform output -raw network_name)" \
  --project=YOUR_PROJECT_ID
autoCreateSubnetworks: false
name: tf-example-vpc
routingConfig:
  bgpBestPathSelectionMode: LEGACY
  routingMode: REGIONAL

autoCreateSubnetworks: falseがカスタムモードであることを示します。自動モードだと全Regionにサブネットが作られるため、意図した範囲だけを持つ構成になっているかがここで分かります。

Subnetを確認します。

gcloud compute networks subnets list \
  --network="$(terraform output -raw network_name)" \
  --project=YOUR_PROJECT_ID
NAME               REGION           NETWORK         RANGE         STACK_TYPE
tf-example-subnet  asia-northeast1  tf-example-vpc  10.10.0.0/24  IPV4_ONLY

Firewall Ruleを確認します。

gcloud compute firewall-rules list \
  --filter="network~$(terraform output -raw network_name)" \
  --project=YOUR_PROJECT_ID
NAME                           NETWORK         DIRECTION  PRIORITY  ALLOW
tf-example-vpc-allow-iap-ssh   tf-example-vpc  INGRESS    1000      tcp:22
tf-example-vpc-allow-internal  tf-example-vpc  INGRESS    1000      icmp,udp,tcp

送信元範囲はdescribeで確認できます。

gcloud compute firewall-rules describe tf-example-vpc-allow-iap-ssh \
  --project=YOUR_PROJECT_ID \
  --format="yaml(name,sourceRanges,allowed)"
allowed:
- IPProtocol: tcp
  ports:
  - '22'
name: tf-example-vpc-allow-iap-ssh
sourceRanges:
- 35.235.240.0/20

35.235.240.0/20はIAPのForwarding元レンジです。この範囲だけを許可しているため、外部IPを持たないVMにもIAP経由でSSHできます。

エラー・注意点
#

CIDRが重複している
#

同じVPC内で既存SubnetとCIDRが重複するとSubnetを作成できません。subnet_cidrを重複しない範囲へ変更します。

Firewall Ruleは通信を発生させない
#

Firewall Ruleは許可条件を定義するだけです。このサンプルではVMを作成しないため、実際のSSHや内部通信は次回以降のサンプルで確認します。

料金
#

VPC、Subnet、Firewall Rule自体には通常追加料金は発生しません。このサンプルではCloud NAT、外部IP、VMなどの課金対象リソースを作成しません。

後片付け
#

terraform destroy

Firewall Rule、Subnet、VPCの依存関係をTerraformが判断し、作成時と逆の順序で削除します。Compute Engine APIはdisable_on_destroy = falseのため有効なまま残ります。

まとめ
#

  • 自動Subnetを作らないカスタムモードVPCを作成できる
  • RegionとCIDRを指定してSubnetを作成できる
  • 内部通信の送信元をSubnet CIDRへ限定できる
  • SSHの送信元をIAP用範囲へ限定できる
  • Terraformの参照からリソース間の依存関係を構成できる

参考資料
#

次回
#

次は、TerraformでCloud Storage Bucketを作成し、Uniform bucket-level accessやPublic access preventionを確認します。

Terraform-GoogleCloud - この記事は連載の一部です
パート 3: この記事

関連記事

Terraform StateをCloud Storage Remote Backendへ移行してみた
2 分
Terraform GoogleCloud CloudStorage
TerraformからGoogle Cloudへ接続してProject情報を取得してみた
3 分
Terraform GoogleCloud
TerraformでArtifact RegistryのDocker Repositoryを作成してみた
2 分
Terraform GoogleCloud Docker
TerraformでArtifact RegistryのコンテナをCloud Runへデプロイしてみた
2 分
Terraform GoogleCloud CloudRun ArtifactRegistry
TerraformでBigQuery DatasetとTableを作成してみた
2 分
Terraform GoogleCloud
TerraformでCloud KMSのKeyRingとCryptoKeyを作成してみた
2 分
Terraform GoogleCloud