The gcp:compute/regionInstanceGroupManager:RegionInstanceGroupManager resource, part of the Pulumi GCP provider, manages pools of identical Compute Engine VMs across multiple zones in a region, using a shared instance template. This guide focuses on three capabilities: multi-zone distribution with auto-healing, canary deployments with version management, and standby instances for rapid scaling.
Regional instance group managers require instance templates and may reference health checks or target pools that must exist separately. The examples are intentionally small. Combine them with your own templates, health checks, and load balancing configuration.
Deploy a managed instance group with auto-healing
Most deployments distribute identical VMs across multiple zones for high availability and configure health checks to replace unhealthy instances automatically.
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.RegionInstanceGroupManager("appserver", {
name: "appserver-igm",
baseInstanceName: "app",
region: "us-central1",
distributionPolicyZones: [
"us-central1-a",
"us-central1-f",
],
versions: [{
instanceTemplate: appserverGoogleComputeInstanceTemplate.selfLinkUnique,
}],
allInstancesConfig: {
metadata: {
metadata_key: "metadata_value",
},
labels: {
label_key: "label_value",
},
},
targetPools: [appserverGoogleComputeTargetPool.id],
targetSize: 2,
namedPorts: [{
name: "custom",
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.RegionInstanceGroupManager("appserver",
name="appserver-igm",
base_instance_name="app",
region="us-central1",
distribution_policy_zones=[
"us-central1-a",
"us-central1-f",
],
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": "custom",
"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.NewRegionInstanceGroupManager(ctx, "appserver", &compute.RegionInstanceGroupManagerArgs{
Name: pulumi.String("appserver-igm"),
BaseInstanceName: pulumi.String("app"),
Region: pulumi.String("us-central1"),
DistributionPolicyZones: pulumi.StringArray{
pulumi.String("us-central1-a"),
pulumi.String("us-central1-f"),
},
Versions: compute.RegionInstanceGroupManagerVersionArray{
&compute.RegionInstanceGroupManagerVersionArgs{
InstanceTemplate: pulumi.Any(appserverGoogleComputeInstanceTemplate.SelfLinkUnique),
},
},
AllInstancesConfig: &compute.RegionInstanceGroupManagerAllInstancesConfigArgs{
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.RegionInstanceGroupManagerNamedPortArray{
&compute.RegionInstanceGroupManagerNamedPortArgs{
Name: pulumi.String("custom"),
Port: pulumi.Int(8888),
},
},
AutoHealingPolicies: &compute.RegionInstanceGroupManagerAutoHealingPoliciesArgs{
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.RegionInstanceGroupManager("appserver", new()
{
Name = "appserver-igm",
BaseInstanceName = "app",
Region = "us-central1",
DistributionPolicyZones = new[]
{
"us-central1-a",
"us-central1-f",
},
Versions = new[]
{
new Gcp.Compute.Inputs.RegionInstanceGroupManagerVersionArgs
{
InstanceTemplate = appserverGoogleComputeInstanceTemplate.SelfLinkUnique,
},
},
AllInstancesConfig = new Gcp.Compute.Inputs.RegionInstanceGroupManagerAllInstancesConfigArgs
{
Metadata =
{
{ "metadata_key", "metadata_value" },
},
Labels =
{
{ "label_key", "label_value" },
},
},
TargetPools = new[]
{
appserverGoogleComputeTargetPool.Id,
},
TargetSize = 2,
NamedPorts = new[]
{
new Gcp.Compute.Inputs.RegionInstanceGroupManagerNamedPortArgs
{
Name = "custom",
Port = 8888,
},
},
AutoHealingPolicies = new Gcp.Compute.Inputs.RegionInstanceGroupManagerAutoHealingPoliciesArgs
{
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.RegionInstanceGroupManager;
import com.pulumi.gcp.compute.RegionInstanceGroupManagerArgs;
import com.pulumi.gcp.compute.inputs.RegionInstanceGroupManagerVersionArgs;
import com.pulumi.gcp.compute.inputs.RegionInstanceGroupManagerAllInstancesConfigArgs;
import com.pulumi.gcp.compute.inputs.RegionInstanceGroupManagerNamedPortArgs;
import com.pulumi.gcp.compute.inputs.RegionInstanceGroupManagerAutoHealingPoliciesArgs;
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 RegionInstanceGroupManager("appserver", RegionInstanceGroupManagerArgs.builder()
.name("appserver-igm")
.baseInstanceName("app")
.region("us-central1")
.distributionPolicyZones(
"us-central1-a",
"us-central1-f")
.versions(RegionInstanceGroupManagerVersionArgs.builder()
.instanceTemplate(appserverGoogleComputeInstanceTemplate.selfLinkUnique())
.build())
.allInstancesConfig(RegionInstanceGroupManagerAllInstancesConfigArgs.builder()
.metadata(Map.of("metadata_key", "metadata_value"))
.labels(Map.of("label_key", "label_value"))
.build())
.targetPools(appserverGoogleComputeTargetPool.id())
.targetSize(2)
.namedPorts(RegionInstanceGroupManagerNamedPortArgs.builder()
.name("custom")
.port(8888)
.build())
.autoHealingPolicies(RegionInstanceGroupManagerAutoHealingPoliciesArgs.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:RegionInstanceGroupManager
properties:
name: appserver-igm
baseInstanceName: app
region: us-central1
distributionPolicyZones:
- us-central1-a
- us-central1-f
versions:
- instanceTemplate: ${appserverGoogleComputeInstanceTemplate.selfLinkUnique}
allInstancesConfig:
metadata:
metadata_key: metadata_value
labels:
label_key: label_value
targetPools:
- ${appserverGoogleComputeTargetPool.id}
targetSize: 2
namedPorts:
- name: custom
port: 8888
autoHealingPolicies:
healthCheck: ${autohealing.id}
initialDelaySec: 300
The versions property specifies which instance template to use. The distributionPolicyZones array spreads instances across zones for fault tolerance. When an instance fails its health check, the autoHealingPolicies configuration triggers replacement after the initialDelaySec grace period. The allInstancesConfig applies metadata and labels to all VMs in the group.
Run canary deployments with multiple instance templates
Teams testing new application versions often run a canary deployment, where a small subset of instances uses the new template while most remain stable.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const appserver = new gcp.compute.RegionInstanceGroupManager("appserver", {
name: "appserver-igm",
baseInstanceName: "app",
region: "us-central1",
targetSize: 5,
versions: [
{
instanceTemplate: appserverGoogleComputeInstanceTemplate.selfLinkUnique,
},
{
instanceTemplate: appserver_canary.selfLinkUnique,
targetSize: {
fixed: 1,
},
},
],
});
import pulumi
import pulumi_gcp as gcp
appserver = gcp.compute.RegionInstanceGroupManager("appserver",
name="appserver-igm",
base_instance_name="app",
region="us-central1",
target_size=5,
versions=[
{
"instance_template": appserver_google_compute_instance_template["selfLinkUnique"],
},
{
"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.NewRegionInstanceGroupManager(ctx, "appserver", &compute.RegionInstanceGroupManagerArgs{
Name: pulumi.String("appserver-igm"),
BaseInstanceName: pulumi.String("app"),
Region: pulumi.String("us-central1"),
TargetSize: pulumi.Int(5),
Versions: compute.RegionInstanceGroupManagerVersionArray{
&compute.RegionInstanceGroupManagerVersionArgs{
InstanceTemplate: pulumi.Any(appserverGoogleComputeInstanceTemplate.SelfLinkUnique),
},
&compute.RegionInstanceGroupManagerVersionArgs{
InstanceTemplate: pulumi.Any(appserver_canary.SelfLinkUnique),
TargetSize: &compute.RegionInstanceGroupManagerVersionTargetSizeArgs{
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.RegionInstanceGroupManager("appserver", new()
{
Name = "appserver-igm",
BaseInstanceName = "app",
Region = "us-central1",
TargetSize = 5,
Versions = new[]
{
new Gcp.Compute.Inputs.RegionInstanceGroupManagerVersionArgs
{
InstanceTemplate = appserverGoogleComputeInstanceTemplate.SelfLinkUnique,
},
new Gcp.Compute.Inputs.RegionInstanceGroupManagerVersionArgs
{
InstanceTemplate = appserver_canary.SelfLinkUnique,
TargetSize = new Gcp.Compute.Inputs.RegionInstanceGroupManagerVersionTargetSizeArgs
{
Fixed = 1,
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.RegionInstanceGroupManager;
import com.pulumi.gcp.compute.RegionInstanceGroupManagerArgs;
import com.pulumi.gcp.compute.inputs.RegionInstanceGroupManagerVersionArgs;
import com.pulumi.gcp.compute.inputs.RegionInstanceGroupManagerVersionTargetSizeArgs;
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 RegionInstanceGroupManager("appserver", RegionInstanceGroupManagerArgs.builder()
.name("appserver-igm")
.baseInstanceName("app")
.region("us-central1")
.targetSize(5)
.versions(
RegionInstanceGroupManagerVersionArgs.builder()
.instanceTemplate(appserverGoogleComputeInstanceTemplate.selfLinkUnique())
.build(),
RegionInstanceGroupManagerVersionArgs.builder()
.instanceTemplate(appserver_canary.selfLinkUnique())
.targetSize(RegionInstanceGroupManagerVersionTargetSizeArgs.builder()
.fixed(1)
.build())
.build())
.build());
}
}
resources:
appserver:
type: gcp:compute:RegionInstanceGroupManager
properties:
name: appserver-igm
baseInstanceName: app
region: us-central1
targetSize: 5
versions:
- instanceTemplate: ${appserverGoogleComputeInstanceTemplate.selfLinkUnique}
- instanceTemplate: ${["appserver-canary"].selfLinkUnique}
targetSize:
fixed: 1
The versions array can include multiple templates. The first version without a targetSize gets the remaining capacity after fixed allocations. Here, one instance runs the canary template while four run the stable version. This lets you validate changes on a small scale before full rollout.
Maintain standby instances for faster scaling
Applications with unpredictable traffic can pre-provision stopped or suspended instances that start faster than creating new VMs.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const igm_sr = new gcp.compute.RegionInstanceGroupManager("igm-sr", {
name: "tf-sr-igm",
baseInstanceName: "tf-sr-igm-instance",
region: "us-central1",
targetSize: 5,
versions: [{
instanceTemplate: sr_igm.selfLink,
name: "primary",
}],
standbyPolicy: {
initialDelaySec: 50,
mode: "SCALE_OUT_POOL",
},
targetSuspendedSize: 1,
targetStoppedSize: 1,
});
import pulumi
import pulumi_gcp as gcp
igm_sr = gcp.compute.RegionInstanceGroupManager("igm-sr",
name="tf-sr-igm",
base_instance_name="tf-sr-igm-instance",
region="us-central1",
target_size=5,
versions=[{
"instance_template": sr_igm["selfLink"],
"name": "primary",
}],
standby_policy={
"initial_delay_sec": 50,
"mode": "SCALE_OUT_POOL",
},
target_suspended_size=1,
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.NewRegionInstanceGroupManager(ctx, "igm-sr", &compute.RegionInstanceGroupManagerArgs{
Name: pulumi.String("tf-sr-igm"),
BaseInstanceName: pulumi.String("tf-sr-igm-instance"),
Region: pulumi.String("us-central1"),
TargetSize: pulumi.Int(5),
Versions: compute.RegionInstanceGroupManagerVersionArray{
&compute.RegionInstanceGroupManagerVersionArgs{
InstanceTemplate: pulumi.Any(sr_igm.SelfLink),
Name: pulumi.String("primary"),
},
},
StandbyPolicy: &compute.RegionInstanceGroupManagerStandbyPolicyArgs{
InitialDelaySec: pulumi.Int(50),
Mode: pulumi.String("SCALE_OUT_POOL"),
},
TargetSuspendedSize: pulumi.Int(1),
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.RegionInstanceGroupManager("igm-sr", new()
{
Name = "tf-sr-igm",
BaseInstanceName = "tf-sr-igm-instance",
Region = "us-central1",
TargetSize = 5,
Versions = new[]
{
new Gcp.Compute.Inputs.RegionInstanceGroupManagerVersionArgs
{
InstanceTemplate = sr_igm.SelfLink,
Name = "primary",
},
},
StandbyPolicy = new Gcp.Compute.Inputs.RegionInstanceGroupManagerStandbyPolicyArgs
{
InitialDelaySec = 50,
Mode = "SCALE_OUT_POOL",
},
TargetSuspendedSize = 1,
TargetStoppedSize = 1,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.RegionInstanceGroupManager;
import com.pulumi.gcp.compute.RegionInstanceGroupManagerArgs;
import com.pulumi.gcp.compute.inputs.RegionInstanceGroupManagerVersionArgs;
import com.pulumi.gcp.compute.inputs.RegionInstanceGroupManagerStandbyPolicyArgs;
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 RegionInstanceGroupManager("igm-sr", RegionInstanceGroupManagerArgs.builder()
.name("tf-sr-igm")
.baseInstanceName("tf-sr-igm-instance")
.region("us-central1")
.targetSize(5)
.versions(RegionInstanceGroupManagerVersionArgs.builder()
.instanceTemplate(sr_igm.selfLink())
.name("primary")
.build())
.standbyPolicy(RegionInstanceGroupManagerStandbyPolicyArgs.builder()
.initialDelaySec(50)
.mode("SCALE_OUT_POOL")
.build())
.targetSuspendedSize(1)
.targetStoppedSize(1)
.build());
}
}
resources:
igm-sr:
type: gcp:compute:RegionInstanceGroupManager
properties:
name: tf-sr-igm
baseInstanceName: tf-sr-igm-instance
region: us-central1
targetSize: 5
versions:
- instanceTemplate: ${["sr-igm"].selfLink}
name: primary
standbyPolicy:
initialDelaySec: 50
mode: SCALE_OUT_POOL
targetSuspendedSize: 1
targetStoppedSize: 1
The standbyPolicy configures how many instances to keep in stopped or suspended states. The mode property controls when standby instances activate; SCALE_OUT_POOL means they start when the group scales beyond targetSize. The targetStoppedSize and targetSuspendedSize properties specify how many instances to maintain in each state. Starting a stopped instance is faster than provisioning a new VM from scratch.
Beyond these examples
These snippets focus on specific instance group manager features: zone distribution and auto-healing, canary deployments with multiple versions, and standby instances for rapid scaling. They’re intentionally minimal rather than full VM deployment modules.
The examples rely on pre-existing infrastructure such as instance templates, health checks for auto-healing, and target pools for load balancing. 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 (rolling updates, surge limits)
- Stateful configuration (persistent disks, IPs)
- Instance lifecycle policies
- Named ports for service discovery
These omissions are intentional: the goal is to illustrate how each instance group feature is wired, not provide drop-in VM management modules. See the RegionInstanceGroupManager resource reference for all available configuration options.
Let's configure GCP Regional 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
Scaling & Autoscaling
targetSize conflicts with autoscaler settings and causes perpetual drift. When using an autoscaler, either omit targetSize or use lifecycle.ignore_changes to prevent Pulumi from modifying it.targetSize sets the number of running instances, targetStoppedSize sets stopped instances, and targetSuspendedSize sets suspended instances. These are used with standbyPolicy to maintain a pool of standby VMs.standbyPolicy with mode set to SCALE_OUT_POOL and specify targetStoppedSize or targetSuspendedSize to maintain a pool of standby instances.Updates & Health Checks
autoHealingPolicies with a health check ID and initialDelaySec (e.g., 300 seconds) to allow instances time to initialize before health checks begin.waitForInstances is true, Pulumi waits for all instances to be created/updated before returning. If the operation fails, the provider continues retrying until timeout, which can cause long-running operations.STABLE waits until instances are stable. UPDATED waits for the version target to be reached, per-instance configs to be applied, and all instances to be stable.Stateful Configuration
updatePolicy before updating statefulDisks on existing instance group managers.statefulDisks preserves disks, statefulExternalIps preserves external IPs, and statefulInternalIps preserves internal IPs. Each is keyed by device name or network interface name.Deployment & Versioning
versions array with multiple entries. Each entry specifies an instanceTemplate and optional targetSize (fixed number or percentage) to control the rollout.custom on port 8888) that load balancers or services can reference instead of using port numbers directly.gcp.compute.InstanceGroupManager instead.