5. Managing Stateful Applications

Kubernetes does not have the notion of an application. One deploys pods as inidividual units or under the control of various types of Resource Controllers such as ReplicaSet, StatefulSet, Deployment, etc. A templatized and more easy to package and deploy a collection of resources in the form of helm charts. A helm chart can be viewed as a Kubernetes Application just as much as a kubectl deployed StatefulSet. And then there are Operators, which are specialized custom controllers written by ISVs to deploy their software on Kubernetes.

5.1. What is an Application?

The lack of a proper Application construct in Kubernetes poses a problem when it comes to performing operations that encompass a group of resources. For example, how would one snapshot, clone or backup an entire helm release that spans PersistVolumeClaims, Secrets, ConfigMaps, SatefulSet, Pods, Services etc? Or how about snapshoting a web-tier, app-tier and database-tier each deployed separately using 3 different kubectl manifest files?

To faciliate this, ROBIN supercharge Kubernetes with the notion of an Application. An Application is a collection of different Kubernetes resources that form a single unit on which a DevOps engineer can perform Data Management operations. ROBIN has the most extensible and powerful constructs to define an application. The following different types of applications are supported by ROBIN:

Helm Release

A Helm release that was deployed using helm install <chart-name>

Custom Operator

A custom resource that is spun up using a Custom Kubernetes
Operator such as a couchbase operator

ROBIN FlexApp

A ROBIN defined construct which allows one to collect one or more
Kubernetes resource into one unit using label-selector rules.
For example, --select app=apache --select app=mysql would select
Pods and PVCs for a web and database tier together into a single
FlexApp object

ROBIN Application Bundle

This type of application is spun up using ROBIN’s own
Super Operator framework which allows one to deploy complex
stateful workloads such as Cloudera, Oracle RAC, Splunk,
SAP HANA, etc on Kubernetes.

Topics covered in this chapter:

robin app register

Register any generic Kubernetes App or Operator with ROBIN

robin app unregister

Unregister a previously registered Kubernetes App or Operator

robin app create

Creates an app from a ROBIN template, K8S selectors, snapshot or backup

robin app delete

Deletes an app

robin app attach

Attaches an external storage repo (S3, GCS, …) to an app

robin app detach

Detaches a previously attached repo

robin app clone

Clones an app from its snapshot

robin app config

Configure various attributes/schedules of an app

robin app restore

Restore an application snapshot that was deleted locally

robin app rollback

Rollback an application to a snapshot

5.2. Creating or Registering an Application

Before data management can be performed on a collection of PersistentVolumeClaims, Pods, etc all the relevant Kubernetes resources that together deliver a service to the end user must be collected together into one single unit, which ROBIN tracks as an Application. There are two ways to build the Application object in ROBIN – either by creating it or by registering it. The difference is as follows:

When you Create an application, ROBIN is responsible for creating all the relevant Kubernetes resources such as PersistentVolumeClaims, StatefulSets etc. But if these resources are already created by other components such as Helm, Custom Operators etc., then you don’t create, but Register them with ROBIN. But in both cases, whether created or registered, ROBIN maintains metadata of each of these objects in its configuration database.

The command robin app create is used to create an application and the command robin app register is used to register an existing Helm Release, Custom Operator etc with ROBIN.

5.2.1. Registering a Helm Release as an Application

Command to register a Helm release:

$ robin app register <appname> --app helm/<helm-release-name>

<appname>

The name to give to this app in ROBIN. To make it
easy to associate with a specfic Helm release that
this app refers to it is best to use a name that
matches the helm release name

helm/<helm-release-name>

Name of the Helm release that is obtained by running helm list

Example: Register Postgres Helm Release as an App in ROBIN:

$ helm install --name pgdb stable/postgresql

$ robin app register mydb --app helm/pgdb

Note

More than one helm release can be tracked in a single app by specifying --app command line option twice. For example, $ robin app register myblog --app helm/apache --app helm/mysql would track two different helm releases – (1) apache and (2) mysql as a single unit named myblog in ROBIN

