Tech ONTAP Blogs

Storage class migration with Astra Control

PatricU
NetApp
885 Views

Introduction

When working with stateful, data-rich applications in Kubernetes, you might run into situations where moving your persistent volumes (PVs) to different storage back ends is required—for example, to achieve better performance or lower cost, or to phase out old storage hardware. When using dynamic provisioning, this involves migrating your PVs to different storage classes. NetApp® Astra™ Control data management capabilities offer you easy and safe means to migrate persistent volumes to a different storage class while minimizing application downtime.

 

NetApp Astra Control provides application-aware data protection, mobility, and disaster recovery for any workload running on any K8s distribution. It’s available both as a fully managed service (Astra Control Service, ACS) and as self-managed software (Astra Control Center, ACC). Astra Control enables administrators to easily protect, back up, migrate, and create working clones of K8s applications, through either its UI or robust APIs. With the NetApp Astra Control Toolkit there’s also an easy way to use a command line interface to interact with Astra Control with built-in guardrails. The toolkit also offers a simple process that can be easily integrated with your existing automation tools through the associated Python package actoolkit.

Setup

We use a WordPress application deployed on an Azure Kubernetes Service (AKS) cluster with two persistent volumes backed by Azure Disk via the AKS default storage class.  We want to migrate these PVs to Azure NetApp Files storage in the premium performance tier with minimum downtime and effort. The corresponding storage class was already created by Astra Control, when we managed the cluster in ACS:

 

~# kubectl get sc
NAME                      PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
azurefile                 file.csi.azure.com      Delete          Immediate              true                   5h50m
azurefile-csi             file.csi.azure.com      Delete          Immediate              true                   5h50m
azurefile-csi-premium     file.csi.azure.com      Delete          Immediate              true                   5h50m
azurefile-premium         file.csi.azure.com      Delete          Immediate              true                   5h50m
default (default)         disk.csi.azure.com      Delete          WaitForFirstConsumer   true                   5h50m
managed                   disk.csi.azure.com      Delete          WaitForFirstConsumer   true                   5h50m
managed-csi               disk.csi.azure.com      Delete          WaitForFirstConsumer   true                   5h50m
managed-csi-premium       disk.csi.azure.com      Delete          WaitForFirstConsumer   true                   5h50m
managed-premium           disk.csi.azure.com      Delete          WaitForFirstConsumer   true                   5h50m
netapp-anf-perf-premium   csi.trident.netapp.io   Delete          Immediate              true                   3h45m

 

Here is the Kubernetes configuration of the WordPress application:

 

~# kubectl get all,pvc -n wordpress
NAME                            READY   STATUS    RESTARTS   AGE
pod/wordpress-7df8fb66b-j52gv   1/1     Running   0          5h3m
pod/wordpress-mariadb-0         1/1     Running   0          5h3m

NAME                        TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
service/wordpress           LoadBalancer   10.0.28.187    20.31.187.138   80:32422/TCP,443:31506/TCP   5h3m
service/wordpress-mariadb   ClusterIP      10.0.155.110   <none>          3306/TCP                     5h3m

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/wordpress   1/1     1            1           5h3m

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/wordpress-7df8fb66b   1         1         1       5h3m

NAME                                 READY   AGE
statefulset.apps/wordpress-mariadb   1/1     5h3m

NAME                                             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/data-wordpress-mariadb-0   Bound    pvc-1f0dd85a-0bfb-42d2-bb32-f5898a9ef7c4   8Gi        RWO            default        5h3m
persistentvolumeclaim/wordpress                  Bound    pvc-65b91227-95e6-483e-9059-e863a494eb4e   10Gi       RWO            default        5h3m

 

The WordPress hosted website is accessible through the external IP address of the WordPress service:

Figure 1: Modified website powered by WordPress.Figure 1: Modified website powered by WordPress.

The WordPress application is already managed in our Astra Control Service account:

 

~# actoolkit list apps --nameFilter wordpress
+------------+--------------------------------------+---------------+-------------+-------------+
| appName    | appID                                | clusterName   | namespace   | state       |
+============+======================================+===============+=============+=============+
| wordpress  | d781434d-a8c8-405f-bbe0-dc8590dd2b12 | pu-aks-test-1 | wordpress   | ready       |
+------------+--------------------------------------+---------------+-------------+-------------+

 

 And we configured protection policies for it that create hourly snapshots and daily backups:

 

~# actoolkit list protections --app wordpress
+--------------------------------------+--------------------------------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+
| appID                                | protectionID                         | granularity   |   minute |   hour | dayOfWeek   | dayOfMonth   |   snapRetention |   backupRetention |
+======================================+======================================+===============+==========+========+=============+==============+=================+=====
==============+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | fd098f74-dee9-4bd7-9f11-a2f01e60076b | hourly        |       30 |        |             |              |               2 |                 0 |
+--------------------------------------+--------------------------------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | f7540fc1-4ff1-4fae-a083-90f9ea6e83cd | daily         |       20 |     12 |             |              |               0 |                 2 |
+--------------------------------------+--------------------------------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+

 

To make sure that the snapshots and backups are application consistent, we also configured pre- and post-snapshot execution hooks for the MariaDB component of WordPress:

 

~# actoolkit list hooks --app wordpress
+--------------------------------------+---------------------+--------------------------------------+------------------------------------------------+
| appID                                | hookName            | hookID                               | matchingImages                                 |
+======================================+=====================+======================================+================================================+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | pre-snap-wordpress  | 0cba8a69-a8ad-4d5d-896f-cc6d00cb43f5 | docker.io/bitnami/mariadb:10.11.4-debian-11-r0 |
+--------------------------------------+---------------------+--------------------------------------+------------------------------------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | post-snap-wordpress | 43925e4e-3d8d-4615-b871-0028d24dcc30 | docker.io/bitnami/mariadb:10.11.4-debian-11-r0 |
+--------------------------------------+---------------------+--------------------------------------+------------------------------------------------+

 

The next sections walk you through two slightly different scenarios that explain how to migrate the two PVs of the WordPress application to a different storage class with minimum application downtime.

Option 1: Clone to a new namespace

This option uses the live clone feature of Astra Control to clone the WordPress application into a new namespace (wordpress-newsc in our example) and into a new storage class. If you don’t need to keep the application in the original namespace, this is the easiest, fastest, and safest way to migrate to a new storage class, because it keeps the original application for an easy failback in the unlikely event that an error occurs. Next, we show how to clone an application by using the Astra Control UI or the Astra Control Toolkit below.

Using the Astra Control UI

First, we stop the application traffic so that we don’t miss any data during the short migration downtime; for example, by stopping the wordpress service:

 

~# kubectl -n wordpress scale deployment wordpress --replicas=0

 

Next, we initiate the live clone process from the application details view in the Astra Control UI:

Figure 2: Initiate live clone process.Figure 2: Initiate live clone process.

In the Clone Application screen, we enter the new Astra Control internal clone name wordpress-new and the destination namespace wordpress-newsc:

Figure 3: Providing clone and namespace name.Figure 3: Providing clone and namespace name.

In the Storage Class screen, we select to clone into a different storage class and select the target storage class netapp-anf-perf-premium from the dropdown list of available storage classes:

Figure 4: Clone into a different storage class and a select destination storage class.Figure 4: Clone into a different storage class and a select destination storage class.

The Summary screen confirms our settings, and we start the clone process:

Figure 5: Starting the clone process to the new storage class.Figure 5: Starting the clone process to the new storage class.

Astra Control now takes a snapshot of the original WordPress application and backs up the snapshot into the default bucket. (Because we are cloning into a new storage class, a direct clone from the snapshot is not possible.) As soon as the backup process finishes, Astra Control restores the backup into the new namespace wordpress-newsc:

 

~# kubectl get ns
NAME              STATUS   AGE
default           Active   6h34m
kube-node-lease   Active   6h34m
kube-public       Active   6h34m
kube-system       Active   6h34m
mysql             Active   103m
trident           Active   4h30m
wordpress         Active   5h48m
wordpress-newsc   Active   8m11s

 

When the Astra Control clone process finishes, we can start WordPress in the new namespace by scaling up the wordpress deployment:

 

~# kubectl -n wordpress-newsc scale deployment wordpress --replicas=1

 

 Checking all the restored services and persistent volume claims (PVCs), we confirm that everything is running in the new namespace as expected and that new PVCs are actually in the destination storage class netapp-anf-perf-premium:

 

~# kubectl get all,pvc -n wordpress-newsc
NAME                            READY   STATUS    RESTARTS   AGE
pod/wordpress-7df8fb66b-vnmtq   1/1     Running   0          3m6s
pod/wordpress-mariadb-0         1/1     Running   0          3m7s

NAME                        TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
service/wordpress           LoadBalancer   10.0.214.169   20.13.64.36   80:30048/TCP,443:32080/TCP   3m7s
service/wordpress-mariadb   ClusterIP      10.0.103.124   <none>        3306/TCP                     3m8s

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/wordpress   1/1     1            1           3m6s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/wordpress-7df8fb66b   1         1         1       3m6s

NAME                                 READY   AGE
statefulset.apps/wordpress-mariadb   1/1     3m7s

NAME                                             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS              AGE
persistentvolumeclaim/data-wordpress-mariadb-0   Bound    pvc-7f9742be-d78d-4a31-a46a-83518641ceb8   100Gi      RWO            netapp-anf-perf-premium   9m25s
persistentvolumeclaim/wordpress                  Bound    pvc-13409730-d0d3-4b27-aafc-5d65ab05c691   100Gi      RWO            netapp-anf-perf-premium   9m25s

 

We also take note of the new EXTERNAL-IP 20.13.64.36 of the LoadBalancer service and confirm that the migrated WordPress application is accessible with the most recent content:

Figure 6: Accessing the migrated WordPress application.Figure 6: Accessing the migrated WordPress application.

To stay compliant with your backup retention policy, you may need to keep the original application in Astra Control as long as required. You can delete the original namespace in K8s to free up resources. Astra Control then marks the original application as FAILED but retains its backups until you unmanage the application in Astra Control:

 

~# actoolkit list backups --app wordpress
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| AppID                                | backupName                      | backupID                             | backupState   | creationTimestamp    |
+======================================+=================================+======================================+===============+======================+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | wordpress-backup-20230814100945 | d3bdfe40-c9d4-4975-90ea-14bcd7f0e6e6 | completed     | 2023-08-14T10:09:51Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | daily-ewgm7-cdc90               | 89e99e9b-f4ae-4a66-97d4-7cc50ad409c1 | completed     | 2023-08-14T12:00:00Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | wordpress-backup-20230814120740 | dd437409-4ec4-4776-9a42-3d9040ef3bf5 | completed     | 2023-08-14T12:07:44Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | daily-ewgm7-rdkws               | f4c846bd-4fa6-42fe-9791-a77abe169742 | completed     | 2023-08-14T12:20:00Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | wordpress-rqbjo                 | 039e9550-4497-4418-acbe-2a166b88016e | completed     | 2023-08-14T14:20:54Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
~# actoolkit list backups --app wordpress-new
+---------+--------------+------------+---------------+---------------------+
| AppID   | backupName   | backupID   | backupState   | creationTimestamp   |
+=========+==============+============+===============+=====================+
+---------+--------------+------------+---------------+---------------------+

 

Using the Astra Control Toolkit CLI

As an alternative to the UI, you can use the actoolkit to change the storage class during a clone. First, gather the app and cluster IDs:

 

~# actoolkit list apps --nameFilter wordpress
+------------+--------------------------------------+---------------+-------------+-------------+
| appName    | appID                                | clusterName   | namespace   | state       |
+============+======================================+===============+=============+=============+
| wordpress  | d781434d-a8c8-405f-bbe0-dc8590dd2b12 | pu-aks-test-1 | wordpress   | ready       |
+------------+--------------------------------------+---------------+-------------+-------------+
~# actoolkit list clusters --nameFilter pu-aks-test-1
+-----------------+--------------------------------------+---------------+------------+---------+----------------+-----------------------+
| clusterName     | clusterID                            | clusterType   | location   | state   | managedState   | tridentStateAllowed   |
+=================+======================================+===============+============+=========+================+=======================+
| pu-aks-test-1   | ef9e613b-2350-4c6c-9b11-edcf0fde1f6d | aks           | westeurope | running | managed        | managed               |
+-----------------+--------------------------------------+---------------+------------+---------+----------------+-----------------------+

 

