Create and use preemptible VMs

Important: Spot VMs are the latest version of preemptible VMs, andwe recommend using Spot VMs instead of preemptible VMs. New andexisting preemptible VMs continue to be available,and preemptible VMs use the same pricing model as Spot VMs. However,Spot VMs provide new features that preemptible VMs do not support.For example, preemptible VMs can only run for up to 24 hours at a time, butSpot VMs do not have a maximum runtime unless youlimit the runtime. Learn more aboutSpot VMs andhow tocreate Spot VMs.

This page explains how to create and use a preemptible virtual machine (VM)instance. Preemptible VMs are available at a discount of up to 91% off of thedefault price of standard VMs. However, Compute Engine mightstop (preempt) these VMs if it needs to reclaim those resources forother tasks. Preemptible VMs always stop after 24 hours.Preemptible VMs are recommended only for fault-tolerantapplications that can withstand VM preemption. Make sure your applicationcan handle preemptions before you decide to create a preemptible VM.To understand the risks and value of preemptible VMs, read thepreemptible VM instances documentation.

Caution: Preemptible VMs are not covered by any Service Level Agreementand are excluded from theCompute Engine SLA.For more information, seelimitations of preemptible VM instances.

Before you begin

Create a preemptible VM

Create a preemptible VM using thegcloud CLI or the Compute Engine API. To use theGoogle Cloud console,create a Spot VMinstead.

Note: You cannot change theautomatic restart and host maintenance optionsfor a preemptible VM.

gcloud

Withgcloud compute, use the sameinstances create command thatyou would use to create a normal VM, but add the--preemptibleflag.

gcloudcomputeinstancescreate[VM_NAME]--preemptible

where[VM_NAME] is thename of the VM.

Go

import("context""fmt""io"compute"cloud.google.com/go/compute/apiv1"computepb"cloud.google.com/go/compute/apiv1/computepb""google.golang.org/protobuf/proto")// createPreemtibleInstance creates a new preemptible VM instance// with Debian 10 operating system.funccreatePreemtibleInstance(wio.Writer,projectID,zone,instanceNamestring,)error{// projectID := "your_project_id"// zone := "europe-central2-b"// instanceName := "your_instance_name"// preemptible := truectx:=context.Background()instancesClient,err:=compute.NewInstancesRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewInstancesRESTClient: %w",err)}deferinstancesClient.Close()imagesClient,err:=compute.NewImagesRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewImagesRESTClient: %w",err)}deferimagesClient.Close()// List of public operating system (OS) images:// https://cloud.google.com/compute/docs/images/os-details.newestDebianReq:=&computepb.GetFromFamilyImageRequest{Project:"debian-cloud",Family:"debian-11",}newestDebian,err:=imagesClient.GetFromFamily(ctx,newestDebianReq)iferr!=nil{returnfmt.Errorf("unable to get image from family: %w",err)}inst:=&computepb.Instance{Name:proto.String(instanceName),Disks:[]*computepb.AttachedDisk{{InitializeParams:&computepb.AttachedDiskInitializeParams{DiskSizeGb:proto.Int64(10),SourceImage:newestDebian.SelfLink,DiskType:proto.String(fmt.Sprintf("zones/%s/diskTypes/pd-standard",zone)),},AutoDelete:proto.Bool(true),Boot:proto.Bool(true),},},Scheduling:&computepb.Scheduling{// Set the preemptible settingPreemptible:proto.Bool(true),},MachineType:proto.String(fmt.Sprintf("zones/%s/machineTypes/n1-standard-1",zone)),NetworkInterfaces:[]*computepb.NetworkInterface{{Name:proto.String("global/networks/default"),},},}req:=&computepb.InsertInstanceRequest{Project:projectID,Zone:zone,InstanceResource:inst,}op,err:=instancesClient.Insert(ctx,req)iferr!=nil{returnfmt.Errorf("unable to create instance: %w",err)}iferr=op.Wait(ctx);err!=nil{returnfmt.Errorf("unable to wait for the operation: %w",err)}fmt.Fprintf(w,"Instance created\n")returnnil}

Java

