11. Example Workflow utilizing ROBIN Storage

In the guide below, we will showcase how to deploy a MariaDB application via Helm using ROBIN Storage and introduce some basic application life cycle management features provided by ROBIN.

11.1. App Deployment

11.1.1. Deploy the necessary Tiller Objects

$ robin k8s deploy-tiller-objects
Tiller objects were successfully deployed for namespace 'default'

11.1.2. Configure helm for your ROBIN cluster

Note

Helm should already be pre-installed on the machine you wish to run ROBIN commands from. The below steps only configure Helm for optimal use. To install Helm, read the instructions available here.

$ robin k8s helm-setup
HELM_HOME has been configured at /root/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!

You should see pod named tiller-deploy running now:

$ kubectl get pods -n default
NAME                             READY   STATUS    RESTARTS   AGE
tiller-deploy-5bfb586db7-4xmk2   1/1     Running   0          77s

11.1.3. Add the stable Helm repositry

$ helm repo add stable https://kubernetes-charts.storage.googleapis.com/
"stable" has been added to your repositories

11.1.4. Deploy the MariaDB helm chart using the ROBIN storage class

First get the name of the ROBIN storage class available on your machine, by running the following command:

$ kubectl get sc
NAME              PROVISIONER   AGE
robin (default)   robin         15m

To create the MariaDB app run the following command with the ROBIN storage class discoved above in place of <robin-sc>:

$ helm install stable/mariadb --name users --set master.persistence.storageClass=<robin-sc> \
  --set master.persistence.size=20Gi --set slave.persistence.storageClass=<robin-sc> \
  --set slave.persistence.size=20Gi --set db.name=testdb --tls --tiller-namespace default

The output should look something similar to this:

$ helm install stable/mariadb --name users --set master.persistence.storageClass=robin \
  --set master.persistence.size=20Gi --set slave.persistence.storageClass=robin \
  --set slave.persistence.size=20Gi --set db.name=testdb --tls --tiller-namespace default

NAME:   users
LAST DEPLOYED: Fri May 24 16:09:44 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME                  DATA  AGE
users-mariadb-master  1     0s
users-mariadb-slave   1     0s
users-mariadb-tests   1     0s

==> v1/Service
NAME                 TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)   AGE
users-mariadb        ClusterIP  172.19.151.176  <none>       3306/TCP  0s
users-mariadb-slave  ClusterIP  172.19.199.152  <none>       3306/TCP  0s

==> v1beta1/StatefulSet
NAME                  DESIRED  CURRENT  AGE
users-mariadb-master  1        1        0s
users-mariadb-slave   1        1        0s

==> v1/Pod(related)
NAME                    READY  STATUS   RESTARTS  AGE
users-mariadb-master-0  0/1    Pending  0         0s
users-mariadb-slave-0   0/1    Pending  0         0s

==> v1/Secret
NAME           TYPE    DATA  AGE
users-mariadb  Opaque  2     0s

The above command will deploy a MariaDB application named users containing a MySQL database named testdb. Note the size values given are arbitrary, change them as per your cluster restrictions.

Note

Before running the install command ensure that the ROBIN storage class name specified is correct as for Kubernetes versions newer than 1.13 it appears as robin but for older versions it is displayed as robin-0-3

We can see that the application is created using the robin storage class by looking at the details of the pvcs created:

$ kubectl get pvc
NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-users-mariadb-master-0    Bound    pvc-0509988e-7e79-11e9-bf41-00155d61160c   20Gi       RWO            robin          7h30m
data-users-mariadb-slave-0     Bound    pvc-0511def7-7e79-11e9-bf41-00155d61160c   20Gi       RWO            robin          7h30m

11.1.5. Register the application with ROBIN

$ robin app register demo --app helm/users
Job:   11 Name: K8SAppRegister       State: WAITING         Error: 0
Job:   11 Name: K8SAppRegister       State: COMPLETED       Error: 0

The above command will allow ROBIN to capture all of the Kubernetes objects related to the specified Helm application.

To verify all of the neccessary objects are being tracked you can run the following command:

$ robin app status demo
+-----------------------+-----------------------------+--------+
| Kind                  | Name                        | Status |
+-----------------------+-----------------------------+--------+
| ConfigMap             | users-mariadb-slave         | Ready  |
| ConfigMap             | users-mariadb-master        | Ready  |
| Secret                | users-mariadb               | Ready  |
| PersistentVolumeClaim | data-users-mariadb-master-0 | Bound  |
| PersistentVolumeClaim | data-users-mariadb-slave-0  | Bound  |
| Pod                   | users-mariadb-slave-0       | Ready  |
| Pod                   | users-mariadb-master-0      | Ready  |
| Service               | users-mariadb-slave         | Ready  |
| Service               | users-mariadb               | Ready  |
| StatefulSet           | users-mariadb-slave         | Ready  |
| StatefulSet           | users-mariadb-master        | Ready  |
+-----------------------+-----------------------------+--------+

Note

It is highly recommended to wait for all the necessary objects to be in a good state before running additional ROBIN commands.

11.2. Application Lifecycle Management Features

Detailed below are quick start commands of some of the advanced application lifecycle management tools that ROBIN provides.

11.2.1. Snapshots

A snapshot is a reference marker for an application at a particular point in time. Snapshots are useful for example to instantaneously recover an application to a known healthy state in the event of corruption. For more details on snapshots please visit this section.

To create a snapshot named snap1 of the registered demo application, run the following command:

$ robin snapshot create snap1 demo --wait
Job:   14 Name: K8SApplicationSnapshot State: VALIDATED       Error: 0
Job:   14 Name: K8SApplicationSnapshot State: WAITING         Error: 0
Job:   14 Name: K8SApplicationSnapshot State: COMPLETED       Error: 0

To verify that has been created, run the following command:

$ robin snapshot list
+----------------------------------+--------+----------+----------+---------------+
| Snapshot ID                      | State  | App Name | App type | Snapshot name |
+----------------------------------+--------+----------+----------+---------------+
| 0283d21e7ebc11e9ba4e39b23cfec954 | ONLINE | demo     | helm     | demo_snap1    |
+----------------------------------+--------+----------+----------+---------------+

For further information on additional snapshot commands click here.

11.2.2. Clones

A clone is a copy of an existing application. Cloning is useful when you want to run reports on a database without affecting the source database application, or for performing UAT tests or for validating patches before applying them to the production database. For more details on clones please visit this section.

To create a clone named clone1 from the snapshot we created previously, run the following command:

$ robin clone create clone1 0283d21e7ebc11e9ba4e39b23cfec954 --wait
Job:   18 Name: K8SApplicationClone  State: WAITING         Error: 0
Job:   18 Name: K8SApplicationClone  State: AGENT_WAIT      Error: 0
Job:   18 Name: K8SApplicationClone  State: COMPLETED       Error: 0

Note

Snapshot IDs are randomly generated with every snapshot creation and hence the command run here will have to be changed to reflect the Snapshot ID generated by your ROBIN cluster.

To verify the clone has been created and registered with ROBIN, run the following command:

$ robin app list
+--------+---------+-----------+-----------+---------+
| Name   | Type    | Namespace | Snapshots | Backups |
+--------+---------+-----------+-----------+---------+
| demo   | helm    | default   | 1         | 0       |
| clone1 | flexapp | default   | 0         | 0       |
+--------+---------+-----------+-----------+---------+

In addition since a cloned application is considered a standalone, independent application we can check the status of its objects by running the following command:

$ robin app status clone1
+-----------------------+------------------------------------+----------+
| Kind                  | Name                               | Status   |
+-----------------------+------------------------------------+----------+
| ConfigMap             | clone1-users-mariadb-master        | Ready    |
| ConfigMap             | clone1-users-mariadb-slave         | Ready    |
| Secret                | clone1-users-mariadb               | Ready    |
| PersistentVolumeClaim | data-clone1-users-mariadb-slave-0  | Bound    |
| PersistentVolumeClaim | data-clone1-users-mariadb-master-0 | Bound    |
| Pod                   | clone1-users-mariadb-master-0      | Ready    |
| Pod                   | clone1-users-mariadb-slave-0       | Ready    |
| Service               | clone1-users-mariadb-slave         | Ready    |
| Service               | clone1-users-mariadb               | Ready    |
| StatefulSet           | clone1-users-mariadb-master        | Ready    |
| StatefulSet           | clone1-users-mariadb-slave         | Ready    |
+-----------------------+------------------------------------+----------+

