All Products
Search
Document Center

Container Service for Kubernetes:Modify resource configurations during application restoration

Last Updated:Mar 26, 2026

The backup center feature of Container Service for Kubernetes (ACK) captures all runtime configurations when backing up cluster resources. During restoration, you can modify specific resource configurations to adapt to the target cluster's environment — for example, switching image registries when migrating across clusters in a hybrid cloud setup.

This topic walks through backing up a StatefulSet and applying three types of resource modifications during restoration.

How it works

Three mechanisms control resource modifications during restoration:

Mechanism How it works Configuration required
Automatic modifications The backup center component automatically adjusts temporary metadata (UIDs), converts FlexVolume to Container Storage Interface (CSI), updates APIs, and applies cross-cloud compatibility changes. None
Restore task parameters Pass parameters in the ApplicationRestore spec to remap namespaces, change StorageClasses, switch image registries, or overwrite Service and Ingress annotations. Configure namespaceMapping, imageRegistryMapping, and similar fields in the restore task.
Velero resource modifiers Create a ConfigMap specifying JSON patch rules to add, remove, or replace resource fields using JSON patches. Create a ConfigMap and reference it from the restore task.
Important

By default, the CSI plug-in dynamically provisions a new volume of the same StorageClass when restoring a volume. Resource modifiers cannot modify volume configurations directly — convert the StorageClass to change volume configurations instead. To use resource modifiers, you must have role-based access control (RBAC) administrator permissions. Resource modifiers cannot modify resource groups or security-sensitive parameters. For more information, see Use RBAC to manage the operation permissions on resources in a cluster.

Prerequisites

Before you begin, ensure that you have:

  • migrate-controller 1.8.1 or later installed in both the backup cluster and the restore cluster. For more information, see Install migrate-controller and grant permissions.

  • A backup vault created in the backup cluster. For more information, see Create a backup vault.

  • (For resource modifiers) Kubernetes 1.20 or later and the CSI plug-in enabled in the cluster.

If the backup cluster, restore cluster, and backup vault reside in different regions, enable public network access on both clusters.

Example scenario

This example backs up an NGINX StatefulSet and restores it with four modifications applied simultaneously:

  • Namespace remapped from default to default1

  • Image registry switched from the OpenAnolis community registry to Container Registry

  • Volume mount path changed from /usr/share/nginx/html/ to /data

  • Node affinity rules removed

The StatefulSet runs in the default namespace of the backup cluster. It uses the image anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6 and mounts a 20 GiB persistent volume claim (PVC) using the alicloud-disk-topology-alltype StorageClass.

<details> <summary>Show StatefulSet YAML</summary>

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
  namespace: default
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  serviceName: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - preference:
              matchExpressions:
              - key: node-role.kubernetes.io/control-plane
                operator: Exists
            weight: 1
      containers:
      - image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
        imagePullPolicy: IfNotPresent
        name: nginx
        ports:
        - containerPort: 80
          name: web
          protocol: TCP
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /usr/share/nginx/html/
          name: www
  volumeClaimTemplates:
  - apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      labels:
        app: nginx
      name: www
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 20Gi
      storageClassName: alicloud-disk-topology-alltype
      volumeMode: Filesystem

</details>

Run the following command to verify that the application is running and the volume is mounted:

kubectl get pod && kubectl get pvc

Expected output:

NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          39s
web-1   1/1     Running   0          30s
NAME        STATUS   VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS                     VOLUMEATTRIBUTESCLASS   AGE
www-web-0   Bound    d-2zefofsg0uzoiaxxxxxx   20Gi       RWO            alicloud-disk-topology-alltype   <unset>                 3m18s
www-web-1   Bound    d-2zedgdlghw2oudxxxxxx   20Gi       RWO            alicloud-disk-topology-alltype   <unset>                 30s

Step 1: Back up the application

Back up the StatefulSet in the backup cluster using kubectl or the ACK console.

kubectl

  1. Create a file named applicationbackup.yaml with the following content:

    apiVersion: csdr.alibabacloud.com/v1beta1
    kind: ApplicationBackup
    metadata:
      # If the backup vault is already registered in this cluster, omit the csdr.alibabacloud.com/backuplocations annotation.
      annotations:
        csdr.alibabacloud.com/backuplocations: '{"name":"<backuplocationName>","region":"<bucketRegion>","bucket":"<bucketName>","prefix":"<path>","provider":"alibabacloud"}'
      name: <backupName>
      namespace: csdr
    spec:
      backupType: AppAndPvBackup
      includedNamespaces:
      - default
      pvBackup:
        defaultPvBackup: true
      storageLocation: <backuplocationName>
      ttl: 720h0m0s
  2. Apply the manifest to create the backup task:

    kubectl apply -f applicationbackup.yaml
  3. Watch the backup task until it reaches the Completed phase:

    kubectl -n csdr get applicationbackup <backupName> --watch

    Expected output:

    NAME           PHASE       AGE
    <backupName>   Completed   18s

