I am trying to schedule for vm shutdown and startup, there is the option from the project instances with Instance Schedules, but I have to configure it in each project, it is also doing it from Cloud Scheduler, but it is also per project.
Is there any way to affect all projects, where the instance has a dev tag, no matter the project, it turns off at a certain time?
}
Thanks & Regards
My suggestion would be to look to Terraform or similar automation tooling. You could define a standard schedule and then attach it to all VMs across all projects based on your requirement of the dev tag. Then in order to ensure this is always the case, get your automation to run on a periodic basis - according to your requirements. For example you could have a task run on a daily basis that applies your policy.
I have similar issues, but would you please share the resource (You could define a standard schedule and then attach it to all VMs across all projects based on your requirement of the dev tag. )
I wanted to do the same thing right before they added instance scheduling and did it this way using cloud function and pubsub. I'm pretty new to GCP so it was a good exercise for me to learn something about cloud function even though it's the long way around. I have mine starting and stopping all VMs in a project with specific tags. I'm looking for "auto_start" and "auto_stop" tags. If you need to affect all projects, then you'd probably have to modify the code a little bit and ensure the cloud function is using a service account that has permissions to all of your VMs. I'm using terraform so it was just as easy to write a module that I apply to each project individually.
Hi Nick,
What terraform module are you using to create the vm scheduler?
Nick, I just followed that instruction and I don't know what I should modify so that it runs in all projects, or what I should modify so that instead of putting {"zone":"us-west1-b","label in the message ":"env=dev"} place something like this {"project":"myproject","label":"env=dev"}
It's a custom module that fits our needs specifically. However, here's the de-modularized code in a nutshell that could be re-modularized for yourself. I created a service account with specific permissions for the cloud function, though could probably be refined with a custom role if you need more security. I also had to give Cloud Function access to my private VPC with a VPC Access Connector which is referenced below. I'm setting auto_on and auto_off labels on my VMs where I need to start or stop.
As I mentioned earlier, I'm still pretty new to this (about a year) and my knowledge of node.js is very limited. So customizing the node.js is something I am unable to do easily. One thing I've been wanting to add to the node.js code is some way to skip the shutdown if the CPU or GPU utilization is above a certain threshold so I can avoid shutting down a VM on somebody that's in the middle of a large overnight calculation.
/******************************************
Cloud Function Service Account with Access to Manage VMs
*****************************************/
resource "google_service_account" "compute_function_service" {
account_id = "compute-function-service"
display_name = "Compute Function Service Account"
project = "[PROJECT_ID]"
}
/******************************************
Cloud Function Code Bucket
*****************************************/
resource "google_storage_bucket" "storage_bucket_cloud_functions" {
name = "[PROJECT_ID]-cloud-functions"
location = "[REGION]"
}
/******************************************
IAM Roles
*****************************************/
resource "google_project_iam_member" "compute_instance_admin_cloud_schedule" {
project = "[PROJECT_ID]"
role = "roles/compute.instanceAdmin.v1"
member = "serviceAccount:${google_service_account.compute_function_service.email}"
}
resource "google_storage_bucket_iam_binding" "bucket_cloud_function_read" {
bucket = "[PROJECT_ID]-cloud-functions"
role = "roles/storage.legacyBucketReader"
members = [
"serviceAccount:${google_service_account.compute_function_service.email}"
]
}
resource "google_storage_bucket_iam_binding" "bucket_cloud_function_write" {
bucket = "[PROJECT_ID]-cloud-functions"
role = "roles/storage.legacyBucketWriter"
members = [
"serviceAccount:${google_service_account.compute_function_service.email}"
]
}
/******************************************
Compute VM Schedule
*****************************************/
# Upload source zip to storage bucket containing index.js, packages.json, README.md from Google example
resource "google_storage_bucket_object" "cloud_functions_schedule_instance" {
name = "scheduleinstance_functions.zip"
bucket = google_storage_bucket.storage_bucket_cloud_functions.name
source = "[LOCAL_PATH_TO_CODE_SOURCE_ZIP]"
}
# Pub/Sub Topics
resource "google_pubsub_topic" "pubsub_start_instance_event" {
name = "start-instance-event"
}
resource "google_pubsub_topic" "pubsub_stop_instance_event" {
name = "stop-instance-event"
}
# Cloud Functions
# Test Function From Cloud Shell:
# echo '{"zone":"[YOUR_ZONE]", "label":"auto_on=true"}' | base64
# gcloud functions call startInstancePubSub --data '{"data":"[RESULTS FROM COMMAND ABOVE]"}'
resource "google_cloudfunctions_function" "function_startInstancePubSub" {
name = "startInstancePubSub"
description = "Start Instance Function"
runtime = "nodejs10"
timeout = 180
region = "[REGION]"
service_account_email = google_service_account.compute_function_service.email
vpc_connector = [VPC_ACCESS_CONNECTOR_SELF_LINK]
vpc_connector_egress_settings = "PRIVATE_RANGES_ONLY"
source_archive_bucket = google_storage_bucket.storage_bucket_cloud_functions.name
source_archive_object = google_storage_bucket_object.cloud_functions_schedule_instance.name
event_trigger {
event_type = "google.pubsub.topic.publish"
resource = "projects/[PROJECT_ID]/topics/start-instance-event"
}
entry_point = "startInstancePubSub"
}
# Test Function From Cloud Shell:
# echo '{"zone":"[YOUR_ZONE]", "label":"auto_off=true"}' | base64
# gcloud functions call stopInstancePubSub --data '{"data":"[RESULTS FROM COMMAND ABOVE]"}'
resource "google_cloudfunctions_function" "function_stopInstancePubSub" {
name = "stopInstancePubSub"
description = "Stop Instance Function"
runtime = "nodejs10"
timeout = 180
region = "[REGION]"
service_account_email = google_service_account.compute_function_service.email
vpc_connector = [VPC_ACCESS_CONNECTOR_SELF_LINK]
vpc_connector_egress_settings = "PRIVATE_RANGES_ONLY"
# available_memory_mb = 128
source_archive_bucket = google_storage_bucket.storage_bucket_cloud_functions.name
source_archive_object = google_storage_bucket_object.cloud_functions_schedule_instance.name
event_trigger {
event_type = "google.pubsub.topic.publish"
resource = "projects/[PROJECT_ID]/topics/stop-instance-event"
}
entry_point = "stopInstancePubSub"
}
# Cloud Schedule
# echo '{"zone":"[YOUR_ZONE]", "label":"auto_on=true"}' | base64
resource "google_cloud_scheduler_job" "schedule_startInstancePubSub" {
name = "startInstancePubSub"
region = "[YOUR_REGION]"
project = "[PROJECT_ID]"
description = "Start Instance - label:auto-on=true"
schedule = "30 7 * * 1-5"
time_zone = "America/New_York"
pubsub_target {
# topic.id is the topic's full resource name.
topic_name = google_pubsub_topic.pubsub_start_instance_event.id
data = "[RESULTE FROM THIS COMMAND: echo '{"zone":"[YOUR_ZONE]", "label":"auto_on=true"}' | base64]"
}
}
# echo '{"zone":"[YOUR_ZONE]", "label":"auto_off=true"}' | base64
resource "google_cloud_scheduler_job" "schedule_stopInstancePubSub" {
name = "stopInstancePubSub"
region = "[YOUR_REGION]"
project = "[PROJECT_ID]"
description = "Stop Instance - label:auto-off=true"
schedule = "30 23 * * 0-6"
time_zone = "America/New_York"
pubsub_target {
# topic.id is the topic's full resource name.
topic_name = google_pubsub_topic.pubsub_stop_instance_event.id
data = "[RESULTE FROM THIS COMMAND: echo '{"zone":"[YOUR_ZONE]", "label":"auto_off=true"}' | base64]"
}
}
Hi Nick ,
Thanks for the solution here , but question is what if we want to implement this cloud function solution for vm auto parking to existing vms that are spanned across multiple regions in multiple project then how would we implement this .
More over the above thread for terraform code will again be taking consideration of a single regions in which we can perform this .
Thanks
Why is such a simple operation so hard/complex? In Azure this is a standard property of an instances that you simply toggle on and off with a schedule and there is a straightforward TF resource to enable it.
###--- Enable auto-shutdown
# VM ID is a little tricky to sort out.
resource "azurerm_dev_test_global_vm_shutdown_schedule" "autoshutdown" {
for_each = var.vmconfigs
location = azurerm_resource_group.multivm_rg.location
virtual_machine_id = azurerm_linux_virtual_machine.vms[each.key].id
enabled = true
daily_recurrence_time = var.shutdown_time
timezone = var.timezone
notification_settings {
enabled = false
}
}
This thread is a little old, but there is a terraform resource for doing very similar now on Google, it is known as a Resource Policy: