avatarGuillermo Musumeci

Summary

The provided web content outlines the process of deploying a Windows Server VM instance in GCP using Terraform, including setup instructions, necessary credentials, network configuration, firewall rules, and considerations for Windows Server versions.

Abstract

The article is a comprehensive guide for deploying a Windows Server virtual machine (VM) instance on Google Cloud Platform (GCP) through the use of Terraform, an infrastructure as code tool. It begins by stating the need for GCP credentials to execute Terraform code, with a reference to a separate article for creating these credentials. The tutorial then details the creation of Terraform files for GCP authentication, network configuration, firewall rules, and Windows Server version selection. It also emphasizes the importance of secure handling of private key files, especially in production environments. The guide includes instructions for creating a VPC, a public subnet, and network firewall rules to allow HTTP and RDP traffic. It provides code snippets for bootstrapping the VM with a PowerShell script to install IIS and demonstrates how to find the correct SKUs for different versions of Windows Server. The article concludes by noting that GCP does not support Windows Server VMs under the free trial, requiring users to enable billing to deploy such instances, and provides a link to the full code on GitHub.

Opinions

  • The author emphasizes that while private key .JSON files are suitable for testing, they are not recommended for production due to security concerns.
  • Using Terraform for deploying infrastructure is advocated for its ease and efficiency in managing cloud resources.
  • The article suggests that GCP's policy of not including Windows Server VMs in the free trial is a notable limitation compared to other cloud providers.
  • The author's inclusion of a script to install IIS on the Windows Server VM implies a preference for immediate verification of the server's functionality post-deployment.
  • The recommendation to use tags for applying firewall rules indicates a best practice for network security management within GCP.

How to Deploy a Windows Server VM Instance in GCP using Terraform

In this story, we will learn how to deploy a Windows Server VM Instance (VM) in GCP (Google Cloud Platform) using Terraform.

Prerequisite: GCP Credentials

Before creating our GCP VM Instances, we will need GCP Credentials to execute our Terraform code.

Please refer to the “How to Create a Service Account for Terraform in GCP (Google Cloud Platform)” story if you need help to create the credentials.

Note: Using private key .JSON files are great for learning and testing however they are not recommended in production environments. Never push private keys files to code repositories.

Creating a Terraform file for GCP Authentication

First, we create a file called “provider-variables.tf”, used by the GCP authentication variables, and add the following code to the file.

We will need a GCP Project Name, a GCP Region, and a .JSON file name with the private keys to authenticate to GCP.

# GCP authentication file
variable "gcp_auth_file" {
  type        = string
  description = "GCP authentication file"
}
# define GCP region
variable "gcp_region" {
  type        = string
  description = "GCP region"
}
# define GCP project name
variable "gcp_project" {
  type        = string
  description = "GCP project name"
}

Then we create the “provider-main.tf” file and add the following code:

The version in the “required_providers” / “google” section is useful to pin a specific version but is not required.

# Define Terraform provider
terraform {
  required_version = "~> 1.0"
  required_providers {
    google = {
      source = "hashicorp/google"
      version = "4.11.0" # pinning version
    }
  }
}
# Define GCP provider
provider "google" {
  credentials = file(var.gcp_auth_file)
  project     = var.gcp_project
  region      = var.gcp_region
  zone        = var.gcp_zone
}

Finally, we use Provider in the “terraform.tfvars” file:

# GCP Settings
gcp_project   = "kopicloud-medium"
gcp_region    = "europe-west4"
gcp_auth_file = "../auth/kopicloud-medium.json"

Creating a Terraform file for the Network

In this step, we will create the file “network-variables.tf” to configure network variables and add the following code:

variable "network-subnet-cidr" {
  type        = string
  description = "The CIDR for the network subnet"
}

Then, we create the “network-main.tf” file to configure the network and add the following code. This simple code will create a VPC and a public subnet.