ACK console

  1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

  2. Click the name of the backup cluster. In the left-side navigation pane, choose Operations > Application Backup. If the backup service component is not installed, follow the on-screen instructions to install it. For registered clusters and ACK dedicated clusters, also configure permissions. For more information, see Install migrate-controller and grant permissions.

  3. On the Application Backup page, click Instant Backup. In the Instant Backup panel, configure the following parameters and click OK. For more information about advanced parameters, see Create a backup plan or back up instantly.

    Parameter Description Example
    Name Name of the instant backup task (required) backup
    Backup vault The backup vault to use (required) cnfs-oss-test
    Backup type Application Backup backs up cluster resources and their volumes. Data Protection backs up only PVCs and persistent volumes (PVs). For more information, see What are the scenarios for application backup and data protection? Application Backup
    Backup namespaces One or more namespaces to back up (required). The kube-system, kube-publish, kube-node-lease, and csdr namespaces cannot be backed up. default
    Backup volume Mounted Volumes backs up volume data to ECS snapshots or Cloud Backup. Disable restores only YAML files without backing up the underlying storage. Mounted Volumes
  4. On the Backup Records tab, confirm that the backup record's Status column shows Completed.

(Optional) Step 2: View the backup JSON file in OSS

The backup task generates a JSON file listing all backed-up resources, including their names, types, sizes, and creation dates. Check this file to confirm the resources you want to restore are included.

The backup vault used in this example has the following configuration:

Backup vault name OSS bucket name OSS bucket subdirectory OSS bucket region
vault cnfs-oss-test subpath cn-beijing
  1. Log on to the OSS console.

  2. In the left-side navigation pane, click Buckets, then click the cnfs-oss-test bucket.

  3. Choose Object Management > Objects.

  4. Navigate to /subpath/backups/<backupName>/, download the <backupName>.tar.gz package, and decompress it to view the resource list.

Step 3: Configure resource modification rules in the restore cluster

A resource modifier ConfigMap has two sections: conditions (which resources to target) and patches (what changes to apply). The ConfigMap must reside in the csdr namespace and follow the naming convention <backupName>-resource-modifier.

The following ConfigMap removes node affinity rules and changes the volume mount path to /data for StatefulSets and pods with the label app: nginx:

apiVersion: v1
kind: ConfigMap
metadata:
  name: <backupName>-resource-modifier
  namespace: csdr
data:
  modifier: |
    version: v1
    resourceModifierRules:
    - conditions:
        groupResource: statefulsets.apps
        namespaces:
        - default
        labelSelector:
          matchLabels:
            app: nginx
      patches:
      - operation: remove
        path: "/spec/template/spec/affinity/nodeAffinity"
      - operation: replace
        path: "/spec/template/spec/containers/0/volumeMounts/0/mountPath"
        value: "/data"
    - conditions:
        groupResource: pods
        resourceNameRegex: "^web.*$"
        namespaces:
        - default
        labelSelector:
          matchLabels:
            app: nginx
      patches:
      - operation: remove
        path: "/spec/affinity"
      - operation: replace
        path: "/spec/containers/0/volumeMounts/0/mountPath"
        value: "/data"

conditions fields

Field Description Required Example
groupResource The Kubernetes resource group. Use the format <resourceName>.<groupName>. Omit the group name for core group resources. Run kubectl api-resources to look up resource group names. Yes statefulsets.apps, pods
namespaces Namespaces containing the resources to modify. If blank, resources in all namespaces are modified. When namespace mapping is active, the original (source) namespace applies here. No default
labelSelector A standard Kubernetes label selector (matchLabels or matchExpressions). Only resources that match are modified. No matchLabels: {app: nginx}
resourceNameRegex A regular expression to match resource names. Only matching resources are modified. No "^web.*$"

patches fields

Field Description Required Example
operation The JSON patch operation to perform. Supported values: add, remove, replace. Yes replace
path The JSON path of the field to modify. Yes "/spec/template/spec/containers/0/volumeMounts/0/mountPath"
value The value to set. Applies to add and replace only — not used with remove. No "/data"

(Optional) Step 4: Initialize the backup vault in the restore cluster

Skip this step if the backup vault is already initialized in the restore cluster.

Apply the following backuplocation.yaml to register the backup vault:

