Skip to content

Enable volume snapshots (AWS EBS)

You’ll enable Velero to capture persistent volume data using AWS EBS snapshots, so your backups include both Kubernetes resources and on-disk application state.

  • UDS CLI installed
  • Access to an EKS cluster with UDS Core deployed
  • Velero storage backend configured (see Configure Velero storage backends)
  • AWS EBS CSI driver installed and an EBS-backed StorageClass available in the cluster
  • Ability to attach IAM policies to the Velero service account’s IRSA role

By default, UDS Core backs up Kubernetes resources only. Volume snapshots are disabled:

SettingDefault
snapshotsEnabledfalse
schedules.udsbackup.template.snapshotVolumesfalse
  1. Configure IAM permissions for EBS

    The Velero service account must have an IAM role (via IRSA) with permissions to manage EBS snapshots. Add the following IAM policy statements to your Velero IRSA role:

    velero-iam-policy.tf
    # Velero AWS plugin policy
    # Reference: https://github.com/vmware-tanzu/velero-plugin-for-aws#set-permissions-for-velero
    data "aws_iam_policy_document" "velero_policy" {
    statement {
    effect = "Allow"
    actions = [
    "kms:ReEncryptFrom",
    "kms:ReEncryptTo"
    ]
    # Replace with the ARN of your EBS volume encryption KMS key
    resources = ["<YOUR_EBS_KMS_KEY_ARN>"]
    }
    statement {
    effect = "Allow"
    actions = ["ec2:DescribeVolumes", "ec2:DescribeSnapshots"]
    resources = ["*"]
    }
    # Replace <YOUR_CLUSTER_NAME> with your EKS cluster name
    statement {
    effect = "Allow"
    actions = ["ec2:CreateVolume"]
    resources = ["*"]
    condition {
    test = "StringEquals"
    variable = "aws:RequestTag/kubernetes.io/cluster/<YOUR_CLUSTER_NAME>"
    values = ["owned"]
    }
    }
    statement {
    effect = "Allow"
    actions = ["ec2:CreateSnapshot"]
    resources = ["*"]
    condition {
    test = "StringEquals"
    variable = "aws:RequestTag/kubernetes.io/cluster/<YOUR_CLUSTER_NAME>"
    values = ["owned"]
    }
    }
    statement {
    effect = "Allow"
    actions = ["ec2:CreateSnapshot"]
    resources = ["*"]
    condition {
    test = "StringEquals"
    variable = "ec2:ResourceTag/kubernetes.io/cluster/<YOUR_CLUSTER_NAME>"
    values = ["owned"]
    }
    }
    statement {
    effect = "Allow"
    actions = ["ec2:DeleteSnapshot"]
    resources = ["*"]
    condition {
    test = "StringEquals"
    variable = "ec2:ResourceTag/kubernetes.io/cluster/<YOUR_CLUSTER_NAME>"
    values = ["owned"]
    }
    }
    statement {
    effect = "Allow"
    actions = ["ec2:CreateTags"]
    resources = ["*"]
    condition {
    test = "StringEquals"
    variable = "aws:RequestTag/kubernetes.io/cluster/<YOUR_CLUSTER_NAME>"
    values = ["owned"]
    }
    condition {
    test = "StringEqualsIfExists"
    variable = "ec2:ResourceTag/kubernetes.io/cluster/<YOUR_CLUSTER_NAME>"
    values = ["owned"]
    }
    }
    }
  2. Enable snapshots in your bundle

    Add the following overrides to enable volume snapshots in the default backup schedule:

    uds-bundle.yaml
    packages:
    - name: core
    repository: registry.defenseunicorns.com/public/core
    ref: x.x.x-upstream
    overrides:
    velero:
    velero:
    values:
    - path: snapshotsEnabled
    value: true
    - path: schedules.udsbackup.template.snapshotVolumes
    value: true
  3. Create and deploy your bundle

    Terminal window
    uds create <path-to-bundle-dir>
    uds deploy uds-bundle-<name>-<arch>-<version>.tar.zst
Terminal window
# Verify snapshots are enabled on the schedule
uds zarf tools kubectl get schedule -n velero velero-udsbackup -o jsonpath='{.spec.template.snapshotVolumes}'
# After a backup completes, check that volume snapshots were taken
uds zarf tools kubectl get backup -n velero <backup-name> -o jsonpath='{.status.volumeSnapshotsCompleted}'

Success criteria:

  • snapshotVolumes is true on the schedule
  • After a backup completes, volumeSnapshotsCompleted is greater than 0 and matches the number of PVCs in the backed-up namespaces
  • EBS snapshots are visible in the AWS Console under EC2 → Snapshots, tagged with your EKS cluster name

To trigger a manual backup for testing, see Perform a manual backup.

Problem: EBS snapshots remain in AWS after backup deletion

Section titled “Problem: EBS snapshots remain in AWS after backup deletion”

Symptoms: After deleting a Velero backup, the corresponding EBS snapshots are still visible in the AWS Console and are not removed.

Solution: Velero’s garbage collection runs hourly and removes expired backups based on TTL. Be cautious when deleting backups that have been used for restores — Velero may defer deletion of snapshots still referenced by restored volumes. If snapshots persist beyond the expected TTL, verify that the Velero IRSA role includes the ec2:DeleteSnapshot permission scoped to the cluster tag.

Problem: IAM permission denied errors in Velero logs

Section titled “Problem: IAM permission denied errors in Velero logs”

Symptoms: Backup fails with AccessDenied errors in Velero logs referencing ec2:CreateSnapshot or similar actions.

Solution: Verify the IRSA role attached to the velero service account in the velero namespace includes all policy statements above. Confirm the role ARN annotation on the service account matches the role with the Velero policy attached.

These guides and concepts may be useful to explore next: