Configure 7-day Continuous Backup Retention For Cosmos DB using Terraform

Configure 7-day Continuous Backup Retention For Cosmos DB using Terraform

Following a guide by James Cook, I enable 7-day continuous backup for Azure Cosmos DB using Terraform. I made some minor modifications to James’s code, mainly for use with the latest versions and a modular deployment method.

First and foremost, full credit to James for the fantastic article:

Click to view


Update: before we start, please review the section Billing Update below, moving to continuous backups with Cosmos DB.


One of my customers had already attempted to follow James’s guide, but had run into some issues - at this point asking me to assist. This customer was updating a pre-existing Terraform config, which is deployed in a modular way.

The first thing I did was set up a local test environment, so that my testing would not interfere with customer work. For those of you that choose to follow along with this, I’m using PowerShell 7.3.0 and Terraform 1.3.5. I’ve set the code out in such a way that you should simply be able to copy, paste and run (providing you have the correct software and permissions).

For any test environment such as this, I make a point of creating a new Service Principal in the Azure portal, with an associated secret set with a short life-span. I then fire up a new PowerShell session, change the directory to where I want to place my Terraform config files, and set the below:

$env:ARM_CLIENT_ID="REDACTED" # Service Principal client iD 

$env:ARM_CLIENT_SECRET="REDACTED" # Service Principal secret 

$env:ARM_SUBSCRIPTION_ID="REDACTED" # Subscription ID 

$env:ARM_TENANT_ID="REDACTED" # Azure tenant ID

With this set, I’m good to create some Terraform files.

The below is an extract of what my customer had set at the root of their Terraform directory (including my changes):

main.tf:

resource "azurerm_resource_group" "rsg" {
  name     = "rsg-cosmosdbtest"
  location = "UK South"
}

module "cosmos" {
  source        = "./cosmos"
  rsg_name      = azurerm_resource_group.rsg.name
  location_name = azurerm_resource_group.rsg.location
}

provider.tf:

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "3.35.0"
    }
    azapi = {
      source = "Azure/azapi"
      version = "1.1.0"
    }
  }
}

provider "azurerm" {
  features {} # different to article - required
}

provider "azapi" {}

Within that Terraform directory was a sub-folder called ‘cosmos’ that contained the ‘cosmos’ module:

main.tf:

resource "azurerm_cosmosdb_account" "my_cosmos_db" {

  name                = "clouddevdancosmosdb"
  location            = var.location_name
  resource_group_name = var.rsg_name
  offer_type          = "Standard"
  kind                = "GlobalDocumentDB"

  enable_automatic_failover = true

  # different to article - required
  consistency_policy {
    consistency_level = "Session"
  }

  geo_location {
    location          = var.location_name
    failover_priority = 0
  }

  backup {
    type = "Continuous" # defaults to Continuous (30 days)
  }

}

resource "azapi_update_resource" "cosmosdb_backup_seven_days" {

  type        = "Microsoft.DocumentDB/databaseAccounts@2022-08-15-preview"
  resource_id = azurerm_cosmosdb_account.my_cosmos_db.id

  body = jsonencode({
    "properties" = {
      "backupPolicy" = {
        "type" : "Continuous",
        "continuousModeProperties" : {
          "tier" : "Continuous7Days" # alt is Continuous30Days, but that is the default
        }
      }
    }
  })

}

provider.tf:

terraform {
  required_providers {
    azapi = {
      source = "Azure/azapi"
    }
  }
}

variables.tf:

variable "rsg_name" {
  description = "The resource group name"
  type        = string
}

variable "location_name" {
  description = "The region to use in Azure"
  type        = string
}

As my customer was using a newer version of both Terraform and the azurerm provider to James, I had to make some modifications. These are highlighted in the above under # different to article - required, but namely they were adding features {} to the azurerm provider in provider.tf, and the Cosmos DB consistency_policy in the cosmos module.

The other error my customer had was the below, when running the terraform init command in their CI/CD pipeline:

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/azurerm from the dependency lock file
- Reusing previous version of azure/azapi from the dependency lock file
- Finding latest version of hashicorp/azapi...
- Using previously-installed hashicorp/azurerm v3.35.0
- Using previously-installed azure/azapi v1.1.0
╷
│ Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider hashicorp/azapi: provider registry registry.terraform.io does not have a provider named
│ registry.terraform.io/hashicorp/azapi
│
│ Did you intend to use azure/azapi? If so, you must specify that source address in each module which requires that provider. To see which modules are currently        
│ depending on hashicorp/azapi, run the following command:
│     terraform providers

This was resolved by adding an additional provider.tf file within the cosmos module directory, as seen above. Alternatively, you could include the terraform/required_providers block within your modules main.tf itself.

To deploy the code, you can run the below Terraform cmdlets:

terraform init terraform apply # -auto-approve # -auto-approve if you want to skip the plan and manual approve phase

Hey presto!

Click to view

Don’t forget to clean up your test environment when you are finished:

terraform destroy # -auto-approve # if you want to skip the plan and manual approve phase

Billing Update

Please note the below, according to the Azure Cosmos DB pricing page:

Continuous backup with 7-day retention will be free of charge until June 30, 2024.

It’s not clear what the costs will be after this date.

It’s also worth noting then once you have moved from Periodic to Continuous backups, there is no going back. The only changes you can make is to alternate between 7-day and 30-day retention.

So watch out for that!