****************************** 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. 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 `` 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 ========================= =========================================================== .. _CreateOrRegister: 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. Registering a Helm Release as an Application ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Command to register a Helm release: .. code-block:: console $ robin app register --app helm/ ============================= ======================================== ```` | 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/`` Name of the Helm release that is obtained by running ``helm list`` ============================= ======================================== **Example: Register Postgres Helm Release as an App in ROBIN:** .. code-block:: console $ 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 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 \ --selector = \ --resource / \ --namespace \ --describe =================================================== ================================= ```` Name to assign to FlexApp ``--selector =`` | Resources with these Kubernetes labels would be | selected to be part of this FlexApp ``--resource /`` | Resources of the specified type and name would | selected to be part of this FlexApp ``--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. =================================================== ================================= 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. 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. 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`` 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 /``, where ```` 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 ```` * Running ``kubectl get `` would list all valid ```` of that specific resource type 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 --template 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 --backupid =========================== ========================== ``appname`` | Name to assign to the app being lit up from backup ``--backup `` | 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 | +---------+---------+-----------+-----------+---------+ 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 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 | +----------+---------+-----------+-----------+---------+ Show information about a specific Application ============================================= The below command can be used to get detailed information about a specific application:: $ robin app info **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 | +----------------------------------+---------+-------------+--------+ 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 **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 | | +----------------------------------+------------+-------------+ Detach an External Repo from an Application =========================================== A previously attached repo can be detached from an Application using the below command:: $ robin app detach **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 | | +----------------------------------+------------+-------------+ .. _SnapshotSchedules: 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 \ --snapshot-schedule \ --snapshot-reservation \ --backup-schedule \ ===================================== ================================================================== ``--snapshot-schedule `` | ROBIN allows configuring a schedule to automatically snapshot | applications and set retention policies. ```` is the path | to the JSON file or JSON string that describes the policy ``--snapshot-reservation `` | A certain amount of storage space can be reserved for holding | snapshots of an application. This is specified in either | absolute storage space via ```` field or in percentage | as `` %`` ``--backup-schedule `` | ROBIN allows configuring a schedule to automatically backup | applications and set retention policies. ```` 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: .. code-block:: json { "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. 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`` | 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 | +----------------------------------+--------+----------+----------+--------------------+ 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 of the application to rollback ```` | Unique ID of the snapshot to rollback to (this is obtained from the output of ``robin snapshot list``) ================= ======================================================================================================== **Example**:: $ robin app rollback mydb 861bd41c5a4e11e9b18bf189ccf1d49b