Skip to main content

Backup and Restore in a Kubernetes Cluster with Velero

This section walks you through setting up and using Velero for backup and restore operations in a Kubernetes cluster, with MinIO as the S3-compatible object storage backend.

Prerequisites

Before you begin, ensure your environment meets the following requirements:

  • A running Kubernetes cluster where workloads are deployed.

  • Installed and configured, used to deploy the MinIO chart.

  • Command-line access to interact with the cluster.

  • Required to pull Helm charts and container images.

  • Every pod whose volumes you want backed up must include the following annotation in spec.template.metadata.annotations:

    annotations:
      backup.velero.io/backup-volumes: "*"

Install MinIO (Object Storage)

MinIO is a high-performance, S3-compatible object storage system that serves as the backend where Velero stores all backup data. Installing MinIO within your cluster gives you a self-hosted, lightweight storage target.

Add Helm repo and update

In this step, you configure your local Helm client to trust and pull charts from the official MinIO Helm chart repository. Run the following command to add the MinIO Helm repository and refresh chart indices.

helm repo add minio https://charts.min.io/
helm repo update

helm repo add registers the MinIO chart repository URL with your local Helm configuration, and helm repo update refreshes Helm’s local chart index so it can discover the latest available chart versions before you install or upgrade MinIO.

Create MinIO values file

The values file lets you customize the MinIO deployment in a repeatable, version-controlled way. Here, it is used to set MinIO to standalone mode, enable persistent storage for backups, specify resource requests, configure service exposure, and control optional components like the MinIO console.

Create a file named minio-values.yaml with the following configuration:

mode: standalone
persistence:
  enabled: true
  size: 50Gi
resources:
  requests:
    memory: 512Mi
    cpu: 250m
rootUser: "minioadmin"
rootPassword: "minioadmin"
service:
  type: ClusterIP
replicas: 1
console:
  enabled: false

The following table provides the details of each field of the above configuration file:

Table 121.

Field

Description

Default value

mode

MinIO deployment mode. standalone runs a single instance.

standalone

persistence.enabled

Ensures data is stored on a PersistentVolume and survives pod restarts.

true

persistence.size

Requested PV capacity for object data.

50Gi

resources.requests.memory/cpu

Minimum guaranteed resources for stable performance.

rootUser/rootPassword

Bootstrap admin credentials for MinIO.

service.type

Exposure method inside the cluster. ClusterIP limits access to in-cluster clients.

ClusterIP

replicas

Number of MinIO pods. 1 for standalone.

1

console.enabled

Enables/disables MinIO Web Console. Disabled here for simplicity and minimal attack surface.

false



Install MinIO

Run the following command to install MinIO in its own namespace using the values file.

helm upgrade --install minio minio/minio \
  -n minio --create-namespace \
  -f minio-values.yaml \
  --version 5.4.0

Configure Buckets with MinIO client (mc)

This step prepares MinIO so that Velero has a known bucket to store backups and a dedicated set of credentials with the right permissions. Open a terminal inside the MinIO container, configure an mc (MinIO Client) alias to point to the MinIO service endpoint. After establishing the connection, create the required bucket, provision a user, and assign the appropriate access permissions.

kubectl exec -it deploy/minio -n minio -- bash
# Inside pod:
mc alias set localminio http://minio:9000 minioadmin minioadmin
mc mb localminio/velero
mc admin user add localminio velero-user vP@assWoRd
mc admin policy attach localminio readwrite --user velero-user
mc ls localminio

Configure cloud credentials for Velero

Configuring cloud credentials enables Velero to authenticate to the MinIO object storage in order to write backups and read them back during restores. Create a Kubernetes Secret named cloud-credentials.yaml containing the access key and secret key in the AWS credential format that Velero expects.

apiVersion: v1
kind: Secret
metadata:
  name: cloud-credentials
  namespace: velero
stringData:
  cloud: |
    [default]
    aws_access_key_id = velero-user
    aws_secret_access_key = vP@assWoRd

The following table defines each field of the above configuration:

Table 122.

Field

Description

Default value

metadata.name

Secret name referenced by OADP/Velero.

cloud-credentials

metadata.namespace

Must match the OADP operator namespace.

velero

stringData.cloud

AWS-style credentials file. Values are injected into Velero for S3-compatible access to MinIO. Replace with your secure credentials.



Run the command to apply the cloud-credentials.yaml so that Velero can use these credentials to access the MinIO S3 bucket for backups and restores.

kubectl apply -f cloud-credentials.yaml

Deploy Velero client pod

This step creates a pod that runs the Velero CLI, which you use to execute backup and restore commands. The pod mounts the cloud credentials secret so Velero can authenticate with MinIO.

Create the velero-client.yaml configuration file:

apiVersion: v1
kind: Pod
metadata:
  name: velero-client
  namespace: velero
spec:
  containers:
  - name: velero
    image: velero/velero:v1.12.0
    command: ["/bin/sh"]
    args: ["-c", "sleep infinity"]
    volumeMounts:
    - name: cloud-credentials
      mountPath: /credentials
      readOnly: true
  volumes:
  - name: cloud-credentials
    secret:
      secretName: cloud-credentials

The following table defines each field of the above configuration:

Table 123.

Field

Description

Default value

metadata.namespace

Namespace to access the credentials secret and Velero CRDs.

velero

spec.containers[].image

The Velero container image and version.

velero/velero:v1.12.0

spec.containers[].command/args

Runs a shell that sleeps indefinitely, keeping the pod alive so you can kubectl exec into it.

spec.containers[].volumeMounts[].mountPath

Path inside the container where the credentials file is mounted.

/credentials

spec.containers[].volumeMounts[].readOnly

Prevents the container from modifying the credentials.

true

spec.volumes[].secret.secretName

References the cloud-credentials secret created before.

cloud-credentials



Run the command to apply the manifest to deploy the Velero client pod, which will mount the cloud credentials and remain running for you to execute backup and restore commands.

kubectl apply -f velero-client.yaml

Create a tuned Backup Storage Location (BSL) (optional)

The Velero configuration uses the information to know where backups are stored and how to connect to that storage. The BSL points Velero to the MinIO S3-compatible service and the velero bucket, so backups and restore artifacts are consistently written to the correct location.

Create a tuned BSL for faster uploads, backup-storage-location.yaml.

apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
  name: default
  namespace: velero
spec:
  provider: aws
  objectStorage:
    bucket: velero
    prefix: backups
  config:
    region: minio
    s3ForcePathStyle: 'true'
    s3Url: 'http://minio.minio.svc.cluster.local:9000'
    maxParallel: "10"
    maxRetries: "5"
    maxRetriesBackoff: "2s"
    partSize: "104857600"
  credential:
    name: cloud-credentials
    key: cloud
  default: true

The following table defines each field of the above configuration:

Table 124.

Field

Description

Default value

metadata.namespace

The namespace where Velero is running.

velero

spec.provider

The storage provider type.

aws

objectStorage.bucket/prefix

Components where backup objects are written within MinIO.

config.region/s3ForcePathStyle/s3Url

The endpoint URL of the S3-compatible object store, pointing to the in-cluster MinIO service.

http://minio.minio.svc.cluster.local:9000

config.maxParallel

The maximum number of parallel upload/download operations Velero performs against this storage location.

10

config.maxRetries

The maximum number of times Velero retries a failed S3 operation before marking it as failed.

5

config.maxRetriesBackoff

The wait duration between retries, using an exponential backoff strategy.

2s

config.partSize

The size of each part in a multipart upload to S3.

104857600

credential.name/key

The name of the Kubernetes Secret that contains the S3 access key and secret key.

default

When true, this location is used as the default destination for all Velero backups unless another location is explicitly specified in the backup command.

true



Run the command to apply the manifest, registering MinIO as Velero's default backup storage location with the configured connection and performance settings.

kubectl apply -f backup-storage-location.yaml

Create a backup

Creating a backup is the step where you define what data and Kubernetes resources Velero should capture and how the backup should be executed and retained.

Create a backup:

velero backup create virtana-io-backup-16sep-01 \
  --include-namespaces virtana-io \
  --ttl 72h

Adjust parameters as required. See Velero Backup Reference for more details.

Run the command to check the backup status:

velero backup get
velero backup describe virtana-io-backup-16sep-01

Restore from Backup

When you need to recover workloads, Velero can restore all resources from a previously created backup. This recreates the Kubernetes objects and restores persistent volume data.

Run the command to restore from backup:

velero restore create virtana-io-restore-16sep-01 \
  --from-backup virtana-io-backup-16sep-01

Adjust parameters as required. See Velero Restore Reference for more details.

Run the command to check the restore status:

velero restore get
velero restore describe virtana-io-restore-16sep-01

Validation

After a backup or restore operation, verify that it completed successfully by checking the status of both the Velero operations and the restored workloads.

Run the command to check the backup and restore status:

velero backup get
-and-
velero restore get

Verify workloads

As a final step, confirm that all pods, persistent volume claims, and services in the restored namespace are running as expected.

Run the following command to verify the workload:

kubectl get pods -n virtana-io
kubectl get pvc -n virtana-io
kubectl get svc -n virtana-io