DEV Community

Franchesco Romero for AWS Community Builders

Posted on

Backing up all your EBS volumes using Terraform

Looking for a quick way to back up all your EBS volumes using Terraform? Look no further.

This quick guide will help you set up an AWS Backup plan for EBS volumes, with a schedule and some rules for lifecycle management, which can be easily extended to any other supported resource.

First, let's get all our EBS volumes using the old trusty data resource.

data "aws_ebs_volumes" "volumes" {
  filter {
    name   = "tag:Name"
    values = ["*"]
  }
}

Enter fullscreen mode Exit fullscreen mode

With the code above, you can fetch all your volumes and filter it by tag; this still won't be enough, as we need to build a list of ARNs that Terraform can iterate, and AWS can use it to set up a backup plan and schedule accordingly.

Let's continue by adding another filter to get the volume details. Again, this is required for setting up the backup plan correctly.

data "aws_ebs_volume" "data" {
  for_each = toset(data.aws_ebs_volumes.volumes.ids)
  filter {
    name   = "volume-id"
    values = [each.value]
  }
}

Enter fullscreen mode Exit fullscreen mode

Ok, that's looking better; this list can now be fed to AWS backup plans, and it should be enough in most cases. One minor drawback with this approach is that if your EBS inventory changes constantly, you'll need to run this often to scan for new volumes.

Now on to the setup. Let's first set up some permissions to make everything work together.

resource "aws_iam_role" "ebs_aws_backup_role" {
  name = "${local.prefix}-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Sid    = "AssumeServiceRole"
        Principal = {
          Service = "backup.amazonaws.com"
        }
      },
    ]
  })

  tags = local.tags
}

resource "aws_iam_role_policy_attachment" "ebs_aws_backup_service_role" {
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup"
  role       = aws_iam_role.ebs_aws_backup_role.name
}
Enter fullscreen mode Exit fullscreen mode

With this config out of the way, we should be able to continue with the setup of the vault

resource "aws_backup_vault" "ebs_backup_vault" {
  name = "${local.prefix}-vault"
  tags = local.tags
}
Enter fullscreen mode Exit fullscreen mode

And now, let's move to the most critical piece, the backup plan; of course, you can adjust your parameters according to your use case; one working example can be seen below.

resource "aws_backup_plan" "ebs_backup_plan" {
  name = "${local.prefix}-plan"

  rule {
    rule_name         = "${local.prefix}-rule-${local.backups.retention}-day"
    target_vault_name = aws_backup_vault.ebs_backup_vault.name
    schedule          = local.backups.schedule
    start_window      = 60
    completion_window = 300

    lifecycle {
      cold_storage_after = local.backups.cold_storage_after
      delete_after       = local.backups.retention
    }
  }

  tags = local.tags
}
Enter fullscreen mode Exit fullscreen mode

Finally, let's enable the backup plan for the resources we got on the first step.

resource "aws_backup_selection" "ebs_backup_selection" {
  iam_role_arn = aws_iam_role.ebs_aws_backup_role.arn
  name         = "${local.prefix}-selection"
  plan_id      = aws_backup_plan.ebs_backup_plan.id

  resources = [for v in data.aws_ebs_volume.data : v.arn]
}
Enter fullscreen mode Exit fullscreen mode

aws_backup_selection supports filtering by tag in case you want to be very specific about which resource you want to be part of the plan. Consider doing that instead if you have all your resources properly tagged.

And that's it. You should be able to apply a Terraform valid plan and have your EBS backed up automatically.

Top comments (0)