Skip to content

Commit

Permalink
vmss: add automatic os upgrades, network profile health probe, and ro…
Browse files Browse the repository at this point in the history
…lling upgrade policy support
  • Loading branch information
agolomoodysaada committed Mar 2, 2018
1 parent 1ea6d1a commit 83b20f2
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 25 deletions.
116 changes: 110 additions & 6 deletions azurerm/resource_arm_virtual_machine_scale_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,47 @@ func resourceArmVirtualMachineScaleSet() *schema.Resource {
Required: true,
},

"automatic_os_upgrade": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},

"rolling_upgrade_policy": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"max_batch_instance_percent": {
Type: schema.TypeInt,
Optional: true,
Default: 20,
},

"max_unhealthy_instance_percent": {
Type: schema.TypeInt,
Optional: true,
Default: 20,
},

"max_unhealthy_upgraded_instance_percent": {
Type: schema.TypeInt,
Optional: true,
Default: 5,
},

"pause_time_between_batches": {
Type: schema.TypeString,
Optional: true,
Default: "PT0S",
},
},
},
Set: resourceArmVirtualMachineScaleSetRollingUpgradePolicyHash,
},

"overprovision": {
Type: schema.TypeBool,
Optional: true,
Expand Down Expand Up @@ -259,6 +300,11 @@ func resourceArmVirtualMachineScaleSet() *schema.Resource {
Optional: true,
},

"health_probe_id": {
Type: schema.TypeString,
Optional: true,
},

"ip_configuration": {
Type: schema.TypeList,
Required: true,
Expand Down Expand Up @@ -604,12 +650,16 @@ func resourceArmVirtualMachineScaleSetCreate(d *schema.ResourceData, meta interf
}

updatePolicy := d.Get("upgrade_policy_mode").(string)
automaticOsUpgrade := d.Get("automatic_os_upgrade").(bool)

overprovision := d.Get("overprovision").(bool)
singlePlacementGroup := d.Get("single_placement_group").(bool)

scaleSetProps := compute.VirtualMachineScaleSetProperties{
UpgradePolicy: &compute.UpgradePolicy{
Mode: compute.UpgradeMode(updatePolicy),
Mode: compute.UpgradeMode(updatePolicy),
AutomaticOSUpgrade: &automaticOsUpgrade,
RollingUpgradePolicy: expandAzureRmRollingUpgradePolicy(d),
},
VirtualMachineProfile: &compute.VirtualMachineScaleSetVMProfile{
NetworkProfile: expandAzureRmVirtualMachineScaleSetNetworkProfile(d),
Expand Down Expand Up @@ -698,6 +748,7 @@ func resourceArmVirtualMachineScaleSetRead(d *schema.ResourceData, meta interfac
properties := resp.VirtualMachineScaleSetProperties

d.Set("upgrade_policy_mode", properties.UpgradePolicy.Mode)
d.Set("automatic_os_upgrade", properties.UpgradePolicy.AutomaticOSUpgrade)
d.Set("overprovision", properties.Overprovision)
d.Set("single_placement_group", properties.SinglePlacementGroup)

Expand All @@ -710,6 +761,12 @@ func resourceArmVirtualMachineScaleSetRead(d *schema.ResourceData, meta interfac
return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile error: %#v", err)
}

if properties.UpgradePolicy.RollingUpgradePolicy != nil {
if err := d.Set("rolling_upgrade_policy", flattenAzureRmVirtualMachineScaleSetRollingUpgradePolicy(properties.UpgradePolicy.RollingUpgradePolicy)); err != nil {
return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Rolling Upgrade Policy error: %#v", err)
}
}

if properties.VirtualMachineProfile.OsProfile.Secrets != nil {
if err := d.Set("os_profile_secrets", flattenAzureRmVirtualMachineScaleSetOsProfileSecrets(properties.VirtualMachineProfile.OsProfile.Secrets)); err != nil {
return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile Secrets error: %#v", err)
Expand Down Expand Up @@ -905,13 +962,25 @@ func flattenAzureRmVirtualMachineScaleSetBootDiagnostics(bootDiagnostic *compute
return []interface{}{b}
}

func flattenAzureRmVirtualMachineScaleSetRollingUpgradePolicy(rollingUpgradePolicy *compute.RollingUpgradePolicy) []interface{} {
b := map[string]interface{}{
"max_batch_instance_percent": *rollingUpgradePolicy.MaxBatchInstancePercent,
"max_unhealthy_instance_percent": *rollingUpgradePolicy.MaxUnhealthyInstancePercent,
"max_unhealthy_upgraded_instance_percent": *rollingUpgradePolicy.MaxUnhealthyUpgradedInstancePercent,
"pause_time_between_batches": *rollingUpgradePolicy.PauseTimeBetweenBatches,
}

return []interface{}{b}
}

func flattenAzureRmVirtualMachineScaleSetNetworkProfile(profile *compute.VirtualMachineScaleSetNetworkProfile) []map[string]interface{} {
networkConfigurations := profile.NetworkInterfaceConfigurations
result := make([]map[string]interface{}, 0, len(*networkConfigurations))
for _, netConfig := range *networkConfigurations {
s := map[string]interface{}{
"name": *netConfig.Name,
"primary": *netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.Primary,
"name": *netConfig.Name,
"primary": *netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.Primary,
"health_probe_id": *profile.HealthProbe.ID,
}

if v := netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.EnableAcceleratedNetworking; v != nil {
Expand Down Expand Up @@ -1163,6 +1232,16 @@ func resourceArmVirtualMachineScaleSetStorageProfileOsDiskHash(v interface{}) in
return hashcode.String(buf.String())
}

func resourceArmVirtualMachineScaleSetRollingUpgradePolicyHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%d-", m["max_batch_instance_percent"].(int32)))
buf.WriteString(fmt.Sprintf("%d-", m["max_unhealthy_instance_percent"].(int32)))
buf.WriteString(fmt.Sprintf("%d-", m["max_unhealthy_upgraded_instance_percent"].(int32)))
buf.WriteString(fmt.Sprintf("%s-", m["pause_time_between_batches"].(string)))
return hashcode.String(buf.String())
}

func resourceArmVirtualMachineScaleSetNetworkConfigurationHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
Expand Down Expand Up @@ -1238,15 +1317,37 @@ func expandVirtualMachineScaleSetSku(d *schema.ResourceData) (*compute.Sku, erro
return sku, nil
}

func expandAzureRmRollingUpgradePolicy(d *schema.ResourceData) *compute.RollingUpgradePolicy {
rollingUpgradePolicyConfigs := d.Get("rolling_upgrade_policy").(*schema.Set).List()
rollingUpgradePolicyConfig := rollingUpgradePolicyConfigs[0]
config := rollingUpgradePolicyConfig.(map[string]interface{})

maxBatchInstancePercent := config["max_batch_instance_percent"].(int32)
maxUnhealthyInstancePercent := config["max_unhealthy_instance_percent"].(int32)
maxUnhealthyUpgradedInstancePercent := config["max_unhealthy_upgraded_instance_percent"].(int32)
pauseTimeBetweenBatches := config["pause_time_between_batches"].(string)

return &compute.RollingUpgradePolicy{
MaxBatchInstancePercent: &maxBatchInstancePercent,
MaxUnhealthyInstancePercent: &maxUnhealthyInstancePercent,
MaxUnhealthyUpgradedInstancePercent: &maxUnhealthyUpgradedInstancePercent,
PauseTimeBetweenBatches: &pauseTimeBetweenBatches,
}
}

func expandAzureRmVirtualMachineScaleSetNetworkProfile(d *schema.ResourceData) *compute.VirtualMachineScaleSetNetworkProfile {
scaleSetNetworkProfileConfigs := d.Get("network_profile").(*schema.Set).List()
networkProfileConfig := make([]compute.VirtualMachineScaleSetNetworkConfiguration, 0, len(scaleSetNetworkProfileConfigs))
networkConfigurations := make([]compute.VirtualMachineScaleSetNetworkConfiguration, 0, len(scaleSetNetworkProfileConfigs))

npProfileConfig := scaleSetNetworkProfileConfigs[0].(map[string]interface{})
healthProbe := npProfileConfig["health_probe_id"].(string)

for _, npProfileConfig := range scaleSetNetworkProfileConfigs {
config := npProfileConfig.(map[string]interface{})

name := config["name"].(string)
primary := config["primary"].(bool)

acceleratedNetworking := config["accelerated_networking"].(bool)

ipConfigurationConfigs := config["ip_configuration"].([]interface{})
Expand Down Expand Up @@ -1338,11 +1439,14 @@ func expandAzureRmVirtualMachineScaleSetNetworkProfile(d *schema.ResourceData) *
nProfile.VirtualMachineScaleSetNetworkConfigurationProperties.NetworkSecurityGroup = &networkSecurityGroupId
}

networkProfileConfig = append(networkProfileConfig, nProfile)
networkConfigurations = append(networkConfigurations, nProfile)
}

return &compute.VirtualMachineScaleSetNetworkProfile{
NetworkInterfaceConfigurations: &networkProfileConfig,
HealthProbe: &compute.APIEntityReference{
ID: &healthProbe,
},
NetworkInterfaceConfigurations: &networkConfigurations,
}
}

Expand Down
62 changes: 43 additions & 19 deletions website/docs/r/virtual_machine_scale_set.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: |-
Create a Virtual Machine scale set.
---

# azurerm\_virtual\_machine\_scale\_set
# azurerm_virtual_machine_scale_set

Create a virtual machine scale set.

Expand Down Expand Up @@ -76,11 +76,28 @@ resource "azurerm_lb_nat_pool" "lbnatpool" {
frontend_ip_configuration_name = "PublicIPAddress"
}
resource "azurerm_lb_probe" "test" {
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "http-probe"
request_path = "/health"
port = 8080
}
resource "azurerm_virtual_machine_scale_set" "test" {
name = "mytestscaleset-1"
location = "West US 2"
resource_group_name = "${azurerm_resource_group.test.name}"
upgrade_policy_mode = "Manual"
# automatic rolling upgrade
upgrade_policy_mode = "Rolling"
automatic_os_upgrade = true
rolling_upgrade_policy {
max_batch_instance_percent = 20
max_unhealthy_instance_percent = 20
max_unhealthy_upgraded_instance_percent = 5
pause_time_between_batches = "PT0S"
}
sku {
name = "Standard_A0"
Expand Down Expand Up @@ -134,6 +151,9 @@ resource "azurerm_virtual_machine_scale_set" "test" {
load_balancer_backend_address_pool_ids = ["${azurerm_lb_backend_address_pool.bpepool.id}"]
load_balancer_inbound_nat_rules_ids = ["${element(azurerm_lb_nat_pool.lbnatpool.*.id, count.index)}"]
}
# required when using rolling upgrade policy
health_probe_id = "${azurerm_lb_probe.test.id}"
}
tags {
Expand Down Expand Up @@ -184,10 +204,10 @@ resource "azurerm_storage_container" "test" {
}
resource "azurerm_virtual_machine_scale_set" "test" {
name = "mytestscaleset-1"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
upgrade_policy_mode = "Manual"
name = "mytestscaleset-1"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
upgrade_policy_mode = "Manual"
sku {
name = "Standard_A0"
Expand Down Expand Up @@ -244,10 +264,12 @@ The following arguments are supported:
* `resource_group_name` - (Required) The name of the resource group in which to create the virtual machine scale set. Changing this forces a new resource to be created.
* `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created.
* `sku` - (Required) A sku block as documented below.
* `upgrade_policy_mode` - (Required) Specifies the mode of an upgrade to virtual machines in the scale set. Possible values, `Manual` or `Automatic`.
* `upgrade_policy_mode` - (Required) Specifies the mode of an upgrade to virtual machines in the scale set. Possible values, `Rolling`, `Manual`, or `Automatic`. When choosing `Rolling`, you will need to set a health probe.
* `automatic_os_upgrade` - (Optional) Automatic OS patches can be applied by Azure to your scaleset. This is particularly useful when `upgrade_policy_mode` is set to `Rolling`. Defaults to `false`.
* `rolling_upgrade_policy` - (Optional) Ignored unless `upgrade_policy_mode` is set to `Rolling`.
* `overprovision` - (Optional) Specifies whether the virtual machine scale set should be overprovisioned.
* `single_placement_group` - (Optional) Specifies whether the scale set is limited to a single placement group with a maximum size of 100 virtual machines. If set to false, managed disks must be used. Default is true. Changing this forces a
new resource to be created. See [documentation](http://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-placement-groups) for more information.
new resource to be created. See [documentation](http://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-placement-groups) for more information.
* `os_profile` - (Required) A Virtual Machine OS Profile block as documented below.
* `os_profile_secrets` - (Optional) A collection of Secret blocks as documented below.
* `os_profile_windows_config` - (Required, when a windows machine) A Windows config block as documented below.
Expand All @@ -261,13 +283,19 @@ The following arguments are supported:
* `plan` - (Optional) A plan block as documented below.
* `tags` - (Optional) A mapping of tags to assign to the resource.


`sku` supports the following:

* `name` - (Required) Specifies the size of virtual machines in a scale set.
* `tier` - (Optional) Specifies the tier of virtual machines in a scale set. Possible values, `standard` or `basic`.
* `capacity` - (Required) Specifies the number of virtual machines in the scale set.

`rolling_upgrade_policy` supports the following:

* `max_batch_instance_percent` - (Optional) The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability. Defaults to `20`.
* `max_unhealthy_instance_percent` - (Optional) The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch. Defaults to `20`.
* `max_unhealthy_upgraded_instance_percent` - (Optional) The maximum percentage of upgraded virtual machine instances that can be found to be in an unhealthy state. This check will happen after each batch is upgraded. If this percentage is ever exceeded, the rolling update aborts. Defaults to `5`.
* `pause_time_between_batches` - (Optional) The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format for duration (https://en.wikipedia.org/wiki/ISO_8601#Durations). Defaults to 0 seconds represented as `PT0S`.

`os_profile` supports the following:

* `computer_name_prefix` - (Required) Specifies the computer name prefix for all of the virtual machines in the scale set. Computer name prefixes must be 1 to 15 characters long.
Expand All @@ -285,7 +313,6 @@ The following arguments are supported:
* `certificate_url` - (Required) It is the Base64 encoding of a JSON Object that which is encoded in UTF-8 of which the contents need to be `data`, `dataType` and `password`.
* `certificate_store` - (Required, on windows machines) Specifies the certificate store on the Virtual Machine where the certificate should be added to.


`os_profile_windows_config` supports the following:

* `provision_vm_agent` - (Optional) Indicates whether virtual machine agent should be provisioned on the virtual machines in the scale set.
Expand All @@ -312,13 +339,13 @@ The following arguments are supported:

~> _**Note:** Please note that the only allowed `path` is `/home/<username>/.ssh/authorized_keys` due to a limitation of Azure_


`network_profile` supports the following:

* `name` - (Required) Specifies the name of the network interface configuration.
* `primary` - (Required) Indicates whether network interfaces created from the network interface configuration will be the primary NIC of the VM.
* `ip_configuration` - (Required) An ip_configuration block as documented below
* `network_security_group_id` - (Optional) Specifies the identifier for the network security group.
* `health_probe_id` - (Optional) Specifies the identifier for the load balancer health probe. Required when using `Rolling` as your `upgrade_policy_mode`.

`ip_configuration` supports the following:

Expand All @@ -328,9 +355,9 @@ The following arguments are supported:
* `load_balancer_inbound_nat_rules_ids` - (Optional) Specifies an array of references to inbound NAT rules for load balancers.
* `primary` - (Optional) Specifies if this ip_configuration is the primary one.
* `accelerated_networking` - (Optional) Specifies whether to enable accelerated networking or not. Defaults to
false.
false.
* `public_ip_address_configuration` - (Optional) describes a virtual machines scale set IP Configuration's
PublicIPAddress configuration. The public_ip_address_configuration is documented below.
PublicIPAddress configuration. The public_ip_address_configuration is documented below.

`public_ip_address_configuration` supports the following:

Expand All @@ -346,8 +373,8 @@ false.
* `create_option` - (Required) Specifies how the virtual machine should be created. The only possible option is `FromImage`.
* `caching` - (Optional) Specifies the caching requirements. Possible values include: `None` (default), `ReadOnly`, `ReadWrite`.
* `image` - (Optional) Specifies the blob uri for user image. A virtual machine scale set creates an os disk in the same container as the user image.
Updating the osDisk image causes the existing disk to be deleted and a new one created with the new image. If the VM scale set is in Manual upgrade mode then the virtual machines are not updated until they have manualUpgrade applied to them.
When setting this field `os_type` needs to be specified. Cannot be used when `vhd_containers`, `managed_disk_type` or `storage_profile_image_reference ` are specified.
Updating the osDisk image causes the existing disk to be deleted and a new one created with the new image. If the VM scale set is in Manual upgrade mode then the virtual machines are not updated until they have manualUpgrade applied to them.
When setting this field `os_type` needs to be specified. Cannot be used when `vhd_containers`, `managed_disk_type` or `storage_profile_image_reference` are specified.
* `os_type` - (Optional) Specifies the operating system Type, valid values are windows, linux.

`storage_profile_data_disk` supports the following:
Expand All @@ -361,7 +388,7 @@ false.
`storage_profile_image_reference` supports the following:

* `id` - (Optional) Specifies the ID of the (custom) image to use to create the virtual
machine scale set, as in the [example below](#example-of-storage_profile_image_reference-with-id).
machine scale set, as in the [example below](#example-of-storage_profile_image_reference-with-id).
* `publisher` - (Optional) Specifies the publisher of the image used to create the virtual machines.
* `offer` - (Optional) Specifies the offer of the image used to create the virtual machines.
* `sku` - (Optional) Specifies the SKU of the image used to create the virtual machines.
Expand All @@ -372,7 +399,6 @@ machine scale set, as in the [example below](#example-of-storage_profile_image_r
* `enabled`: (Required) Whether to enable boot diagnostics for the virtual machine.
* `storage_uri`: (Required) Blob endpoint for the storage account to hold the virtual machine's diagnostic files. This must be the root of a storage account, and not a storage container.


`extension` supports the following:

* `name` - (Required) Specifies the name of the extension.
Expand All @@ -392,7 +418,6 @@ machine scale set, as in the [example below](#example-of-storage_profile_image_r
## Example of storage_profile_image_reference with id

```hcl
resource "azurerm_image" "test" {
name = "test"
...
Expand All @@ -415,7 +440,6 @@ The following attributes are exported:

* `id` - The virtual machine scale set ID.


## Import

Virtual Machine Scale Sets can be imported using the `resource id`, e.g.
Expand Down

0 comments on commit 83b20f2

Please sign in to comment.