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

Terraformで外部IPなしのCompute Engine Spot VMを作成してみた

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

概要
#

検証用のVMを1台立てるだけのつもりでも、VPC、Subnet、Firewall、SSHの経路まで揃える必要があります。コンソールで作ると既定のVPCに外部IP付きのVMができてしまい、あとから閉じるのに手間がかかります。

Terraformなら、この一式をまとめて作り、まとめて消せます。ここでは外部IPを持たないSpot VMを、専用VPCとIAP経由のSSH経路ごと作成します。

Terraformの基本操作は前提としています。Google Cloudのネットワークまわりに不慣れな方向けです。

短時間の学習・検証向けに、コストを抑えた構成にしています。Spot VMはいつでも回収されうるため本番用途には使えず、SLAの対象外です。

Managed Instance Groupによる冗長化やAuto Healingも扱いません。

検証すること
#

  • Debian 12の最新ImageをData Sourceで取得する
  • Spot VMを作成する
  • 外部IPを付けず、IAP経由のSSH経路だけを用意する
  • OS Loginを有効化する
  • VMとネットワークをまとめてdestroyする

今回の構成
#

まず、何がどこに置かれるかです。VMはProject内の専用VPCにあり、外部IPを持ちません。IAPはVPCの外側にある、Google管理のサービスです。

flowchart TB
    User["手元の端末"]

    subgraph GCP["Google Cloud"]
        IAP["Identity-Aware Proxy
VPC外・Google管理"] subgraph Project["Project"] subgraph Region["asia-northeast1"] subgraph VPC["VPC"] FW["Firewall: allow-iap-ssh
src 35.235.240.0/20 / TCP:22"] subgraph Subnet["Subnet 10.20.0.0/24"] VM["Spot VM: tf-example-gce-01
zone asia-northeast1-a
10.20.0.2(外部IPなし)"] end end end end end User -->|"SSH over HTTPS"| IAP IAP -->|"TCP:22"| FW FW --> VM

外部IPがないため、インターネットからVMへ直接届く経路はありません。到達できるのはIAPを通る経路だけです。

その手順を時系列で見ると、次のようになります。

sequenceDiagram
    actor User as 手元の端末
    participant IAP as Identity-Aware Proxy
    participant FW as Firewall
    participant VM as Spot VM (外部IPなし)

    User->>IAP: gcloud compute ssh --tunnel-through-iap
    Note over User,IAP: IAMで接続可否を判定
    IAP->>FW: TCP:22 (送信元 35.235.240.0/20)
    FW->>VM: 許可して転送
    VM-->>User: SSHセッション確立

前提環境
#

  • ADCで認証済み
  • 課金が有効な検証用Project
  • Compute Admin相当の権限
  • IAP SSHを試す場合はIAP-secured Tunnel Userなどの権限
  • 検証時のバージョン:Terraform 1.14.3、google 7.43.0

使用するTerraformコード
#

ファイル構成
#

04-compute-engine/
├── network.tf   # VPC / Subnet / Firewall
├── main.tf      # API / Image / VM
├── variables.tf
├── outputs.tf
└── terraform.tfvars.example

今回重要なTerraformコード
#

Debian 12ファミリーの最新Imageを参照します。

data "google_compute_image" "debian" {
  family  = "debian-12"
  project = "debian-cloud"
}

VMは外部IPなしでSubnetへ接続します。access_configブロックを置かないことがポイントです。

resource "google_compute_instance" "vm" {
  name         = var.instance_name
  machine_type = var.machine_type
  zone         = var.zone
  tags         = ["iap-ssh"]

  boot_disk {
    initialize_params {
      image = data.google_compute_image.debian.self_link
      size  = 20
      type  = "pd-balanced"
    }
  }

  network_interface {
    subnetwork = google_compute_subnetwork.primary.id
  }

  scheduling {
    provisioning_model = "SPOT"
    preemptible        = true
    automatic_restart  = false
  }

  metadata = {
    enable-oslogin = "TRUE"
  }
}

Spot VMは回収後の自動再起動を前提にしないため、automatic_restart = falseとします。永続的な処理や重要データの保存先には向きません。

IAPからのSSHだけをVMのNetwork Tagへ許可します。

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"]
  target_tags   = ["iap-ssh"]
}

設定と実行
#

cd Basic-Examples/04-compute-engine
cp terraform.tfvars.example terraform.tfvars
project_id = "your-project-id"
region     = "asia-northeast1"
zone       = "asia-northeast1-a"
terraform init
terraform fmt -check
terraform validate
terraform plan
terraform apply

VPC、Subnet、Firewall、VMの5つが作成されます。

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

Outputs:

instance_name = "tf-example-gce-01"
internal_ip = "10.20.0.2"
network_name = "tf-example-gce-vpc"
ssh_via_iap_example = "gcloud compute ssh tf-example-gce-01 --zone=asia-northeast1-a --tunnel-through-iap --project=YOUR_PROJECT_ID"
zone = "asia-northeast1-a"

GCP側で確認する
#

gcloud compute instances describe \
  "$(terraform output -raw instance_name)" \
  --zone="$(terraform output -raw zone)" \
  --project=YOUR_PROJECT_ID
machineType: e2-medium
name: tf-example-gce-01
networkInterfaces:
- networkIP: 10.20.0.2
scheduling:
  automaticRestart: false
  instanceTerminationAction: STOP
  onHostMaintenance: TERMINATE
  preemptible: true
  provisioningModel: SPOT
status: RUNNING

provisioningModelがSPOTになっています。networkInterfacesにはnetworkIPだけがあり、accessConfigs(外部IP)は出力されません。一覧でも外部IPの列は空になります。

gcloud compute instances list --project=YOUR_PROJECT_ID
NAME               ZONE               MACHINE_TYPE  PROVISIONING_MODEL  STATUS   NETWORK_IP  EXTERNAL_IP
tf-example-gce-01  asia-northeast1-a  e2-medium     SPOT                RUNNING  10.20.0.2

IAP SSHを試す場合:

gcloud compute ssh "$(terraform output -raw instance_name)" \
  --zone="$(terraform output -raw zone)" \
  --tunnel-through-iap \
  --project=YOUR_PROJECT_ID

外部IPがなくても接続できます。

Warning: Permanently added 'compute.INSTANCE_ID' (ED25519) to the list of known hosts.
tf-example-gce-01
6.1.0-52-cloud-amd64
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"

外部IPやCloud NATがないため、VMから一般のインターネットへの通信は制限されます。

後片付けと注意点
#

terraform destroy

VMとPersistent Diskは利用中に料金が発生します。検証後は必ずdestroyします。Spot VMは安価ですが可用性保証がなく、本番の常時稼働用途には適しません。

まとめ
#

  • Image Familyから最新Debian Imageを参照できる
  • Spot VMで短時間検証向けの構成を作成できる
  • 外部IPなしでIAP SSH経路を用意できる
  • OS LoginでSSH鍵管理をGoogle Cloud側へ寄せられる

参考資料
#

次回
#

次はService Accountを作成し、Project IAM Roleを最小権限で付与します。

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

関連記事

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