Next, we stop application traffic:

 

~# kubectl -n wordpress scale deployment wordpress --replicas=0

 

Next, we run the actoolkit clone command, being sure to specify the --cloneStorageClass argument (the following command is functionally equivalent to the UI clone workflow):

 

~# actoolkit clone --cloneAppName wordpress-new \
    --cloneNamespace wordpress-newsc \
    --clusterID ef9e613b-2350-4c6c-9b11-edcf0fde1f6d \
    --sourceAppID d781434d-a8c8-405f-bbe0-dc8590dd2b12 \
    --cloneStorageClass netapp-anf-perf-premium
{"type": "application/astra-app", "version": "2.2", "id": "29fe01f1-8af8-44c1-981e-8fe2f1f4666d", "name": "wordpress-new", "namespaceScopedResources": [{"namespace": "wordpress-newsc", ...
Submitting clone succeeded.
Waiting for clone to become available.......Cloning operation complete.

 

 The last step after the clone operation is to start WordPress again in the new namespace by scaling up the wordpress deployment:

 

~# kubectl -n wordpress-new scale deployment wordpress --replicas=1

 

The next section describes how to easily copy the execution hooks and protection policies to the cloned application by using the NetApp Astra Control Toolkit.

Option 2: Restore to the same namespace

Use this approach if your workflows require the application to remain in the same K8s namespace after the storage class migration. In this case, we must delete the original namespace before we can restore an application backup into the same namespace and into a different storage class. Again, we show you how to migrate using the Astra Control UI and the Astra Control Toolkit CLI.

Using the Astra Control UI

As in the previous option, the first step is to stop traffic to the application:

 

~# kubectl -n wordpress scale deployment wordpress --replicas=0

 

Now we start an application backup in the Astra Control UI:

Figure 7: Starting backup of the WordPress application.Figure 7: Starting backup of the WordPress application.

When the backup finishes, we delete the original namespace wordpress of the WordPress application:

 

~# kubectl delete ns wordpress
namespace "wordpress" deleted

 

After some seconds, Astra Control detects the deleted namespace and puts the WordPress application in the UNAVAILABLE state:

 

~# actoolkit list apps -f wordpress
+---------------+--------------------------------------+---------------+-----------------+-------------+
| appName       | appID                                | clusterName   | namespace       | state       |
+===============+======================================+===============+=================+=============+
| wordpress     | d781434d-a8c8-405f-bbe0-dc8590dd2b12 | pu-aks-test-1 | wordpress       | unavailable |
+---------------+--------------------------------------+---------------+-----------------+-------------+

 

Now we can restore the WordPress application from the latest backup into the same namespace wordpress. During the restore process, we need to choose a new application name in Astra Control and restore the backup into the new storage class:

Figure 8: Starting the application restore.Figure 8: Starting the application restore.

In the first step, we select Restore to New Namespaces, but again enter the original namespace name wordpress as the Destination Namespace. For the Astra Control internal application name, we select wordpress-new2:

Figure 9: Setting the application name and destination namespace.Figure 9: Setting the application name and destination namespace.

In the Summary screen, we confirm the destination namespace and storage class settings and start the restore process:

Figure 11: Restore summary.Figure 11: Restore summary.

Astra Control now creates the namespace wordpress on the K8s cluster and restores the WordPress application into it:

Figure 12: Restoring the WordPress application.Figure 12: Restoring the WordPress application.

When the restore is complete, we start WordPress in the wordpress namespace by scaling up the wordpress deployment:

 

~# kubectl -n wordpress scale deployment wordpress --replicas=1

 

Checking all the restored services and PVCs, we confirm that everything is running again in the original namespace as expected, and that the new PVCs are actually in the destination storage class netapp-anf-perf-premium:

 

~# kubectl get ns
NAME              STATUS   AGE
default           Active   8h
kube-node-lease   Active   8h
kube-public       Active   8h
kube-system       Active   8h
mysql             Active   55m
trident           Active   6h46m
wordpress         Active   5m21s
wordpress-newsc   Active   144m

~# kubectl get all,pvc -n wordpress
NAME                            READY   STATUS    RESTARTS   AGE
pod/wordpress-7df8fb66b-m6br4   1/1     Running   0          2m43s
pod/wordpress-mariadb-0         1/1     Running   0          2m42s

NAME                        TYPE           CLUSTER-IP   EXTERNAL-IP    PORT(S)                      AGE
service/wordpress           LoadBalancer   10.0.9.59    20.76.39.151   80:31141/TCP,443:30157/TCP   2m44s
service/wordpress-mariadb   ClusterIP      10.0.45.30   <none>         3306/TCP                     2m42s

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/wordpress   1/1     1            1           2m43s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/wordpress-7df8fb66b   1         1         1       2m44s

NAME                                 READY   AGE
statefulset.apps/wordpress-mariadb   1/1     2m42s

NAME                                             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS              AGE
persistentvolumeclaim/data-wordpress-mariadb-0   Bound    pvc-b01f87a2-2001-4b8e-ac73-17dab4235496   100Gi      RWO            netapp-anf-perf-premium   5m30s
persistentvolumeclaim/wordpress                  Bound    pvc-5af52447-02be-43fe-bc71-22cbd1cc8617   100Gi      RWO            netapp-anf-perf-premium   5m30s

 

Finally, we note the new EXTERNAL-IP 20.76.39.151 of the LoadBalancer service and confirm that the migrated WordPress application is accessible and contains the most recent content:

Figure 13: Testing the migrated WordPress application.Figure 13: Testing the migrated WordPress application.

Using the Astra Control Toolkit CLI

As an alternative to the Astra Control UI, actoolkit can also be used to change the storage class in an easy and scriptable way. First, we gather the application and cluster IDs:

 

~# actoolkit list apps -f wordpress
+-----------+--------------------------------------+---------------+-------------+---------+
| appName   | appID                                | clusterName   | namespace   | state   |
+===========+======================================+===============+=============+=========+
| wordpress | d781434d-a8c8-405f-bbe0-dc8590dd2b12 | pu-aks-test-1 | wordpress   | ready   |
+-----------+--------------------------------------+---------------+-------------+---------+

~# actoolkit list clusters --nameFilter pu-aks-test-1
+-----------------+--------------------------------------+---------------+------------+---------+----------------+-----------------------+
| clusterName     | clusterID                            | clusterType   | location   | state   | managedState   | tridentStateAllowed   |
+=================+======================================+===============+============+=========+================+=======================+
| pu-aks-test-1   | ef9e613b-2350-4c6c-9b11-edcf0fde1f6d | aks           | westeurope | running | managed        | managed               |
+-----------------+--------------------------------------+---------------+------------+---------+----------------+-----------------------+

 

Next, we stop the application:

 

~# kubectl -n wordpress scale deployment wordpress --replicas=0

 

Then we start a backup with the actoolkit create backup command and wait until it finishes:

 

~# actoolkit create backup d781434d-a8c8-405f-bbe0-dc8590dd2b12 wordpress-backup-20230814163111
{"type": "application/astra-appBackup", "version": "1.1", "id": " d5770b72-3259-4812-be15-31d8d586aa08", "name": "wordpress-backup-20230814163111", "bucketID": "05d522a4-24f0-454c-87fa-c7ed1e135f77", "state": "pending", "stateUnready": [], "metadata": {"labels": [{"name": "astra.netapp.io/labels/read-only/triggerType", "value": "backup"}], "creationTimestamp": "2023-08-14T16:31:11Z", "modificationTimestamp": "2023-08-14T16:31:11Z", "createdBy": "8247e00f-481b-444c-9171-afcfbe296e94"}}
Starting backup of d781434d-a8c8-405f-bbe0-dc8590dd2b12
Waiting for backup to complete......................complete!

 

With the backupID d5770b72-3259-4812-be15-31d8d586aa08, we run the following actoolkit command to clone the application from the backup into the namespace wordpress, with netapp-anf-per-premium as the destination storage class:

 

~# actoolkit clone --cloneAppName wordpress-new2 \
    --cloneNamespace wordpress \
    --clusterID ef9e613b-2350-4c6c-9b11-edcf0fde1f6d \
    --backupID d5770b72-3259-4812-be15-31d8d586aa08 \
    --cloneStorageClass netapp-anf-perf-premium
{"type": "application/astra-app", "version": "2.2", "id": "c22082ca-2c6c-4ded-8533-1c8773864faf", "name": "wordpress-new2", "namespaceScopedResources": [{"namespace": "wordpress", ...
Submitting clone succeeded.
Waiting for clone to become available.......Cloning operation complete.

 

When the restore is complete, we start WordPress in the wordpress namespace by scaling up the wordpress deployment:

 

~# kubectl -n wordpress scale deployment wordpress --replicas=1

 

As in option 1, we can keep the “old” wordpress app (in Unavailable) managed in Astra Control as long as needed so that we have access to its older backups:

 

~# actoolkit list apps -n wordpress
+----------------+--------------------------------------+---------------+-------------+-------------+
| appName        | appID                                | clusterName   | namespace   | state       |
+================+======================================+===============+=============+=============+
| wordpress      | d781434d-a8c8-405f-bbe0-dc8590dd2b12 | pu-aks-test-1 | wordpress   | unavailable |
+----------------+--------------------------------------+---------------+-------------+-------------+
| wordpress-new2 | c22082ca-2c6c-4ded-8533-1c8773864faf | pu-aks-test-1 | wordpress   | ready       |
+----------------+--------------------------------------+---------------+-------------+-------------+
~# actoolkit list backups –a wordpress
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| AppID                                | backupName                      | backupID                             | backupState   | creationTimestamp    |
+======================================+=================================+======================================+===============+======================+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | wordpress-backup-20230814100945 | d3bdfe40-c9d4-4975-90ea-14bcd7f0e6e6 | completed     | 2023-08-14T10:09:51Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | daily-ewgm7-cdc90               | 89e99e9b-f4ae-4a66-97d4-7cc50ad409c1 | completed     | 2023-08-14T12:00:00Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | wordpress-backup-20230814120740 | dd437409-4ec4-4776-9a42-3d9040ef3bf5 | completed     | 2023-08-14T12:07:44Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | daily-ewgm7-rdkws               | f4c846bd-4fa6-42fe-9791-a77abe169742 | completed     | 2023-08-14T12:20:00Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | wordpress-rqbjo                 | 039e9550-4497-4418-acbe-2a166b88016e | completed     | 2023-08-14T14:20:54Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | wordpress-backup-20230814163111 | d5770b72-3259-4812-be15-31d8d586aa08 | completed     | 2023-08-14T16:31:34Z |
+--------------------------------------+---------------------------------+--------------------------------------+---------------+----------------------+

 

When you no longer need the old backups, simply unmanage the old app wordpress in Astra Control and the backups will be deleted.

Restore or copy execution hooks and protection schedules

In both storage class migration options outlined above, we restored the demo WordPress application into a new Astra Control application (wordpress-new and wordpress-new2 respectively). In such cases, Astra Control does not restore the protection policies and execution hook definitions of the original application. Therefore, we need to redefine them for the migrated application after the restores. Here, the newly introduced copy functionality of the Astra Control Toolkit makes this a quick and easy post-migration task.

 

We can list the configured execution hooks and protection policies of the original application wordpress with these two actoolkit list commands:

~# actoolkit list hooks --app wordpress
+--------------------------------------+---------------------+--------------------------------------+------------------------------------------------+
| appID                                | hookName            | hookID                               | matchingImages                                 |
+======================================+=====================+======================================+================================================+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | pre-snap-wordpress  | 0cba8a69-a8ad-4d5d-896f-cc6d00cb43f5 | docker.io/bitnami/mariadb:10.11.4-debian-11-r0 |
+--------------------------------------+---------------------+--------------------------------------+------------------------------------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | post-snap-wordpress | 43925e4e-3d8d-4615-b871-0028d24dcc30 | docker.io/bitnami/mariadb:10.11.4-debian-11-r0 |
+--------------------------------------+---------------------+--------------------------------------+------------------------------------------------+
~# actoolkit list protections --app wordpress
+--------------------------------------+--------------------------------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+
| appID                                | protectionID                         | granularity   |   minute |   hour | dayOfWeek   | dayOfMonth   |   snapRetention |   backupRetention |
+======================================+======================================+===============+==========+========+=============+==============+=================+===================+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | fd098f74-dee9-4bd7-9f11-a2f01e60076b | hourly        |       30 |        |             |              |               2 |                 0 |
+--------------------------------------+--------------------------------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+
| d781434d-a8c8-405f-bbe0-dc8590dd2b12 | f7540fc1-4ff1-4fae-a083-90f9ea6e83cd | daily         |       20 |     12 |             |              |               0 |                 2 |
+--------------------------------------+--------------------------------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+

For the wordpress-new2 application, no execution hooks and protection policies are configured yet:

~# actoolkit list hooks --app wordpress-new2
+---------+------------+----------+------------------+
| appID   | hookName   | hookID   | matchingImages   |
+=========+============+==========+==================+
+---------+------------+----------+------------------+
~# actoolkit list protections --app wordpress-new2
+---------+----------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+
| appID   | protectionID   | granularity   | minute   | hour   | dayOfWeek   | dayOfMonth   | snapRetention   | backupRetention   |
+=========+================+===============+==========+========+=============+==============+=================+===================+
+---------+----------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+

We now copy the execution hooks and protection policies from the original application to the wordpress-new2 application used with option 2; the steps for the application used in option 1 are the same.

Restoring execution hooks

With the newest version of the Astra Control Toolkit, we can copy and restore hooks from the original application to wordpress-new2 with a single command. First, we find the Astra Control application IDs of the original application wordpress (d781434d-a8c8-405f-bbe0-dc8590dd2b12) and the migrated application wordpress-new2 (c22082ca-2c6c-4ded-8533-1c8773864faf):

~# actoolkit list apps -f wordpress
+----------------+--------------------------------------+---------------+-----------------+-------------+
| appName        | appID                                | clusterName   | namespace       | state       |
+================+======================================+===============+=================+=============+
| wordpress      | d781434d-a8c8-405f-bbe0-dc8590dd2b12 | pu-aks-test-1 | wordpress       | unavailable |
+----------------+--------------------------------------+---------------+-----------------+-------------+
| wordpress-new  | 29fe01f1-8af8-44c1-981e-8fe2f1f4666d | pu-aks-test-1 | wordpress-newsc | ready       |
+----------------+--------------------------------------+---------------+-----------------+-------------+
| wordpress-new2 | c22082ca-2c6c-4ded-8533-1c8773864faf | pu-aks-test-1 | wordpress       | ready       |
+----------------+--------------------------------------+---------------+-----------------+-------------+

Then we copy the hook definitions with the copy hooks command from wordpress to wordpress-new2:

~# actoolkit copy hooks d781434d-a8c8-405f-bbe0-dc8590dd2b12 c22082ca-2c6c-4ded-8533-1c8773864faf
{"metadata": {"labels": [], "creationTimestamp": "2023-08-17T12:58:18Z", "modificationTimestamp": "2023-08-17T12:58:18Z", "createdBy": "8247e00f-481b-444c-9171-afcfbe296e94"}, "type": "application/astra-executionHook", "version": "1.3", "id": "d3a61436-12a2-4087-853d-5e87271bc36b", "name": "pre-snap-wordpress", "hookType": "custom", "matchingCriteria": [{"type": "podName", "value": "wordpress-mariadb-0$"}], "action": "snapshot", "stage": "pre", "hookSourceID": "a6dd222e-5f2d-4182-b392-58adef897c7f", "arguments": ["pre"], "appID": "c22082ca-2c6c-4ded-8533-1c8773864faf", "enabled": "true"}
{"metadata": {"labels": [], "creationTimestamp": "2023-08-17T12:58:19Z", "modificationTimestamp": "2023-08-17T12:58:19Z", "createdBy": "8247e00f-481b-444c-9171-afcfbe296e94"}, "type": "application/astra-executionHook", "version": "1.3", "id": "8798b59f-f17b-409a-9506-8f919ac1553a", "name": "post-snap-wordpress", "hookType": "custom", "matchingCriteria": [{"type": "podName", "value": "wordpress-mariadb-0$"}], "action": "snapshot", "stage": "post", "hookSourceID": "a6dd222e-5f2d-4182-b392-58adef897c7f", "arguments": ["post"], "appID": "c22082ca-2c6c-4ded-8533-1c8773864faf", "enabled": "true"}

A final check with the list hooks command confirms that the pre- and post-snapshot hook definitions are now in place for wordpress-new2:

~# actoolkit list hooks --app wordpress-new2
+--------------------------------------+---------------------+--------------------------------------+------------------------------------------------+
| appID                                | hookName            | hookID                               | matchingImages                                 |
+======================================+=====================+======================================+================================================+
| c22082ca-2c6c-4ded-8533-1c8773864faf | pre-snap-wordpress  | d3a61436-12a2-4087-853d-5e87271bc36b | docker.io/bitnami/mariadb:10.11.4-debian-11-r0 |
+--------------------------------------+---------------------+--------------------------------------+------------------------------------------------+
| c22082ca-2c6c-4ded-8533-1c8773864faf | post-snap-wordpress | 8798b59f-f17b-409a-9506-8f919ac1553a | docker.io/bitnami/mariadb:10.11.4-debian-11-r0 |
+--------------------------------------+---------------------+--------------------------------------+------------------------------------------------+

Protection policies

Copying the protection policies to the migrated application wordpress-new2 is as easy as copying the execution hooks. We use the copy protections command with the application IDs from the previous screenshot to copy the protection schedules:

~# actoolkit copy protections d781434d-a8c8-405f-bbe0-dc8590dd2b12 c22082ca-2c6c-4ded-8533-1c8773864faf
{"type": "application/astra-schedule", "version": "1.3", "id": "949bcb92-321d-45eb-a70c-9bed795643c5", "name": "hourly-spi0m", "enabled": "true", "granularity": "hourly", "minute": "30", "snapshotRetention": "2", "backupRetention": "0", "metadata": {"labels": [], "creationTimestamp": "2023-08-17T13:20:41Z", "modificationTimestamp": "2023-08-17T13:20:41Z", "createdBy": "8247e00f-481b-444c-9171-afcfbe296e94"}}
{"type": "application/astra-schedule", "version": "1.3", "id": "911f8e9a-7f3d-46a0-b0e8-f311f9198856", "name": "daily-39d6j", "enabled": "true", "granularity": "daily", "minute": "20", "hour": "12", "snapshotRetention": "0", "backupRetention": "2", "metadata": {"labels": [], "creationTimestamp": "2023-08-17T13:20:42Z", "modificationTimestamp": "2023-08-17T13:20:42Z", "createdBy": "8247e00f-481b-444c-9171-afcfbe296e94"}}

Checking with list protections, we see that the migrated application wordpress-new2 is now also protected by protection policies:

~# actoolkit list protections --app wordpress-new2
+--------------------------------------+--------------------------------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+
| appID                                | protectionID                         | granularity   |   minute |   hour | dayOfWeek   | dayOfMonth   |   snapRetention |   backupRetention |
+======================================+======================================+===============+==========+========+=============+==============+=================+===================+
| c22082ca-2c6c-4ded-8533-1c8773864faf | 949bcb92-321d-45eb-a70c-9bed795643c5 | hourly        |       30 |        |             |              |               2 |                 0 |
+--------------------------------------+--------------------------------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+
| c22082ca-2c6c-4ded-8533-1c8773864faf | 911f8e9a-7f3d-46a0-b0e8-f311f9198856 | daily         |       20 |     12 |             |              |               0 |                 2 |
+--------------------------------------+--------------------------------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+

Conclusion

When you need to migrate data of your data-rich Kubernetes applications between storage classes, the data management capabilities of NetApp Astra Control offer easy and safe means to migrate persistent volumes to a different storage class with minimal application downtime. 

 

In this blog post we demonstrated two different ways of migrating a stateful K8s application to a different storage class with Astra Control, depending on whether your application can be migrated to a different namespace or needs to remain in the same namespace after the storage migration. For both options, we showed how to use either the intuitive Astra Control UI for the migration or the powerful Astra Control Toolkit if you prefer the CLI or want to script the migration. Finally, we demonstrated using the Astra Control Toolkit how to quickly restore the protection policies and execution hooks to the migrated applications.

Take advantage of NetApp’s continuing innovation

To see for yourself how easy it is to protect persistent Kubernetes applications with Astra Control, by using either its UI or the powerful Astra Control Toolkit, apply for a free trial. Get started today!

Public