你是否还在为花费大量Azure Resource打标签而烦恼呢?你是否还在因为这样低效的重复劳动而痛苦呢?

在很长一段时间内,笔者既要做云架构调整,又要做日常系统维护,还要参与各种各样的项目,在这种情况下,如果我还花许多时间在打标签这种小事上,不仅劳累了自己,还会耽误其他更重要的任务。

作为高级懒人,我们绝对不能够允许这样的情况存在,一切能够自动化的操作绝不能允许自己去手动完成。

虽然话是这么说,具体打什么样的标签还是要你自己决定的。但是我相信绝大多数企业至少都会打application或者project的标签。那基于这种情况,我介绍一种比较讨巧的方法可以让resource自动打标签,但是这种方法目前有几个限制:

1.不会重复检查已经打好的标签

2.资源组的标签还是要手动提前打好

3.所打的标签参照资源所属的资源组已有的标签

在这里我们要用到Azure两个服务,一个是azure policy另一个则是经常用到的automation,步骤其实很简单,如下

1.利用Azure policy中的“Append tag and its default value”, 指定tag Name为application, tag value 为undefined

我狠起来连自己都打---如何简单实现Azure resource自动打标签-LMLPHP

至此之后你所有建立的azure resource 都会在创建之初就带有这个预设的tag

2.建立资源组时做好tagging

3. 利用azure automation的runbook去遍历所有带有预设tag的resource, 并将对应的resource group的标签应用在其自身。

具体runbook sample 如下:

$connectionName = "AzureRunAsConnection"
try
{

    $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName

    "Logging in to Azure..."
    Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint `
        -EnvironmentName AzureChinaCloud
 }
catch {
    if (!$servicePrincipalConnection)
    {
        $ErrorMessage = "Connection $connectionName not found."
        throw $ErrorMessage
    } else{
        Write-Error -Message $_.Exception
        throw $_.Exception
    }
}

Select-AzureRmSubscription -Subscription SubscriptionName
$Resources = (Get-azurermresource -Tag @{ Application="undefined"})

Foreach ($resource in $Resources)
{
    $Rgname = $resource.Resourcegroupname

    $resourceid = $resource.resourceId
    $RGTags = (Get-AzureRmResourceGroup -Name $Rgname).Tags

    $resourcetags = $resource.Tags

            $RGTagFinal = @{}
            $RGTagFinal = $RGTags
                    Foreach ($resourcetag in $resourcetags.GetEnumerator())
                    {

                    If ($RGTags.Keys -inotcontains $resourcetag.Key)
                        {
                                Write-Output "------------------------------------------------"
                                Write-Output "Keydoesn't exist in RG Tags adding to Hash Table" $resourcetag
                                Write-Output "------------------------------------------------"
                                $RGTagFinal.Add($resourcetag.Key,$resourcetag.Value)
                        }

                    }
            Write-Output "---------------------------------------------"
            Write-Output "Applying the following Tags to $($resourceid)" $RGTagFinal
            Write-Output "---------------------------------------------"
            $Settag = Set-AzureRmResource -ResourceId $resourceid -Tag $RGTagFinal -Force

}

如果你的资源比较多并且在各个订阅都有,可以把runbook该进为workflow,并且多一个遍历所有订阅的嵌套。

另外还有一点再提一下就是automation 的run as account必须对所有的资源至少拥有可以修改标签的权限。

这里你可能会说,为什么我们不去遍历所有的resource去自动apply RG的标签呢?想想一下当你的resource数量上千上万的时候,你这个job得run多久。因此简单的一个预设标签作为get-azurermresource 的filter就大大节省去了之后重复多余的标签动作,只需要给新增的resource tagging即可。

笔者先提供自己的方法作为抛砖引玉,大家可以在此基础上进行一些优化。或者如果有更好的自动标签的方案也欢迎提出交流。

07-25 08:03