Terraform/Opentofu VM Provisioning in Google Cloud Platform
A not-so-comprehensive guide to provisioning a VM in Google Cloud Platform—because my bank account has… boundaries.
Cloud can get expensive real fast. If you’re using your company’s account, go wild. Live your best cloud life. Spin up instances like there’s no tomorrow.
But if you’re like me—personally funding this adventure—then welcome. We’ll be keeping things practical, efficient, and, most importantly, affordable.
For now, I’ll cover the basics and the stuff that actually matters. I’ll update this guide if I ever stumble upon a pot of gold.
Table of Contents
Free Tier Account
If your just testing GCP, then I advice you use the free tier account.
Check this link.
Service Account
Create service account that have permission to create vm compute engine.
Account
If you already have account in GCP, then you already have a default project. Create new or keep using the default-make sure to use the project-id (e.g. myproject-123456).
1gcloud iam service-accounts create <your-tf-tofu-service-account> \
2 --display-name=<service account description> \
3 --project=<project-id>
The full service account email will look like:
1my-service-account@my-sample-project-123.iam.gserviceaccount.com
Role/Permission
If you don’t care about security, RBAC and don’t want to worry about permission error that may arise.
1gcloud projects add-iam-policy-binding <project-id> \
2 --member=serviceAccount:tofu-sa@coltrane-492510.iam.gserviceaccount.com \
3 --role=roles/roles/compute.admin
This is overkill for most real-world use cases.
Instead of roles/compute.admin, use more specific roles:
1#!/bin/bash
2
3PROJECT_ID="my-sample-project-123"
4SA="my-service-account@$PROJECT_ID.iam.gserviceaccount.com"
5
6for ROLE in \
7 roles/compute.instanceAdmin.v1 \
8 roles/compute.networkAdmin \
9 roles/iam.serviceAccountUser
10do
11 gcloud projects add-iam-policy-binding $PROJECT_ID \
12 --member="serviceAccount:$SA" \
13 --role="$ROLE"
14done
Export Service Account
1gcloud iam service-accounts keys create ./service-account.json \
2 --iam-account=<full_service_account_email> \
3 --project=<project-id>
Service
Enable GCP service, this is usually disabled by default.
1gcloud services enable cloudresourcemanager.googleapis.com --project=<project-id>
2gcloud services enable compute.googleapis.com --project=<project-id>
3gcloud services enable networkmanagement.googleapis.com --project=<project-id>
4gcloud services enable iap.googleapis.com --project=<project-id>
5gcloud services enable monitoring.googleapis.com --project=<project-id>
Basic VM
This will create VM:
- create
e2-micro - internal IP/subnet
- ssh through
IAPtunnel only - no extra disk
- no scaling
provider.tf
1terraform {
2 required_providers {
3 google = {
4 source = "hashicorp/google"
5 version = "7.26.0"
6 }
7 }
8}
9
10provider "google" {
11 credentials = file("${path.module}/service-account.json")
12 project = var.project_id
13 region = var.region
14}
variables.tf
1variable "project_id" {
2 type = string
3}
4variable "region" {
5 type = string
6 description = "Region"
7}
8variable "zone" {
9 type = string
10 description = "Zone"
11}
12variable "compute_instance_name" {
13 type = string
14 description = "Compute Instance Name"
15}
16variable "machine_type" {
17 type = string
18 description = "Machine Type"
19}
20variable "hostname" {
21 type = string
22 description = "VM Hostname"
23}
24variable "image_type" {
25 type = string
26 description = "Image Type"
27}
28variable "network_name" {
29 type = string
30 description = "Network Name"
31}
terraform.tfvars
1project_id = "yourproject-123456"
2
3region = "us-west1"
4zone = "us-west1-c"
5
6compute_instance_name = "vm-name"
7machine_type = "e2-micro"
8image_type = "debian-cloud/debian-13"
9network_name = "vm-network"
10
11hostname = "vm-hostname"
main.tf
1resource "google_compute_network" "vm_network" {
2 name = var.network_name
3 auto_create_subnetworks = false
4}
5
6resource "google_compute_subnetwork" "vm_sub_network" {
7 name = "my-subnet"
8 ip_cidr_range = "10.0.1.0/24"
9 region = var.region
10 network = google_compute_network.vm_network.id
11}
12
13
14resource "google_compute_instance" "vm_instance" {
15 name = var.compute_instance_name
16 tags = ["vm-test", "os-login"]
17 zone = var.zone
18 machine_type = var.machine_type
19 network_interface {
20 network = google_compute_network.vm_network.id
21 subnetwork = google_compute_subnetwork.vm_sub_network.id
22 }
23 boot_disk {
24 initialize_params {
25 image = var.image_type
26 }
27 }
28 hostname = var.hostname # if not set, default to vm google_compute_instance.name
29}
Provision using tf or tofu.
1tofu plan
2tofu apply
List VM instances.
1gcloud compute instances list
2NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
3miles-vm us-west1-c e2-micro 10.0.1.2 RUNNING
Network
Before we can SSH to the server we must first define the network.
Firewall
Allow SSH.
- “35.235.240.0/20” - IAP Subnet
- “0.0.0.0/0” - allow public access
1resource "google_compute_firewall" "allow_ssh" {
2 name = "allow-ssh-iap"
3 network = google_compute_network.vm_network.id
4
5 source_ranges = ["35.235.240.0/20", "0.0.0.0/0"]
6
7 allow {
8 protocol = "tcp"
9 ports = ["22"]
10 }
11
12 target_tags = ["vm-test"]
13}
Make sure that target_tags is the same tag set in vm_tags.
Public IP
Skip this if you don’t want to expose the VM in public domain. You can only login using IAP tunnel.
1resource "google_compute_address" "vm_address" {
2 name = "external-test-ip"
3 region = var.region
4}
5
6resource "google_compute_instance" "vm_instance" {
7 name = var.compute_instance_name
8 tags = ["vm-test", "os-login"]
9 zone = var.zone
10 machine_type = var.machine_type
11 network_interface {
12 network = google_compute_network.vm_network.id
13 subnetwork = google_compute_subnetwork.vm_sub_network.id
14
15 # acquire public/external ip
16 access_config {
17 nat_ip = google_compute_address.vm_address.address
18 }
19 }
20}
Login Method
IAM-Based
First enable osloginapi.
1# compute engine api
2resource "google_project_service" "project" {
3 service = "oslogin.googleapis.com"
4 disable_on_destroy = false
5}
6
7data "google_project" "project" {
8}
9resource "google_project_iam_member" "os_login_admin_users" {
10 project = data.google_project.project.project_id
11 role = "roles/compute.osAdminLogin"
12 member = "serviceAccount:service-${data.google_project.project.number}@compute-system.iam.gserviceaccount.com"
13}
If you want to enable IAM-Based login to all the VM then define the metadata resources outside the compute engine bracket/resources.
1resource "google_compute_project_metadata" "default" {
2 metadata = {
3 enable-oslogin = "TRUE"
4 }
5}
If not and explicit to specific VM.
1resource "google_compute_instance" "vm_instance" {
2 name = var.compute_instance_name
3 tags = ["vm-test", "os-login"]
4 zone = var.zone
5 machine_type = var.machine_type
6 network_interface {
7 network = google_compute_network.vm_network.id
8 subnetwork = google_compute_subnetwork.vm_sub_network.id
9 }
10 boot_disk {
11 initialize_params {
12 image = var.image_type
13 }
14 }
15 metadata = {
16 enable-oslogin : "TRUE"
17 }
18}
To login to the vm/server.
1gcloud compute ssh --zone "zone" "vm-name" --tunnel-through-iap --project "project-id"
SSH-Based
This is the traditional method-you would need to assign public IP to the VM.
Using file (public-key), this will apply to all the VM created.
1resource "google_os_login_ssh_public_key" "default" {
2 user = data.google_client_openid_userinfo.me.email
3 key = file("id_rsa.pub")
4}
Using manifest, this will apply to all VM created.
1resource "google_compute_project_metadata" "default" {
2 metadata = {
3 ssh-keys = <<EOF
4 dev:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILg6UtHDNyMNAh0GjaytsJdrUxjtLy3APXqZfNZhvCeT dev
5 test:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILg6UtHDNyMNAh0GjaytsJdrUxjtLy3APXqZfNZhvCeT test
6 EOF
7 }
8}
Or apply metadata inside compute engine resources, this will apply only to this VM.
1resource "google_compute_instance" "vm_instance" {
2 name = var.compute_instance_name
3 tags = ["vm-test", "os-login"]
4 zone = var.zone
5 machine_type = var.machine_type
6 network_interface {
7 network = google_compute_network.vm_network.id
8 subnetwork = google_compute_subnetwork.vm_sub_network.id
9
10 # acquire public/external ip
11 access_config {
12 nat_ip = google_compute_address.vm_address.address
13 }
14 }
15 boot_disk {
16 initialize_params {
17 image = var.image_type
18 }
19 }
20 metadata = {
21 "ssh-keys" = var.ssh_keys
22 }
23}
List VM instances.
1gcloud compute instances list
2NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
3miles-vm us-west1-c e2-micro 10.0.1.2 136.109.82.172 RUNNING
Login to the VM through External IP.
1ssh <user>@<external_ip>
Extra Disk
Persistent Storage
By default the Disk limit is 10gb, if you are using free tier set limit to 30gb and disk type to pd-standard.
1resource "google_compute_instance" "vm_instance" {
2 name = var.compute_instance_name
3 tags = ["vm-test", "os-login"]
4 zone = var.zone
5 machine_type = var.machine_type
6 network_interface {
7 network = google_compute_network.vm_network.id
8 subnetwork = google_compute_subnetwork.vm_sub_network.id
9 }
10 boot_disk {
11 initialize_params {
12 image = var.image_type
13 size = 30
14 type = "pd-standard"
15 }
16 }
17 metadata = {
18 "ssh-keys" = var.ssh_keys
19 }
20}
| Disk Type | Free Tier | Speed |
|---|---|---|
| pd-standard | free | slow |
| pd-balanced | paid | medium |
| pd-ssd | paid | fast |
List disk.
1mcbtaguiad@miles:~$ sudo fdisk -l
2Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
3Disk model: PersistentDisk
4Units: sectors of 1 * 512 = 512 bytes
5Sector size (logical/physical): 512 bytes / 4096 bytes
6I/O size (minimum/optimal): 4096 bytes / 4096 bytes
7Disklabel type: gpt
8Disk identifier: A2056751-613C-B043-B7CA-DDB01D9057BD
9
10Device Start End Sectors Size Type
11/dev/sda1 262144 62912512 62650369 29.9G Linux root (x86-64)
12/dev/sda14 2048 8191 6144 3M BIOS boot
13/dev/sda15 8192 262143 253952 124M EFI System
14
15Partition table entries are not in disk order.
To add extra persistent disk.
1resource "google_compute_disk" "extra_disk" {
2 name = "extra-disk"
3 type = "pd-standard"
4 zone = var.zone
5 size = "15"
6}
7resource "google_compute_instance" "vm_instance" {
8 name = var.compute_instance_name
9 tags = ["vm-test"]
10 zone = var.zone
11 machine_type = var.machine_type
12 network_interface {
13 network = google_compute_network.vm_network.id
14 subnetwork = google_compute_subnetwork.vm_sub_network.id
15
16 # acquire public/external ip
17 access_config {
18 nat_ip = google_compute_address.vm_address.address
19 }
20 }
21 boot_disk {
22 initialize_params {
23 image = var.image_type
24 size = var.disk_size
25 type = var.disk_type
26 }
27 }
28 attached_disk {
29 source = google_compute_disk.extra_disk.id
30 device_name = google_compute_disk.extra_disk.name
31 }
32 metadata = {
33 "ssh-keys" = var.ssh_keys
34 }
35 hostname = var.hostname # if not set, default to vm google_compute_instance.name
36}
List disk.
1mcbtaguiad@miles:~$ sudo fdisk -l
2Disk /dev/sda: 15 GiB, 16106127360 bytes, 31457280 sectors
3Disk model: PersistentDisk
4Units: sectors of 1 * 512 = 512 bytes
5Sector size (logical/physical): 512 bytes / 4096 bytes
6I/O size (minimum/optimal): 4096 bytes / 4096 bytes
7Disklabel type: gpt
8Disk identifier: A2056751-613C-B043-B7CA-DDB01D9057BD
9
10Device Start End Sectors Size Type
11/dev/sda1 262144 31455232 31193089 14.9G Linux root (x86-64)
12/dev/sda14 2048 8191 6144 3M BIOS boot
13/dev/sda15 8192 262143 253952 124M EFI System
14
15Partition table entries are not in disk order.
16
17
18Disk /dev/sdb: 15 GiB, 16106127360 bytes, 31457280 sectors
19Disk model: PersistentDisk
20Units: sectors of 1 * 512 = 512 bytes
21Sector size (logical/physical): 512 bytes / 4096 bytes
22I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Ephemeral Storage
Use for cache or temp data, this uses NVME or SCSI (and money hahaha).
1resource "google_compute_instance" "default" {
2 name = "my-vm-instance-with-scratch"
3 machine_type = "n2-standard-8"
4 zone = "us-central1-a"
5
6 boot_disk {
7 initialize_params {
8 image = "debian-cloud/debian-13"
9 }
10 }
11
12 # Local SSD interface type; NVME for image with optimized NVMe drivers or SCSI
13 # Local SSD are 375 GiB in size
14 scratch_disk {
15 interface = "SCSI"
16 }
17
18 network_interface {
19 network = "default"
20 access_config {}
21 }
22}
Snapshots
Manual
List the disk created.
1gcloud compute disks list
2NAME LOCATION LOCATION_SCOPE SIZE_GB TYPE STATUS
3extra-disk us-west1-c zone 15 pd-standard READY
4miles-vm us-west1-c zone 10 pd-standard READY
Manual run snapshot.
1gcloud compute disks snapshot miles-vm \
2 --snapshot-names=snapshot-$(date +%Y%m%d-%H%M%S) \
3 --zone=us-west1-c
4
5Creating snapshot(s) snapshot-20260408-140531...done.
List snapshots.
1gcloud compute snapshots list
2NAME DISK_SIZE_GB SRC_DISK STATUS
3snapshot-20260408-140531 15 us-west1-c/disks/miles-vm READY
To delete.
1gcloud compute snapshots delete SNAPSHOT_NAME
Automatic/Scheduled
Create google_compute_disk for boot.
1resource "google_compute_disk" "boot_disk" {
2 name = "boot-disk"
3 type = "pd-standard"
4 zone = var.zone
5 size = var.disk_size
6 image = var.image_type
7}
Create google_compute_snapshot. Note that you would also need to create for other disk present.
1resource "google_compute_snapshot" "boot_disk_snapshot" {
2 name = "vm-snapshot-extra-disk"
3 source_disk = google_compute_disk.boot_disk.name
4 zone = var.zone
5
6 depends_on = [google_compute_disk.boot_disk]
7}
Create snapshot_policy.
1resource "google_compute_resource_policy" "snapshot_policy" {
2 name = "daily-snapshot-policy"
3 region = var.region
4
5 snapshot_schedule_policy {
6 schedule {
7 daily_schedule {
8 days_in_cycle = 1
9 start_time = "04:00"
10 }
11 }
12
13 retention_policy {
14 max_retention_days = 3
15 on_source_disk_delete = "KEEP_AUTO_SNAPSHOTS"
16 }
17 }
18}
If you are not broke, also add regional clone.
1resource "google_compute_region_disk" "regiondisk" {
2 name = "region-disk-name"
3 snapshot = google_compute_snapshot.boot_disk_snapshot.id
4 type = "pd-ssd"
5 region = "us-central1"
6 physical_block_size_bytes = 4096
7 size = 11
8
9 replica_zones = ["us-central1-a", "us-central1-f"]
10}
Asynchronous Disk Replication
This replicate boot_disk to a regional/secondary disk replication_disk.
Create google_compute_disk.
1resource "google_compute_disk" "boot_disk" {
2 name = "boot-disk"
3 type = "pd-standard"
4 zone = var.zone
5 size = var.disk_size
6 image = var.image_type
7}
8
9resource "google_compute_disk" "replication_disk" {
10 name = "replication-disk"
11 type = "pd-ssd"
12 zone = "europe-west3-a"
13
14 async_primary_disk {
15 disk = google_compute_disk.boot_disk.id
16 }
17
18 physical_block_size_bytes = 4096
19}
Create google_compute_disk_async_replication.
1resource "google_compute_disk_async_replication" "repli_disk" {
2 primary_disk = google_compute_disk.boot_disk.id
3 secondary_disk {
4 disk = google_compute_disk.replication_disk.id
5 }
6}
Autoscaler
This defines the blueprint for the instances that will be part of the managed instance group.
1resource "google_compute_instance_template" "default" {
2 name = "my-instance-template"
3 machine_type = "e2-medium"
4 can_ip_forward = false
5
6 tags = ["vm-test"]
7
8 disk {
9 source_image = data.google_compute_image.debian_13.id
10 }
11
12 network_interface {
13 network = "default"
14 }
15
16 metadata = {
17 name = "value"
18 }
19
20 service_account {
21 scopes = ["userinfo-email", "compute-ro", "storage-ro"]
22 }
23}
Fetches the latest Debian 11 image from debian-cloud.
1data "google_compute_image" "debian_11" {
2 family = "debian-11"
3 project = "debian-cloud"
4}
Creates a Managed Instance Group (MIG) in a specific zone.
- handle creating, deleting, and updating instances automatically based on the template.
1resource "google_compute_instance_group_manager" "default" {
2 name = "my-igm"
3 zone = "us-central1-f"
4
5 version {
6 instance_template = google_compute_instance_template.default.id
7 name = "primary"
8 }
9
10 base_instance_name = "autoscaler-sample"
11}
Automatically scales the MIG based on CPU usage, load, or schedule.
- minimum 1 vm
- maximum 5 vm
- automatically ensures 2 instances every weekday starting 7AM New York time for 12 hours (43,200 seconds).
- outside this period, it can scale down to the min (1 instance).
1resource "google_compute_autoscaler" "default" {
2 provider = google-beta
3 name = "my-autoscaler"
4 zone = "us-central1-f"
5 target = google_compute_instance_group_manager.default.id
6
7 autoscaling_policy {
8 max_replicas = 5
9 min_replicas = 1
10 cooldown_period = 60
11
12 scaling_schedules {
13 name = "every-weekday-morning"
14 description = "Increase to 2 every weekday at 7AM for 12 hours."
15 min_required_replicas = 2
16 schedule = "0 7 * * MON-FRI"
17 time_zone = "America/New_York"
18 duration_sec = 43200
19 }
20 }
21}
Full Example
- SSH and IAM based login
- with external/public IP
- firewall rule
- extra disk attached
- boot disk - async replication
- boot disk - automatic snapshot
variables.tf
1variable "project_id" {
2 type = string
3}
4
5variable "region" {
6 type = string
7 description = "Region"
8}
9
10variable "zone" {
11 type = string
12 description = "Zone"
13}
14
15variable "compute_instance_name" {
16 type = string
17 description = "Compute Instance Name"
18}
19
20variable "machine_type" {
21 type = string
22 description = "Machine Type"
23}
24
25variable "hostname" {
26 type = string
27 description = "VM Hostname"
28}
29
30variable "image_type" {
31 type = string
32 description = "Image Type"
33}
34
35variable "network_name" {
36 type = string
37 description = "Network Name"
38}
39
40variable "subnetwork_name" {
41 type = string
42 description = "Sub Network Name"
43}
44
45variable "address_name" {
46 type = string
47 description = "Address Name"
48}
49
50variable "service_account" {
51 type = string
52 description = "Service Account"
53}
54
55variable "user_email" {
56 type = string
57 description = "User Email"
58}
59
60variable "ssh_keys" {
61 description = "SSH Keys"
62 type = string
63}
64
65variable "boot_disk_name" {
66 type = string
67 description = "Boot Disk Name"
68}
69
70variable "boot_disk_size" {
71 type = string
72 description = "Boot Disk Size"
73}
74
75variable "boot_disk_type" {
76 type = string
77 description = "Boot Disk Type"
78}
79
80variable "extra_disk_name" {
81 type = string
82 description = "Extra Disk Name"
83}
84
85variable "extra_disk_size" {
86 type = string
87 description = "Disk Size"
88}
89
90variable "extra_disk_type" {
91 type = string
92 description = "Disk Type"
93}
94
95variable "replication_disk_name" {
96 type = string
97 description = "Replication Disk Name"
98}
99
100variable "replication_disk_size" {
101 type = string
102 description = "Replication Disk Size"
103}
104
105variable "replication_disk_type" {
106 type = string
107 description = "Replication Disk Type"
108}
109
110variable "replication_disk_zone" {
111 type = string
112 description = "Replication Disk Zone"
113}
terraform.tfvars
1project_id = "project-123456"
2
3region = "us-west1"
4zone = "us-west1-c"
5
6compute_instance_name = "vm-name"
7machine_type = "e2-micro"
8image_type = "debian-cloud/debian-13"
9network_name = "vm-network"
10subnetwork_name = "vm-subnet"
11address_name = "external-test-ip"
12
13hostname = "vm.example.com"
14
15boot_disk_name = "boot-disk"
16boot_disk_size = 10
17boot_disk_type = "pd-standard"
18
19
20extra_disk_name = "extra-disk"
21extra_disk_size = 10
22extra_disk_type = "pd-standard"
23
24replication_disk_name = "replication-disk"
25replication_disk_size = 10
26replication_disk_type = "pd-ssd"
27replication_disk_zone = "us-west1-c"
28
29service_account = "tofu-sa@project-123456.iam.gserviceaccount.com"
30user_email = "youremail@gmail.com"
31
32ssh_keys = <<EOF
33admin:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDtf3e9lQR1uAypz4nrq2nDj0DvZZGONku5wO+M87wUVTistrY8REsWO admin
34dev:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDtf3e9lQR1uAypz4nrq2nDj0DvZZGONku5wO+M87wUVTistrY8REsWO dev
35EOF
main.tf
1resource "google_compute_network" "vm_network" {
2 name = var.network_name
3 auto_create_subnetworks = false
4}
5
6resource "google_compute_subnetwork" "vm_sub_network" {
7 name = var.subnetwork_name
8 ip_cidr_range = "10.0.1.0/24"
9 region = var.region
10 network = google_compute_network.vm_network.id
11}
12
13resource "google_compute_address" "vm_address" {
14 name = var.address_name
15 region = var.region
16}
17
18resource "google_compute_firewall" "allow_ssh" {
19 name = "allow-ssh-iap"
20 network = google_compute_network.vm_network.id
21
22 source_ranges = ["35.235.240.0/20", "0.0.0.0/0"]
23
24 allow {
25 protocol = "tcp"
26 ports = ["22"]
27 }
28
29 target_tags = ["vm-test"]
30}
31
32resource "google_project_service" "project" {
33 service = "oslogin.googleapis.com"
34 disable_on_destroy = false
35}
36
37resource "google_compute_project_metadata" "default" {
38 metadata = {
39 enable-oslogin = "TRUE"
40 }
41}
42
43data "google_project" "project" {
44}
45resource "google_project_iam_member" "os_login_admin_users" {
46 project = data.google_project.project.project_id
47 role = "roles/compute.osAdminLogin"
48 member = "serviceAccount:service-${data.google_project.project.number}@compute-system.iam.gserviceaccount.com"
49}
50
51resource "google_compute_disk" "boot_disk" {
52 name = var.boot_disk_name
53 type = var.boot_disk_type
54 zone = var.zone
55 size = var.boot_disk_size
56 image = var.image_type
57}
58
59resource "google_compute_disk" "replication_disk" {
60 name = var.replication_disk_name
61 type = var.replication_disk_type
62 zone = var.replication_disk_zone
63
64 async_primary_disk {
65 disk = google_compute_disk.boot_disk.id
66 }
67
68 physical_block_size_bytes = 4096
69}
70
71resource "google_compute_disk" "extra_disk" {
72 name = var.extra_disk_name
73 type = var.extra_disk_type
74 zone = var.zone
75 size = var.extra_disk_size
76}
77
78resource "google_compute_disk_async_replication" "async_replication_disk" {
79 primary_disk = google_compute_disk.boot_disk.id
80 secondary_disk {
81 disk = google_compute_disk.replication_disk.id
82 }
83}
84
85resource "google_compute_snapshot" "boot_disk_snapshot" {
86 name = "vm-snapshot-extra-disk"
87 source_disk = google_compute_disk.boot_disk.name
88 zone = var.zone
89
90 depends_on = [google_compute_disk.boot_disk]
91}
92
93resource "google_compute_resource_policy" "snapshot_policy" {
94 name = "daily-snapshot-policy"
95 region = var.region
96
97 snapshot_schedule_policy {
98 schedule {
99 daily_schedule {
100 days_in_cycle = 1
101 start_time = "04:00"
102 }
103 }
104
105 retention_policy {
106 max_retention_days = 3
107 on_source_disk_delete = "KEEP_AUTO_SNAPSHOTS"
108 }
109 }
110}
111
112resource "google_compute_instance" "vm_instance" {
113 name = var.compute_instance_name
114 tags = ["vm-test"]
115 zone = var.zone
116 machine_type = var.machine_type
117 network_interface {
118 network = google_compute_network.vm_network.id
119 subnetwork = google_compute_subnetwork.vm_sub_network.id
120
121 # acquire public/external ip
122 access_config {
123 nat_ip = google_compute_address.vm_address.address
124 }
125 }
126 boot_disk {
127 source = google_compute_disk.boot_disk.id
128 device_name = google_compute_disk.boot_disk.name
129 }
130 attached_disk {
131 source = google_compute_disk.extra_disk.id
132 device_name = google_compute_disk.extra_disk.name
133 }
134 metadata = {
135 "ssh-keys" = var.ssh_keys
136 enable-oslogin : "TRUE"
137 }
138 hostname = var.hostname # if not set, default to vm google_compute_instance.name
139}