In the previous article, we discussed how to deploy Azure Recovery Services Vault with custom backup policies defined in Locals. In this article, we will continue building on that and focus on deploying backup policies for Azure File Shares using Terraform variables instead of locals.

Azure Recovery Services Vault - azurerm_recovery_services_vault

Azure Recovery Services Terraform Module Structure

Module Structure: To deploy an Azure Recovery Services Vault with private endpoints and custom backup policies using Terraform azurerm_recovery_services_vault resource, we will use a module structure. The module will consist of four main Terraform files: main.tf, variables.tf, data.tf, and outputs.tf.

main.tf: The main.tf file is where we define the resources we want to create including the main one - azurerm_recovery_services_vault resource. In this file, we will define our Recovery Services Vault and its associated resources, including private endpoints and backup policies.

variables.tf: The variables.tf file is where we define the variables we will use throughout our Terraform code. In this file, we will define our Azure subscription ID, Recovery Services Vault name, location, and other required parameters.

data.tf: The data.tf file is where we will define our data sources. In this file, we will use the existing virtual network and subnet to deploy our private endpoint.

outputs.tf: The outputs.tf file is where we define the output values we want to retrieve after we run our Terraform code. In this file, we will define the Recovery Services Vault name, private endpoint ID, storage account keys, and backup policy IDs.

Benefits of using variables.tf instead of locals for defining backup policies

Using Variables for Backup Policies: In our previous blog article, we used locals to define our custom backup policies. However, in this blog article, we will use variables to define our custom backup policies. 

The advantage of using variables is that we can easily change the policy values without modifying the code:

  1. Easier to manage and maintain: When you use variables.tf to define your input variables, it creates a clear separation between the inputs and the actual implementation of the resources in the module. This makes it easier to manage and maintain your code, as you can quickly identify the inputs and their default values, if any, without having to go through the entire implementation. On the other hand, when using locals, the values are defined within the module itself, making it harder to separate input configuration from implementation details.

  2. Simplifies the process of updating backup policies: When using variables.tf to define backup policies, you can easily update the policies by modifying the variable values or providing new values when calling the module. This approach simplifies the process of updating backup policies, as you can make changes without altering the core implementation of the module. In contrast, when using locals, updating backup policies would require modifying the module's code, which can be more cumbersome and error-prone.

  3. Makes it easier to reuse the module in different projects with different backup policies: By defining backup policies as variables in variables.tf, you can reuse the module in different projects by providing different values for the variables. This allows you to create project-specific backup policies while still utilizing the same module implementation. Using locals would require you to either modify the module's code for each project or create different versions of the module with different locals values, making it less reusable.

In summary, using variables.tf instead of locals provides a more organized, maintainable, and reusable approach to managing backup policies in Terraform modules. This approach simplifies updates and allows for easier customization across different projects.

To use variables for backup policies, we will define a map variable in our variables.tf file.

We will define the default backup policy with the following parameters:

  • Daily : 35 days #(Incremental - daily)
  • Weekly: 90 days
  • Monthly: 1 year
  • Yearly: 10 years

Deploying Private Endpoints for Azure Recovery Services Vault

Similar to the previous article, we will deploy a Private Endpoint to ensure that the traffic between our Recovery Services Vault and our file share does not leave the Azure network, assuming that or File Shares going to be deployed with Private Endpoints enabled. We will use the data source to reference an existing virtual network and subnet for our Private Endpoint.

File Share Backup Policies for Azure Recovery Services Vault

To define our file share backup policies, we will use variables in our variables.tf file. Our default file share backup policy will have the following parameters: Daily (Incremental - daily): 35 days, Weekly: 90 days, Monthly: 1 year, Yearly: 10 years.

Main.tf

 provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "example" {
  name     = var.resource_group_name
  location = var.location
}

resource "azurerm_recovery_services_vault" "example" {
  name                = "example-recovery-vault"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  sku                 = var.vault_sku
  storage_mode_type   = var.storage_mode_type
}

