Create Self-destructing VM Instances on Google CloudJanne Kemppainen |
When you run temporary workloads you may not want to leave old machine instances lingering behind. Preemptible VM instances let you run at a significantly discounted price but they are shut down automatically after 24 hours, or earlier if Google needs those resources. The instances will still remain there in shut down state and they can still be turned back on later. What if you wanted to delete the machines automatically when you're done with them?
There is no direct way to configure a machine to delete itself when it is stopped. However, we can circumvent this by writing our own shutdown script.
What's a shutdown script?
Just like a bootstrap script that Compute Engine will run at instance creation time it is possible to define a shutdown script that should be run when the instance is shut down. Normally this is used in environments where the VM needs to remove itself from a load balancer, or it is shut down by an autoscaler and needs to do final preparations.
After receiving the shutdown signal the instance has a limited time to perform any needed operations before it is taken offline. Normal on-demand instances have at least 90 seconds to prepare for shutdown, but preemptible instances must shut down in 30 seconds. Google does not guarantee that the script will always complete but failures should be quite rare.
The shutdown script is called when:
instances.stopevent is requested through the API,
- Compute Engine stops a preemptible instance,
- the OS is shut down with
sudo reboot, or
- the instance is manually shut down.
The shutdown script can be provided directly through instance metadata, or as a link to Cloud Storage. In Cloud Console the metadata can be configured in the instance editor's Metadata section. The key should be
shutdown-script, and you can type the actual script in the value field.
If you're automating the instance deletion, then it is quite likely that you also want to create the instance programmatically. The Cloud Console can still be quite helpful here since you can first configure everything properly, then scroll to the bottom of the page and view the equivalent command line call to create the instance.
The relevant part for creating an instance with a startup script is this:
gcloud compute instances create my-instance \ --metadata-from-file shutdown-script=shutdown.sh
The command assumes that the shutdown script is stored locally as
shutdown.sh. If you want to create a preemptible VM, add the
Configure a service account
Before your VM can delete itself it needs to get the proper rights for that. So create a new service account in the Identity & Access Management (IAM) section on Cloud Console.
The service account needs to have at least these rights, in addition to whatever rights your application requires:
roles/compute.instanceAdminadds permissions to create, modify and delete VM instances
roles/iam.serviceAccountUseradds permissions to manage VMs that are configured to run as a service account
For the rest of the post I'll assume that the service account will be called
[email protected] and that it has all the required rights.
Create a VM with auto-deletion
The actual shutdown script is quite simple:
#!/usr/bin/env bash ZONE=$(gcloud compute instances list --filter=$(hostname) --format 'csv[no-heading](zone)') gcloud compute instances delete $(hostname) --quiet --zone="$ZONE"
It basically uses the
gcloud command that is pre-installed on all Compute Engine machines to call the instance deletion API. We can use the
hostname command to get the name of the currently running instance, which is safe to use since all instances within a project need to have unique names.
The delete command requires that the zone is also defined, so we need to perform some trickery to store the instance's current zone to a temporary variable.
If you have stored this file locally as
shutdown.sh then the instance creation command could look a bit like this:
gcloud compute instances create my-instance \ --zone=us-central1-a \ --machine-type=e2-medium \ --preemptible \ --metadata-from-file shutdown-script=shutdown.sh \ [email protected]ount.com \ --scopes=https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/trace.append,https://www.googleapis.com/auth/compute \ ...
Note that in the scopes section you have to include
https://www.googleapis.com/auth/compute! Otherwise the service account cannot delete the instance.
I omitted the rest of the arguments since they largely depend on your use case, so use this as an example to fill in the missing details.
Now go ahead and test that the shutdown script works by stopping the instance!
If everything worked well you are now ready to run your own workloads on a disposable VM. If you're using preemptible instances the nice thing is that they will be automatically deleted after 24 hours, no matter what you do. So you can't accidentally leave them running for long periods.
Still, when your instance has done its business it can call
sudo shutdown on itself to get deleted and to stop incurring more charges.
While GCP doesn't give us disposable VMs we can do some scripting trickery to delete instances that we don't need anymore. And remember that shutdown scripts can be used for many other purposes too!