Terraform: destroy azure rm virtual machine doesn't destroy it's vhd blob (meaning apply will fail the next time)

Created on 11 May 2016  ยท  26Comments  ยท  Source: hashicorp/terraform

I believe this is a bug but i am new to azure and terraform so maybe i am just doing things wrong.

i have a terraform configuration which creates a virtual machine and all the networking and storage to go along with it. and i want to be able to destroy the vm and recreate it regularly.

however when i call:

terraform destroy -target="azurerm_virtual_machine.WS"
terraform apply

it fails on the apply because the destroy never cleaned up the associated vhd created for the storage of the OS for the image.

NOTE: I only want to recreate the virtual machine and not everything so that the process is much quicker.

here is my terraform config for reference:

provider "azurerm" {
    # see https://www.terraform.io/docs/providers/azurerm/index.html
    # Credentials must be provided via the ARM_SUBSCRIPTION_ID, ARM_CLIENT_ID, ARM_CLIENT_SECRET and ARM_TENANT_ID environment variables
}

# Create a resource group
resource "azurerm_resource_group" "ait" {
    name     = "ait-res-group"
    location = "Australia Southeast"
}

# Create a virtual network
resource "azurerm_virtual_network" "ait" {
  name                = "ait-net"
  address_space       = ["10.0.0.0/16"]
  location            = "Australia Southeast"
  resource_group_name = "${azurerm_resource_group.ait.name}"
}

resource "azurerm_subnet" "ait" {
    name = "subnet"
    resource_group_name = "${azurerm_resource_group.ait.name}"
    virtual_network_name = "${azurerm_virtual_network.ait.name}"
    address_prefix = "10.0.1.0/24"
}

resource "azurerm_public_ip" "ait" {
    name = "aitpublicip"
    location = "Australia Southeast"
    resource_group_name = "${azurerm_resource_group.ait.name}"
    public_ip_address_allocation = "static"

    tags {
        environment = "Production"
    }
}

resource "azurerm_network_interface" "ait" {
    name = "ait-net-int"
    location = "Australia Southeast"
    resource_group_name = "${azurerm_resource_group.ait.name}"

    network_security_group_id = "${azurerm_network_security_group.ait.id}"

    ip_configuration {
        name = "ait-config"
        subnet_id = "${azurerm_subnet.ait.id}"
        private_ip_address_allocation = "dynamic"
        public_ip_address_id = "${azurerm_public_ip.ait.id}"
    }
}

resource "azurerm_network_security_group" "ait" {
    name = "ait-netsecgrp"
    location = "Australia Southeast"
    resource_group_name = "${azurerm_resource_group.ait.name}"

    security_rule {
        name = "allowtcp"
        priority = 1000
        direction = "Inbound"
        access = "Allow"
        protocol = "Tcp"
        source_port_range = "*"
        destination_port_range = "*"
        source_address_prefix = "*"
        destination_address_prefix = "*"
    }

    tags {
        environment = "Production"
    }
}

resource "azurerm_storage_account" "ait" {
    name = "aitstoragetransmax"
    resource_group_name = "${azurerm_resource_group.ait.name}"
    location = "Australia Southeast"
    account_type = "Standard_LRS"

    tags {
        environment = "ait"
    }
}

resource "azurerm_storage_container" "ait" {
    name = "vhds"
    resource_group_name = "${azurerm_resource_group.ait.name}"
    storage_account_name = "${azurerm_storage_account.ait.name}"
    container_access_type = "private"
}

# Create a VM
resource "azurerm_virtual_machine" "WS" {
    name = "ait-ws81"
    location = "Australia Southeast"
    resource_group_name = "${azurerm_resource_group.ait.name}"
    network_interface_ids = ["${azurerm_network_interface.ait.id}"]
    vm_size = "Standard_D2_V2" #2 core, 7GB RAM, 4x500IOPS

    storage_image_reference {
        publisher = "MicrosoftVisualStudio"
        offer = "Windows"
        sku = "8.1-Enterprise-N"
        version = "latest"
    }

    storage_os_disk {
        name = "aitWS81disk"
        vhd_uri = "${azurerm_storage_account.ait.primary_blob_endpoint}${azurerm_storage_container.ait.name}/ait-ws81-disk.vhd"
        caching = "ReadWrite"
        create_option = "FromImage"
    }

    os_profile {
        computer_name = "ait-ws81"
        admin_username = "aituser"
        admin_password = "Password!"
    }

    os_profile_windows_config {
        enable_automatic_upgrades = true
    }

    tags {
        environment = "ait"
    }
}
bug provideazurerm

