Configure GCP Instance Group Managers

The gcp:compute/instanceGroupManager:InstanceGroupManager resource, part of the Pulumi GCP provider, manages pools of homogeneous Compute Engine instances from a common template, handling creation, health monitoring, and version management. 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 hardware.

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 templates, networking, and load balancing configuration.

Deploy instances with health checks and auto-healing

Most managed instance groups start with a single instance template and health checks that automatically replace unhealthy instances.

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

The versions property specifies which instance template to use. The autoHealingPolicies property connects a health check and sets initialDelaySec, which delays health checks after instance startup to allow application initialization. When an instance fails health checks, the manager automatically replaces it. The targetSize property sets the desired number of running instances.

Run canary deployments with multiple instance templates

Teams testing new application versions often run a small canary deployment alongside the stable version.

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 contain multiple entries, each with its own instance template. The targetSize property within a version controls how many instances run that template. Here, one instance runs the canary template while the remaining instances run the stable version. This allows gradual traffic shifting as confidence builds.

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.

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 configures how the manager handles stopped and suspended instances. The mode property controls whether standby instances are managed automatically or manually. The targetSuspendedSize and targetStoppedSize properties specify how many instances to keep in each state. Stopped and suspended instances start faster than creating new instances from scratch, reducing scaling latency.

Apply workload policies for specialized hardware

Workloads running on specialized hardware like GPUs or high-throughput machines often need resource policies that optimize scheduling and 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 to the instance group. The ResourcePolicy resource defines the policy type (here, HIGH_THROUGHPUT for high-performance networking). This configuration works with specialized machine types like a4-highgpu-8g, which require specific quotas and are optimized for GPU workloads.

Beyond these examples

These snippets focus on specific instance group manager features: health checks and auto-healing, canary deployments with multiple versions, standby policies for stopped/suspended instances, and resource policies for specialized workloads. They’re intentionally minimal rather than full application deployments.

The examples may reference pre-existing infrastructure such as instance templates, target pools for load balancing, health checks, and VPC networks and subnets implicit 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
  • Instance lifecycle policies
  • Wait conditions for deployment synchronization

These omissions are intentional: the goal is to illustrate how each instance group feature is wired, not provide drop-in compute 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 FREE

Frequently Asked Questions

Resource Selection & Scope
When should I use RegionInstanceGroupManager instead of InstanceGroupManager?
Use gcp.compute.RegionInstanceGroupManager to create a regional (multi-zone) instance group manager. Use InstanceGroupManager for zonal (single-zone) deployments.
Autoscaling & Target Sizes
Why is my autoscaler conflicting with targetSize?
Setting targetSize when using an autoscaler causes conflicts because both try to control instance count. Either don’t set targetSize when using an autoscaler, or use lifecycle.ignore_changes to prevent Pulumi from modifying it.
What's the default value for targetSize?
targetSize defaults to 0, so you must explicitly set it if you want running instances without an autoscaler.
Instance Versions & Updates
How do I implement canary deployments with multiple versions?
Use multiple entries in the versions array, each with a different instanceTemplate. You can specify targetSize.fixed for each version to control the rollout (e.g., 1 canary instance alongside your main version).
Why aren't my allInstancesConfig changes applying to existing instances?
After setting allInstancesConfig, you must manually update the group’s instances to apply the configuration. Changes don’t automatically propagate to existing instances.
What's the difference between STABLE and UPDATED wait status?
STABLE waits until instances are stable. UPDATED waits for the version target to be reached, per-instance configs to be effective, and all instances to be stable before returning.
What happens if I set waitForInstances to true and creation fails?
Pulumi will continue trying until it times out, which can result in long wait times. Consider whether you need synchronous instance creation before enabling this.
Stateful Configuration
How do I preserve disks and IPs across instance updates or deletes?
Use statefulDisks for persistent disks, statefulExternalIps for external IPs, and statefulInternalIps for internal IPs. These resources are preserved on instance delete, update, and other operations.
Health & Lifecycle
How do I configure auto-healing for unhealthy instances?
Set autoHealingPolicies with a healthCheck ID and initialDelaySec (time to wait before checking health on new instances). The health check monitors instances and replaces unhealthy ones.
Can I have stopped or suspended instances in my managed instance group?
Yes, configure standbyPolicy with targetStoppedSize and targetSuspendedSize to maintain a pool of stopped or suspended instances. Set the mode to MANUAL or let the system manage it automatically.
What are named ports used for?
namedPorts define port mappings (name and port number) that load balancers and other services can reference. For example, you might define a customhttp port at 8888 for routing traffic.
Immutability & Constraints
What properties can't I change after creating the instance group manager?
baseInstanceName, name, project, zone, and params are immutable and cannot be changed after creation. You’ll need to recreate the resource to modify these.
What naming constraints apply to the instance group manager?
The name must be 1-63 characters long and comply with RFC1035: lowercase letters, numbers, and hyphens only. The baseInstanceName follows the same rules and is used as a prefix for instance names.

Using a different cloud?

Explore compute guides for other cloud providers: