The gcp:compute/instanceGroupManager:InstanceGroupManager resource, part of the Pulumi GCP provider, manages pools of homogeneous Compute Engine VM instances created from a common instance template. This guide focuses on four capabilities: auto-healing with health checks, canary deployments with multiple versions, standby policies for fast scaling, and resource policies for specialized workloads.
Instance group managers require instance templates and may reference health checks, target pools, or resource policies that must exist separately. The examples are intentionally small. Combine them with your own instance templates, networking, and monitoring infrastructure.
Deploy instances with health checks and auto-healing
Most managed instance groups start with a single instance template and auto-healing to maintain availability.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const autohealing = new gcp.compute.HealthCheck("autohealing", {
name: "autohealing-health-check",
checkIntervalSec: 5,
timeoutSec: 5,
healthyThreshold: 2,
unhealthyThreshold: 10,
httpHealthCheck: {
requestPath: "/healthz",
port: 8080,
},
});
const appserver = new gcp.compute.InstanceGroupManager("appserver", {
name: "appserver-igm",
baseInstanceName: "app",
zone: "us-central1-a",
versions: [{
instanceTemplate: appserverGoogleComputeInstanceTemplate.selfLinkUnique,
}],
allInstancesConfig: {
metadata: {
metadata_key: "metadata_value",
},
labels: {
label_key: "label_value",
},
},
targetPools: [appserverGoogleComputeTargetPool.id],
targetSize: 2,
namedPorts: [{
name: "customhttp",
port: 8888,
}],
autoHealingPolicies: {
healthCheck: autohealing.id,
initialDelaySec: 300,
},
});
import pulumi
import pulumi_gcp as gcp
autohealing = gcp.compute.HealthCheck("autohealing",
name="autohealing-health-check",
check_interval_sec=5,
timeout_sec=5,
healthy_threshold=2,
unhealthy_threshold=10,
http_health_check={
"request_path": "/healthz",
"port": 8080,
})
appserver = gcp.compute.InstanceGroupManager("appserver",
name="appserver-igm",
base_instance_name="app",
zone="us-central1-a",
versions=[{
"instance_template": appserver_google_compute_instance_template["selfLinkUnique"],
}],
all_instances_config={
"metadata": {
"metadata_key": "metadata_value",
},
"labels": {
"label_key": "label_value",
},
},
target_pools=[appserver_google_compute_target_pool["id"]],
target_size=2,
named_ports=[{
"name": "customhttp",
"port": 8888,
}],
auto_healing_policies={
"health_check": autohealing.id,
"initial_delay_sec": 300,
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
autohealing, err := compute.NewHealthCheck(ctx, "autohealing", &compute.HealthCheckArgs{
Name: pulumi.String("autohealing-health-check"),
CheckIntervalSec: pulumi.Int(5),
TimeoutSec: pulumi.Int(5),
HealthyThreshold: pulumi.Int(2),
UnhealthyThreshold: pulumi.Int(10),
HttpHealthCheck: &compute.HealthCheckHttpHealthCheckArgs{
RequestPath: pulumi.String("/healthz"),
Port: pulumi.Int(8080),
},
})
if err != nil {
return err
}
_, err = compute.NewInstanceGroupManager(ctx, "appserver", &compute.InstanceGroupManagerArgs{
Name: pulumi.String("appserver-igm"),
BaseInstanceName: pulumi.String("app"),
Zone: pulumi.String("us-central1-a"),
Versions: compute.InstanceGroupManagerVersionArray{
&compute.InstanceGroupManagerVersionArgs{
InstanceTemplate: pulumi.Any(appserverGoogleComputeInstanceTemplate.SelfLinkUnique),
},
},
AllInstancesConfig: &compute.InstanceGroupManagerAllInstancesConfigArgs{
Metadata: pulumi.StringMap{
"metadata_key": pulumi.String("metadata_value"),
},
Labels: pulumi.StringMap{
"label_key": pulumi.String("label_value"),
},
},
TargetPools: pulumi.StringArray{
appserverGoogleComputeTargetPool.Id,
},
TargetSize: pulumi.Int(2),
NamedPorts: compute.InstanceGroupManagerNamedPortArray{
&compute.InstanceGroupManagerNamedPortArgs{
Name: pulumi.String("customhttp"),
Port: pulumi.Int(8888),
},
},
AutoHealingPolicies: &compute.InstanceGroupManagerAutoHealingPoliciesArgs{
HealthCheck: autohealing.ID(),
InitialDelaySec: pulumi.Int(300),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var autohealing = new Gcp.Compute.HealthCheck("autohealing", new()
{
Name = "autohealing-health-check",
CheckIntervalSec = 5,
TimeoutSec = 5,
HealthyThreshold = 2,
UnhealthyThreshold = 10,
HttpHealthCheck = new Gcp.Compute.Inputs.HealthCheckHttpHealthCheckArgs
{
RequestPath = "/healthz",
Port = 8080,
},
});
var appserver = new Gcp.Compute.InstanceGroupManager("appserver", new()
{
Name = "appserver-igm",
BaseInstanceName = "app",
Zone = "us-central1-a",
Versions = new[]
{
new Gcp.Compute.Inputs.InstanceGroupManagerVersionArgs
{
InstanceTemplate = appserverGoogleComputeInstanceTemplate.SelfLinkUnique,
},
},
AllInstancesConfig = new Gcp.Compute.Inputs.InstanceGroupManagerAllInstancesConfigArgs
{
Metadata =
{
{ "metadata_key", "metadata_value" },
},
Labels =
{
{ "label_key", "label_value" },
},
},
TargetPools = new[]
{
appserverGoogleComputeTargetPool.Id,
},
TargetSize = 2,
NamedPorts = new[]
{
new Gcp.Compute.Inputs.InstanceGroupManagerNamedPortArgs
{
Name = "customhttp",
Port = 8888,
},
},
AutoHealingPolicies = new Gcp.Compute.Inputs.InstanceGroupManagerAutoHealingPoliciesArgs
{
HealthCheck = autohealing.Id,
InitialDelaySec = 300,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.HealthCheck;
import com.pulumi.gcp.compute.HealthCheckArgs;
import com.pulumi.gcp.compute.inputs.HealthCheckHttpHealthCheckArgs;
import com.pulumi.gcp.compute.InstanceGroupManager;
import com.pulumi.gcp.compute.InstanceGroupManagerArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerVersionArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerAllInstancesConfigArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerNamedPortArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerAutoHealingPoliciesArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var autohealing = new HealthCheck("autohealing", HealthCheckArgs.builder()
.name("autohealing-health-check")
.checkIntervalSec(5)
.timeoutSec(5)
.healthyThreshold(2)
.unhealthyThreshold(10)
.httpHealthCheck(HealthCheckHttpHealthCheckArgs.builder()
.requestPath("/healthz")
.port(8080)
.build())
.build());
var appserver = new InstanceGroupManager("appserver", InstanceGroupManagerArgs.builder()
.name("appserver-igm")
.baseInstanceName("app")
.zone("us-central1-a")
.versions(InstanceGroupManagerVersionArgs.builder()
.instanceTemplate(appserverGoogleComputeInstanceTemplate.selfLinkUnique())
.build())
.allInstancesConfig(InstanceGroupManagerAllInstancesConfigArgs.builder()
.metadata(Map.of("metadata_key", "metadata_value"))
.labels(Map.of("label_key", "label_value"))
.build())
.targetPools(appserverGoogleComputeTargetPool.id())
.targetSize(2)
.namedPorts(InstanceGroupManagerNamedPortArgs.builder()
.name("customhttp")
.port(8888)
.build())
.autoHealingPolicies(InstanceGroupManagerAutoHealingPoliciesArgs.builder()
.healthCheck(autohealing.id())
.initialDelaySec(300)
.build())
.build());
}
}
resources:
autohealing:
type: gcp:compute:HealthCheck
properties:
name: autohealing-health-check
checkIntervalSec: 5
timeoutSec: 5
healthyThreshold: 2
unhealthyThreshold: 10 # 50 seconds
httpHealthCheck:
requestPath: /healthz
port: '8080'
appserver:
type: gcp:compute:InstanceGroupManager
properties:
name: appserver-igm
baseInstanceName: app
zone: us-central1-a
versions:
- instanceTemplate: ${appserverGoogleComputeInstanceTemplate.selfLinkUnique}
allInstancesConfig:
metadata:
metadata_key: metadata_value
labels:
label_key: label_value
targetPools:
- ${appserverGoogleComputeTargetPool.id}
targetSize: 2
namedPorts:
- name: customhttp
port: 8888
autoHealingPolicies:
healthCheck: ${autohealing.id}
initialDelaySec: 300
When health checks detect unhealthy instances, the group automatically replaces them. The autoHealingPolicies property connects to a health check and sets initialDelaySec to allow instances time to start before monitoring begins. The versions array specifies which instance template to use, and targetSize controls the number of running instances.
Run canary deployments with multiple instance versions
Teams rolling out new application versions often run a small canary deployment alongside the stable version to validate changes.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const appserver = new gcp.compute.InstanceGroupManager("appserver", {
name: "appserver-igm",
baseInstanceName: "app",
zone: "us-central1-a",
targetSize: 5,
versions: [
{
name: "appserver",
instanceTemplate: appserverGoogleComputeInstanceTemplate.selfLinkUnique,
},
{
name: "appserver-canary",
instanceTemplate: appserver_canary.selfLinkUnique,
targetSize: {
fixed: 1,
},
},
],
});
import pulumi
import pulumi_gcp as gcp
appserver = gcp.compute.InstanceGroupManager("appserver",
name="appserver-igm",
base_instance_name="app",
zone="us-central1-a",
target_size=5,
versions=[
{
"name": "appserver",
"instance_template": appserver_google_compute_instance_template["selfLinkUnique"],
},
{
"name": "appserver-canary",
"instance_template": appserver_canary["selfLinkUnique"],
"target_size": {
"fixed": 1,
},
},
])
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewInstanceGroupManager(ctx, "appserver", &compute.InstanceGroupManagerArgs{
Name: pulumi.String("appserver-igm"),
BaseInstanceName: pulumi.String("app"),
Zone: pulumi.String("us-central1-a"),
TargetSize: pulumi.Int(5),
Versions: compute.InstanceGroupManagerVersionArray{
&compute.InstanceGroupManagerVersionArgs{
Name: pulumi.String("appserver"),
InstanceTemplate: pulumi.Any(appserverGoogleComputeInstanceTemplate.SelfLinkUnique),
},
&compute.InstanceGroupManagerVersionArgs{
Name: pulumi.String("appserver-canary"),
InstanceTemplate: pulumi.Any(appserver_canary.SelfLinkUnique),
TargetSize: &compute.InstanceGroupManagerVersionTargetSizeArgs{
Fixed: pulumi.Int(1),
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var appserver = new Gcp.Compute.InstanceGroupManager("appserver", new()
{
Name = "appserver-igm",
BaseInstanceName = "app",
Zone = "us-central1-a",
TargetSize = 5,
Versions = new[]
{
new Gcp.Compute.Inputs.InstanceGroupManagerVersionArgs
{
Name = "appserver",
InstanceTemplate = appserverGoogleComputeInstanceTemplate.SelfLinkUnique,
},
new Gcp.Compute.Inputs.InstanceGroupManagerVersionArgs
{
Name = "appserver-canary",
InstanceTemplate = appserver_canary.SelfLinkUnique,
TargetSize = new Gcp.Compute.Inputs.InstanceGroupManagerVersionTargetSizeArgs
{
Fixed = 1,
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.InstanceGroupManager;
import com.pulumi.gcp.compute.InstanceGroupManagerArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerVersionArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerVersionTargetSizeArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var appserver = new InstanceGroupManager("appserver", InstanceGroupManagerArgs.builder()
.name("appserver-igm")
.baseInstanceName("app")
.zone("us-central1-a")
.targetSize(5)
.versions(
InstanceGroupManagerVersionArgs.builder()
.name("appserver")
.instanceTemplate(appserverGoogleComputeInstanceTemplate.selfLinkUnique())
.build(),
InstanceGroupManagerVersionArgs.builder()
.name("appserver-canary")
.instanceTemplate(appserver_canary.selfLinkUnique())
.targetSize(InstanceGroupManagerVersionTargetSizeArgs.builder()
.fixed(1)
.build())
.build())
.build());
}
}
resources:
appserver:
type: gcp:compute:InstanceGroupManager
properties:
name: appserver-igm
baseInstanceName: app
zone: us-central1-a
targetSize: 5
versions:
- name: appserver
instanceTemplate: ${appserverGoogleComputeInstanceTemplate.selfLinkUnique}
- name: appserver-canary
instanceTemplate: ${["appserver-canary"].selfLinkUnique}
targetSize:
fixed: 1
The versions array can include multiple entries, each with its own instance template. Setting targetSize with a fixed value on the canary version limits how many instances run the new code. The remaining instances use the primary version, allowing you to test changes with a subset of traffic before full rollout.
Maintain stopped and suspended instances for fast scaling
Applications with predictable traffic spikes can pre-provision stopped or suspended instances that start faster than creating new instances from scratch.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const igm_sr = new gcp.compute.InstanceGroupManager("igm-sr", {
name: "tf-sr-igm",
baseInstanceName: "tf-sr-igm-instance",
zone: "us-central1-a",
targetSize: 5,
versions: [{
instanceTemplate: sr_igm.selfLink,
name: "primary",
}],
standbyPolicy: {
initialDelaySec: 30,
mode: "MANUAL",
},
targetSuspendedSize: 2,
targetStoppedSize: 1,
});
import pulumi
import pulumi_gcp as gcp
igm_sr = gcp.compute.InstanceGroupManager("igm-sr",
name="tf-sr-igm",
base_instance_name="tf-sr-igm-instance",
zone="us-central1-a",
target_size=5,
versions=[{
"instance_template": sr_igm["selfLink"],
"name": "primary",
}],
standby_policy={
"initial_delay_sec": 30,
"mode": "MANUAL",
},
target_suspended_size=2,
target_stopped_size=1)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewInstanceGroupManager(ctx, "igm-sr", &compute.InstanceGroupManagerArgs{
Name: pulumi.String("tf-sr-igm"),
BaseInstanceName: pulumi.String("tf-sr-igm-instance"),
Zone: pulumi.String("us-central1-a"),
TargetSize: pulumi.Int(5),
Versions: compute.InstanceGroupManagerVersionArray{
&compute.InstanceGroupManagerVersionArgs{
InstanceTemplate: pulumi.Any(sr_igm.SelfLink),
Name: pulumi.String("primary"),
},
},
StandbyPolicy: &compute.InstanceGroupManagerStandbyPolicyArgs{
InitialDelaySec: pulumi.Int(30),
Mode: pulumi.String("MANUAL"),
},
TargetSuspendedSize: pulumi.Int(2),
TargetStoppedSize: pulumi.Int(1),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var igm_sr = new Gcp.Compute.InstanceGroupManager("igm-sr", new()
{
Name = "tf-sr-igm",
BaseInstanceName = "tf-sr-igm-instance",
Zone = "us-central1-a",
TargetSize = 5,
Versions = new[]
{
new Gcp.Compute.Inputs.InstanceGroupManagerVersionArgs
{
InstanceTemplate = sr_igm.SelfLink,
Name = "primary",
},
},
StandbyPolicy = new Gcp.Compute.Inputs.InstanceGroupManagerStandbyPolicyArgs
{
InitialDelaySec = 30,
Mode = "MANUAL",
},
TargetSuspendedSize = 2,
TargetStoppedSize = 1,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.InstanceGroupManager;
import com.pulumi.gcp.compute.InstanceGroupManagerArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerVersionArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerStandbyPolicyArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var igm_sr = new InstanceGroupManager("igm-sr", InstanceGroupManagerArgs.builder()
.name("tf-sr-igm")
.baseInstanceName("tf-sr-igm-instance")
.zone("us-central1-a")
.targetSize(5)
.versions(InstanceGroupManagerVersionArgs.builder()
.instanceTemplate(sr_igm.selfLink())
.name("primary")
.build())
.standbyPolicy(InstanceGroupManagerStandbyPolicyArgs.builder()
.initialDelaySec(30)
.mode("MANUAL")
.build())
.targetSuspendedSize(2)
.targetStoppedSize(1)
.build());
}
}
resources:
igm-sr:
type: gcp:compute:InstanceGroupManager
properties:
name: tf-sr-igm
baseInstanceName: tf-sr-igm-instance
zone: us-central1-a
targetSize: 5
versions:
- instanceTemplate: ${["sr-igm"].selfLink}
name: primary
standbyPolicy:
initialDelaySec: 30
mode: MANUAL
targetSuspendedSize: 2
targetStoppedSize: 1
The standbyPolicy property controls how the group manages stopped and suspended instances. Setting mode to MANUAL prevents automatic transitions, while targetSuspendedSize and targetStoppedSize specify how many instances to keep in each state. These instances start faster than provisioning new ones, reducing scaling latency during traffic spikes.
Apply workload policies for specialized hardware
High-performance workloads on specialized hardware benefit from resource policies that optimize instance placement.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const myImage = gcp.compute.getImage({
family: "debian-11",
project: "debian-cloud",
});
const workloadPolicy = new gcp.compute.ResourcePolicy("workload_policy", {
name: "tf-test-gce-policy",
region: "us-central1",
workloadPolicy: {
type: "HIGH_THROUGHPUT",
},
});
const igm_basic = new gcp.compute.InstanceTemplate("igm-basic", {
name: "igm-instance-template",
machineType: "a4-highgpu-8g",
canIpForward: false,
tags: [
"foo",
"bar",
],
disks: [{
sourceImage: myImage.then(myImage => myImage.selfLink),
autoDelete: true,
boot: true,
diskType: "hyperdisk-balanced",
}],
networkInterfaces: [{
network: "default",
}],
serviceAccount: {
scopes: [
"userinfo-email",
"compute-ro",
"storage-ro",
],
},
});
const igm_workload_policy = new gcp.compute.InstanceGroupManager("igm-workload-policy", {
description: "Terraform test instance group manager",
name: "igm-basic-workload-policy",
versions: [{
name: "prod",
instanceTemplate: igm_basic.selfLink,
}],
baseInstanceName: "tf-test-igm-no-tp",
zone: "us-central1-b",
targetSize: 0,
resourcePolicies: {
workloadPolicy: workloadPolicy.selfLink,
},
});
import pulumi
import pulumi_gcp as gcp
my_image = gcp.compute.get_image(family="debian-11",
project="debian-cloud")
workload_policy = gcp.compute.ResourcePolicy("workload_policy",
name="tf-test-gce-policy",
region="us-central1",
workload_policy={
"type": "HIGH_THROUGHPUT",
})
igm_basic = gcp.compute.InstanceTemplate("igm-basic",
name="igm-instance-template",
machine_type="a4-highgpu-8g",
can_ip_forward=False,
tags=[
"foo",
"bar",
],
disks=[{
"source_image": my_image.self_link,
"auto_delete": True,
"boot": True,
"disk_type": "hyperdisk-balanced",
}],
network_interfaces=[{
"network": "default",
}],
service_account={
"scopes": [
"userinfo-email",
"compute-ro",
"storage-ro",
],
})
igm_workload_policy = gcp.compute.InstanceGroupManager("igm-workload-policy",
description="Terraform test instance group manager",
name="igm-basic-workload-policy",
versions=[{
"name": "prod",
"instance_template": igm_basic.self_link,
}],
base_instance_name="tf-test-igm-no-tp",
zone="us-central1-b",
target_size=0,
resource_policies={
"workload_policy": workload_policy.self_link,
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
myImage, err := compute.LookupImage(ctx, &compute.LookupImageArgs{
Family: pulumi.StringRef("debian-11"),
Project: pulumi.StringRef("debian-cloud"),
}, nil)
if err != nil {
return err
}
workloadPolicy, err := compute.NewResourcePolicy(ctx, "workload_policy", &compute.ResourcePolicyArgs{
Name: pulumi.String("tf-test-gce-policy"),
Region: pulumi.String("us-central1"),
WorkloadPolicy: &compute.ResourcePolicyWorkloadPolicyArgs{
Type: pulumi.String("HIGH_THROUGHPUT"),
},
})
if err != nil {
return err
}
igm_basic, err := compute.NewInstanceTemplate(ctx, "igm-basic", &compute.InstanceTemplateArgs{
Name: pulumi.String("igm-instance-template"),
MachineType: pulumi.String("a4-highgpu-8g"),
CanIpForward: pulumi.Bool(false),
Tags: pulumi.StringArray{
pulumi.String("foo"),
pulumi.String("bar"),
},
Disks: compute.InstanceTemplateDiskArray{
&compute.InstanceTemplateDiskArgs{
SourceImage: pulumi.String(myImage.SelfLink),
AutoDelete: pulumi.Bool(true),
Boot: pulumi.Bool(true),
DiskType: pulumi.String("hyperdisk-balanced"),
},
},
NetworkInterfaces: compute.InstanceTemplateNetworkInterfaceArray{
&compute.InstanceTemplateNetworkInterfaceArgs{
Network: pulumi.String("default"),
},
},
ServiceAccount: &compute.InstanceTemplateServiceAccountArgs{
Scopes: pulumi.StringArray{
pulumi.String("userinfo-email"),
pulumi.String("compute-ro"),
pulumi.String("storage-ro"),
},
},
})
if err != nil {
return err
}
_, err = compute.NewInstanceGroupManager(ctx, "igm-workload-policy", &compute.InstanceGroupManagerArgs{
Description: pulumi.String("Terraform test instance group manager"),
Name: pulumi.String("igm-basic-workload-policy"),
Versions: compute.InstanceGroupManagerVersionArray{
&compute.InstanceGroupManagerVersionArgs{
Name: pulumi.String("prod"),
InstanceTemplate: igm_basic.SelfLink,
},
},
BaseInstanceName: pulumi.String("tf-test-igm-no-tp"),
Zone: pulumi.String("us-central1-b"),
TargetSize: pulumi.Int(0),
ResourcePolicies: &compute.InstanceGroupManagerResourcePoliciesArgs{
WorkloadPolicy: workloadPolicy.SelfLink,
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var myImage = Gcp.Compute.GetImage.Invoke(new()
{
Family = "debian-11",
Project = "debian-cloud",
});
var workloadPolicy = new Gcp.Compute.ResourcePolicy("workload_policy", new()
{
Name = "tf-test-gce-policy",
Region = "us-central1",
WorkloadPolicy = new Gcp.Compute.Inputs.ResourcePolicyWorkloadPolicyArgs
{
Type = "HIGH_THROUGHPUT",
},
});
var igm_basic = new Gcp.Compute.InstanceTemplate("igm-basic", new()
{
Name = "igm-instance-template",
MachineType = "a4-highgpu-8g",
CanIpForward = false,
Tags = new[]
{
"foo",
"bar",
},
Disks = new[]
{
new Gcp.Compute.Inputs.InstanceTemplateDiskArgs
{
SourceImage = myImage.Apply(getImageResult => getImageResult.SelfLink),
AutoDelete = true,
Boot = true,
DiskType = "hyperdisk-balanced",
},
},
NetworkInterfaces = new[]
{
new Gcp.Compute.Inputs.InstanceTemplateNetworkInterfaceArgs
{
Network = "default",
},
},
ServiceAccount = new Gcp.Compute.Inputs.InstanceTemplateServiceAccountArgs
{
Scopes = new[]
{
"userinfo-email",
"compute-ro",
"storage-ro",
},
},
});
var igm_workload_policy = new Gcp.Compute.InstanceGroupManager("igm-workload-policy", new()
{
Description = "Terraform test instance group manager",
Name = "igm-basic-workload-policy",
Versions = new[]
{
new Gcp.Compute.Inputs.InstanceGroupManagerVersionArgs
{
Name = "prod",
InstanceTemplate = igm_basic.SelfLink,
},
},
BaseInstanceName = "tf-test-igm-no-tp",
Zone = "us-central1-b",
TargetSize = 0,
ResourcePolicies = new Gcp.Compute.Inputs.InstanceGroupManagerResourcePoliciesArgs
{
WorkloadPolicy = workloadPolicy.SelfLink,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.ComputeFunctions;
import com.pulumi.gcp.compute.inputs.GetImageArgs;
import com.pulumi.gcp.compute.ResourcePolicy;
import com.pulumi.gcp.compute.ResourcePolicyArgs;
import com.pulumi.gcp.compute.inputs.ResourcePolicyWorkloadPolicyArgs;
import com.pulumi.gcp.compute.InstanceTemplate;
import com.pulumi.gcp.compute.InstanceTemplateArgs;
import com.pulumi.gcp.compute.inputs.InstanceTemplateDiskArgs;
import com.pulumi.gcp.compute.inputs.InstanceTemplateNetworkInterfaceArgs;
import com.pulumi.gcp.compute.inputs.InstanceTemplateServiceAccountArgs;
import com.pulumi.gcp.compute.InstanceGroupManager;
import com.pulumi.gcp.compute.InstanceGroupManagerArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerVersionArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerResourcePoliciesArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var myImage = ComputeFunctions.getImage(GetImageArgs.builder()
.family("debian-11")
.project("debian-cloud")
.build());
var workloadPolicy = new ResourcePolicy("workloadPolicy", ResourcePolicyArgs.builder()
.name("tf-test-gce-policy")
.region("us-central1")
.workloadPolicy(ResourcePolicyWorkloadPolicyArgs.builder()
.type("HIGH_THROUGHPUT")
.build())
.build());
var igm_basic = new InstanceTemplate("igm-basic", InstanceTemplateArgs.builder()
.name("igm-instance-template")
.machineType("a4-highgpu-8g")
.canIpForward(false)
.tags(
"foo",
"bar")
.disks(InstanceTemplateDiskArgs.builder()
.sourceImage(myImage.selfLink())
.autoDelete(true)
.boot(true)
.diskType("hyperdisk-balanced")
.build())
.networkInterfaces(InstanceTemplateNetworkInterfaceArgs.builder()
.network("default")
.build())
.serviceAccount(InstanceTemplateServiceAccountArgs.builder()
.scopes(
"userinfo-email",
"compute-ro",
"storage-ro")
.build())
.build());
var igm_workload_policy = new InstanceGroupManager("igm-workload-policy", InstanceGroupManagerArgs.builder()
.description("Terraform test instance group manager")
.name("igm-basic-workload-policy")
.versions(InstanceGroupManagerVersionArgs.builder()
.name("prod")
.instanceTemplate(igm_basic.selfLink())
.build())
.baseInstanceName("tf-test-igm-no-tp")
.zone("us-central1-b")
.targetSize(0)
.resourcePolicies(InstanceGroupManagerResourcePoliciesArgs.builder()
.workloadPolicy(workloadPolicy.selfLink())
.build())
.build());
}
}
resources:
workloadPolicy:
type: gcp:compute:ResourcePolicy
name: workload_policy
properties:
name: tf-test-gce-policy
region: us-central1
workloadPolicy:
type: HIGH_THROUGHPUT
igm-basic:
type: gcp:compute:InstanceTemplate
properties:
name: igm-instance-template
machineType: a4-highgpu-8g
canIpForward: false
tags:
- foo
- bar
disks:
- sourceImage: ${myImage.selfLink}
autoDelete: true
boot: true
diskType: hyperdisk-balanced
networkInterfaces:
- network: default
serviceAccount:
scopes:
- userinfo-email
- compute-ro
- storage-ro
igm-workload-policy:
type: gcp:compute:InstanceGroupManager
properties:
description: Terraform test instance group manager
name: igm-basic-workload-policy
versions:
- name: prod
instanceTemplate: ${["igm-basic"].selfLink}
baseInstanceName: tf-test-igm-no-tp
zone: us-central1-b
targetSize: 0
resourcePolicies:
workloadPolicy: ${workloadPolicy.selfLink}
variables:
myImage:
fn::invoke:
function: gcp:compute:getImage
arguments:
family: debian-11
project: debian-cloud
The resourcePolicies property attaches a workload policy that optimizes instance configuration for specific hardware. In this example, the HIGH_THROUGHPUT policy optimizes networking for GPU workloads on a4-highgpu-8g machine types. The policy must be created separately and referenced by self-link.
Beyond these examples
These snippets focus on specific instance group manager features: auto-healing and health monitoring, canary deployments and version management, and standby policies and resource optimization. They’re intentionally minimal rather than full VM deployment solutions.
The examples rely on pre-existing infrastructure such as instance templates with application configuration, health checks, target pools, and load balancers, and VPC networks and subnets referenced in templates. They focus on configuring the instance group manager rather than provisioning everything around it.
To keep things focused, common instance group patterns are omitted, including:
- Update policies for rolling updates (updatePolicy)
- Stateful disk and IP preservation (statefulDisks, statefulExternalIps)
- Named ports for service discovery
- Wait conditions for deployment synchronization (waitForInstances)
These omissions are intentional: the goal is to illustrate how each instance group manager feature is wired, not provide drop-in VM management modules. See the Instance Group Manager resource reference for all available configuration options.
Let's configure GCP Instance Group Managers
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Regional vs Zonal Deployment
gcp.compute.RegionInstanceGroupManager to create a regional (multi-zone) instance group manager for higher availability across multiple zones.Instance Configuration & Immutability
baseInstanceName, name, zone, project, and params. Changing these requires recreating the resource.baseInstanceName. The base name must be RFC1035-compliant (lowercase letters, numbers, hyphens).Scaling & Target Sizes
targetSize should never be set because the autoscaler manages the size automatically. Set targetSize explicitly only when not using an autoscaler.targetSize controls running instances, targetStoppedSize controls stopped instances, and targetSuspendedSize controls suspended instances. Use standbyPolicy to manage stopped and suspended instances.Updates & Rollouts
versions array, each with a name and instanceTemplate. Use targetSize.fixed to control how many instances run each version (e.g., fixed: 1 for a single canary instance).STABLE waits until instances are stable before returning. UPDATED waits for the version target to be reached, per-instance configs to be effective, and all instances to be stable.waitForInstances is true and the operation doesn’t succeed, Pulumi will continue trying until it times out. Use this setting with caution and consider appropriate timeout values.allInstancesConfig (metadata or labels), you must manually update the group’s instances to apply the configuration. The changes don’t automatically propagate to existing instances.Health & Auto-healing
initialDelaySec parameter delays health checks after instance creation. The example shows 300 seconds (5 minutes), which gives instances time to start up before health checks begin.Networking & Load Balancing
namedPorts array with name and port fields. For example, name: "customhttp" with port: 8888 creates a named port for load balancer backends.targetPools attribute only affects new instances added to the group. Existing instances remain in their original target pools.statefulDisks for disks, statefulExternalIps for external IPs, and statefulInternalIps for internal IPs. These resources are preserved on instance delete, update, and other operations.