5.2.2. Registering any set of Kubernetes resources as an Application

This is the most powerful and flexible way to register any set of Kubernetes resources as an applicationin ROBIN. These are called FlexApps and created using the below command:

$ robin app register <app-name>                                         \
                     --selector <label-name>=<label-value>              \
                     --resource <resource-type>/<resource-name>         \
                     --namespace <namespace>                            \
                     --describe

<app-name>

Name to assign to FlexApp

--selector <label-name>=<label-value>

Resources with these Kubernetes labels would be
selected to be part of this FlexApp

--resource <resource-type>/<resource-name>

Resources of the specified type and name would
selected to be part of this FlexApp

--namespace <namespace>

Namespace in which the Kubernetes resources are
deployed.

--describe

Using this option would describe (print) the
resources that would be selected into the FlexApp,
instead of actually creating the FlexApp.

5.2.2.1. Selecting resources that have more than one matching label (AND condition)

This is achieved by comma-seperating label name=value pairs as follows: --select tier=frontend,env=dev will select resources that have both tier = frontend AND env = dev labels on it.

5.2.2.2. Selecting resources that have at least one of the matching labels (OR condition)

This is achieved by specifing the --select option multiple times. For example: --select env=dev --select env=prod will select any resource that has either env = dev or env = prod labels on it.

5.2.2.3. Selecting resources of a certain type with matching labels

Let’s say one wants to only select PersistentVolumeClaims and StatefulSelect type resources with matching labels. That is, any other resource with a matching label should not be selected. This is achieved by specifying the resource name as a prefix to the label name as follows: --select pvc,statefulset:tier=database

5.2.2.4. Explicitly selecting certain resources

The --resource option is used to explicitly specify which Kubernetes resources are to be made part of the FlexApp. The format to specify this is as follows: --resource <resource-type>/<resource-name>, where <resource-name> is any of the resources (“Kind”) that the Kubernetes cluster recognizes, such as PersistentVolumeClaims (pvc), StatefulSets, Services, etc.

  • Running kubectl api-resources would list all valid values of <resource-type>

  • Running kubectl get <resource-type> would list all valid <resource-name> of that specific resource type

5.2.3. Creating an Application using ROBIN Application Bundle

Robin.io ships two products – ROBIN Storage (which is described in this document) and ROBIN Plaform. The latter offers a new type of application deployment framework called “Application Bundles”. Think about them as Helm++, because it extends the capability of Kubernetes to deploy any complex enterprise app, including the likes of Cloudera, Hortonworks, Spark, Splunk, ElasticSearch, MongoDB, Oracle, Oracle RAC, SAP HANA, etc., This is done using ROBIN’s SuperOperator framework. While deploying ROBIN Application Bundles is not in scope of this documentation, for completelness, the below command can be used to create them:

$ robin app create <name> --template <app-template>

5.2.4. Creating an Application from ROBIN Application Backup Image

ROBIN also allows one to create (or light up) entire apps from backups that were taken using ROBIN Storage. This is done using the below command:

$ robin app create <appname> --backupid <backupid>

appname

Name to assign to the app being lit up from backup

--backup <backupid>

Backup ID of the app. This is obtained by running
robin repo contents command which is explained later

Example:

$ robin app create import1 --backupid 5eccc5285a5211e9a1c3417886f14cc5

We can verify the app has been created using the following command:

$ robin app list
+---------+---------+-----------+-----------+---------+
| Name    | Type    | Namespace | Snapshots | Backups |
+---------+---------+-----------+-----------+---------+
| mydb    | helm    | default   | 2         | 1       |
| mysql-1 | helm    | default   | 1         | 1       |
| import1 | flexapp | default   | 0         | 0       |
+---------+---------+-----------+-----------+---------+

5.3. Deleting an Application

An application that was created using ROBIN can be deleted in its entirety. This means that all the objects created alongside the application will be deleted. However an application that was registered with ROBIN will only have its registration deleted and not the objects associated with it. To understand the difference between creation and deletion, see CreateOrRegister.