apiVersion: csdr.alibabacloud.com/v1beta1
kind: BackupLocation
metadata:
  name: <backup-vault-name>
  namespace: csdr
spec:
  backupSyncPeriod: 0s
  config:
    network: internal
    region: <oss-bucket-region>    # Must match the backup vault's initial configuration
  objectStorage:
    bucket: <oss-bucket-name>
    prefix: <oss-bucket-subpath>
  provider: alibabacloud

Step 5: Restore the application with modifications

Create a restore task in the restore cluster. The task below references the ConfigMap from Step 3 and uses namespaceMapping and imageRegistryMapping to remap the namespace and switch the image registry.

Sync the image to the new registry before changing the image address. The restore task references registry.cn-beijing.aliyuncs.com/<acrRegistry> — make sure the image exists there before applying.
  1. Create a file named applicationrestore.yaml with the following content:

    apiVersion: csdr.alibabacloud.com/v1beta1
    kind: ApplicationRestore
    metadata:
      name: <restoreName>
      namespace: csdr
    spec:
      backupName: <backupName>
      namespaceMapping:
        default: default1                      # Restore resources into the default1 namespace
      imageRegistryMapping:
        anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis: registry.cn-beijing.aliyuncs.com/<acrRegistry>
      resourceModifier:
        kind: ConfigMap
        name: <backupName>-resource-modifier   # Must match the ConfigMap created in Step 3
  2. Apply the manifest to start the restore task:

    kubectl apply -f applicationrestore.yaml
  3. Watch the restore task until it reaches the Completed phase:

    kubectl -n csdr get applicationrestore <restoreName> --watch

    Expected output:

    NAME              PHASE       AGE
    <restoreName>     Completed   18h

    To view the restore task in the ACK console instead, see Step 3: Restore applications and volumes.

Step 6: Verify the restored application

Query the restored StatefulSet to confirm all modifications were applied:

kubectl -n default1 get sts web -o yaml

<details> <summary>Show expected output</summary>

apiVersion: apps/v1
kind: StatefulSet
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"StatefulSet","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"web","namespace":"default"},"spec":{"replicas":2,"selector":{"matchLabels":{"app":"nginx"}},"serviceName":"nginx","template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"affinity":{"nodeAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"preference":{"matchExpressions":[{"key":"node-role.kubernetes.io/master","operator":"Exists"}]},"weight":1}]}},"containers":[{"image":"anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.2","imagePullPolicy":"IfNotPresent","name":"nginx","ports":[{"containerPort":80,"name":"web","protocol":"TCP"}],"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","volumeMounts":[{"mountPath":"/usr/share/nginx/html/","name":"www"}]}]}},"volumeClaimTemplates":[{"apiVersion":"v1","kind":"PersistentVolumeClaim","metadata":{"labels":{"app":"nginx"},"name":"www"},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"20Gi"}},"storageClassName":"alicloud-disk-topology-alltype","volumeMode":"Filesystem"}}]}}
  creationTimestamp: "2024-10-09T08:32:50Z"
  generation: 1
  labels:
    app: nginx
    velero.io/backup-name: <backupName>
    velero.io/restore-name: <restoreName>
  name: web
  namespace: default1
  resourceVersion: "119622"
  uid: d23878ea-0b9f-40ba-b61b-1ff6bb77eb43
spec:
  persistentVolumeClaimRetentionPolicy:
    whenDeleted: Retain
    whenScaled: Retain
  podManagementPolicy: OrderedReady
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  serviceName: nginx
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      affinity: {}
      containers:
      - image: registry.cn-beijing.aliyuncs.com/<acrRegistry>/nginx:1.14.1-8.6
        imagePullPolicy: IfNotPresent
        name: nginx
        ports:
        - containerPort: 80
          name: web
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /data
          name: www
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
  updateStrategy:
    rollingUpdate:
      partition: 0
    type: RollingUpdate
  volumeClaimTemplates:
  - apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
      name: www
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 20Gi
      storageClassName: alicloud-disk-topology-alltype
      volumeMode: Filesystem
    status:
      phase: Pending
status:
  availableReplicas: 0
  collisionCount: 0
  currentRevision: web-7b454646b4
  observedGeneration: 1
  replicas: 2
  updateRevision: web-7b454646b4

</details>

The output confirms all four modifications were applied:

  • Namespace: defaultdefault1

  • Image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6registry.cn-beijing.aliyuncs.com/<acrRegistry>/nginx:1.14.1-8.6

  • Volume mount path: /usr/share/nginx/html//data

  • Node affinity: removed (affinity: {})

Some fields in the output (such as resourceVersion, uid, and creationTimestamp) are automatically added by Kubernetes and were not present in the original backup.

What's next