Most helpful comment

@avdhoot did you set this option on azurerm_virtual_machine resource?

delete_os_disk_on_termination = "true"

by default its set to false.

All 26 comments

i should mention if i do the following instead it works:

terraform destroy -target="azurerm_virtual_machine.WS"
terraform destroy -target="azurerm_storage_container.ait"
terraform apply

which is a reasable workaround for now, but it does delete the whole stoarge container and recreate it which only works if i make sure i dont reuse that container for anything else.

So the original post is still definately a bug (and one with a decent priority IMO) but i thought i would mention this for anyone else looking for a workaround

Hi @MattFenner

apologies for the confusion here. When you are targetting a specific resource - you are only destroying that resource - NOT it's dependencies. The dependency of the VM (in this case the storageblob) may actually be a dependency for something else as well - so destroying it may cause a chain of events. Does this sort of make sense?

P.

Thanks @stack72, what is confusing me is that the blob is defined as part of the virtual machine not as a separate resource.

So what would be the way to specify to destroy the vm along with the image?

i.e.

resource "azurerm_virtual_machine" "test" {

    ....

    storage_os_disk {
        name = "myosdisk1"
        vhd_uri = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}/myosdisk1.vhd"
        caching = "ReadWrite"
        create_option = "FromImage"
    }

}

@MattFenner

I totally understand what you mean now - i thought you meant the blob itself! I will try and look into this

P.

+1

@stack72 i think i did mean the blob. IMO it should delete the blob for the disk (which is configured as part of the VM), but it should leave the container which is specified as a separate resource

i.e. the blob specified by vhd_uri

+1 also having this issue

+1 also having this.

+1

+1, same here

Deleting the whole storage container might not be an option but does the job for the time being.
A constrain is to ensure that VM exists within its own storage container, and then don't forget to delete it all the time.

+1 Also having this issue

+1 also having this issue. Unfortunately I keep more than just the vdh for the instance I want to taint in the storage container it uses meaning the workaround isn't suitable for me. I have to go into the portal and delete the vhd manually

@stack72 still facing same issue. with 0.7.7

Hi @avdhoot

by any chance is the storage account in a different resource group?

@avdhoot did you set this option on azurerm_virtual_machine resource?

delete_os_disk_on_termination = "true"

by default its set to false.

@stack72 @rbrutas my bad missed "delete_os_disk_on_termination" option. I think default value should be true. what you guy's think?

@avdhoot the default value via the Azure portal is not true and we are going to try and replicate that so it's an explicit opt-in

+1

@AzCii I believe this is a solved thing - please post your config and I can see if there is an issue here

I'm using Terraform v0.7.13.

and my virtual machine looks like this:

resource "azurerm_virtual_machine" "unifi" {
    provider = "azurerm.MSDN"
    name = "unifivirtualmachine"
    location = "North Europe"
    resource_group_name = "${azurerm_resource_group.azcii.name}"
    network_interface_ids = ["${azurerm_network_interface.unifi.id}"]
    vm_size = "Basic_A2"

    storage_image_reference {
        publisher = "MicrosoftWindowsServer"
        offer = "WindowsServer"
        sku = "2016-Datacenter"
        version = "latest"
    }

    storage_os_disk {
        name = "unifistorageosdisk"
        vhd_uri = "${azurerm_storage_account.azcii.primary_blob_endpoint}${azurerm_storage_container.azciiprivate.name}/unifistorageosdisk.vhd"
        caching = "ReadWrite"
        create_option = "FromImage"
    }

    os_profile {
        computer_name = "unifi"
        admin_username = "${var.shared_username}"
        admin_password = "${var.shared_password}"
    }

    os_profile_windows_config {
        enable_automatic_upgrades = true
        provision_vm_agent = true
    }

}

I'm not removing the container, i'm only to remove the machine, but when i when add it again, the disk is already there and it fails because of that.

Hi @AzCii

you are missing this:

delete_os_disk_on_termination = "true"

This is described above

Thanks

Paul

OMG you are right, I must have missed it the last time I rolled back.
Thanks.

Hi guys, I think I am having this problem with managed data disks. @stack72 is there a flag like that to destroy the data disks?

Thanks @BookOfGreg

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings