Tech ONTAP Blogs
Tech ONTAP Blogs
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.
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:
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.
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.
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:
In the Clone Application screen, we enter the new Astra Control internal clone name wordpress-new and the destination namespace wordpress-newsc:
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:
The Summary screen confirms our settings, and we start the clone process:
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:
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 |
+=========+==============+============+===============+=====================+
+---------+--------------+------------+---------------+---------------------+
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.
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.
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:
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:
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:
In the Summary screen, we confirm the destination namespace and storage class settings and start the restore process:
Astra Control now creates the namespace wordpress on the K8s cluster and restores the WordPress application into it:
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:
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.
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.
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 |
+--------------------------------------+---------------------+--------------------------------------+------------------------------------------------+
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 |
+--------------------------------------+--------------------------------------+---------------+----------+--------+-------------+--------------+-----------------+-------------------+
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.
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!