Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
411 lines (323 sloc) 15.1 KB
title description author ms.service ms.topic ms.date ms.author
Tag Azure resources for logical organization | Microsoft Docs
Shows how to apply tags to organize Azure resources for billing and managing.
tfitzmac
azure-resource-manager
conceptual
07/17/2019
tomfitz

Use tags to organize your Azure resources

[!INCLUDE resource-manager-governance-tags]

To apply tags to resources, the user must have write access to that resource type. To apply tags to all resource types, use the Contributor role. To apply tags to only one resource type, use the contributor role for that resource. For example, to apply tags to virtual machines, use the Virtual Machine Contributor.

[!INCLUDE Handle personal data]

Policies

You can use Azure Policy to enforce tagging rules and conventions. By creating a policy, you avoid the scenario of resources being deployed to your subscription that don't comply with the expected tags for your organization. Instead of manually applying tags or searching for resources that aren't compliant, you can create a policy that automatically applies the needed tags during deployment. Tags can also now be applied to existing resources with the new Modify effect and a remediation task. The following section shows example policies for tags.

[!INCLUDE Tag policies]

PowerShell

[!INCLUDE updated-for-az]

To see the existing tags for a resource group, use:

(Get-AzResourceGroup -Name examplegroup).Tags

That script returns the following format:

Name                           Value
----                           -----
Dept                           IT
Environment                    Test

To see the existing tags for a resource that has a specified resource ID, use:

(Get-AzResource -ResourceId /subscriptions/<subscription-id>/resourceGroups/<rg-name>/providers/Microsoft.Storage/storageAccounts/<storage-name>).Tags

Or, to see the existing tags for a resource that has a specified name and resource group, use:

(Get-AzResource -ResourceName examplevnet -ResourceGroupName examplegroup).Tags

To get resource groups that have a specific tag, use:

(Get-AzResourceGroup -Tag @{ Dept="Finance" }).ResourceGroupName

To get resources that have a specific tag, use:

(Get-AzResource -Tag @{ Dept="Finance"}).Name

To get resources that have a specific tag name, use:

(Get-AzResource -TagName Dept).Name

Every time you apply tags to a resource or a resource group, you overwrite the existing tags on that resource or resource group. Therefore, you must use a different approach based on whether the resource or resource group has existing tags.

To add tags to a resource group without existing tags, use:

Set-AzResourceGroup -Name examplegroup -Tag @{ Dept="IT"; Environment="Test" }

To add tags to a resource group that has existing tags, retrieve the existing tags, add the new tag, and reapply the tags:

$tags = (Get-AzResourceGroup -Name examplegroup).Tags
$tags.Add("Status", "Approved")
Set-AzResourceGroup -Tag $tags -Name examplegroup

To add tags to a resource without existing tags, use:

$r = Get-AzResource -ResourceName examplevnet -ResourceGroupName examplegroup
Set-AzResource -Tag @{ Dept="IT"; Environment="Test" } -ResourceId $r.ResourceId -Force

To add tags to a resource that has existing tags, use:

$r = Get-AzResource -ResourceName examplevnet -ResourceGroupName examplegroup
$r.Tags.Add("Status", "Approved")
Set-AzResource -Tag $r.Tags -ResourceId $r.ResourceId -Force

To apply all tags from a resource group to its resources, and not keep existing tags on the resources, use the following script:

$groups = Get-AzResourceGroup
foreach ($g in $groups)
{
    Get-AzResource -ResourceGroupName $g.ResourceGroupName | ForEach-Object {Set-AzResource -ResourceId $_.ResourceId -Tag $g.Tags -Force }
}

To apply all tags from a resource group to its resources, and keep existing tags on resources that aren't duplicates, use the following script:

$group = Get-AzResourceGroup "examplegroup"
if ($null -ne $group.Tags) {
    $resources = Get-AzResource -ResourceGroupName $group.ResourceGroupName
    foreach ($r in $resources)
    {
        $resourcetags = (Get-AzResource -ResourceId $r.ResourceId).Tags
        if ($resourcetags)
        {
            foreach ($key in $group.Tags.Keys)
            {
                if (-not($resourcetags.ContainsKey($key)))
                {
                    $resourcetags.Add($key, $group.Tags[$key])
                }
            }
            Set-AzResource -Tag $resourcetags -ResourceId $r.ResourceId -Force
        }
        else
        {
            Set-AzResource -Tag $group.Tags -ResourceId $r.ResourceId -Force
        }
    }
}

To remove all tags, pass an empty hash table:

Set-AzResourceGroup -Tag @{} -Name examplegroup

Azure CLI

To see the existing tags for a resource group, use:

az group show -n examplegroup --query tags

That script returns the following format:

{
  "Dept"        : "IT",
  "Environment" : "Test"
}

Or, to see the existing tags for a resource that has a specified name, type, and resource group, use:

az resource show -n examplevnet -g examplegroup --resource-type "Microsoft.Network/virtualNetworks" --query tags

When looping through a collection of resources, you might want to show the resource by resource ID. A complete example is shown later in this article. To see the existing tags for a resource that has a specified resource ID, use:

az resource show --id <resource-id> --query tags

To get resource groups that have a specific tag, use az group list:

az group list --tag Dept=IT

To get all the resources that have a particular tag and value, use az resource list:

az resource list --tag Dept=Finance

Every time you apply tags to a resource or a resource group, you overwrite the existing tags on that resource or resource group. Therefore, you must use a different approach based on whether the resource or resource group has existing tags.

To add tags to a resource group without existing tags, use:

az group update -n examplegroup --set tags.Environment=Test tags.Dept=IT

To add tags to a resource without existing tags, use:

az resource tag --tags Dept=IT Environment=Test -g examplegroup -n examplevnet --resource-type "Microsoft.Network/virtualNetworks"

To add tags to a resource that already has tags, retrieve the existing tags, reformat that value, and reapply the existing and new tags:

jsonrtag=$(az resource show -g examplegroup -n examplevnet --resource-type "Microsoft.Network/virtualNetworks" --query tags)
rt=$(echo $jsonrtag | tr -d '"{},' | sed 's/: /=/g')
az resource tag --tags $rt Project=Redesign -g examplegroup -n examplevnet --resource-type "Microsoft.Network/virtualNetworks"

To apply all tags from a resource group to its resources, and not keep existing tags on the resources, use the following script:

groups=$(az group list --query [].name --output tsv)
for rg in $groups
do
  jsontag=$(az group show -n $rg --query tags)
  t=$(echo $jsontag | tr -d '"{},' | sed 's/: /=/g')
  r=$(az resource list -g $rg --query [].id --output tsv)
  for resid in $r
  do
    az resource tag --tags $t --id $resid
  done
done

To apply all tags from a resource group to its resources, and keep existing tags on resources, use the following script:

groups=$(az group list --query [].name --output tsv)
for rg in $groups
do
  jsontag=$(az group show -n $rg --query tags)
  t=$(echo $jsontag | tr -d '"{},' | sed 's/: /=/g')
  r=$(az resource list -g $rg --query [].id --output tsv)
  for resid in $r
  do
    jsonrtag=$(az resource show --id $resid --query tags)
    rt=$(echo $jsonrtag | tr -d '"{},' | sed 's/: /=/g')
    az resource tag --tags $t$rt --id $resid
  done
done

Templates

To tag a resource during deployment, add the tags element to the resource you're deploying. Provide the tag name and value.

Apply a literal value to the tag name

The following example shows a storage account with two tags (Dept and Environment) that are set to literal values:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]"
        }
    },
    "resources": [
        {
            "apiVersion": "2019-04-01",
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[concat('storage', uniqueString(resourceGroup().id))]",
            "location": "[parameters('location')]",
            "tags": {
                "Dept": "Finance",
                "Environment": "Production"
            },
            "sku": {
                "name": "Standard_LRS"
            },
            "kind": "Storage",
            "properties": {}
        }
    ]
}

To set a tag to a datetime value, use the utcNow function.

Apply an object to the tag element

You can define an object parameter that stores several tags, and apply that object to the tag element. Each property in the object becomes a separate tag for the resource. The following example has a parameter named tagValues that is applied to the tag element.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]"
        },
        "tagValues": {
            "type": "object",
            "defaultValue": {
                "Dept": "Finance",
                "Environment": "Production"
            }
        }
    },
    "resources": [
        {
            "apiVersion": "2019-04-01",
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[concat('storage', uniqueString(resourceGroup().id))]",
            "location": "[parameters('location')]",
            "tags": "[parameters('tagValues')]",
            "sku": {
                "name": "Standard_LRS"
            },
            "kind": "Storage",
            "properties": {}
        }
    ]
}

Apply a JSON string to the tag name

To store many values in a single tag, apply a JSON string that represents the values. The entire JSON string is stored as one tag that can't exceed 256 characters. The following example has a single tag named CostCenter that contains several values from a JSON string:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]"
        }
    },
    "resources": [
        {
            "apiVersion": "2019-04-01",
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[concat('storage', uniqueString(resourceGroup().id))]",
            "location": "[parameters('location')]",
            "tags": {
                "CostCenter": "{\"Dept\":\"Finance\",\"Environment\":\"Production\"}"
            },
            "sku": {
                "name": "Standard_LRS"
            },
            "kind": "Storage",
            "properties": {}
        }
    ]
}

Apply tags from resource group

To apply tags from a resource group to a resource, use the resourceGroup function. When getting the tag value, use the tags.[tag-name] syntax instead of the tags.tag-name syntax, because some characters aren't parsed correctly in the dot notation.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]"
        }
    },
    "resources": [
        {
            "apiVersion": "2019-04-01",
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[concat('storage', uniqueString(resourceGroup().id))]",
            "location": "[parameters('location')]",
            "tags": {
                "Dept": "[resourceGroup().tags['Dept']]",
                "Environment": "[resourceGroup().tags['Environment']]"
            },
            "sku": {
                "name": "Standard_LRS"
            },
            "kind": "Storage",
            "properties": {}
        }
    ]
}

Portal

[!INCLUDE resource-manager-tag-resource]

REST API

The Azure portal and PowerShell both use the Resource Manager REST API behind the scenes. If you need to integrate tagging into another environment, you can get tags by using GET on the resource ID and update the set of tags by using a PATCH call.

Tags and billing

You can use tags to group your billing data. For example, if you're running multiple VMs for different organizations, use the tags to group usage by cost center. You can also use tags to categorize costs by runtime environment, such as the billing usage for VMs running in the production environment.

You can retrieve information about tags through the Azure Resource Usage and RateCard APIs or the usage comma-separated values (CSV) file. You download the usage file from the Azure Account Center or Azure portal. For more information, see Download or view your Azure billing invoice and daily usage data. When downloading the usage file from the Azure Account Center, select Version 2. For services that support tags with billing, the tags appear in the Tags column.

For REST API operations, see Azure Billing REST API Reference.

Next steps

You can’t perform that action at this time.