当前位置: 代码迷 >> 综合 >> [Azure]使用Powershell清理ARM中的无效资源
  详细解决方案

[Azure]使用Powershell清理ARM中的无效资源

热度:19   发布时间:2023-12-14 21:55:33.0

Azure ARM模式将资源进一步细化,比经典模式要更为灵活,但是带来的的问题是,资源整理和维护起来就要更为琐碎。举一个比较实际的例子,创建了一台虚拟机,会为虚拟机指定虚拟网络(对应子网会生成网络接口),存储账号,公网IP地址,NSG(网络安全组),可用性集,当然还可能有其他资源与其关联。如果删除这台虚拟机,默认虚拟机的所有磁盘会被保留,存储账号会保留,容器会保留,公网IP地址,网络接口会保留,NSG和可用性集也都还在订阅中。一方面是费用上,可能这些保留下来的资源不会再用了,而有些可能仍然会继续计费,另一方面管理上会很混乱,有一大堆“游离”的资源在订阅下,让人眼花缭乱,而且这些资源可能还会占用订阅的配额。


我们可以使用下面的脚本进行这些资源的清理工作,除此之外,脚本中还有对花销比较大的资源(DS虚拟机,高级存储,应用程序网关)的停止和删除逻辑,并且在脚本开始时,我们通过一些布尔变量进行整个脚本逻辑的控制(例如是否关停,是否删除),可以进行一个“test run”来看一下脚本的执行结果(利用脚本中的输出语句和前面的布尔变量控制),这样可以保证我们执行出我们想要的结果,避免关闭或删除掉我们希望保留的资源。同时脚本也定义了一些例外规则(有兴趣的同学可以仿照添加其他例外资源的逻辑)。

对整个脚本进行一些学习,也可以熟悉和掌握遍历订阅下的ARM常见资源的语句和方法。

脚本如下:

#True: Real run/ False: Test run
$doActions = $TRUE;#True: Real rum/ False: Test run
$doCleanUnusedResources = $TRUE;#True: Real rum/ False: Test run
$doShutdowns = $TRUE;#switch for delete/shutdown expensive resources
$doDeleteAppGateway = $TRUE;
$doDeletePremiumStorageAccounts = $TRUE;#Login Credentials
$e1=Get-AzureRmEnvironment -Name AzureChinaCloud
$Cred = New-Object System.Management.Automation.PSCredential(“XXXX@XXX.parter.onmschina.cn”, (ConvertTo-SecureString “XXXXX” -AsPlainText -Force));#exceptions
$VMExceptions = @{#<ResourceGroupName> = "<VM Name 1>;<VM Name 2>;<VM Name 3> ..."; #"Example 1"="VM1;VM2;VM3"; #"Example 2"="VM1;VM2" };$AppGWExceptions = @{#<ResourceGroupName> = "<Application Gateway 1>;<Application Gateway 2>;<Application Gateway 3> ..."; #"Example 1"="ApplicationGateway1;ApplicationGateway2;ApplicationGateway3"; #"Example 2"="ApplicationGateway1;ApplicationGateway2" };#Login
$AzureRMCred = Get-Credential -Credential $Cred;
Login-AzureRmAccount -Environment $e1 -Credential $AzureRMCred;#get all subscriptions
$subscriptions = Get-AzureRmSubscription;#loop every subscriptions
foreach ($subscription in $subscriptions)
{ #skip disabled subscriptions if ($subscription.State -eq "Disabled") { continue; } Write-Host "========== Switched to subscription " + $subscription.SubscriptionName + " =========="; Select-AzureRmSubscription -SubscriptionName $subscription.SubscriptionName; #================================================ #Begin# shut down/remove expensive resources ================================================ #shutdown/delete Application Gateways $applicationGateways = Get-AzureRmApplicationGateway; foreach ($applicationGateway in $applicationGateways) { if ($doDeleteAppGateway) { Write-Host " [ApplicationGateway]Removing ApplicationGateway " + $applicationGateway.Name + "..."; if ($doActions) { Remove-AzureRmApplicationGateway -Name $applicationGateway.Name -ResourceGroupName $applicationGateway.ResourceGroupName -Force; } Write-Host " [ApplicationGateway]ApplicationGateway " + $applicationGateway.Name + " removed."; } elseif ($doShutdowns) { Write-Host " [ApplicationGateway]Stopping ApplicationGateway " + $applicationGateway.Name + "..."; if ($doActions) { Stop-AzureRmApplicationGateway -ApplicationGateway $applicationGateway; } Write-Host " [ApplicationGateway]ApplicationGateway " + $applicationGateway.Name + " stopped."; } } #stop ARM VMs $DSVMs = @{}; $vms = Get-AzureRmVM; foreach ($vm in $vms) { $except = $FALSE; foreach ($resourceGroupName in $VMExceptions.Keys) { if ($vm.ResourceGroupName.ToLower().Equals($resourceGroupName.ToLower())) { $vmnames = $VMExceptions[$resourceGroupName].Split(";"); foreach ($vmname in $vmnames) { if($vmname.ToLower().Equals($vm.Name.ToLower())) { $except = $true; break; } } } } if ($vm.HardwareProfile.VmSize.Contains("DS")) { #add to DSVM dict to be deleted if ($DSVMs.ContainsKey($vm.ResourceGroupName)) { $DSVMs[$vm.ResourceGroupName] += ";"; $DSVMs[$vm.ResourceGroupName] += $vm.Name; } else { $DSVMs.Add($vm.ResourceGroupName, $vm.Name); } } if ($except) { Write-Host " [VirtualMachine]Virtual Machine" + $vm.Name + " skipped(In exception list)"; } else { $vmStatuses = (Get-AzureRmVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status).Statuses; $status = ""; foreach ($code in $vmStatuses.Code) { if ($code.Contains("PowerState")) { $status = $code.Substring($code.LastIndexOf('/') + 1); } } if (($status -eq "running") -or ($status -eq "stopped")) { Write-Host " [VirtualMachine]Stoping VirtualMachine " + $vm.Name + "..."; if ($doActions -and $doShutdowns) { Stop-AzureRmVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Force; } Write-Host " [VirtualMachine]Virtual Machine " + $vm.Name + " stopped."; } else { Write-Host " [VirtualMachine]Virtual Machine " + $vm.Name + " status is " + $status + ", skipped"; } } } #remove ARM DS VMs foreach ($resoruceGroupName in $DSVMs.Keys) { $vmNames = $DSVMs[$resoruceGroupName].Split(';'); foreach ($vmName in $vmNames) { Write-Host " [VirtualMachine]Removing DS VirtualMachine " + $vmName + "..."; if ($doActions) { Remove-AzureRmVM -ResourceGroupName $resoruceGroupName -Name $vmName -Force; } Write-Host " [VirtualMachine]DS VirtualMachine " + $vmName + " Removed."; } } #remove Premium Storage Account $storageAccounts = Get-AzureRmStorageAccount; foreach ($storageAccount in $storageAccounts) { if($storageAccount.Sku.Tier -eq "Premium") { $storageName = $storageAccount.StorageAccountName; $context = $storageAccount.Context; $containers = Get-AzureStorageContainer -Context $context; foreach ($container in $containers) { $blobs = Get-AzureStorageBlob -Container $container.Name -Context $context; if ($blobs.Count -ne 0) { #Remove blobs foreach ($blob in $blobs) { Write-Host " [Blob]Removing Blob " + $blob.Name + " in container " + $storageName + "\\" + $container.Name + "..."; if ($doActions -and $doDeletePremiumStorageAccounts) { Remove-AzureStorageBlob -Blob $blob.Name -Container $container.Name -Context $context -Force; } sleep(5); $blobTest = Get-AzureStorageBlob -Blob $blob.Name -Container $container.Name -Context $context; if ($blobTest -ne $NULL) { Write-Host " [Blob]Failed to remove Blob " + $blob.Name; } else { Write-Host " [Blob]Blob " + $blob.Name + " Removed."; } } } #Remove container Write-Host " [Container]Removing Container " + $container.Name + " under storage account " + $storageName + "..."; if ($doActions -and $doDeletePremiumStorageAccounts) { Remove-AzureStorageContainer -Name $container.Name -Context $context -Force; } sleep(5); $containerTest = Get-AzureStorageContainer -Name $container.Name -Context $context; if ($containerTest -ne $NULL) { Write-Host " [Container]Failed to remove Container " + $container.Name; } else { Write-Host " [Container]Container " + $container.Name + " Removed."; } } #Remove storage account Write-Host " [PremiumStorageAccount]Removing Premium Storage Account " + $storageName; if ($doActions -and $doDeletePremiumStorageAccounts) { Remove-AzureRmStorageAccount -ResourceGroupName $storageAccount.ResourceGroupName -Name $storageName -Force; } sleep(5); $storageTest = Get-AzureRmStorageAccount -StorageAccountName $storageName -ResourceGroupName $storageAccount.ResourceGroupName; if ($storageTest -ne $NULL) { Write-Host " [PremiumStorageAccount]Failed to remove Premium Storage Account " + $storageName; } else { Write-Host " [PremiumStorageAccount]Premium Storage Account " + $storageName + " Removed."; } } } #================================================ #End# shut down/remove expensive resources ================================================ #================================================ #Begin# clean unused resources ================================================ #clear unused network interfaces $nics = Get-AzureRmNetworkInterface; foreach ($nic in $nics) { if ($nic.VirtualMachine -eq $NULL) { Write-Host " [NIC]Removing unused NIC " + $nic.Name + "..."; if ($doActions -and $doCleanUnusedResources) { Remove-AzureRmNetworkInterface -Name $nic.Name -ResourceGroupName $nic.ResourceGroupName -Force; } Write-Host " [NIC]NIC " + $nic.Name + " removed."; } else { Write-Host " [NIC]NIC " + $nic.Name + " is in use, skipped"; } } #clear unused public IPAddresses $ips = Get-AzureRmPublicIpAddress; foreach ($ip in $ips) { if ($ip.IpConfiguration -eq $NULL) { Write-Host " [IP]Removing unused IPAddress " + $ip.Name + "..."; if ($doActions -and $doCleanUnusedResources) { Remove-AzureRmPublicIpAddress -Name $ip.Name -ResourceGroupName $ip.ResourceGroupName -Force; } Write-Host " [IP]IPAddress " + $ip.Name + " removed."; } else { Write-Host " [IP]IPAddress " + $ip.Name + " is in use, skipped"; } } #clear unused NSGs $nsgs = Get-AzureRmNetworkSecurityGroup; foreach ($nsg in $nsgs) { if ($nsg.Subnets.Count -eq 0 -and $nsg.NetworkInterfaces.Count -eq 0) { Write-Host " [NSG]Removing unused NetworkSecurityGroup " + $nsg.Name + "..."; if ($doActions -and $doCleanUnusedResources) { Remove-AzureRmNetworkSecurityGroup -Name $nsg.Name -ResourceGroupName $nsg.ResourceGroupName -Force; } Write-Host " [NSG]NetworkSecurityGroup " + $nsg.Name + " removed."; } else { Write-Host " [NSG]NetworkSecurityGroup " + $nsg.Name + " is in use, skipped"; } } $resourceGroups = Get-AzureRmResourceGroup; foreach ($resourceGroup in $resourceGroups) { #clear unused AvailabilitySets $avaSets = Get-AzureRmAvailabilitySet -ResourceGroupName $resourceGroup.ResourceGroupName; foreach ($avaSet in $avaSets) { if ($avaSet.VirtualMachinesReferences.Count -eq 0) { Write-Host " [AvaSet]Removing unused AvailabilitySet " + $avaSet.Name + "..."; if ($doActions -and $doCleanUnusedResources) { Remove-AzureRmAvailabilitySet -ResourceGroupName $resourceGroup.ResourceGroupName -Name $avaSet.Name -Force; } Write-Host " [AvaSet]AvailabilitySet " + $avaSet.Name + " removed."; } else { Write-Host " [AvaSet]AvailabilitySet " + $avaSet.Name + " is in use, skipped";} } #shutdown Vmss $vmsses = Get-AzureRmVmss -ResourceGroupName $resourceGroup.ResourceGroupName; foreach ($vmssName in $vmsses.Name) { Write-Host " [Vmss]Stopping Vmss " + $vmssName + "..."; if ($doActions -and $doShutdowns) { Stop-AzureRmVmss -ResourceGroupName $resourceGroup.ResourceGroupName -VMScaleSetName $vmssName; } Write-Host " [Vmss]Vmss " + $vmssName + " stopped."; } } #clear unused Disks $storages = Get-AzureRmStorageAccount; foreach ($storage in $storages) { $context = $storage.Context; #get page blobs under container vhds $blobs = Get-AzureStorageBlob -Context $context -Container "vhds" | where {$_.BlobType -eq "PageBlob"}; foreach ($blob in $blobs) { if ($blob.Name.EndsWith(".vhd") -and $blob.ICloudBlob.Properties.LeaseState -eq "Available" -and $blob.ICloudBlob.Properties.LeaseStatus -eq "Unlocked") { Write-Host " [VHD]Removing unused VHD " + $blob.Name + "..."; if ($doActions -and $doCleanUnusedResources) { Remove-AzureStorageBlob -Blob $blob.Name -Container vhds -Context $context -Force; } Write-Host " [VHD]VHD " + $blob.Name + " removed."; } else { Write-Host " [VHD]VHD " + $blob.Name + " is in use, skipped"; } } } #clear empty storages foreach ($storage in $storages) { $context = $storage.Context; #get containers $containers = Get-AzureStorageContainer -Context $context; #clear empty containers foreach ($container in $containers) { $blobs = Get-AzureStorageBlob -Container $container.Name -Context $context; if ($blobs.Count -eq 0) { Write-Host " [Container]Removing empty Container " + $container.Name + "..."; if ($doActions -and $doCleanUnusedResources) { Remove-AzureStorageContainer -Name $container.Name -Context $context -Force; } Write-Host " [Container]Container " + $container.Name + " removed."; } else { Write-Host " [Container]Container " + $container.Name + " is not empty, skipped"; } } #get containers $containers = Get-AzureStorageContainer -Context $context; if ($containers.Count -eq 0) { Write-Host " [Storage]Removing empty Storage " + $storage.StorageAccountName + "..."; if ($doActions -and $doCleanUnusedResources) { Remove-AzureRmStorageAccount -ResourceGroupName $storage.ResourceGroupName -Name $storage.StorageAccountName -Force; } Write-Host " [Storage]Storage " + $storage.StorageAccountName + " removed."; } else { Write-Host " [Storage]Storage " + $storage.StorageAccountName + " is not empty, skipped"; } } #clear empty resourcegroups $resourceGroups = Get-AzureRmResourceGroup; $resources = Get-AzureRmResource; foreach ($resourceGroup in $resourceGroups) { $resourcesInGroup = $resources | where {$_.ResourceGroupName.Equals($resourceGroup.ResourceGroupName)} if ($resourcesInGroup.Count -eq 0) {Write-Host " [ResourceGroup]Removing empty ResourceGroup " + $resourceGroup.ResourceGroupName + "..."; if ($doActions -and $doCleanUnusedResources) { Remove-AzureRmResourceGroup -Name $resourceGroup.ResourceGroupName -Force; } Write-Host " [ResourceGroup]ResourceGroup " + $resourceGroup.ResourceGroupName + " removed."; } else { Write-Host " [ResourceGroup]ResourceGroup " + $resourceGroup.ResourceGroupName + " is not empty, skipped"; } } #================================================ #End# clean unused resources ================================================
}Write-Host "Task finished..."; 


??

  相关解决方案