Tech ONTAP Blogs

Introducing tridentctl-protect, the powerful CLI for Trident protect

PatricU
NetApp
251 Views

In a recent blog post, we introduced the advanced data management and protection capabilities of NetApp® Trident protect software for stateful Kubernetes applications. We discussed how its Kubernetes-native custom resources (CRs) can help to integrate application protection into your automation and deployment workflows.

 

This blog post shows you how to easily manage, protect, and restore a stateful Kubernetes application using Trident protect’s CLI tridentctl-protect.

Prerequisites

This blog post assumes that you’re working with the default admin user. In an upcoming blog post, we’ll show you how Trident protect’s role-based access model enables you to isolate tenant user activity while using ’s capabilities.

 

If you plan to follow this blog step by step, you need to have the following available:

  • A Kubernetes cluster with the latest Trident and Trident protect installed, and its associated kubeconfig 
  • A NetApp ONTAP® storage back end and Trident with configured storage back ends, storage classes, and volumesnapshot classes
  • A configured object storage bucket for storing backups and metadata information
  • A workstation with kubectl configured to use kubeconfig 
  • A workstation with Helm installed (or a different means of deploying a sample Kubernetes application)

Installing the tridentctl-protect CLI

Before using the command line utility, you need to install it on the machine you use to access your cluster. Follow these steps, depending on if your machine uses an x64 or ARM CPU.

  • Download the Trident protect CLI plugin for Linux AMD64 CPUs:

 

$ curl -L -o tridentctl-protect https://github.com/NetApp/tridentctl-protect/releases/download/24.10.0/tridentctl-protect-linux-amd64

 

  • Download the Trident protect CLI plugin for Linux ARM64 CPUs:

 

$ curl -L -o tridentctl-protect https://github.com/NetApp/tridentctl-protect/releases/download/24.10.0/tridentctl-protect-linux-arm64

 

  • Download the Trident protect CLI plugin for Mac AMD64 CPUs:

 

$ curl -L -o tridentctl-protect https://github.com/NetApp/tridentctl-protect/releases/download/24.10.0/tridentctl-protect-macos-amd64

 

  • Download the Trident protect CLI plugin for Mac ARM64 CPUs:

 

$ curl -L -o tridentctl-protect https://github.com/NetApp/tridentctl-protect/releases/download/24.10.0/tridentctl-protect-macos-arm64

 

Then enable execute permissions for the binary you just downloaded:

 

$ chmod +x ./tridentctl-protect

 

And copy the binary into any folder that is in your PATH environment on your desktop machine.

Application management

Before we can manage and protect the first application, we need to define at least one appVault CR corresponding to an existing object storage bucket, because buckets are used to store application (and snapshot) metadata in addition to backup data by Trident protect.

 

The following example configures an appVault CR demo backed by an Azure storage container demo in the Azure storage account putest. First, we create a secret containing the accountName and accountKey of the Azure storage account in the default trident-protect namespace:

 

$ kubectl -n trident-protect create secret generic bucket-demo --from-literal=accountName=putest --from-literal=accountKey=<ACCOUNT-KEY>

 

With the secret in place, we now create the appVault CR using the tridentctl-protect create appvault subcommand:

 

$ tridentctl-protect create appvault azure demo --account puneptunetest --bucket demo --endpoint core.windows.net --secret bucket-demo

 

We check the successful creation of the appVault CR:

 

$ tridentctl-protect get appvault
+------+----------+-----------+-----+-------+
| NAME | PROVIDER |   STATE   | AGE | ERROR |
+------+----------+-----------+-----+-------+
| demo | Azure    | Available | 9s  |       |
+------+----------+-----------+-----+-------+

 

With an appVault CR configured, we’re ready to manage our first application with Trident protect. As a sample application for the purpose of this blog post, we use a simple WordPress application deployed on an Azure Kubernetes Service (AKS) cluster in the namespace wordpress with two persistent volumes provisioned through Trident and backed by Azure NetApp Files volumes:

 

$ kubectl get all,pvc,volumesnapshots -n wordpress
NAME                             READY   STATUS    RESTARTS      AGE
pod/wordpress-64955d44c7-hxcpv   1/1     Running   4 (47h ago)   2d
pod/wordpress-mariadb-0          1/1     Running   0             2d
 
NAME                        TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)                      AGE
service/wordpress           LoadBalancer   10.0.126.27    20.61.36.107   80:31547/TCP,443:30778/TCP   2d
service/wordpress-mariadb   ClusterIP      10.0.131.236   <none>         3306/TCP                     2d
 
NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/wordpress   1/1     1            1           2d
 
NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/wordpress-64955d44c7   1         1         1       2d
 
NAME                                 READY   AGE
statefulset.apps/wordpress-mariadb   1/1     2d
 
NAME                                             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS              VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/data-wordpress-mariadb-0   Bound    pvc-3ca3230a-bbd3-42fd-9eba-9b2f91aa7293   100Gi      RWO            netapp-anf-perf-premium   <unset>                 2d
persistentvolumeclaim/wordpress                  Bound    pvc-46c277a5-ac29-48b4-bffd-c78e1d2ec7cf   100Gi      RWO            netapp-anf-perf-premium   <unset>                 2d

 

If your cluster already has any other test application with Trident-provisioned persistent volumes running on it, feel free to use it instead.

Managing this single-namespaced application is as simple as this:

 

$ tridentctl-protect create application wordpress --namespaces wordpress -n wordpress
Application wordpress created.

 

The tridentctl-protect command just shown creates the corresponding application CR for us:

 

$ kubectl -n wordpress get application wordpress -o yaml
apiVersion: protect.trident.netapp.io/v1
kind: Application
metadata:
  creationTimestamp: "2024-10-15T13:49:02Z"
  finalizers:
  - protect.trident.netapp.io/finalizer
  generation: 1
  name: wordpress
  namespace: wordpress
  resourceVersion: "9570159"
  uid: cb0d2eda-abda-41be-ab9d-0a12b581c4f3
spec:
  includedNamespaces:
  - labelSelector: {}
    namespace: wordpress
status:
  conditions:
  - lastTransitionTime: "2024-10-15T13:49:02Z"
    message: ""
    reason: Ready
    status: "True"
    type: Ready
  protectionState: none

 

Trident protect enforces to create the application data management CRs in the same namespace as their associated application, so we create it in the wordpress namespace.

We can list all managed applications by adding the -A flag to the tridentctl-protect command:

 

$ tridentctl-protect get apps -A
+-----------+-----------+------------+-------+-----+
| NAMESPACE |   NAME    | NAMESPACES | STATE | AGE |
+-----------+-----------+------------+-------+-----+
| wordpress | wordpress | wordpress  | Ready | 33s |
+-----------+-----------+------------+-------+-----+

 

For a more complex application covering multiple namespaces, we’d simply specify all the namespaces to be included in the application definition as a comma-separated list after the --namespaces flag and create the application CR in one of these namespaces. The --csr flag allows you to include cluster-scoped resources into the definition of the application, and if you want to include only resources matching the specified key/value pairs, you can include label selectors in parentheses after each namespace. The following example includes only the MariaDB resources of the wordpress application namespace, labeled by app.kubernetes.io/name=mariadb:

 

$ tridentctl-protect create application wordpress-db --namespaces 'wordpress(app.kubernetes.io/name=mariadb)' -n wordpress

 

The resulting application CR spec is:

 

$ kubectl -n wordpress get application wordpress-db -o yaml | yq '.spec'
includedNamespaces:
  - labelSelector:
      matchLabels:
        app.kubernetes.io/name: mariadb
    namespace: wordpress

 

Now that our application is defined, let’s perform some application data management operations on it.

Snapshot creation

We’ve successfully managed our application by creating an application CR. We can now carry out any other application data management operation in the same manner, and we’ll start with a snapshot. 

 

Execute the following command in your terminal to create the first snapshot wordpress-snap-1 of our sample application.

 

$ tridentctl-protect create snapshot wordpress-snap-1 --app wordpress --appvault demo -n wordpress

 

Besides the snapshot and application name, we also need to specify the appVault CR to instruct tridentctl-protect to store the application metadata in this appVault (or bucket).

Spoiler

Even though the application metadata is stored in an external bucket for a snapshot, the Kubernetes persistent volumes are still stored locally on the cluster through Container Storage Interface (CSI) volume snapshots. This means that if the namespace or cluster is destroyed, so will the application snapshot data. This is the key difference between a snapshot and a backup, where the volume snapshot data is also stored on the referenced bucket. 

Let’s make sure that our snapshot completed successfully by running the following command. Again, by adding the -A flag, we check snapshots in all available namespaces.

 

$ tridentctl-protect get snapshots --app wordpress -A
+-----------+------------------+-----------+-----------+-----+-------+
| NAMESPACE |       NAME       |  APP REF  |   STATE   | AGE | ERROR |
+-----------+------------------+-----------+-----------+-----+-------+
| wordpress | wordpress-snap-1 | wordpress | Completed | 31s |       |
+-----------+------------------+-----------+-----------+-----+-------+

 

So, we have successfully taken an application snapshot from our CR definition. Next, let’s make this snapshot more robust in case of a disaster.

Backup creation

As mentioned in the previous section, if our wordpress namespace or the Kubernetes cluster is destroyed, we’ll lose our application’s persistent volumes, including their snapshots. Let’s change that by applying the following command to create a backup from the snapshot we just created.

 

$ tridentctl-protect create backup wordpress-bkup-1 --app wordpress --appvault demo -n wordpress

 

Specifying the snapshot is optional; if it isn’t specified, a new snapshot will first be created before the data is copied from the snapshot to the referenced appVault.

We can check the status of the backup with this command and confirm that it completed successfully after some minutes.

 

$ tridentctl-protect get backup --app wordpress -A
+-----------+------------------+-----------+-----------+-------+-------+
| NAMESPACE |       NAME       |  APP REF  |   STATE   |  AGE  | ERROR |
+-----------+------------------+-----------+-----------+-------+-------+
| wordpress | wordpress-bkup-1 | wordpress | Completed | 5m44s |       |
+-----------+------------------+-----------+-----------+-------+-------+

 

Protection schedules

If we want to protect our application by regularly taking snapshots and backups, we can assign one (or multiple) protection schedules to it. The following command assigns a protection schedule to our sample app that creates a daily snapshot and backup at 17:30 UTC and retains the last three snapshots and backups.

 

$ tridentctl-protect create schedule wordpress-sched --app wordpress --appVault demo --granularity daily --hour 17 --minute 30 --snapshot-retention 3 --backup-retention 3 -n wordpress 

 

Note that if we don’t specify a name for the schedule, tridentctl-protect will create a unique name for it. The following command shows us all protection schedules assigned to the application wordpress.

 

$ tridentctl-protect get schedule --app wordpress -A
+-----------+-----------------+-----------+----------------------+---------+-------+-----+-------+
| NAMESPACE |      NAME       |    APP    |       SCHEDULE       | ENABLED | STATE | AGE | ERROR |
+-----------+-----------------+-----------+----------------------+---------+-------+-----+-------+
| wordpress | wordpress-sched | wordpress | Daily:hour=17,min=30 | true    |       | 24s |       |
+-----------+-----------------+-----------+----------------------+---------+-------+-----+-------+

 

Application restore operations

Trident protect allows you to restore your protected application completely or partially from snapshots or backups, either on the same cluster, across clusters, to different namespaces or the same namespace, or to the same or a different storage class. With our sample application protected by a snapshot and a backup, we can now go through some of the possible restore scenarios using the tridentctl-protect utility.

Restore to a new namespace on the same cluster

You might remember that when doing restores using the Trident protect CRs, the first step is always to find the appArchivePath of the snapshot or backup to restore from. Luckily, the tridentctl-protect CLI will do this in the background for us, so restores are much more comfortable.

 

This simple command restores our sample application from the snapshot wordpress-snap-1 into the namespace wordpress-restore-1.

 

$ tridentctl-protect create snapshotrestore wordpress-restore-1 --namespace-mapping wordpress:wordpress-restore-1 --snapshot wordpress/wordpress-snap-1 -n wordpress-restore-1

 

The namespace mapping wordpress:wordpress-restore-1 instructs tridentctl-protect to restore resource definitions from the original namespace wordpress in the namespace wordpress-restore-1, which will be created by tridentctl-protect. Note that we create the snapshotrestore CR in the new namespace of the restored application.

 

A restore from backup works in an analogous way, except that we use the create backuprestore subcommand and obviously specify the backup to restore from, as shown here:

 

$ tridentctl-protect create backuprestore wordpress-restore-2 --namespace-mapping wordpress:wordpress-restore-2 --backup wordpress/wordpress-bkup-1 -n wordpress-restore-2

 

If we want to select only certain resources of the application to restore either from a snapshot or backup, we can add filtering options that include or exclude resources of certain kinds or marked with particular labels by adding the --resource-filter-exclude and --resource-filter-include flags to the tridentctl-protect restore command.

 

For example, the following command would exclude all secrets from the restore.

 

$ tridentctl-protect create backuprestore wordpress-restore-nosecrets --namespace-mapping wordpress:wordpress-restore-nosecrets --backup wordpress-bkup-1 --resource-filter-exclude '[{"Kind":"Secret","Version":"v1"}]' -n wordpress-restore-nosecrets

 

Another handy flag is --storage-class-mapping, which allows you to migrate the persistent volumes to a different storage class during a restore operation. For example, this command would restore our wordpress application persistent volumes from the storage class netapp-anf-perf-premium into the storage class netapp-anf-perf-standard:

 

$ tridentctl-protect create backuprestore wordpress-restore-scmig --namespace-mapping wordpress:wordpress-standard --backup wordpress-bkup-1 --storageclass-mapping netapp-anf-perf-premium:netapp-anf-perf-standard -n wordpress-restore-scmig

 

Restore to the original namespace

When restoring an application from a backup or snapshot to its original namespace on the same cluster, Trident protect first stops the application and removes its resources from the namespace. Then it restores the data from a backup or snapshot, and finally restores the application metadata. To do this, we use tridentctl-protect’s backupinplacerestore and snapshotinplacerestore subcommands or their convenient aliases bir and sir. So, this command will restore wordpress from its backup into the original namespace:

 

$ tridentctl-protect create bir wordpress-bir-1 --backup wordpress/wordpress-bkup-1 -n wordpress

 

Restore to a different cluster from a backup

Restoring from a backup to a different cluster can be a bit tedious if the original backup CR is not available—for example, if the original cluster was lost due to a disaster. In such a scenario, information about available backups and details like the appArchivePath information would need to be found by browsing the information stored in the object storage bucket. Thankfully, tridentctl-protect offers an option to comfortably find the necessary information from the backups in object storage.  

 

In this section, we show how you can restore your application to a different cluster if the backup CRs are not available for some reason.

 

The destination cluster must obviously have Trident protect installed, access to the object storage bucket containing the backup, and the respective appVault CR defined.

 

First, we check for the existence and availability of the appVault CR on our second cluster pu-aks-northeu by using the --context flag.

 

$ tridentctl-protect get appvault --context pu-aks-northeu
+-------+----------+-----------+-------+-------+
| NAME  | PROVIDER |   STATE   |  AGE  | ERROR |
+-------+----------+-----------+-------+-------+
| demo  | Azure    | Available | 6d1h  |       |
| test3 | Azure    | Available | 1d20h |       |
+-------+----------+-----------+-------+-------+

 

We also make sure that the namespace we’ll restore the application into does not exist on the destination cluster.

Now we can browse the backup contents of our appVault demo from the target cluster:

 

$ tridentctl-protect get appvaultcontent demo --show-resources backup --show-paths --context pu-aks-northeu
+---------------+-----------+--------+-------------------------+---------------------------+---------------------------------------------------------------------------------------------------------------------+
|    CLUSTER    |    APP    |  TYPE  |          NAME           |         TIMESTAMP         |                                                        PATH                                                         |
+---------------+-----------+--------+-------------------------+---------------------------+---------------------------------------------------------------------------------------------------------------------+
| pu-aks-westeu | wordpress | backup | wordpress-bkup-1        | 2024-10-30 08:37:40 (UTC) | wordpress_3b9abe58-59c1-48d7-a6e8-6bc02eb1e5b3/backups/wordpress-bkup-1_e52def64-e69c-4ac6-8020-6d36e8e97b96        |
| pu-aks-westeu | wordpress | backup | wordpress-bkup-restic-1 | 2024-10-30 08:43:03 (UTC) | wordpress_3b9abe58-59c1-48d7-a6e8-6bc02eb1e5b3/backups/wordpress-bkup-restic-1_cad87a5d-25ab-4a87-8601-558d0ec38654 |
+---------------+-----------+--------+-------------------------+---------------------------+---------------------------------------------------------------------------------------------------------------------+

 

The output shows us the available backups in the appVault, their originating clusters, the corresponding application name, timestamp, and appArchivePath. With this information at hand, it’s now a simple task to restore our sample application to the destination cluster by providing the appVault name and appArchivePath information to the tridentctl-protect create backuprestore command:

 

$ tridentctl-protect create backuprestore wordpress-restore --namespace-mapping wordpress:wordpress --appvault demo --path wordpress_3b9abe58-59c1-48d7-a6e8-6bc02eb1e5b3/backups/wordpress-bkup-1_e52def64-e69c-4ac6-8020-6d36e8e97b96 -n wordpress --context pu-aks-northeu 

 

We can also filter the listed backups by using the --app flag, which is helpful in real-life scenarios with larger environments and more backups.

Other helpful tridentctl-protect options

Finally, let’s take a look at three more options and subcommands of tridentctl-protect.

The get all subcommand creates a list of all Trident protect CRs configured on the cluster and accessible by the user executing the command.

 

$ tridentctl-protect get all -A

 

The --dry-run flag, which can be used with all create subcommands, prints only the object that’s about to be created, without actually sending it. This can be very helpful when you want to create more complex manifests to include in your automation workflows. For example, this command prints the manifest for a backuprestore CR with storage mapping and exclude filters:

 

$ tridentctl-protect create backuprestore wordpress-restore-scmig --namespace-mapping wordpress:wordpress-standard --backup wordpress-bkup-1 --storageclass-mapping netapp-anf-perf-premium:netapp-anf-perf-standard --resource-filter-exclude '[{"Kind":"Secret","Version":"v1"}]' -n wordpress-restore-mig --dry-run 
apiVersion: protect.trident.netapp.io/v1
kind: BackupRestore
metadata:
  creationTimestamp: null
  name: wordpress-restore-scmig
  namespace: wordpress-restore-mig
spec:
  appArchivePath: wordpress_cb0d2eda-abda-41be-ab9d-0a12b581c4f3/backups/wordpress-bkup-1_01d063df-fe0a-4ff4-aee1-f5c544da6284
  appVaultRef: demo
  namespaceMapping:
  - destination: wordpress-standard
    source: wordpress
  resourceFilter:
    resourceMatchers:
    - kind: Secret
      version: v1
    resourceSelectionCriteria: exclude
  storageClassMapping:
  - destination: netapp-anf-perf-standard
    source: netapp-anf-perf-premium
status:
  conditions: null
  state: ""

 

Last, the --show-full-error flag enables you to see the full error message if a data management command fails, as in this example.

 

$ tridentctl-protect get snapshot -A
+--------------+---------+-------+--------+-------------------------+
|     NAME     | APP REF | STATE |  AGE   |          ERROR          |
+--------------+---------+-------+--------+-------------------------+
| pgsql-snap-1 | pgsql   | Error | 10m34s | Application.protect.... |
+--------------+---------+-------+--------+-------------------------+

$ tridentctl-protect get snapshot --show-full-error -A
+--------------+---------+-------+--------+---------------------------------------+
|     NAME     | APP REF | STATE |  AGE   |                 ERROR                 |
+--------------+---------+-------+--------+---------------------------------------+
| pgsql-snap-1 | pgsql   | Error | 10m45s | Application.protect.trident.netapp.io |
|              |         |       |        | "pgsql" not found                     |
+--------------+---------+-------+--------+---------------------------------------+

 

Conclusion

In summary, we installed the Trident protect CLI tridentctl-protect on our workstation and then showed how it simplifies ad hoc data management operations like backup and restore. We also showed how tridentctl-protect simplifies application restores to a different cluster in disaster recovery scenarios, where the original cluster or backup CR is no longer available.

Public