# create VPC
resource "google_compute_network" "vpc" {
  name                    = "kopicloud-vpc"
  auto_create_subnetworks = "false"
  routing_mode            = "GLOBAL"
}
# create public subnet
resource "google_compute_subnetwork" "network_subnet" {
  name          = "kopicloud-subnet"
  ip_cidr_range = var.network-subnet-cidr
  network       = google_compute_network.vpc.name
  region        = var.gcp_region
}

Creating a Terraform file for Network Firewall Rules

Now we will create the “network-firewall.tf” file used to create network firewall rules.

All traffic to VM instances in GCP, even from other instances, is blocked by the firewall unless firewall rules are created to allow it.

We will use the “target_tags” to apply firewall rules to VM instances. If no “target_tags” are specified, the firewall rule applies to all instances on the specified VPC network.

# Allow http
resource "google_compute_firewall" "allow-http" {
  name    = "kopicloud-fw-allow-http"
  network = google_compute_network.vpc.name
  allow {
    protocol = "tcp"
    ports    = ["80"]
  }
  
  source_ranges = ["0.0.0.0/0"]
  target_tags = ["http"] 
}
# allow rdp
resource "google_compute_firewall" "allow-rdp" {
  name    = "kopicloud-fw-allow-rdp"
  network = google_compute_network.vpc.name
  allow {
    protocol = "tcp"
    ports    = ["3389"]
  }
  source_ranges = ["0.0.0.0/0"]
  target_tags = ["rdp"]
}

Creating a Terraform file for Windows Server Versions Variables

We will create the “windows-versions.tf” file, used to store variables for the different versions of Windows Server.

variable "windows_2012_r2_sku" {
  type        = string
  description = "SKU for Windows Server 2012 R2"
  default     = "windows-cloud/windows-2012-r2"
}
variable "windows_2016_sku" {
  type        = string
  description = "SKU for Windows Server 2016"
  default     = "windows-cloud/windows-2016"
}
variable "windows_2019_sku" {
  type        = string
  description = "SKU for Windows Server 2019"
  default     = "windows-cloud/windows-2019"
}
variable "windows_2022_sku" {
  type        = string
  description = "SKU for Windows Server 2022"
  default     = "windows-cloud/windows-2022"
}

Creating a Terraform file for the Windows Server VM Variables

Now we will create the “windows-vm-variables.tf” file, used to store variables for the Windows Server operating system.

variable "windows_instance_type" {
  type        = string
  description = "VM instance type for Windows Server"
  default     = "n2-standard-2"
}

Creating a Terraform file for the Windows Server VM Main File

Finally, create the “windows-vm-main.tf” file to build the GCP VM Instance. We will split the code for better clarity.

We will use a simple PowerShell script to bootstrap the VM instance. Next, the script will install IIS (Internet Information Server) on the server. This extra step is useful to make sure the server is working properly.

Note: this step is optional. If we don’t want to deploy IIS, we will need to remove the “metadata” section from the “windows-vm-main.tf” file and the http rule from tags.

For Windows Server, we can use different options to bootstrap VM instances.

  • sysprep-specialize-script-ps1 = PowerShell script during the initial boot
  • sysprep-specialize-script-cmd = Command Shell script during the initial boot
  • windows-startup-script-ps1 = PowerShell script during each boot after the initial boot
  • windows-startup-script-cmd = Command Shell script during each boot after the initial boot

We can use multiple startup scripts.

data "template_file" "windows-metadata" {
template = <<EOF
# Install IIS
Install-WindowsFeature -name Web-Server -IncludeManagementTools;
EOF
}

This section of code will create the VM Instance. To update the version of Windows Server, update the image line with a variable from the “windows-versions.tf” file.