11.2.3. Backups

ROBIN allows users to backup their applications (along with the data attached) by creating copies of the metadata and volume data referenced by a snapshot in an external repository such as S3 Object Store, Google Cloud Storage, etc. This in turn makes their stateful applications portable across Kubernetes clusters spanning on-prem, publc and hybrid cloud environments.

11.2.3.1. Registering a Repository

To create a backup, one must register the repository to which the data will be pushed with ROBIN. To do so run the following command:

$ robin repo register demo-backup gcs://demos-backup-tutorial /root/gcs.json readwrite --wait
Job:   20 Name: StorageRepoAdd       State: WAITING         Error: 0
Job:   20 Name: StorageRepoAdd       State: COMPLETED       Error: 0

An example of the JSON file needed to register a GCS bucket is detailed below:

 {
     "type": "service_account",
     "project_id": "rock-range-805623",
     "privbte_key_id": "c9fde8c819735439248147457629895ebbcc1f21",
     "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgpqkkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDXlyNg3997PJlA\nyS9doXSfX5lEpDgmk7nATyOrKQkl1D3/bWvoFMR372i0WKopj5FvLNY42jrcRzjF\nTlbJuwP4WAU652ss3qEvnUgd+mD7CcjOWd9bAA6vPJAJDo/TtTleZNQWd96y2WbT\nH/BqI9UCxdWNfsuYHQtpVViPdviizU3AxFtD6NTN/KmUX9mlM6RuF2RXAc5N/p4X\nhbeSV+rSfEgb9PA2U+fwobGzeR97V4SwK15btPpSN5twf0Wy49zGQLONFcmfwhRc\n+3r3gpPfqb+cb1xWiiD5fgO4yWYcWQXJJgUumVtVZxikc6k+9Vbko9zw20NNzRgp\nKfZdtm1jAgMBAAECggEABx+l2h4bntFWSQc3yu26UkfQ4y0/37pe4WVcCtxMwpS3\nUEbV+7Gv+mbYwVjKqpvlVNSY3YD4f+3UiOR5RIzK6UpTRep+ppoPzGh4iREMYk3k\n9PiQQkwCsDSil3IE65xp3F4die6FC3jWNFdSVNeBQtmxoD7H0GtpRJ4+0mK+fXbW\nr5f6O3WES4nOTNRonOdg9bIJJKklt3GSjtd1X5JWfGU53sbrksvy31+hL71pXCQn\nUZlkoilc3KYGnesd3KwIpxX9Pi5TldNUWuSnibvgXnDjM05PuQ0YI9VEfVR+eDfI\nBZAw2b/dmCWyU3QVAMtRbhwISmbxB33rZ133gTVN/QKBgQD5ZTZSnf7/b0YdKcAD\nP3bevN3/0s9EXO+D62MTRdrNeyb46hAcbNHmzAvgqtB74bQxiF5hs6RbmTmUpVpL\nSyCl6lqf3eMzP2gdECRLmkeZKpiWtfbPNbTefGVvbvWG6vi3E6+b/5cKPVHMLSV6\n4LIbqpVyWFWM905MXU9cgFgJDwKBgQDdTL5Yl3G/91HnyFieQ9pju6C9v1S3277k\nN10hcmldkJWludgT3WzDsNmbcAdCp+KOtQusf6KMKT5sd5ickMmAI3IZkzsgb7rS\n7AVBf3bpLG+3kOGJ4PVGKXfTEONw7hSo1UwLQxSZj1SMTtOd63pFcVea1hYQXifr\nADUrkwhObQKBgQCTb9pljTIrIEV7CCuTwChTv6QekSonaCnQ+19fDXUE9UFc9kMA\nCvUsVITRFSqbkhHXlp71c5Y+3J6x2e3/g/KRI7Lfv/WJXnrWc6yBZXveeOgscPaK\nQ13iCfiNndX5JQBXb+vo3iEU1Jt+3VGvCxc/3IjtSHuLEskfLCq2rMle0QKBgQCX\nsTJM0gGKT8KCCc/M9J/vez6Msmkk+mkYUGbzNVTKQQCDMCfQPhh+72vKY3lmlGP1\nBF7zKC5Iu0DB4xzmPU0SG/DBzS1bZ5r9V7GmmvPsk3wkrRgcheo65NPxBwOQdnIM\n5OCSW7H0LM58us/N0UG+Zhnx1cwb/h6ItIS90LSB5QKBgCwZPxhDhlKXGn3J8sLn\nuZ9WjFTBlabt8mksHpnE4xgj5BeOXee29CtaX+mPIcPEOO9ynsbizaSv7I2kBM+d\n9DZt9XiM6NcjrqtP7FCdgvZeQV0GIHjlqj2zH0UDxImGmENyHeXA1X2d0fZwzuJ+\n5dEZAfYh4QAnnPiAF5K9QFEi\n-----END PRIVATE KEY-----\n",
     "client_email": "jamesbond-cloud-repo@rock-range-805623.iam.gserviceaccount.com",
     "client_id": "1815195052297641083965",
     "auth_uri": "https://accounts.google.com/o/oauth2/auth",
     "token_uri": "https://oauth2.googleapis.com/token",
     "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
     "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/jamesbond-cloud-repo%40rock-range-805623.iam.gserviceaccount.com"
}

To verify the repository has been successfully added, run the following command:

$ robin repo list
+-------------+------+------------------+--------------+-----------------------+------+-------------+
| Name        | Type | Owner/Tenant     | BackupTarget | Bucket                | Path | Permissions |
+-------------+------+------------------+--------------+-----------------------+------+-------------+
| demo-backup | GCS  | robin/K8sCluster | 1            | demos-backup-tutorial | -    | readwrite   |
+-------------+------+------------------+--------------+-----------------------+------+-------------+

For further information on how to register a repository or additional repo commands, click here.

11.2.3.2. Attaching a Repository

Since snapshots are linked to applications, repositories to which their backups need to be pushed to also need to be attached to the respective applications. To attach a registered repository to an appliction, run the following command:

$ robin repo attach demo-backup demo --wait
Job:   21 Name: K8SApplicationAddRepo State: DONE            Error: 0
Job:   21 Name: K8SApplicationAddRepo State: COMPLETED       Error: 0

To verify the repository demo-backup has been attached to app demo, run the following command:

$ robin repo info demo-backup
Name                   : demo-backup
Type                   : GCS
Bucket                 : demos-backup-tutorial
Path                   : -
Permissions            : readwrite

Scan Details
-------
Scan State             : SUCCESS
Start Time             : 2019-05-25 01:17:02
End Time               : 2019-05-25 01:17:02
Time Taken             : 0s
Scan Error             : -
Scan Diff              : {'added': 0, 'removed': 0}

Apps attached: 1
        helm/demo

For further information on additional repo commands, click here.

11.2.3.3. Creating a Backup

After your destination repository has been successfully registered and attached to the appropriate app one can create a backup by running the following command:

$ robin backup create backup1 0283d21e7ebc11e9ba4e39b23cfec954 demo-backup --wait
Job:   22 Name: K8SApplicationBackup State: VALIDATED       Error: 0
Job:   22 Name: K8SApplicationBackup State: AGENT_WAIT      Error: 0
Job:   22 Name: K8SApplicationBackup State: COMPLETED       Error: 0

Note

Snapshot IDs are randomly generated with every snapshot creation and hence the command run here will have to be changed to reflect the Snapshot ID generated by your ROBIN cluster.

To verify the backup has been successfully pushed, run the following command:

$ robin backup list
+----------------------------------+-------------+-------------+---------------+--------+
| Backup ID                        | Backup Name | Repo        | Snapshot Name | State  |
+----------------------------------+-------------+-------------+---------------+--------+
| 2a4edd9a7ec611e9a36c9fa69c009ecb | backup1     | demo-backup | demo_snap1    | Pushed |
+----------------------------------+-------------+-------------+---------------+--------+

For further information on additional repo commands, click here.