首页 > 其他分享 >解决terraform部署storage account management policy问题

解决terraform部署storage account management policy问题

时间:2024-02-06 17:00:59浏览次数:29  
标签:account management recovery each policy vault s% azurerm

承接上文Terraform Azure diagnostic setting升级,之前说到azurerm_monitor_diagnostic_setting里的retention policy已经deprecated了,需要用azurerm_storage_management_policy替换

以recovery service vault的诊断设置为例,对应的azurerm_storage_management_policy可以参考下边的代码,其中各个Azure服务唯一有区别的地方就是prefix_match这里,因为每个服务对应的文件名都是不一样的,所以prefix也各不相同,这就导致很难用一段代码覆盖所有的服务

resource "azurerm_storage_management_policy" "recovery_vault_diagnostic" {

  for_each = local.settings


  storage_account_id = each.value.storage_account_id
  rule {

    name    = format("%s%s", "RecoveryVaultRetentionPolicy_", each.value.diagnostic_settings.storage_account_name)
    enabled = true
    filters {
      blob_types = ["blockBlob"]
      prefix_match = [
        format("%s%s%s%s%s%s", "insights-logs-addonazurebackupjobs/resourceId=/SUBSCRIPTIONS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].id), 2)), "/RESOURCEGROUPS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].resource_group_name), 4)), "/PROVIDERS/MICROSOFT.RECOVERYSERVICES/VAULTS/", upper(each.key)),
        format("%s%s%s%s%s%s", "insights-logs-azurebackupreport/resourceId=/SUBSCRIPTIONS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].id), 2)), "/RESOURCEGROUPS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].resource_group_name), 4)), "/PROVIDERS/MICROSOFT.RECOVERYSERVICES/VAULTS/", upper(each.key)),
        format("%s%s%s%s%s%s", "insights-logs-coreazurebackup/resourceId=/SUBSCRIPTIONS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].id), 2)), "/RESOURCEGROUPS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].resource_group_name), 4)), "/PROVIDERS/MICROSOFT.RECOVERYSERVICES/VAULTS/", upper(each.key))
      ]
    }




    actions {
      base_blob {

        delete_after_days_since_modification_greater_than = each.value.retention_policy.days

      }
    }

  }


}

在上一篇说过部署的时候这里会有一些坑,现在这个坑来了,上边的代码在部署之后会遇到报错,提示这个policy已经存在了

解决terraform部署storage account management policy问题_PowerShell

这是因为我之前在storage account里有其他的lifecycle management rule,这本来是很正常事情,没想到用terraform部署其他rule的时候会报错,而这个报错的原因也并不复杂,就是因为这个management policy的rules其实是个[],这个policy也是一个单独的对象,导致在用terraform部署的时候是新建一个policy,而不是修改原来的,这就会导致提示资源已经存在

解决terraform部署storage account management policy问题_PowerShell_02

这应该属于是设计上的问题,terraform只能部署新的policy,而一旦之前创建过rule,policy就会同时被创建出来,再用terraform部署policy就会报错了,这种问题看起来应该是没办法绕过去了,只能换个别的方向,尝试用ARM Template来部署,具体的代码就不贴了,直接说下结果,ARM Template确实可以部署成功,不会再报错,但是新的问题是ARM Template部署出来之后,会直接覆盖掉之前的rule。。而且这个policy里default这名字也是写死了的,只允许存在一个命名为default的policy,没办法同时存在多个policy

这导致ARM Template这条路也走不通,剩下的只能尝试用脚本来做了,事实证明这是可以的,原理就是在Terraform里通过null_resource来运行PowerShell命令,而在PowerShell命令里我们就不需要受Terraform或者ARM Template的限制了,完全可以做自己想做的任何事,我们可以先获取到当前的policy,然后把新建的rule合并到之前的policy里,这样就可以解决之前的问题了

逻辑基本就是这样,接下来直接把代码贴出来

resource "null_resource" "recovery_vault_diagnostic" {

  for_each = local.settings

  provisioner "local-exec" {

    interpreter = ["pwsh", "-Command"]
    command     = <<-EOT
          select-azSubscription  ${element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].id), 2)}
          $rgName = "${each.value.diagnostic_settings.storage_account_resource_group_name}"
          $accountName = "${each.value.diagnostic_settings.storage_account_name}"
          $prefix1="${format("%s%s%s%s%s%s", "insights-logs-addonazurebackupjobs/resourceId=/SUBSCRIPTIONS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].id), 2)), "/RESOURCEGROUPS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].resource_group_name), 4)), "/PROVIDERS/MICROSOFT.RECOVERYSERVICES/VAULTS/", upper(each.key))}"
          $prefix2="${format("%s%s%s%s%s%s", "insights-logs-azurebackupreport/resourceId=/SUBSCRIPTIONS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].id), 2)), "/RESOURCEGROUPS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].resource_group_name), 4)), "/PROVIDERS/MICROSOFT.RECOVERYSERVICES/VAULTS/", upper(each.key))}"
          $prefix3="${format("%s%s%s%s%s%s", "insights-logs-coreazurebackup/resourceId=/SUBSCRIPTIONS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].id), 2)), "/RESOURCEGROUPS/", upper(element(split("/", azurerm_recovery_services_vault.recovery_vault[each.key].resource_group_name), 4)), "/PROVIDERS/MICROSOFT.RECOVERYSERVICES/VAULTS/", upper(each.key))}"

          # Create a new action object.
          $action = Add-AzStorageAccountManagementPolicyAction -BaseBlobAction Delete `
              -daysAfterModificationGreaterThan ${each.value.retention_policy.days}

          # Create a new filter object.
          $filter = New-AzStorageAccountManagementPolicyFilter -PrefixMatch $prefix1,$prefix2,$prefix3 `
              -BlobType blockBlob

          # Create a new rule object.
          $rule1 = New-AzStorageAccountManagementPolicyRule -Name "${format("%s%s%s%s", "RecoveryVaultRetentionPolicy_", each.key, "_", each.value.diagnostic_settings.storage_account_name)}" `
              -Action $action `
              -Filter $filter

          # Get the current policy.
          $Policy=Get-AzStorageAccountManagementPolicy -ResourceGroupName $rgName -StorageAccountName $accountName
          if ($null -ne $Policy.Rules) {

              # rules already exists
              $rules=$Policy.Rules += $rule1

          }else{

              # rules not exist
              $rules=$rule1
          }

          # Create the policy.
          Set-AzStorageAccountManagementPolicy -ResourceGroupName $rgName `
              -StorageAccountName $accountName `
              -Rule $rules

EOT

  }

  depends_on = [azurerm_recovery_services_vault.recovery_vault]

}

最后附上截图,可以看到rules里会包含两条rule,一个是新建的,一个是之前就已经有的

解决terraform部署storage account management policy问题_Azure_03

标签:account,management,recovery,each,policy,vault,s%,azurerm
From: https://blog.51cto.com/mxyit/9629892

相关文章