importcom.google.cloud.compute.v1.AttachedDisk;importcom.google.cloud.compute.v1.AttachedDiskInitializeParams;importcom.google.cloud.compute.v1.InsertInstanceRequest;importcom.google.cloud.compute.v1.Instance;importcom.google.cloud.compute.v1.InstancesClient;importcom.google.cloud.compute.v1.NetworkInterface;importcom.google.cloud.compute.v1.Operation;importcom.google.cloud.compute.v1.Scheduling;importjava.io.IOException;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.TimeoutException;publicclassCreatePreemptibleInstance{publicstaticvoidmain(String[]args)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// TODO(developer): Replace these variables before running the sample.// projectId: project ID or project number of the Cloud project you want to use.// zone: name of the zone you want to use. For example: “us-west3-b”// instanceName: name of the new virtual machine.StringprojectId="your-project-id-or-number";Stringzone="zone-name";StringinstanceName="instance-name";createPremptibleInstance(projectId,zone,instanceName);}// Send an instance creation request with preemptible settings to the Compute Engine API// and wait for it to complete.publicstaticvoidcreatePremptibleInstance(StringprojectId,Stringzone,StringinstanceName)throwsIOException,ExecutionException,InterruptedException,TimeoutException{StringmachineType=String.format("zones/%s/machineTypes/e2-small",zone);StringsourceImage="projects/debian-cloud/global/images/family/debian-11";longdiskSizeGb=10L;StringnetworkName="default";try(InstInstancesClienttancesClient=InstInstancesClientate()){AttaAttachedDiskk=AttaAttachedDiskBuilder().setBoot(true).setAutoDelete(true).setType(AttaAttachedDiske.PERSISTENT.toString()).setIsetInitializeParams// Describe the size and source image of the boot disk to attach to the instance.AttaAttachedDiskInitializeParamsBuilder().setSourceImage(sourceImage).setDiskSizeGb(diskSizeGb).build()).build();// Use the default VPC network.NetwNetworkInterfaceworkInterface=NetwNetworkInterfaceBuilder().setName(networkName).build();// Collect information into the Instance object.InstInstancetanceResource=InstInstanceBuilder().setName(instanceName).setMachineType(machineType).addDisks(disk).addNetworkInterfaces(networkInterface)// Set the preemptible setting..setScheduling(ScheSchedulingBuilder().setPsetPreemptiblee).build()).build();System.out.printf("Creating instance: %s at %s %n",instanceName,zone);// Prepare the request to insert an instance.InseInsertInstanceRequestertInstanceRequest=InseInsertInstanceRequestBuilder().setProject(projectId).setZone(zone).setInstanceResource(instanceResource).build();// Wait for the create operation to complete.OperOperationponse=instancesClient.insertAsync(insertInstanceRequest).get(3,TimeUnit.MINUTES);;if(respresponse.hasError()System.out.println("Instance creation failed ! ! "+response);return;}System.out.printf("Instance created : %s\n",instanceName);System.out.println("Operation Status: "+respresponse.getStatus()}}}

Node.js

/** * TODO(developer): Uncomment and replace these variables before running the sample. */// const projectId = 'YOUR_PROJECT_ID';// const zone = 'europe-central2-b';// const instanceName = 'YOUR_INSTANCE_NAME';constcompute=require('@google-cloud/compute');asyncfunctioncreatePreemptible(){constinstancesClient=newcompute.InstancesClient();const[response]=awaitinstancesClient.insert({instanceResource:{name:instanceName,disks:[{initializeParams:{diskSizeGb:'64',sourceImage:'projects/debian-cloud/global/images/family/debian-11/',},autoDelete:true,boot:true,},],scheduling:{// Set the preemptible settingpreemptible:true,},machineType:`zones/${zone}/machineTypes/e2-small`,networkInterfaces:[{name:'global/networks/default',},],},project:projectId,zone,});letoperation=response.latestResponse;constoperationsClient=newcompute.ZoneOperationsClient();// Wait for the create operation to complete.while(operation.status!=='DONE'){[operation]=awaitoperationsClient.wait({operation:operation.name,project:projectId,zone:operation.zone.split('/').pop(),});}console.log('Instance created.');}createPreemptible();

Python

from__future__importannotationsimportreimportsysfromtypingimportAnyimportwarningsfromgoogle.api_core.extended_operationimportExtendedOperationfromgoogle.cloudimportcompute_v1defget_image_from_family(project:str,family:str)->compute_v1.Image:"""    Retrieve the newest image that is part of a given family in a project.    Args:        project: project ID or project number of the Cloud project you want to get image from.        family: name of the image family you want to get image from.    Returns:        An Image object.    """image_client=compute_v1.ImagesClient()# List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-detailsnewest_image=image_client.get_from_family(project=project,family=family)returnnewest_imagedefdisk_from_image(disk_type:str,disk_size_gb:int,boot:bool,source_image:str,auto_delete:bool=True,)->compute_v1.AttachedDisk:"""    Create an AttachedDisk object to be used in VM instance creation. Uses an image as the    source for the new disk.    Args:         disk_type: the type of disk you want to create. This value uses the following format:            "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".            For example: "zones/us-west3-b/diskTypes/pd-ssd"        disk_size_gb: size of the new disk in gigabytes        boot: boolean flag indicating whether this disk should be used as a boot disk of an instance        source_image: source image to use when creating this disk. You must have read access to this disk. This can be one            of the publicly available images or an image from one of your projects.            This value uses the following format: "projects/{project_name}/global/images/{image_name}"        auto_delete: boolean flag indicating whether this disk should be deleted with the VM that uses it    Returns:        AttachedDisk object configured to be created using the specified image.    """boot_disk=compute_v1.AttachedDisk()initialize_params=compute_v1.AttachedDiskInitializeParams()initialize_params.source_image=source_imageinitialize_params.disk_size_gb=disk_size_gbinitialize_params.disk_type=disk_typeboot_disk.initialize_params=initialize_params# Remember to set auto_delete to True if you want the disk to be deleted when you delete# your VM instance.boot_disk.auto_delete=auto_deleteboot_disk.boot=bootreturnboot_diskdefwait_for_extended_operation(operation:ExtendedOperation,verbose_name:str="operation",timeout:int=300)->Any:"""    Waits for the extended (long-running) operation to complete.    If the operation is successful, it will return its result.    If the operation ends with an error, an exception will be raised.    If there were any warnings during the execution of the operation    they will be printed to sys.stderr.    Args:        operation: a long-running operation you want to wait on.        verbose_name: (optional) a more verbose name of the operation,            used only during error and warning reporting.        timeout: how long (in seconds) to wait for operation to finish.            If None, wait indefinitely.    Returns:        Whatever the operation.result() returns.    Raises:        This method will raise the exception received from `operation.exception()`        or RuntimeError if there is no exception set, but there is an `error_code`        set for the `operation`.        In case of an operation taking longer than `timeout` seconds to complete,        a `concurrent.futures.TimeoutError` will be raised.    """result=operation.result(timeout=timeout)ifoperation.error_code:print(f"Error during{verbose_name}: [Code:{operation.error_code}]:{operation.error_message}",file=sys.stderr,flush=True,)print(f"Operation ID:{operation.name}",file=sys.stderr,flush=True)raiseoperation.exception()orRuntimeError(operation.error_message)ifoperation.warnings:print(f"Warnings during{verbose_name}:\n",file=sys.stderr,flush=True)forwarninginoperation.warnings:print(f" -{warning.code}:{warning.message}",file=sys.stderr,flush=True)returnresultdefcreate_instance(project_id:str,zone:str,instance_name:str,disks:list[compute_v1.AttachedDisk],machine_type:str="n1-standard-1",network_link:str="global/networks/default",subnetwork_link:str=None,internal_ip:str=None,external_access:bool=False,external_ipv4:str=None,accelerators:list[compute_v1.AcceleratorConfig]=None,preemptible:bool=False,spot:bool=False,instance_termination_action:str="STOP",custom_hostname:str=None,delete_protection:bool=False,)->compute_v1.Instance:"""    Send an instance creation request to the Compute Engine API and wait for it to complete.    Args:        project_id: project ID or project number of the Cloud project you want to use.        zone: name of the zone to create the instance in. For example: "us-west3-b"        instance_name: name of the new virtual machine (VM) instance.        disks: a list of compute_v1.AttachedDisk objects describing the disks            you want to attach to your new instance.        machine_type: machine type of the VM being created. This value uses the            following format: "zones/{zone}/machineTypes/{type_name}".            For example: "zones/europe-west3-c/machineTypes/f1-micro"        network_link: name of the network you want the new instance to use.            For example: "global/networks/default" represents the network            named "default", which is created automatically for each project.        subnetwork_link: name of the subnetwork you want the new instance to use.            This value uses the following format:            "regions/{region}/subnetworks/{subnetwork_name}"        internal_ip: internal IP address you want to assign to the new instance.            By default, a free address from the pool of available internal IP addresses of            used subnet will be used.        external_access: boolean flag indicating if the instance should have an external IPv4            address assigned.        external_ipv4: external IPv4 address to be assigned to this instance. If you specify            an external IP address, it must live in the same region as the zone of the instance.            This setting requires `external_access` to be set to True to work.        accelerators: a list of AcceleratorConfig objects describing the accelerators that will            be attached to the new instance.        preemptible: boolean value indicating if the new instance should be preemptible            or not. Preemptible VMs have been deprecated and you should now use Spot VMs.        spot: boolean value indicating if the new instance should be a Spot VM or not.        instance_termination_action: What action should be taken once a Spot VM is terminated.            Possible values: "STOP", "DELETE"        custom_hostname: Custom hostname of the new VM instance.            Custom hostnames must conform to RFC 1035 requirements for valid hostnames.        delete_protection: boolean value indicating if the new virtual machine should be            protected against deletion or not.    Returns:        Instance object.    """instance_client=compute_v1.InstancesClient()# Use the network interface provided in the network_link argument.network_interface=compute_v1.NetworkInterface()network_interface.network=network_linkifsubnetwork_link:network_interface.subnetwork=subnetwork_linkifinternal_ip:network_interface.network_i_p=internal_ipifexternal_access:access=compute_v1.AccessConfig()access.type_=compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT.nameaccess.name="External NAT"access.network_tier=access.NetworkTier.PREMIUM.nameifexternal_ipv4:access.nat_i_p=external_ipv4network_interface.access_configs=[access]# Collect information into the Instance object.instance=compute_v1.Instance()instance.network_interfaces=[network_interface]instance.name=instance_nameinstance.disks=disksifre.match(r"^zones/[a-z\d\-]+/machineTypes/[a-z\d\-]+$",machine_type):instance.machine_type=machine_typeelse:instance.machine_type=f"zones/{zone}/machineTypes/{machine_type}"instance.scheduling=compute_v1.Scheduling()ifaccelerators:instance.guest_accelerators=acceleratorsinstance.scheduling.on_host_maintenance=(compute_v1.Scheduling.OnHostMaintenance.TERMINATE.name)ifpreemptible:# Set the preemptible settingwarnings.warn("Preemptible VMs are being replaced by Spot VMs.",DeprecationWarning)instance.scheduling=compute_v1.Scheduling()instance.scheduling.preemptible=Trueifspot:# Set the Spot VM settinginstance.scheduling.provisioning_model=(compute_v1.Scheduling.ProvisioningModel.SPOT.name)instance.scheduling.instance_termination_action=instance_termination_actionifcustom_hostnameisnotNone:# Set the custom hostname for the instanceinstance.hostname=custom_hostnameifdelete_protection:# Set the delete protection bitinstance.deletion_protection=True# Prepare the request to insert an instance.request=compute_v1.InsertInstanceRequest()request.zone=zonerequest.project=project_idrequest.instance_resource=instance# Wait for the create operation to complete.print(f"Creating the{instance_name} instance in{zone}...")operation=instance_client.insert(request=request)wait_for_extended_operation(operation,"instance creation")print(f"Instance{instance_name} created.")returninstance_client.get(project=project_id,zone=zone,instance=instance_name)defcreate_preemptible_instance(project_id:str,zone:str,instance_name:str)->compute_v1.Instance:"""    Create a new preemptible VM instance with Debian 10 operating system.    Args:        project_id: project ID or project number of the Cloud project you want to use.        zone: name of the zone to create the instance in. For example: "us-west3-b"        instance_name: name of the new virtual machine (VM) instance.    Returns:        Instance object.    """newest_debian=get_image_from_family(project="debian-cloud",family="debian-11")disk_type=f"zones/{zone}/diskTypes/pd-standard"disks=[disk_from_image(disk_type,10,True,newest_debian.self_link)]instance=create_instance(project_id,zone,instance_name,disks,preemptible=True)returninstance

REST

In the API, construct a normal request tocreate a VM,but include thepreemptible property underscheduling and set it totrue. For example:

POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/instances{  'machineType': 'zones/[ZONE]/machineTypes/[MACHINE_TYPE]',  'name': '[INSTANCE_NAME]',  'scheduling':  {    'preemptible': true  },  ...}

Preemptible CPU quotas

Preemptible VMs require availableCPU quotas like standard VMs. To avoidpreemptible VMs consuming the CPU quotas for your standard VMs,you can request a special "Preemptible CPU" quota. AfterCompute Engine grants you preemptible CPU quota in that region, allpreemptible VMs count against that quota, and all standard VMscontinue to count against the standard CPU quota.

In regions where you don't have preemptible CPU quota, you can use standard CPUquota to launch preemptible VMs. You also need sufficient IP anddisk quota, as usual. Preemptible CPU quota is not visible in the gcloud CLI orGoogle Cloud console quota pages unless Compute Engine has grantedthe quota.

For more information about quotas, visit theResource Quotas page.

Start a preempted VM

Like any other VM, if a preemptible VM is stopped or preempted, you canstart the VMagain and bring it back to theRUNNING state. Starting a preemptible VMresets the 24-hour counter but as it is still a preemptible VM, Compute Enginecan preempt before 24 hours. It isn't possible to convert a preemptibleVM to a standard VM while it's running.

If Compute Engine stops a preemptible VM in an autoscalingmanaged instance group (MIG) or Google Kubernetes Engine (GKE) cluster, thegroup restarts the VM when the resources become available again.

Handle preemption with a shutdown script

When Compute Engine preempts a VM, youcan use ashutdown script to try to perform cleanupactions before the VM is preempted. For example, you can gracefully stop arunning process and copy a checkpoint file toCloud Storage.Notably, the maximum length of the shutdown period is shorter for a preemptionnotice than for a user-initiated shutdown. For more information about theshutdown period for a preemption notice, seePreemption processin the conceptual documentation.

The following is a shutdown script that you can add to a running preemptibleVM or add to a new preemptible VM when you create it. This scriptruns when the VM starts to shut down, before the operatingsystem's normalkill command stops all remaining processes. Aftergracefully stopping the desired program, the script performs a parallelupload of a checkpoint file to a Cloud Storage bucket.

#!/bin/bashMY_PROGRAM="[PROGRAM_NAME]"# For example, "apache2" or "nginx"MY_USER="[LOCAL_USERNAME]"CHECKPOINT="/home/$MY_USER/checkpoint.out"BUCKET_NAME="[BUCKET_NAME]"# For example, "my-checkpoint-files" (without gs://)echo"Shutting down!  Seeing if${MY_PROGRAM} is running."# Find the newest copy of $MY_PROGRAMPID="$(pgrep-n"$MY_PROGRAM")"if[["$?"-ne0]];thenecho"${MY_PROGRAM} not running, shutting down immediately."exit0fiecho"Sending SIGINT to$PID"kill-2"$PID"# Portable waitpid equivalentwhilekill-0"$PID";dosleep1doneecho"$PID is done, copying${CHECKPOINT} to gs://${BUCKET_NAME} as${MY_USER}"su"${MY_USER}"-c"gcloud storage cp$CHECKPOINT gs://${BUCKET_NAME}/"echo"Done uploading, shutting down."

To add this script to a VM, configure the script to work with anapplication on your VM and add it to the VM's metadata.

  1. Copy or download theshutdown script to your local workstation.
  2. Open the file for edit and change the following variables:
    • [PROGRAM_NAME] is the name of the process or program you want to shutdown. For example,apache2 ornginx.
    • [LOCAL_USER] is the username you are logged into the virtual machine as.
    • [BUCKET_NAME] is the name of the Cloud Storage bucket where youwant to save the program's checkpoint file. Note the bucket name does notstart withgs:// in this case.
  3. Save your changes.
  4. Add the shutdown script to anew VMor anexisting VM.

This script assumes the following:

  • The VM was created with at least read/write access to Cloud Storage.See theauthentication documentationfor instructions about how to create a VM with the appropriate scopes.

  • You have an existing Cloud Storage bucket and permission to write toit.

Identify preemptible VMs

To check if a VM is a preemptible VM, follow the steps toIdentify a VM's provisioning model and termination action.

Determine if a VM was preempted

Determine if a VM was preempted with theGoogle Cloud console, thegcloud CLI, or theAPI.

Console

You can check if an VM was preempted by checking the system activitylogs.

  1. In the Google Cloud console, go to theLogs page.

    Go to Logs

  2. Select your project and clickContinue.

  3. Addcompute.instances.preempted to thefilter by label or text search field.

  4. Optionally, you can also entera VM name if you want to see preemption operations for a specificVM.

  5. Press enter to apply the specified filters. The Google Cloud consoleupdates the list of logs to show only the operations where a VMwas preempted.

  6. Select an operation in the list to see details about the VM thatwas preempted.

gcloud


Use thegcloud compute operations listcommand with afilter parameter toget a list of preemption events in your project.

gcloud compute operations list \    --filter="operationType=compute.instances.preempted"

You can use the filter param to further scope the results. For example, tosee preemption events only for VMs within a managed instance group:

gcloudcomputeoperationslist\--filter="operationType=compute.instances.preempted AND targetLink:instances/[BASE_VM_NAME]"

gcloud returns a response similar to:

NAME                  TYPE                         TARGET                                   HTTP_STATUS STATUS TIMESTAMPsystemevent-xxxxxxxx  compute.instances.preempted  us-central1-f/instances/example-vm-xxx  200         DONE   2015-04-02T12:12:10.881-07:00

An operation type ofcompute.instances.preempted indicates that theVM was preempted. You can use theoperations describe command to getmore information about a specific preemption operation.

gcloud compute operations describe \    systemevent-xxxxxxxx

gcloud returns a response similar to:

...operationType: compute.instances.preemptedprogress: 100selfLink: https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-f/operations/systemevent-xxxxxxxxstartTime: '2015-04-02T12:12:10.881-07:00'status: DONEstatusMessage: Instance was preempted....

REST


To get a list of recent system operations, send aGET request to the URIof zone operations.

GET https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/operations

The response contains a list of recent operations.

{  "kind": "compute#operation",  "id": "15041793718812375371",  "name": "systemevent-xxxxxxxx",  "zone": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-f",  "operationType": "compute.instances.preempted",  "targetLink": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-f/instances/example-vm",  "targetId": "12820389800990687210",  "status": "DONE",  "statusMessage": "Instance was preempted.",  ...}

To scope the response to show only preemption operations, you can add afilter to your API request:operationType="compute.instances.preempted". To see preemption operationsfor a specific VM, add atargetLink param to the filter:operationType="compute.instances.preempted" ANDtargetLink="https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/instances/[VM_NAME]".

Alternatively, you can determine if a VM was preempted from inside theVM itself. This is useful if you want to handle a shutdown due to aCompute Engine preemption differently from a normalshutdown in ashutdown script. To do this, simply checkthe metadata server for thepreempted value in your VM'sdefault instance metadata.

For example, usecurl from within your VM to obtain the value forpreempted:

curl "http://metadata.google.internal/computeMetadata/v1/instance/preempted" -H "Metadata-Flavor: Google"TRUE

If this value isTRUE, the VM was preempted by Compute Engine,otherwise it isFALSE.

If you want to use this outside of a shutdown script, you can append?wait_for_change=trueto the URL. This performs a hanging HTTP GET requestthat only returns when the metadata has changed and the VM has beenpreempted.

curl "http://metadata.google.internal/computeMetadata/v1/instance/preempted?wait_for_change=true" -H "Metadata-Flavor: Google"TRUE

Test preemption settings

You can run simulated maintenance events on yourVMs to force them to preempt. Use this feature to test how your appshandle preemptible VMs. Readtesting your availability policiesto learn how to test maintenance events on your VMs.

You can also simulate a VM's preemption bystopping the VM,which can be used instead of simulating a maintenance event and which avoids quotalimits.

Best practices

Here are some best practices to help you get the most out of preemptibleVM instances.

Using the bulk instance API

Rather than creating single VMs, you canuse the bulk instanceAPI.

Pick smaller machine shapes

Resources for preemptible VMs come out of excess and backup Google Cloudcapacity. Capacity is often easier to get forsmaller machine types, meaningmachine types with less resources like vCPUs and memory. You might find morecapacity for preemptible VMs by selecting a smaller custom machine type, butcapacity is even more likely for smaller predefined machine types. Forexample, compared to capacity for then2-standard-32 predefinedmachine type, capacity for then2-custom-24-96 custom machine type ismore likely, but capacity for then2-standard-16 predefined machine typeis even more likely.

Run large preemptible VM clusters during off peak times

The load on Google Cloud data centers varies withlocation and time of day, but generally lowest on nights and weekends. As such,nights and weekends are the best times to run large preemptible VM clusters.

Design your applications to be fault and preemption tolerant

It's important to be prepared for the fact that there are changes inpreemption patterns at different points in time. For example,if a zone suffers a partial outage, large numbers of preemptible VMscould be preempted to make room for standard VMs that need to bemoved as part of the recovery. In that small window of time, the preemption ratewould look very different than on any other day. If your application assumesthat preemptions are always done in small groups, you might not be preparedfor such an event. You can test your application's behavior under a preemptionevent by stopping the VM instance.

Retry creating VMs that have been preempted

If your VM instance been preempted, try creating new preemptible VMsonce or twice before falling back to standard VMs. Depending on yourrequirements, it might be a good idea to combine standard and preemptibleVMs in your clusters to ensure that work proceeds at an adequate pace.

Use shutdown scripts

Manage shutdown and preemption notices with ashutdown script that can save a job's progressso that it can pick up where it left off, rather than start over from scratch.

What's next?

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.