resource "azurerm_backup_policy_file_share" "example" {
  for_each = var.backup_policies

  name                = each.value.name
  resource_group_name = var.resource_group_name
  recovery_vault_name = azurerm_recovery_services_vault.example.name

  backup {
    frequency = each.value.frequency
    time      = each.value.time
  }

  retention_daily {
    count = each.value.retention_daily
  }

  retention_weekly {
    count    = each.value.retention_weekly
    weekdays = ["Sunday"]
  }

  retention_monthly {
    count    = each.value.retention_monthly
    weekdays = ["Sunday"]
    weeks    = ["First"]
  }

  retention_yearly {
    count    = each.value.retention_yearly
    weekdays = ["Sunday"]
    weeks    = ["First"]
    months   = toset(["January"])
  }
}

resource "azurerm_private_endpoint" "example" {
  name                = "example-private-endpoint"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  subnet_id           = data.azurerm_subnet.example.id

  private_service_connection {
    name                           = "example-private-connection"
    is_manual_connection           = false
    private_connection_resource_id = azurerm_recovery_services_vault.example.id
    subresource_names              = ["AzureBackup"]
  }
}

Variables.tf

variable "vault_name" {
  description = "The name of the Recovery Services Vault"
  type        = string
  default     = "myrsv-02"
}

variable "location" {
  description = "The location of the Recovery Services Vault"
  type        = string
  default     = "Australia East"
}

variable "resource_group_name" {
  description = "The name of the resource group"
  type        = string
  default     = "myTFResourceGroup1"
}

variable "vault_sku" {
  description = "The SKU of the Recovery Services Vault. Possible values are Standard and Premium."
  type        = string
  default     = "Standard"
}

variable "private_endpoint_name" {
  description = "The name of the private endpoint"
  type        = string
  default     = "private-endpoint"
}

variable "storage_mode_type" {
  description = "The storage type of the Recovery Services Vault."
  type        = string
  default     = "ZoneRedundant"
}

variable "backup_policies" {
  type = map(object({
    name                   = string
    frequency              = string
    time                   = string
    retention_daily        = number
    retention_weekly       = number
    retention_monthly      = number
    retention_yearly       = number
    tags                   = map(string)
  }))
  description = "A map of backup policies to be created in the Recovery Services Vault."
  default = {
    default_policy = {
      name                   = "default_policy"
      frequency              = "Daily"
      time                   = "12:00"
      retention_daily        = 35
      retention_weekly       = 90
      retention_monthly      = 12
      retention_yearly       = 10
      tags                   = {}
    }
  }
}

Data.tf

data "azurerm_virtual_network" "example" {
  name                = "HubVnet-d-aus"
  resource_group_name = "rg-wth-network-d-aus"
}

data "azurerm_subnet" "example" {
  name                 = "snet-identity-d-aus"
  virtual_network_name = data.azurerm_virtual_network.example.name
  resource_group_name  = "rg-wth-network-d-aus"
}

Outputs.tf

output "recovery_vault_id" {
  description = "The ID of the Recovery Services Vault."
  value       = azurerm_recovery_services_vault.example.id
}

output "recovery_vault_name" {
  description = "The name of the Recovery Services Vault."
  value       = azurerm_recovery_services_vault.example.name
}

output "backup_policy_ids" {
  description = "The IDs of the created Azure File Share backup policies."
  value       = { for policy in azurerm_backup_policy_file_share.example : policy.name => policy.id }
}

Conclusion

In this article, we learned about using variables instead of locals to define backup policies for the Recovery Services Vault using Terraform azurerm_recovery_services_vault resource. We also discussed the benefits of using variables for larger and more complex projects. Finally, we deployed a Private Endpoint and defined our file share backup policies using variables. By following the steps outlined in this article, you should be able to deploy a fully functional Recovery Services Vault with custom backup policies for file shares using Terraform azurerm_recovery_services_vault.