An application can be deleted using the following command:

$ robin app delete <appname>

5.4. Listing all Applications

The command to list all applications created or registered with ROBIN is:

$ robin app list

Example:

$ robin app list

+----------+---------+-----------+-----------+---------+
| Name     | Type    | Namespace | Snapshots | Backups |
+----------+---------+-----------+-----------+---------+
| mydb     | helm    | default   | 1         | 1       |
| mysql-1  | helm    | default   | 1         | 0       |
+----------+---------+-----------+-----------+---------+

5.5. Show information about a specific Application

The below command can be used to get detailed information about a specific application:

$ robin app info <appname>

Example:

$ robin app info mydb

Name                      : mydb
Kind                      : helm
State                     : ONLINE
Snapshot schedule         : {}
Backup schedule           : None
Number of repos           : 1
Number of snapshots       : 1
Number of backups         : 1

Query:
-------
{'namespace': 'default', 'apps': ['helm/pgdb'], 'resources': [], 'selectors': []}

Repos:
+----------+-----------------+--------+------------+
| Name     | Bucket          | Path   | Permission |
+----------+-----------------+--------+------------+
| datadump | datadump-bucket | dumps/ | readwrite  |
+----------+-----------------+--------+------------+

Snapshots:
+----------------------------------+------------+-------------+
| Id                               | Name       | Description |
+----------------------------------+------------+-------------+
| 861bd41c5a4e11e9b18bf189ccf1d49b | mydb_snap1 |             |
+----------------------------------+------------+-------------+

Backups:
+----------------------------------+---------+-------------+--------+
| Id                               | Name    | Description | State  |
+----------------------------------+---------+-------------+--------+
| 5eccc5285a5211e9a1c3417886f14cc5 | backup1 | None        | Pushed |
+----------------------------------+---------+-------------+--------+

5.6. Attach an External Repo for Backing up an Appliction

ROBIN Storage allows entire applications, plus thier data to be backed up to an external storage device/service such as AWS S3 or Google GCS object stores etc. Repo management is explained at length here. Below command can be used to attach a repo to an application:

$ robin app attach <appname> <reponame>

Example:

$ robin app attach mydb datadump

$ robin app info mydb

Name                      : mydb
Kind                      : helm
State                     : ONLINE
Snapshot schedule         : {}
Backup schedule           : None
Number of repos           : 1
Number of snapshots       : 1
Number of backups         : 0

Query:
-------
{'namespace': 'default', 'apps': ['helm/pgdb'], 'resources': [], 'selectors': []}

Repos:
+----------+-----------------+--------+------------+
| Name     | Bucket          | Path   | Permission |
+----------+-----------------+--------+------------+
| datadump | datadump-bucket | dumps/ | readwrite  |
+----------+-----------------+--------+------------+

Snapshots:
+----------------------------------+------------+-------------+
| Id                               | Name       | Description |
+----------------------------------+------------+-------------+
| 861bd41c5a4e11e9b18bf189ccf1d49b | mydb_snap1 |             |
+----------------------------------+------------+-------------+

5.7. Detach an External Repo from an Application

A previously attached repo can be detached from an Application using the below command:

$ robin app detach <appname> <reponame>

Example:

$ robin app detach mydb datadump

$ robin app info mydb

Name                      : mydb
Kind                      : helm
State                     : ONLINE
Snapshot schedule         : {}
Backup schedule           : None
Number of repos           : 0
Number of snapshots       : 1
Number of backups         : 0

Query:
-------
{'namespace': 'default', 'apps': ['helm/pgdb'], 'resources': [], 'selectors': []}

Snapshots:
+----------------------------------+------------+-------------+
| Id                               | Name       | Description |
+----------------------------------+------------+-------------+
| 861bd41c5a4e11e9b18bf189ccf1d49b | mydb_snap1 |             |
+----------------------------------+------------+-------------+

5.8. Configuring Data Management Attributes of an Application

Data Management attributes of an application, such as snapshot schedules and retention policies etc., can be configured using the command below:

$ robin app config <appname>                  \
           --snapshot-schedule <schedule>     \
           --snapshot-reservation <gb|%>      \
           --backup-schedule <schedule>       \

--snapshot-schedule <schedule>

ROBIN allows configuring a schedule to automatically snapshot
applications and set retention policies. <schedule> is the path
to the JSON file or JSON string that describes the policy

--snapshot-reservation <size|%>

A certain amount of storage space can be reserved for holding
snapshots of an application. This is specified in either
absolute storage space via <size> field or in percentage
as <num> %

--backup-schedule <schedule>

ROBIN allows configuring a schedule to automatically backup
applications and set retention policies. <schedule> is the path
to the JSON file or JSON string that describes the policy

The fields that can be specified in the JSON file describing a schedule are detailed below:

frequency

The overall frequency at which to take snapshots/backups. Valid values
include: ‘hourly’, ‘daily’, ‘weekly’, ‘monthly’.

disable

A boolean value indicating whether or not to set the specified schedule.

retain

The number of copies of snapshots/backups created by this schedule to keep.
This field is optional and the default value is 1 if not specified.

minute

An integer between 1-59 representing the minute at which the operation should
be run. This field is optional, and the default value is 1 if not specified.

hour

An integer between 0-23 representing the hour at which the operation should
be run. This field is optional, and the default value is 0 if not specified.

weekday

An integer between 1-7 representing the day of the week on which the operation should
be run. Monday is represented by 1 and so on and so forth. This field is optional,
and the default value is 1 if not specified.

monthday

An integer between 1-28 representing the day of the month on which the operation should
be run. This field is optional, and the default value is 1 if not specified.

An example of a JSON file that can be used to describe a snapshot/backup schedule is detailed below:

 {
     "frequency": "weekly",
     "retain": 2,
     "weekday": 3,
     "hour": 5,
     "minute": 30,
     "disable": false,
}

The above JSON will enable a snapshot or backup schedule which will run every week on Wednesday at 05:30 AM, retaining 2 snapshots/backups.

Note

Only one snapshot or backup schedule of each frequncy type can be created. Thus one cannot have 2 different hourly snapshot schedules for example, however 1 hourly snapshot schedule and 1 hourly backup schedule is supported.

5.9. Restoring an Application snapshot from Backup

Application snapshots that are deleted locally can be restored from data stored in a backup using the command:

$ robin app restore <appname> <backupid>

appname

Name of the ROBIN registered application that needs to be restored.

backupid

Unique ID for the snapshot within the repo. This is obtained when the snapshot
was pushed to the repo.

Note

The backup id specified must refer to the backup that was originally created of the snapshot that is to be restored.

Example:

Verify the snapshot does not exist locally

$ robin snapshot list
+----------------------------------+--------+----------+----------+--------------------+
| Snapshot ID                      | State  | App Name | App type | Snapshot name      |
+----------------------------------+--------+----------+----------+--------------------+
+----------------------------------+--------+----------+----------+--------------------+

Restore the snapshot via:

$ robin app restore mydb 5eccc5285a5211e9a1c3417886f14cc5

This will re-create a snapshot that was deleted locally earlier:

$ robin snapshot list
+----------------------------------+--------+----------+----------+--------------------+
| Snapshot ID                      | State  | App Name | App type | Snapshot name      |
+----------------------------------+--------+----------+----------+--------------------+
| 861bd41c5a4e11e9b18bf189ccf1d49b | ONLINE | mydb     | helm     | mydb_snap1         |
+----------------------------------+--------+----------+----------+--------------------+

5.10. Rolling back an Application to a snapshot

Applications can be rolled back to previous state saved via snapshots from the command:

$ robin app rollback <name> <snapshotid>

<name>

Name of the application to rollback

<snapshotid>

Unique ID of the snapshot to rollback to (this is obtained from the output of robin snapshot list)

Example:

$ robin app rollback mydb 861bd41c5a4e11e9b18bf189ccf1d49b