resource "google_compute_instance" "vm_instance_public" {
  name         = "kopicloud-vm"
  machine_type = var.windows_instance_type
  zone         = var.gcp_zone
  hostname     = "kopicloud-vm.kopicloud.com"
  tags         = ["rdp","http"]
  boot_disk {
    initialize_params {
      image = var.windows_2022_sku
    }
  }
  metadata = {
    sysprep-specialize-script-ps1 = data.template_file.windows-metadata.rendered
  }
  network_interface {
    network       = google_compute_network.vpc.name
    subnetwork    = google_compute_subnetwork.network_subnet.name
    access_config { }
  }
}

How to Find Windows Server VM SKUs for Terraform

We open the “gcloud CLI” tool or the “Cloud Shell” in the GCP Console and type:

gcloud compute images list --filter 'family ~ windows'

and we will get the list of Windows Server images available. The “PROJECT” and “FAMILY” columns are the two we need to combine to create the image name.

NAME: windows-server-2012-r2-dc-core-v20220210
PROJECT: windows-cloud
FAMILY: windows-2012-r2-core
DEPRECATED:
STATUS: READY
NAME: windows-server-2012-r2-dc-v20220210
PROJECT: windows-cloud
FAMILY: windows-2012-r2
DEPRECATED:
STATUS: READY
NAME: windows-server-2016-dc-core-v20220210
PROJECT: windows-cloud
FAMILY: windows-2016-core
DEPRECATED:
STATUS: READY
NAME: windows-server-2016-dc-v20220210
PROJECT: windows-cloud
FAMILY: windows-2016
DEPRECATED:
STATUS: READY
NAME: windows-server-2019-dc-core-for-containers-v20220211
PROJECT: windows-cloud
FAMILY: windows-2019-core-for-containers
DEPRECATED:
STATUS: READY
NAME: windows-server-2019-dc-core-v20220210
PROJECT: windows-cloud
FAMILY: windows-2019-core
DEPRECATED:
STATUS: READY
NAME: windows-server-2019-dc-for-containers-v20220211
PROJECT: windows-cloud
FAMILY: windows-2019-for-containers
DEPRECATED:
STATUS: READY
NAME: windows-server-2019-dc-v20220210
PROJECT: windows-cloud
FAMILY: windows-2019
DEPRECATED:
STATUS: READY
NAME: windows-server-2022-dc-core-v20220215
PROJECT: windows-cloud
FAMILY: windows-2022-core
DEPRECATED:
STATUS: READY
NAME: windows-server-2022-dc-v20220215
PROJECT: windows-cloud
FAMILY: windows-2022
DEPRECATED:
STATUS: READY
NAME: windows-server-20h2-dc-core-v20220210
PROJECT: windows-cloud
FAMILY: windows-20h2-core
DEPRECATED:
STATUS: READY

Creating the Input Definition Variables File

In the last step, we are going to create input definition variables file “terraform.tfvars” and add the following code to the file:

# Application Definition 
company     = "kopicloud"
app_name    = "iac-windows"
app_domain  = "kopicloud.com"
environment = "dev" # Dev, Test, Prod, etc
# GCP Settings
gcp_project   = "kopicloud-medium"
gcp_region    = "europe-west4"
gcp_zone      = "europe-west4-b"
gcp_auth_file = "../auth/kopicloud-medium.json"
# GCP Netwok
network-subnet-cidr = "10.10.15.0/24"
# Windows VM
windows_instance_type = "n2-standard-2"

Windows Servers VM are NOT Allowed in Free Trials

Unfortunately, GCP is the only cloud provider that doesn’t support deploying Windows VM on the Free Trial, so if you try to run this code, you will get the following error:

Error: Error creating instance: googleapi: Error 400: Windows VM instances are not included with the free trial. To use them, first enable billing on your account. You’ll still be able to apply your free trial credits to eligible products and services., windowsVmNotAllowedInFreeTrialProject

The solution is to enable the Billing Account in our GCP Account.

The full code is available at https://github.com/KopiCloud/terraform-gcp-windows-vm

And that’s all, folks. If you liked this story, please show your support by 👏 this story. Thank you for reading!

Windows
Gcp
Terraform
Vm Instance
Infrastructure As Code
Recommended from ReadMedium