Skip to content

Multi-Cluster Backups

The operator can back up PVCs from remote Kubernetes clusters by using an external kubeconfig. The operator runs in one cluster and creates CronJobs that access PVCs in another cluster.

How It Works

  1. You create a kubeconfig Secret containing credentials for the remote cluster
  2. The VolumeBackup references this kubeconfig in spec.kubeconfig
  3. The operator uses the external kubeconfig to read PVC/PV information from the remote cluster
  4. CronJobs are created in the local cluster but mount PVCs from the remote cluster

Create a Kubeconfig Secret

apiVersion: v1
kind: Secret
metadata:
  name: remote-cluster-kubeconfig
  namespace: default
type: Opaque
data:
  kubeconfig: <base64-encoded-kubeconfig>

Generate the base64-encoded kubeconfig:

kubectl create secret generic remote-cluster-kubeconfig \
  --from-file=kubeconfig=$HOME/.kube/remote-cluster.yaml

VolumeBackup with External Kubeconfig

apiVersion: backups.k8s.bnerd.com/v1
kind: VolumeBackup
metadata:
  name: remote-backup
  namespace: default
spec:
  volumeClaimRef:
    name: app-data
    namespace: production

  kubeconfig:
    inCluster: false
    secretRef:
      name: remote-cluster-kubeconfig
      namespace: default
      key: kubeconfig            # Key in the Secret, defaults to "kubeconfig"

  schedule: "0 3 * * *"

  repository:
    type: s3
    url: s3:s3.amazonaws.com/my-bucket/remote-backups
    secretRef:
      name: backup-credentials

Kubeconfig Configuration

Field Default Description
kubeconfig.inCluster true Use in-cluster credentials (set to false for external)
kubeconfig.secretRef.name -- Secret containing the kubeconfig
kubeconfig.secretRef.namespace -- Namespace of the kubeconfig Secret
kubeconfig.secretRef.key kubeconfig Key in the Secret containing kubeconfig data

Remote Cluster RBAC

The kubeconfig user/ServiceAccount in the remote cluster needs read access to PVCs and PVs:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: backup-operator-reader
rules:
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch"]

Bind this role to the ServiceAccount used in the kubeconfig.

VolumeRestore with External Kubeconfig

The same kubeconfig pattern works for VolumeRestore:

apiVersion: backups.k8s.bnerd.com/v1
kind: VolumeRestore
metadata:
  name: remote-restore
spec:
  kubeconfig:
    inCluster: false
    secretRef:
      name: remote-cluster-kubeconfig

  sourceBackup:
    volumeBackupRef:
      name: remote-backup

  targetPVC:
    createNew: true
    name: "restored-remote-data"
    size: "20Gi"

Troubleshooting

"unable to connect to API server"

  • Verify the kubeconfig is valid: kubectl --kubeconfig=remote.yaml get nodes
  • Check that the API server is reachable from the operator pod (firewall, network policies)
  • Ensure the kubeconfig uses an endpoint accessible from within the cluster (not localhost)

"certificate verification failed"

  • Ensure the kubeconfig includes the CA certificate or uses insecure-skip-tls-verify: true (not recommended for production)
  • If the remote cluster uses a private CA, include it in the kubeconfig's certificate-authority-data