main.tf (264 lines of code) (raw):
/**
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
locals {
exemplar_machine_type = "e2-medium"
node_machine_type = "e2-micro"
subnet_name = "${var.deployment_name}-subnet-01"
custom_network = var.network_id != ""
network_id = local.custom_network ? var.network_id : module.vpc[0].network_id
subnet_self_link = var.subnet_self_link != "" ? var.subnet_self_link : module.vpc[0].subnets["${var.region}/${local.subnet_name}"].self_link
network_project_id = var.network_project_id != "" ? var.network_project_id : var.project_id
lb_endpoint = "http://${module.gce-lb-http.external_ip}/"
}
# Enabling services in your GCP project
module "project-services" {
source = "terraform-google-modules/project-factory/google//modules/project_services"
version = "~> 17.0"
disable_services_on_destroy = false
project_id = var.project_id
enable_apis = var.enable_apis
activate_apis = [
"compute.googleapis.com"
]
}
module "vpc" {
count = local.custom_network ? 0 : 1
source = "terraform-google-modules/network/google"
version = "~> 9.0"
project_id = var.project_id
network_name = "${var.deployment_name}-network"
routing_mode = "GLOBAL"
subnets = [
{
subnet_name = local.subnet_name
subnet_ip = "10.10.10.0/24"
subnet_region = var.region
}
]
depends_on = [
module.project-services
]
}
resource "google_compute_firewall" "private-allow-ssh" {
name = "${var.deployment_name}-allow-ssh"
project = local.network_project_id
network = local.network_id
allow {
protocol = "tcp"
ports = ["22"]
}
source_ranges = ["0.0.0.0/0"]
target_tags = ["private-ssh"]
}
data "local_file" "index" {
filename = "${path.module}/files/index.html"
}
# Create Instance Exemplar on which to base Managed VMs
resource "google_compute_instance" "exemplar" {
name = "${var.deployment_name}-exemplar"
machine_type = local.exemplar_machine_type
zone = var.zone
project = var.project_id
labels = var.labels
tags = ["http-server", "private-ssh"]
metadata_startup_script = <<EOF
apt-get update -y
apt-get install nginx -y
printf '${data.local_file.index.content}' | tee /var/www/html/index.html
chgrp root /var/www/html/index.html
chown root /var/www/html/index.html
chmod +r /var/www/html/index.html
sleep 300
shutdown -h now
EOF
boot_disk {
auto_delete = true
device_name = "${var.deployment_name}-exemplar"
initialize_params {
image = "family/debian-12"
size = 200
type = "pd-standard"
}
}
network_interface {
subnetwork = local.subnet_self_link
subnetwork_project = local.network_project_id
access_config {
// Ephemeral public IP
}
}
}
resource "time_sleep" "startup_completion" {
create_duration = "120s"
depends_on = [google_compute_instance.exemplar]
}
resource "google_compute_snapshot" "main" {
project = var.project_id
name = "${var.deployment_name}-snapshot"
source_disk = google_compute_instance.exemplar.boot_disk[0].device_name
zone = var.zone
storage_locations = [var.region]
depends_on = [time_sleep.startup_completion]
labels = var.labels
}
# Create Disk Image for Instance Template
resource "google_compute_image" "exemplar" {
project = var.project_id
name = "${var.deployment_name}-latest"
family = var.deployment_name
source_snapshot = google_compute_snapshot.main.self_link
depends_on = [google_compute_snapshot.main]
labels = var.labels
}
# Create Instance Template
resource "google_compute_instance_template" "main" {
project = var.project_id
name = "${var.deployment_name}-template"
description = "This template is used to create app server instances."
tags = ["http-server", "private-ssh"]
labels = var.labels
metadata_startup_script = "sed -i.bak \"s/{{NODENAME}}/$HOSTNAME/\" /var/www/html/index.html"
instance_description = "${var.deployment_name} node"
machine_type = local.node_machine_type
can_ip_forward = false
// Create a new boot disk from an image
disk {
source_image = google_compute_image.exemplar.self_link
auto_delete = true
boot = true
}
network_interface {
subnetwork = local.subnet_self_link
subnetwork_project = local.network_project_id
}
}
resource "google_compute_target_pool" "main" {
project = var.project_id
name = "${var.deployment_name}-target-pool"
region = var.region
}
resource "google_compute_health_check" "autohealing" {
project = var.project_id
name = "${var.deployment_name}-autohealing-health-check"
check_interval_sec = 5
timeout_sec = 5
healthy_threshold = 2
unhealthy_threshold = 10 # 50 seconds
http_health_check {
request_path = "/"
port = "80"
}
}
# Create Managed Instance Group
resource "google_compute_instance_group_manager" "main" {
project = var.project_id
provider = google-beta
name = "${var.deployment_name}-mig"
zone = var.zone
target_size = var.nodes
base_instance_name = "${var.deployment_name}-mig"
target_pools = [google_compute_target_pool.main.id]
version {
instance_template = google_compute_instance_template.main.id
}
all_instances_config {
labels = var.labels
}
named_port {
name = "http"
port = "80"
}
auto_healing_policies {
health_check = google_compute_health_check.autohealing.id
initial_delay_sec = 300
}
}
resource "google_compute_autoscaler" "main" {
project = var.project_id
name = "${var.deployment_name}-autoscaler"
zone = var.zone
target = google_compute_instance_group_manager.main.id
autoscaling_policy {
max_replicas = var.nodes * 2
min_replicas = var.nodes
cooldown_period = 60
cpu_utilization {
target = 0.5
}
}
}
module "gce-lb-http" {
source = "GoogleCloudPlatform/lb-http/google"
version = "~> 12.0"
project = var.project_id
name = "${var.deployment_name}-lb"
firewall_networks = [local.network_id]
backends = {
default = {
description = null
protocol = "HTTP"
port = "80"
port_name = "http"
timeout_sec = 10
enable_cdn = false
custom_request_headers = null
custom_response_headers = null
security_policy = null
connection_draining_timeout_sec = null
session_affinity = null
affinity_cookie_ttl_sec = null
health_check = {
check_interval_sec = null
timeout_sec = null
healthy_threshold = null
unhealthy_threshold = null
request_path = "/"
port = "80"
name = "${var.deployment_name}-health-chk"
host = null
logging = null
}
log_config = {
enable = true
sample_rate = 1.0
}
groups = [
{
group = google_compute_instance_group_manager.main.instance_group
balancing_mode = null
capacity_scaler = null
description = null
max_connections = null
max_connections_per_instance = null
max_connections_per_endpoint = null
max_rate = null
max_rate_per_instance = null
max_rate_per_endpoint = null
max_utilization = null
},
]
iap_config = {
enable = false
oauth2_client_id = null
oauth2_client_secret = null
}
}
}
}
data "http" "check" {
url = local.lb_endpoint
retry {
attempts = 50
max_delay_ms = 10 * 1000
min_delay_ms = 5 * 1000
}
depends_on = [module.gce-lb-http]
}