2020-04-30 08:08:18 -07:00
# GCE Managed Instance Group module
2021-12-15 05:56:53 -08:00
This module allows creating a managed instance group supporting one or more application versions via instance templates. Optionally, a health check and an autoscaler can be created, and the managed instance group can be configured to be stateful.
2020-04-30 08:08:18 -07:00
2023-06-26 00:50:10 -07:00
This module can be coupled with the [`compute-vm` ](../compute-vm ) module which can manage instance templates, and the [`net-lb-int` ](../net-lb-int ) module to assign the MIG to a backend wired to an Internal Load Balancer. The first use case is shown in the examples below.
2021-12-15 05:56:53 -08:00
Stateful disks can be created directly, as shown in the last example below.
2020-04-30 08:08:18 -07:00
2023-08-11 08:25:17 -07:00
<!-- BEGIN TOC -->
- [Examples ](#examples )
- [Simple Example ](#simple-example )
- [Multiple Versions ](#multiple-versions )
- [Health Check and Autohealing Policies ](#health-check-and-autohealing-policies )
- [Autoscaling ](#autoscaling )
- [Update Policy ](#update-policy )
- [Stateful MIGs - MIG Config ](#stateful-migs-mig-config )
- [Stateful MIGs - Instance Config ](#stateful-migs-instance-config )
- [Variables ](#variables )
- [Outputs ](#outputs )
<!-- END TOC -->
2020-04-30 08:08:18 -07:00
## Examples
2023-08-11 08:25:17 -07:00
### Simple Example
2020-04-30 08:08:18 -07:00
This example shows how to manage a simple MIG that leverages the `compute-vm` module to manage the underlying instance template. The following sub-examples will only show how to enable specific features of this module, and won't replicate the combined setup.
```hcl
module "cos-nginx" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/cloud-config-container/nginx"
2020-04-30 08:08:18 -07:00
}
module "nginx-template" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/compute-vm"
2020-11-07 01:28:33 -08:00
project_id = var.project_id
name = "nginx-template"
2022-11-15 04:19:52 -08:00
zone = "europe-west1-b"
2020-11-07 01:28:33 -08:00
tags = ["http-server", "ssh"]
2020-04-30 08:08:18 -07:00
network_interfaces = [{
2020-11-07 01:28:33 -08:00
network = var.vpc.self_link
subnetwork = var.subnet.self_link
nat = false
2020-04-30 08:08:18 -07:00
addresses = null
}]
boot_disk = {
2023-03-12 01:53:59 -08:00
initialize_params = {
image = "projects/cos-cloud/global/images/family/cos-stable"
}
2020-04-30 08:08:18 -07:00
}
2021-10-04 01:46:44 -07:00
create_template = true
2020-04-30 08:08:18 -07:00
metadata = {
user-data = module.cos-nginx.cloud_config
}
}
module "nginx-mig" {
2022-11-01 01:38:59 -07:00
source = "./fabric/modules/compute-mig"
project_id = "my-project"
location = "europe-west1-b"
name = "mig-test"
target_size = 2
instance_template = module.nginx-template.template.self_link
2020-04-30 08:08:18 -07:00
}
2023-04-21 07:02:34 -07:00
# tftest modules=2 resources=2 inventory=simple.yaml
2020-04-30 08:08:18 -07:00
```
2023-08-11 08:25:17 -07:00
### Multiple Versions
2020-04-30 08:08:18 -07:00
If multiple versions are desired, use more `compute-vm` instances for the additional templates used in each version (not shown here), and reference them like this:
```hcl
2020-11-07 01:28:33 -08:00
module "cos-nginx" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/cloud-config-container/nginx"
2020-11-07 01:28:33 -08:00
}
module "nginx-template" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/compute-vm"
2020-11-07 01:28:33 -08:00
project_id = var.project_id
name = "nginx-template"
2022-11-15 04:19:52 -08:00
zone = "europe-west1-b"
2020-11-07 01:28:33 -08:00
tags = ["http-server", "ssh"]
network_interfaces = [{
network = var.vpc.self_link
subnetwork = var.subnet.self_link
nat = false
addresses = null
}]
boot_disk = {
2023-03-12 01:53:59 -08:00
initialize_params = {
image = "projects/cos-cloud/global/images/family/cos-stable"
}
2020-11-07 01:28:33 -08:00
}
2022-11-15 04:19:52 -08:00
create_template = true
2020-11-07 01:28:33 -08:00
metadata = {
user-data = module.cos-nginx.cloud_config
}
}
2020-04-30 08:08:18 -07:00
module "nginx-mig" {
2022-11-01 01:38:59 -07:00
source = "./fabric/modules/compute-mig"
project_id = "my-project"
location = "europe-west1-b"
name = "mig-test"
target_size = 3
instance_template = module.nginx-template.template.self_link
2020-04-30 08:08:18 -07:00
versions = {
canary = {
2020-11-07 01:28:33 -08:00
instance_template = module.nginx-template.template.self_link
2022-11-01 01:38:59 -07:00
target_size = {
fixed = 1
}
2020-04-30 08:08:18 -07:00
}
}
}
2022-01-28 11:15:35 -08:00
# tftest modules=2 resources=2
2020-04-30 08:08:18 -07:00
```
2023-08-11 08:25:17 -07:00
### Health Check and Autohealing Policies
2020-04-30 08:08:18 -07:00
Autohealing policies can use an externally defined health check, or have this module auto-create one:
```hcl
2020-11-07 01:28:33 -08:00
module "cos-nginx" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/cloud-config-container/nginx"
2020-11-07 01:28:33 -08:00
}
module "nginx-template" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/compute-vm"
2020-11-07 01:28:33 -08:00
project_id = var.project_id
name = "nginx-template"
2022-11-15 04:19:52 -08:00
zone = "europe-west1-b"
2020-11-07 01:28:33 -08:00
tags = ["http-server", "ssh"]
network_interfaces = [{
network = var.vpc.self_link,
subnetwork = var.subnet.self_link,
nat = false,
addresses = null
}]
boot_disk = {
2023-03-12 01:53:59 -08:00
initialize_params = {
image = "projects/cos-cloud/global/images/family/cos-stable"
}
2020-11-07 01:28:33 -08:00
}
2022-11-15 04:19:52 -08:00
create_template = true
2020-11-07 01:28:33 -08:00
metadata = {
user-data = module.cos-nginx.cloud_config
}
}
2020-04-30 08:08:18 -07:00
module "nginx-mig" {
2022-11-01 01:38:59 -07:00
source = "./fabric/modules/compute-mig"
project_id = "my-project"
location = "europe-west1-b"
name = "mig-test"
target_size = 3
instance_template = module.nginx-template.template.self_link
2020-04-30 08:08:18 -07:00
auto_healing_policies = {
initial_delay_sec = 30
}
health_check_config = {
2022-11-01 01:38:59 -07:00
enable_logging = true
http = {
port = 80
}
2020-04-30 08:08:18 -07:00
}
}
2023-04-21 07:02:34 -07:00
# tftest modules=2 resources=3 inventory=health-check.yaml
2020-04-30 08:08:18 -07:00
```
### Autoscaling
The module can create and manage an autoscaler associated with the MIG. When using autoscaling do not set the `target_size` variable or set it to `null` . Here we show a CPU utilization autoscaler, the other available modes are load balancing utilization and custom metric, like the underlying autoscaler resource.
```hcl
2020-11-07 01:28:33 -08:00
module "cos-nginx" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/cloud-config-container/nginx"
2020-11-07 01:28:33 -08:00
}
module "nginx-template" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/compute-vm"
2020-11-07 01:28:33 -08:00
project_id = var.project_id
name = "nginx-template"
2022-11-15 04:19:52 -08:00
zone = "europe-west1-b"
2020-11-07 01:28:33 -08:00
tags = ["http-server", "ssh"]
network_interfaces = [{
network = var.vpc.self_link
subnetwork = var.subnet.self_link
nat = false
addresses = null
}]
boot_disk = {
2023-03-12 01:53:59 -08:00
initialize_params = {
image = "projects/cos-cloud/global/images/family/cos-stable"
}
2020-11-07 01:28:33 -08:00
}
2022-11-15 04:19:52 -08:00
create_template = true
2020-11-07 01:28:33 -08:00
metadata = {
user-data = module.cos-nginx.cloud_config
}
}
2020-04-30 08:08:18 -07:00
module "nginx-mig" {
2022-11-01 01:38:59 -07:00
source = "./fabric/modules/compute-mig"
project_id = "my-project"
location = "europe-west1-b"
name = "mig-test"
target_size = 3
instance_template = module.nginx-template.template.self_link
2020-04-30 08:08:18 -07:00
autoscaler_config = {
2022-11-01 01:38:59 -07:00
max_replicas = 3
min_replicas = 1
cooldown_period = 30
scaling_signals = {
cpu_utilization = {
target = 0.65
}
}
2020-04-30 08:08:18 -07:00
}
}
2023-04-21 07:02:34 -07:00
# tftest modules=2 resources=3 inventory=autoscaling.yaml
2020-04-30 08:08:18 -07:00
```
2023-08-11 08:25:17 -07:00
### Update Policy
2020-04-30 08:08:18 -07:00
```hcl
2020-11-07 01:28:33 -08:00
module "cos-nginx" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/cloud-config-container/nginx"
2020-11-07 01:28:33 -08:00
}
module "nginx-template" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/compute-vm"
2020-11-07 01:28:33 -08:00
project_id = var.project_id
name = "nginx-template"
2022-11-15 04:19:52 -08:00
zone = "europe-west1-b"
2020-11-07 01:28:33 -08:00
tags = ["http-server", "ssh"]
network_interfaces = [{
network = var.vpc.self_link
subnetwork = var.subnet.self_link
nat = false
addresses = null
}]
boot_disk = {
2023-03-12 01:53:59 -08:00
initialize_params = {
image = "projects/cos-cloud/global/images/family/cos-stable"
}
2020-11-07 01:28:33 -08:00
}
2022-11-15 04:19:52 -08:00
create_template = true
2020-11-07 01:28:33 -08:00
metadata = {
user-data = module.cos-nginx.cloud_config
}
}
2020-04-30 08:08:18 -07:00
module "nginx-mig" {
2022-11-01 01:38:59 -07:00
source = "./fabric/modules/compute-mig"
project_id = "my-project"
location = "europe-west1-b"
name = "mig-test"
target_size = 3
instance_template = module.nginx-template.template.self_link
2020-04-30 08:08:18 -07:00
update_policy = {
2022-12-16 03:53:56 -08:00
minimal_action = "REPLACE"
type = "PROACTIVE"
min_ready_sec = 30
2022-11-01 01:38:59 -07:00
max_surge = {
fixed = 1
}
2020-04-30 08:08:18 -07:00
}
}
2022-01-28 11:15:35 -08:00
# tftest modules=2 resources=2
2020-04-30 08:08:18 -07:00
```
2021-12-15 05:56:53 -08:00
### Stateful MIGs - MIG Config
2022-11-01 01:38:59 -07:00
Stateful MIGs have some limitations documented [here ](https://cloud.google.com/compute/docs/instance-groups/configuring-stateful-migs#limitations ). Enforcement of these requirements is the responsibility of users of this module.
2021-12-15 05:56:53 -08:00
You can configure a disk defined in the instance template to be stateful for all instances in the MIG by configuring in the MIG's stateful policy, using the `stateful_disk_mig` variable. Alternatively, you can also configure stateful persistent disks individually per instance of the MIG by setting the `stateful_disk_instance` variable. A discussion on these scenarios can be found in the [docs ](https://cloud.google.com/compute/docs/instance-groups/configuring-stateful-disks-in-migs ).
An example using only the configuration at the MIG level can be seen below.
2023-08-11 08:25:17 -07:00
Note that when referencing the stateful disk, you use `device_name` and not `disk_name` . Specifying an existing disk in the template (and stateful config) only allows a single instance to be managed by the MIG, typically coupled with an autohealing policy (shown in the examples above).
2021-12-15 05:56:53 -08:00
```hcl
module "cos-nginx" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/cloud-config-container/nginx"
2021-12-15 05:56:53 -08:00
}
module "nginx-template" {
2023-08-11 08:25:17 -07:00
source = "./fabric/modules/compute-vm"
project_id = "my-prj"
name = "nginx-template"
zone = "europe-west8-b"
tags = ["http-server", "ssh"]
instance_type = "e2-small"
2021-12-15 05:56:53 -08:00
network_interfaces = [{
network = var.vpc.self_link
subnetwork = var.subnet.self_link
}]
boot_disk = {
2023-03-12 01:53:59 -08:00
initialize_params = {
image = "projects/cos-cloud/global/images/family/cos-stable"
}
2021-12-15 05:56:53 -08:00
}
attached_disks = [{
source_type = "attach"
2023-08-11 08:25:17 -07:00
name = "data-1"
size = 10
source = "test-data-1"
2021-12-15 05:56:53 -08:00
}]
2022-11-15 04:19:52 -08:00
create_template = true
2021-12-15 05:56:53 -08:00
metadata = {
user-data = module.cos-nginx.cloud_config
}
}
module "nginx-mig" {
2022-11-01 01:38:59 -07:00
source = "./fabric/modules/compute-mig"
2023-08-11 08:25:17 -07:00
project_id = "my-prj"
location = "europe-west8-b"
name = "mig-test-2"
target_size = 1
2022-11-01 01:38:59 -07:00
instance_template = module.nginx-template.template.self_link
stateful_disks = {
2023-08-11 08:25:17 -07:00
data-1 = false
2022-11-01 01:38:59 -07:00
}
2021-12-15 05:56:53 -08:00
}
2023-08-11 08:25:17 -07:00
# tftest modules=2 resources=2
2021-12-15 05:56:53 -08:00
```
### Stateful MIGs - Instance Config
2022-11-01 01:38:59 -07:00
2023-08-11 08:25:17 -07:00
Here is an example defining the stateful config at the instance level. As in the example above, specifying an existing disk in the template (and stateful config) only allows a single instance to be managed by the MIG, typically coupled with an autohealing policy (shown in the examples above).
2021-12-15 05:56:53 -08:00
```hcl
module "cos-nginx" {
2022-09-06 08:46:09 -07:00
source = "./fabric/modules/cloud-config-container/nginx"
2021-12-15 05:56:53 -08:00
}
module "nginx-template" {
2023-08-11 08:25:17 -07:00
source = "./fabric/modules/compute-vm"
project_id = "my-prj"
name = "nginx-template"
zone = "europe-west8-b"
tags = ["http-server", "ssh"]
instance_type = "e2-small"
2021-12-15 05:56:53 -08:00
network_interfaces = [{
network = var.vpc.self_link
subnetwork = var.subnet.self_link
}]
boot_disk = {
2023-03-12 01:53:59 -08:00
initialize_params = {
image = "projects/cos-cloud/global/images/family/cos-stable"
}
2021-12-15 05:56:53 -08:00
}
attached_disks = [{
source_type = "attach"
2023-08-11 08:25:17 -07:00
name = "data-1"
size = 10
source = "test-data-1"
2021-12-15 05:56:53 -08:00
}]
2022-11-15 04:19:52 -08:00
create_template = true
2021-12-15 05:56:53 -08:00
metadata = {
user-data = module.cos-nginx.cloud_config
}
}
module "nginx-mig" {
2022-11-01 01:38:59 -07:00
source = "./fabric/modules/compute-mig"
2023-08-11 08:25:17 -07:00
project_id = "my-prj"
location = "europe-west8-b"
2022-11-01 01:38:59 -07:00
name = "mig-test"
instance_template = module.nginx-template.template.self_link
2021-12-15 05:56:53 -08:00
stateful_config = {
2022-11-01 01:38:59 -07:00
instance-1 = {
2022-12-16 03:53:56 -08:00
minimal_action = "NONE",
most_disruptive_allowed_action = "REPLACE"
2022-11-01 01:38:59 -07:00
preserved_state = {
disks = {
2023-08-11 08:25:17 -07:00
data-1 = {
source = "projects/my-prj/zones/europe-west8-b/disks/test-data-1"
2022-11-01 01:38:59 -07:00
}
}
2021-12-15 05:56:53 -08:00
metadata = {
foo = "bar"
2022-11-01 01:38:59 -07:00
}
2021-12-15 05:56:53 -08:00
}
}
}
}
2023-08-11 08:25:17 -07:00
# tftest modules=2 resources=3 inventory=stateful.yaml
2021-12-15 05:56:53 -08:00
```
2020-04-30 08:08:18 -07:00
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
2021-12-20 23:51:51 -08:00
|---|---|:---:|:---:|:---:|
2022-12-22 09:12:17 -08:00
| [instance_template ](variables.tf#L177 ) | Instance template for the default version. | < code > string</ code > | ✓ | |
| [location ](variables.tf#L182 ) | Compute zone or region. | < code > string</ code > | ✓ | |
| [name ](variables.tf#L187 ) | Managed group name. | < code > string</ code > | ✓ | |
| [project_id ](variables.tf#L198 ) | Project id. | < code > string</ code > | ✓ | |
2022-11-01 01:38:59 -07:00
| [all_instances_config ](variables.tf#L17 ) | Metadata and labels set to all instances in the group. | < code title = "object({ labels = optional(map(string)) metadata = optional(map(string)) })" > object({…}) </ code > | | < code > null</ code > |
| [auto_healing_policies ](variables.tf#L26 ) | Auto-healing policies for this group. | < code title = "object({ health_check = optional(string) initial_delay_sec = number })" > object({…}) </ code > | | < code > null</ code > |
2023-09-12 04:58:09 -07:00
| [autoscaler_config ](variables.tf#L35 ) | Optional autoscaler configuration. | < code title = "object({ max_replicas = number min_replicas = number cooldown_period = optional(number) mode = optional(string) # OFF, ONLY_UP, ON scaling_control = optional(object({ down = optional(object({ max_replicas_fixed = optional(number) max_replicas_percent = optional(number) time_window_sec = optional(number) })) in = optional(object({ max_replicas_fixed = optional(number) max_replicas_percent = optional(number) time_window_sec = optional(number) })) }), {}) scaling_signals = optional(object({ cpu_utilization = optional(object({ target = number optimize_availability = optional(bool) })) load_balancing_utilization = optional(object({ target = number })) metrics = optional(list(object({ name = string type = optional(string) # GAUGE, DELTA_PER_SECOND, DELTA_PER_MINUTE target_value = optional(number) single_instance_assignment = optional(number) time_series_filter = optional(string) }))) schedules = optional(list(object({ duration_sec = number name = string min_required_replicas = number cron_schedule = string description = optional(bool) timezone = optional(string) disabled = optional(bool) }))) }), {}) })" > object({…}) </ code > | | < code > null</ code > |
2022-11-01 01:38:59 -07:00
| [default_version_name ](variables.tf#L83 ) | Name used for the default version. | < code > string</ code > | | < code > " default" </ code > |
| [description ](variables.tf#L89 ) | Optional description used for all resources managed by this module. | < code > string</ code > | | < code > " Terraform managed." </ code > |
| [distribution_policy ](variables.tf#L95 ) | DIstribution policy for regional MIG. | < code title = "object({ target_shape = optional(string) zones = optional(list(string)) })" > object({…}) </ code > | | < code > null</ code > |
2022-11-02 10:05:20 -07:00
| [health_check_config ](variables.tf#L104 ) | Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | < code title = "object({ check_interval_sec = optional(number) description = optional(string, "Terraform managed.") enable_logging = optional(bool, false) healthy_threshold = optional(number) timeout_sec = optional(number) unhealthy_threshold = optional(number) grpc = optional(object({ port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT service_name = optional(string) })) http = optional(object({ host = optional(string) port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT proxy_header = optional(string) request_path = optional(string) response = optional(string) })) http2 = optional(object({ host = optional(string) port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT proxy_header = optional(string) request_path = optional(string) response = optional(string) })) https = optional(object({ host = optional(string) port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT proxy_header = optional(string) request_path = optional(string) response = optional(string) })) tcp = optional(object({ port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT proxy_header = optional(string) request = optional(string) response = optional(string) })) ssl = optional(object({ port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT proxy_header = optional(string) request = optional(string) response = optional(string) })) })" > object({…}) </ code > | | < code > null</ code > |
2022-12-22 09:12:17 -08:00
| [named_ports ](variables.tf#L192 ) | Named ports. | < code > map( number) </ code > | | < code > null</ code > |
| [stateful_config ](variables.tf#L203 ) | Stateful configuration for individual instances. | < code title = "map(object({ minimal_action = optional(string) most_disruptive_action = optional(string) remove_state_on_destroy = optional(bool) preserved_state = optional(object({ disks = optional(map(object({ source = string delete_on_instance_deletion = optional(bool) read_only = optional(bool) }))) metadata = optional(map(string)) })) }))" > map( object({…})) </ code > | | < code > {} </ code > |
| [stateful_disks ](variables.tf#L222 ) | Stateful disk configuration applied at the MIG level to all instances, in device name => on permanent instance delete rule as boolean. | < code > map( bool) </ code > | | < code > {} </ code > |
| [target_pools ](variables.tf#L229 ) | Optional list of URLs for target pools to which new instances in the group are added. | < code > list( string) </ code > | | < code > [] </ code > |
| [target_size ](variables.tf#L235 ) | Group target size, leave null when using an autoscaler. | < code > number</ code > | | < code > null</ code > |
| [update_policy ](variables.tf#L241 ) | Update policy. Minimal action and type are required. | < code title = "object({ minimal_action = string type = string max_surge = optional(object({ fixed = optional(number) percent = optional(number) })) max_unavailable = optional(object({ fixed = optional(number) percent = optional(number) })) min_ready_sec = optional(number) most_disruptive_action = optional(string) regional_redistribution_type = optional(string) replacement_method = optional(string) })" > object({…}) </ code > | | < code > null</ code > |
| [versions ](variables.tf#L262 ) | Additional application versions, target_size is optional. | < code title = "map(object({ instance_template = string target_size = optional(object({ fixed = optional(number) percent = optional(number) })) }))" > map( object({…})) </ code > | | < code > {} </ code > |
| [wait_for_instances ](variables.tf#L275 ) | Wait for all instances to be created/updated before returning. | < code title = "object({ enabled = bool status = optional(string) })" > object({…}) </ code > | | < code > null</ code > |
2020-04-30 08:08:18 -07:00
## Outputs
| name | description | sensitive |
|---|---|:---:|
2022-01-22 04:34:35 -08:00
| [autoscaler ](outputs.tf#L17 ) | Auto-created autoscaler resource. | |
| [group_manager ](outputs.tf#L26 ) | Instance group resource. | |
| [health_check ](outputs.tf#L35 ) | Auto-created health-check resource. | |
2023-06-02 07:07:22 -07:00
| [id ](outputs.tf#L44 ) | Fully qualified group manager id. | |
2020-04-30 08:08:18 -07:00
<!-- END TFDOC -->