Fix: Instance level stateful disk config (#1578)
* update doco * fix bug in TF code * change instance name in README to fix test * revert disk name * Update stateful.yaml * fix examples and tests --------- Co-authored-by: Julio Castillo <juliocc@gmail.com> Co-authored-by: Ludovico Magnocavallo <ludomagno@google.com>
This commit is contained in:
parent
5a12e2a773
commit
b1679ad21a
|
@ -6,8 +6,23 @@ This module can be coupled with the [`compute-vm`](../compute-vm) module which c
|
||||||
|
|
||||||
Stateful disks can be created directly, as shown in the last example below.
|
Stateful disks can be created directly, as shown in the last example below.
|
||||||
|
|
||||||
|
<!-- 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 -->
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
### Simple Example
|
||||||
|
|
||||||
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.
|
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
|
```hcl
|
||||||
|
@ -49,7 +64,7 @@ module "nginx-mig" {
|
||||||
# tftest modules=2 resources=2 inventory=simple.yaml
|
# tftest modules=2 resources=2 inventory=simple.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
### Multiple versions
|
### Multiple Versions
|
||||||
|
|
||||||
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:
|
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:
|
||||||
|
|
||||||
|
@ -100,7 +115,7 @@ module "nginx-mig" {
|
||||||
# tftest modules=2 resources=2
|
# tftest modules=2 resources=2
|
||||||
```
|
```
|
||||||
|
|
||||||
### Health check and autohealing policies
|
### Health Check and Autohealing Policies
|
||||||
|
|
||||||
Autohealing policies can use an externally defined health check, or have this module auto-create one:
|
Autohealing policies can use an externally defined health check, or have this module auto-create one:
|
||||||
|
|
||||||
|
@ -205,7 +220,7 @@ module "nginx-mig" {
|
||||||
# tftest modules=2 resources=3 inventory=autoscaling.yaml
|
# tftest modules=2 resources=3 inventory=autoscaling.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
### Update policy
|
### Update Policy
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "cos-nginx" {
|
module "cos-nginx" {
|
||||||
|
@ -262,7 +277,7 @@ You can configure a disk defined in the instance template to be stateful for al
|
||||||
|
|
||||||
An example using only the configuration at the MIG level can be seen below.
|
An example using only the configuration at the MIG level can be seen below.
|
||||||
|
|
||||||
Note that when referencing the stateful disk, you use `device_name` and not `disk_name`.
|
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).
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "cos-nginx" {
|
module "cos-nginx" {
|
||||||
|
@ -271,15 +286,14 @@ module "cos-nginx" {
|
||||||
|
|
||||||
module "nginx-template" {
|
module "nginx-template" {
|
||||||
source = "./fabric/modules/compute-vm"
|
source = "./fabric/modules/compute-vm"
|
||||||
project_id = var.project_id
|
project_id = "my-prj"
|
||||||
name = "nginx-template"
|
name = "nginx-template"
|
||||||
zone = "europe-west1-b"
|
zone = "europe-west8-b"
|
||||||
tags = ["http-server", "ssh"]
|
tags = ["http-server", "ssh"]
|
||||||
|
instance_type = "e2-small"
|
||||||
network_interfaces = [{
|
network_interfaces = [{
|
||||||
network = var.vpc.self_link
|
network = var.vpc.self_link
|
||||||
subnetwork = var.subnet.self_link
|
subnetwork = var.subnet.self_link
|
||||||
nat = false
|
|
||||||
addresses = null
|
|
||||||
}]
|
}]
|
||||||
boot_disk = {
|
boot_disk = {
|
||||||
initialize_params = {
|
initialize_params = {
|
||||||
|
@ -287,15 +301,10 @@ module "nginx-template" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
attached_disks = [{
|
attached_disks = [{
|
||||||
name = "repd-1"
|
|
||||||
size = null
|
|
||||||
source_type = "attach"
|
source_type = "attach"
|
||||||
source = "regions/${var.region}/disks/repd-test-1"
|
name = "data-1"
|
||||||
options = {
|
size = 10
|
||||||
mode = "READ_ONLY"
|
source = "test-data-1"
|
||||||
replica_zone = "${var.region}-c"
|
|
||||||
type = "PERSISTENT"
|
|
||||||
}
|
|
||||||
}]
|
}]
|
||||||
create_template = true
|
create_template = true
|
||||||
metadata = {
|
metadata = {
|
||||||
|
@ -305,34 +314,21 @@ module "nginx-template" {
|
||||||
|
|
||||||
module "nginx-mig" {
|
module "nginx-mig" {
|
||||||
source = "./fabric/modules/compute-mig"
|
source = "./fabric/modules/compute-mig"
|
||||||
project_id = "my-project"
|
project_id = "my-prj"
|
||||||
location = "europe-west1-b"
|
location = "europe-west8-b"
|
||||||
name = "mig-test"
|
name = "mig-test-2"
|
||||||
target_size = 3
|
target_size = 1
|
||||||
instance_template = module.nginx-template.template.self_link
|
instance_template = module.nginx-template.template.self_link
|
||||||
autoscaler_config = {
|
|
||||||
max_replicas = 3
|
|
||||||
min_replicas = 1
|
|
||||||
cooldown_period = 30
|
|
||||||
scaling_signals = {
|
|
||||||
cpu_utilization = {
|
|
||||||
target = 0.65
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stateful_disks = {
|
stateful_disks = {
|
||||||
repd-1 = false
|
data-1 = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# tftest modules=2 resources=3
|
# tftest modules=2 resources=2
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Stateful MIGs - Instance Config
|
### Stateful MIGs - Instance Config
|
||||||
|
|
||||||
Here is an example defining the stateful config at the instance level.
|
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).
|
||||||
|
|
||||||
Note that you will need to know the instance name in order to use this configuration.
|
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "cos-nginx" {
|
module "cos-nginx" {
|
||||||
|
@ -341,15 +337,14 @@ module "cos-nginx" {
|
||||||
|
|
||||||
module "nginx-template" {
|
module "nginx-template" {
|
||||||
source = "./fabric/modules/compute-vm"
|
source = "./fabric/modules/compute-vm"
|
||||||
project_id = var.project_id
|
project_id = "my-prj"
|
||||||
name = "nginx-template"
|
name = "nginx-template"
|
||||||
zone = "europe-west1-b"
|
zone = "europe-west8-b"
|
||||||
tags = ["http-server", "ssh"]
|
tags = ["http-server", "ssh"]
|
||||||
|
instance_type = "e2-small"
|
||||||
network_interfaces = [{
|
network_interfaces = [{
|
||||||
network = var.vpc.self_link
|
network = var.vpc.self_link
|
||||||
subnetwork = var.subnet.self_link
|
subnetwork = var.subnet.self_link
|
||||||
nat = false
|
|
||||||
addresses = null
|
|
||||||
}]
|
}]
|
||||||
boot_disk = {
|
boot_disk = {
|
||||||
initialize_params = {
|
initialize_params = {
|
||||||
|
@ -357,15 +352,10 @@ module "nginx-template" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
attached_disks = [{
|
attached_disks = [{
|
||||||
name = "repd-1"
|
|
||||||
size = null
|
|
||||||
source_type = "attach"
|
source_type = "attach"
|
||||||
source = "regions/${var.region}/disks/repd-test-1"
|
name = "data-1"
|
||||||
options = {
|
size = 10
|
||||||
mode = "READ_ONLY"
|
source = "test-data-1"
|
||||||
replica_zone = "${var.region}-c"
|
|
||||||
type = "PERSISTENT"
|
|
||||||
}
|
|
||||||
}]
|
}]
|
||||||
create_template = true
|
create_template = true
|
||||||
metadata = {
|
metadata = {
|
||||||
|
@ -375,30 +365,18 @@ module "nginx-template" {
|
||||||
|
|
||||||
module "nginx-mig" {
|
module "nginx-mig" {
|
||||||
source = "./fabric/modules/compute-mig"
|
source = "./fabric/modules/compute-mig"
|
||||||
project_id = "my-project"
|
project_id = "my-prj"
|
||||||
location = "europe-west1-b"
|
location = "europe-west8-b"
|
||||||
name = "mig-test"
|
name = "mig-test"
|
||||||
target_size = 3
|
|
||||||
instance_template = module.nginx-template.template.self_link
|
instance_template = module.nginx-template.template.self_link
|
||||||
autoscaler_config = {
|
|
||||||
max_replicas = 3
|
|
||||||
min_replicas = 1
|
|
||||||
cooldown_period = 30
|
|
||||||
scaling_signals = {
|
|
||||||
cpu_utilization = {
|
|
||||||
target = 0.65
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stateful_config = {
|
stateful_config = {
|
||||||
# name needs to match a MIG instance name
|
|
||||||
instance-1 = {
|
instance-1 = {
|
||||||
minimal_action = "NONE",
|
minimal_action = "NONE",
|
||||||
most_disruptive_allowed_action = "REPLACE"
|
most_disruptive_allowed_action = "REPLACE"
|
||||||
preserved_state = {
|
preserved_state = {
|
||||||
disks = {
|
disks = {
|
||||||
persistent-disk-1 = {
|
data-1 = {
|
||||||
source = "test-disk",
|
source = "projects/my-prj/zones/europe-west8-b/disks/test-data-1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
metadata = {
|
metadata = {
|
||||||
|
@ -408,8 +386,7 @@ module "nginx-mig" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# tftest modules=2 resources=4 inventory=stateful.yaml
|
# tftest modules=2 resources=3 inventory=stateful.yaml
|
||||||
|
|
||||||
```
|
```
|
||||||
<!-- BEGIN TFDOC -->
|
<!-- BEGIN TFDOC -->
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ resource "google_compute_per_instance_config" "default" {
|
||||||
zone = var.location
|
zone = var.location
|
||||||
name = each.key
|
name = each.key
|
||||||
instance_group_manager = try(
|
instance_group_manager = try(
|
||||||
google_compute_instance_group_manager.default.0.id, null
|
google_compute_instance_group_manager.default.0.name, null
|
||||||
)
|
)
|
||||||
minimal_action = each.value.minimal_action
|
minimal_action = each.value.minimal_action
|
||||||
most_disruptive_allowed_action = each.value.most_disruptive_action
|
most_disruptive_allowed_action = each.value.most_disruptive_action
|
||||||
|
@ -59,7 +59,7 @@ resource "google_compute_region_per_instance_config" "default" {
|
||||||
region = var.location
|
region = var.location
|
||||||
name = each.key
|
name = each.key
|
||||||
region_instance_group_manager = try(
|
region_instance_group_manager = try(
|
||||||
google_compute_region_instance_group_manager.default.0.id, null
|
google_compute_region_instance_group_manager.default.0.name, null
|
||||||
)
|
)
|
||||||
minimal_action = each.value.minimal_action
|
minimal_action = each.value.minimal_action
|
||||||
most_disruptive_allowed_action = each.value.most_disruptive_action
|
most_disruptive_allowed_action = each.value.most_disruptive_action
|
||||||
|
|
|
@ -626,7 +626,6 @@ module "instance" {
|
||||||
# tftest modules=1 resources=5 inventory=snapshot-schedule-create.yaml
|
# tftest modules=1 resources=5 inventory=snapshot-schedule-create.yaml
|
||||||
```
|
```
|
||||||
<!-- BEGIN TFDOC -->
|
<!-- BEGIN TFDOC -->
|
||||||
|
|
||||||
## Variables
|
## Variables
|
||||||
|
|
||||||
| name | description | type | required | default |
|
| name | description | type | required | default |
|
||||||
|
@ -636,7 +635,7 @@ module "instance" {
|
||||||
| [project_id](variables.tf#L277) | Project id. | <code>string</code> | ✓ | |
|
| [project_id](variables.tf#L277) | Project id. | <code>string</code> | ✓ | |
|
||||||
| [zone](variables.tf#L379) | Compute zone. | <code>string</code> | ✓ | |
|
| [zone](variables.tf#L379) | Compute zone. | <code>string</code> | ✓ | |
|
||||||
| [attached_disk_defaults](variables.tf#L17) | Defaults for attached disks options. | <code title="object({ auto_delete = optional(bool, false) mode = string replica_zone = string type = string })">object({…})</code> | | <code title="{ auto_delete = true mode = "READ_WRITE" replica_zone = null type = "pd-balanced" }">{…}</code> |
|
| [attached_disk_defaults](variables.tf#L17) | Defaults for attached disks options. | <code title="object({ auto_delete = optional(bool, false) mode = string replica_zone = string type = string })">object({…})</code> | | <code title="{ auto_delete = true mode = "READ_WRITE" replica_zone = null type = "pd-balanced" }">{…}</code> |
|
||||||
| [attached_disks](variables.tf#L38) | Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null. | <code title="list(object({ name = string device_name = optional(string) size = string snapshot_schedule = optional(string) source = optional(string) source_type = optional(string) options = optional( object({ auto_delete = optional(bool, false) mode = optional(string, "READ_WRITE") replica_zone = optional(string) type = optional(string, "pd-balanced") }), { auto_delete = true mode = "READ_WRITE" replica_zone = null type = "pd-balanced" } ) }))">list(object({…}))</code> | | <code>[]</code> |
|
| [attached_disks](variables.tf#L37) | Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null. | <code title="list(object({ name = string device_name = optional(string) size = string snapshot_schedule = optional(string) source = optional(string) source_type = optional(string) options = optional( object({ auto_delete = optional(bool, false) mode = optional(string, "READ_WRITE") replica_zone = optional(string) type = optional(string, "pd-balanced") }), { auto_delete = true mode = "READ_WRITE" replica_zone = null type = "pd-balanced" } ) }))">list(object({…}))</code> | | <code>[]</code> |
|
||||||
| [boot_disk](variables.tf#L83) | Boot disk properties. | <code title="object({ auto_delete = optional(bool, true) snapshot_schedule = optional(string) source = optional(string) initialize_params = optional(object({ image = optional(string, "projects/debian-cloud/global/images/family/debian-11") size = optional(number, 10) type = optional(string, "pd-balanced") })) use_independent_disk = optional(bool, false) })">object({…})</code> | | <code title="{ initialize_params = {} }">{…}</code> |
|
| [boot_disk](variables.tf#L83) | Boot disk properties. | <code title="object({ auto_delete = optional(bool, true) snapshot_schedule = optional(string) source = optional(string) initialize_params = optional(object({ image = optional(string, "projects/debian-cloud/global/images/family/debian-11") size = optional(number, 10) type = optional(string, "pd-balanced") })) use_independent_disk = optional(bool, false) })">object({…})</code> | | <code title="{ initialize_params = {} }">{…}</code> |
|
||||||
| [can_ip_forward](variables.tf#L117) | Enable IP forwarding. | <code>bool</code> | | <code>false</code> |
|
| [can_ip_forward](variables.tf#L117) | Enable IP forwarding. | <code>bool</code> | | <code>false</code> |
|
||||||
| [confidential_compute](variables.tf#L123) | Enable Confidential Compute for these instances. | <code>bool</code> | | <code>false</code> |
|
| [confidential_compute](variables.tf#L123) | Enable Confidential Compute for these instances. | <code>bool</code> | | <code>false</code> |
|
||||||
|
@ -678,7 +677,6 @@ module "instance" {
|
||||||
| [service_account_iam_email](outputs.tf#L74) | Service account email. | |
|
| [service_account_iam_email](outputs.tf#L74) | Service account email. | |
|
||||||
| [template](outputs.tf#L82) | Template resource. | |
|
| [template](outputs.tf#L82) | Template resource. | |
|
||||||
| [template_name](outputs.tf#L87) | Template name. | |
|
| [template_name](outputs.tf#L87) | Template name. | |
|
||||||
|
|
||||||
<!-- END TFDOC -->
|
<!-- END TFDOC -->
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ variable "attached_disk_defaults" {
|
||||||
replica_zone = null
|
replica_zone = null
|
||||||
type = "pd-balanced"
|
type = "pd-balanced"
|
||||||
}
|
}
|
||||||
|
|
||||||
validation {
|
validation {
|
||||||
condition = var.attached_disk_defaults.mode == "READ_WRITE" || !var.attached_disk_defaults.auto_delete
|
condition = var.attached_disk_defaults.mode == "READ_WRITE" || !var.attached_disk_defaults.auto_delete
|
||||||
error_message = "auto_delete can only be specified on READ_WRITE disks."
|
error_message = "auto_delete can only be specified on READ_WRITE disks."
|
||||||
|
@ -40,6 +39,7 @@ variable "attached_disks" {
|
||||||
type = list(object({
|
type = list(object({
|
||||||
name = string
|
name = string
|
||||||
device_name = optional(string)
|
device_name = optional(string)
|
||||||
|
# TODO: size can be null when source_type is attach
|
||||||
size = string
|
size = string
|
||||||
snapshot_schedule = optional(string)
|
snapshot_schedule = optional(string)
|
||||||
source = optional(string)
|
source = optional(string)
|
||||||
|
|
|
@ -13,25 +13,49 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
values:
|
values:
|
||||||
|
module.nginx-mig.google_compute_instance_group_manager.default[0]:
|
||||||
|
all_instances_config: []
|
||||||
|
auto_healing_policies: []
|
||||||
|
base_instance_name: mig-test
|
||||||
|
description: Terraform managed.
|
||||||
|
list_managed_instances_results: PAGELESS
|
||||||
|
name: mig-test
|
||||||
|
named_port: []
|
||||||
|
project: my-prj
|
||||||
|
stateful_disk: []
|
||||||
|
stateful_external_ip: []
|
||||||
|
stateful_internal_ip: []
|
||||||
|
target_pools: null
|
||||||
|
timeouts: null
|
||||||
|
version:
|
||||||
|
- name: default
|
||||||
|
target_size: []
|
||||||
|
wait_for_instances: false
|
||||||
|
wait_for_instances_status: STABLE
|
||||||
|
zone: europe-west8-b
|
||||||
module.nginx-mig.google_compute_per_instance_config.default["instance-1"]:
|
module.nginx-mig.google_compute_per_instance_config.default["instance-1"]:
|
||||||
|
instance_group_manager: mig-test
|
||||||
minimal_action: NONE
|
minimal_action: NONE
|
||||||
most_disruptive_allowed_action: REPLACE
|
most_disruptive_allowed_action: REPLACE
|
||||||
name: instance-1
|
name: instance-1
|
||||||
preserved_state:
|
preserved_state:
|
||||||
- disk:
|
- disk:
|
||||||
- delete_rule: NEVER
|
- delete_rule: NEVER
|
||||||
device_name: persistent-disk-1
|
device_name: data-1
|
||||||
mode: READ_WRITE
|
mode: READ_WRITE
|
||||||
source: test-disk
|
source: projects/my-prj/zones/europe-west8-b/disks/test-data-1
|
||||||
metadata:
|
metadata:
|
||||||
foo: bar
|
foo: bar
|
||||||
project: my-project
|
project: my-prj
|
||||||
remove_instance_state_on_destroy: false
|
remove_instance_state_on_destroy: false
|
||||||
timeouts: null
|
timeouts: null
|
||||||
zone: europe-west1-b
|
zone: europe-west8-b
|
||||||
|
|
||||||
counts:
|
counts:
|
||||||
google_compute_autoscaler: 1
|
|
||||||
google_compute_instance_group_manager: 1
|
google_compute_instance_group_manager: 1
|
||||||
google_compute_instance_template: 1
|
google_compute_instance_template: 1
|
||||||
google_compute_per_instance_config: 1
|
google_compute_per_instance_config: 1
|
||||||
|
modules: 2
|
||||||
|
resources: 3
|
||||||
|
|
||||||
|
outputs: {}
|
||||||
|
|
Loading…
Reference in New Issue