Skip to content

Commit

Permalink
Update mysql app and blueprint for 8.x chart (#824)
Browse files Browse the repository at this point in the history
* Update mysql app and blueprint for 8.x chart

* Resolve golint issues
  • Loading branch information
ankitjain235 committed Dec 1, 2020
1 parent 6cd39e7 commit 5305b92
Show file tree
Hide file tree
Showing 5 changed files with 372 additions and 22 deletions.
278 changes: 278 additions & 0 deletions examples/stable/mysql/6.x/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
# MySQL

[MySQL](https://MySQL.org) is one of the most popular database servers in the world. Notable users include Wikipedia, Facebook and Google.

## Introduction

This chart bootstraps a single node MySQL deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.

## Prerequisites

- Kubernetes 1.6+ with Beta APIs enabled
- PV provisioner support in the underlying infrastructure
- Kanister controller version 0.43.0 installed in your cluster, let's assume in Namespace `kanister`
- Kanctl CLI installed (https://docs.kanister.io/tooling.html#install-the-tools)

## Installing the Chart

To install the MySQL database using the `bitnami` chart with the release name `mysql-release`:

```bash
# Add bitnami in your local chart repository
$ helm repo add bitnami https://charts.bitnami.com/bitnami

# Update your local chart repository
$ helm repo update

# Install the MySQL database (Helm Version 3)
$ kubectl create namespace mysql-test
$ helm install mysql-release bitnami/mysql --version 6.14.11 --namespace mysql-test \
--set root.password='asd#45@mysqlEXAMPLE'

```

The command deploys a MySQL instance in the `mysql-test` namespace.

By default a random password will be generated for the root user. For setting your own password, use the `root.password` param as shown above.

You can retrieve your root password by running the following command. Make sure to replace [YOUR_RELEASE_NAME] and [YOUR_NAMESPACE]:

`kubectl get secret [YOUR_RELEASE_NAME] --namespace [YOUR_NAMESPACE] -o jsonpath="{.data.mysql-root-password}" | base64 --decode`

> **Tip**: List all releases using `helm list --all-namespaces`, using Helm Version 3.
## Integrating with Kanister

If you have deployed MySQL application with name other than `mysql-release` and namespace other than `mysql-test`, you need to modify the commands(backup, restore and delete) used below to use the correct release name and namespace

### Create Profile
Create Profile CR if not created already

```bash
$ kanctl create profile s3compliant --access-key <aws-access-key-id> \
--secret-key <aws-secret-key> \
--bucket <s3-bucket-name> --region <region-name> \
--namespace mysql-test
```

You can read more about the Profile custom Kanister resource [here](https://docs.kanister.io/architecture.html?highlight=profile#profiles).

**NOTE:**

The above command will configure a location where artifacts resulting from Kanister
data operations such as backup should go. This is stored as a `profiles.cr.kanister.io`
*CustomResource (CR)* which is then referenced in Kanister ActionSets. Every ActionSet
requires a Profile reference to complete the action. This CR (`profiles.cr.kanister.io`)
can be shared between Kanister-enabled application instances.

### Create Blueprint

Create Blueprint in the same namespace as the Kanister controller

```bash
$ kubectl create -f ./mysql-blueprint.yaml -n kanister
```

Once MySQL is running, you can populate it with some data. Let's add a table called "pets" to a test database:

```bash
# Connect to MySQL by running a shell inside MySQL's pod
$ kubectl exec -ti $(kubectl get pods -n mysql-test --selector=release=mysql-release -o=jsonpath='{.items[0].metadata.name}') -n mysql-test -- bash

# From inside the shell, use the mysql CLI to insert some data into the test database
# Create "test" db

# Replace mysql-root-password with the password that you have set while installing MySQL
$ mysql --user=root --password=<mysql-root-password>

mysql> CREATE DATABASE test;
Query OK, 1 row affected (0.00 sec)

mysql> USE test;
Database changed

# Create "pets" table
mysql> CREATE TABLE pets (name VARCHAR(20), owner VARCHAR(20), species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);
Query OK, 0 rows affected (0.02 sec)

# Insert row to the table
mysql> INSERT INTO pets VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);
Query OK, 1 row affected (0.01 sec)

# View data in "pets" table
mysql> SELECT * FROM pets;
+----------+-------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+----------+-------+---------+------+------------+-------+
| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
+----------+-------+---------+------+------------+-------+
1 row in set (0.00 sec)
```

## Protect the Application

You can now take a backup of the MySQL data using an ActionSet defining backup for this application. Create an ActionSet in the same namespace as the controller.

```bash
# Find profile name
$ kubectl get profile -n mysql-test
NAME AGE
s3-profile-drnw9 2m

# Create Actionset
# Please make sure the value of profile and blueprint matches with the names of profile and blueprint that we have created already
$ kanctl create actionset --action backup --namespace kanister --blueprint mysql-blueprint --statefulset mysql-test/mysql-release-master --profile mysql-test/s3-profile-drnw9 --secrets mysql=mysql-test/mysql-release
actionset backup-rslmb created

$ kubectl --namespace kanister get actionsets.cr.kanister.io
NAME AGE
backup-rslmb 1m

# View the status of the actionset
# Please make sure the name of the actionset here matches with name of the name of actionset that we have created already
$ kubectl --namespace kanister describe actionset backup-rslmb
```

### Disaster strikes!

Let's say someone accidentally deleted the test database using the following command:
```bash
# Connect to MySQL by running a shell inside MySQL's pod
$ kubectl exec -ti $(kubectl get pods -n mysql-test --selector=app=mysql-release -o=jsonpath='{.items[0].metadata.name}') -n mysql-test -- bash

$ mysql --user=root --password=asd#45@mysqlEXAMPLE

# Drop the test database
$ mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)

mysql> DROP DATABASE test;
Query OK, 1 row affected (0.03 sec)

mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)

```

### Restore the Application

To restore the missing data, you should use the backup that you created before. An easy way to do this is to leverage `kanctl`, a command-line tool that helps create ActionSets that depend on other ActionSets:

```bash
# Make sure to use correct backup actionset name here
$ kanctl --namespace kanister create actionset --action restore --from "backup-rslmb"
actionset restore-backup-62vxm-2hdsz created

# View the status of the ActionSet
# Make sure to use correct restore actionset name here
$ kubectl --namespace kanister describe actionset restore-backup-62vxm-2hdsz
```

Once the ActionSet status is set to "complete", you can see that the data has been successfully restored to MySQL

```bash
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)

mysql> USE test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW TABLES;
+----------------+
| Tables_in_test |
+----------------+
| pets |
+----------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM pets;
+----------+-------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+----------+-------+---------+------+------------+-------+
| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
+----------+-------+---------+------+------------+-------+
1 row in set (0.00 sec)

```

### Delete the Artifacts

The artifacts created by the backup action can be cleaned up using the following command:

```bash
$ kanctl --namespace kanister create actionset --action delete --from backup-rslmb --namespacetargets kanister
actionset delete-backup-glptq-cq6bw created

# View the status of the ActionSet
$ kubectl --namespace kanister describe actionset delete-backup-glptq-cq6bw
```


## Troubleshooting

If you run into any issues with the above commands, you can check the logs of the controller using:

```bash
$ kubectl --namespace kanister logs -l app=kanister-operator
```

you can also check events of the actionset

```bash
$ kubectl describe actionset restore-backup-62vxm-2hdsz -n kanister
```


## Cleanup

### Uninstalling the Chart

To uninstall/delete the `mysql-release` deployment:

```bash
# Helm Version 3
$ helm delete mysql-release -n mysql-test
```

The command removes all the Kubernetes components associated with the chart and deletes the release.

### Delete CRs
Remove Blueprint and Profile CR

```bash
$ kubectl delete blueprints.cr.kanister.io mysql-blueprint -n kanister

$ kubectl get profiles.cr.kanister.io -n mysql-test
NAME AGE
s3-profile-drnw9 122m

$ kubectl delete profiles.cr.kanister.io s3-profile-drnw9 -n mysql-test
```
80 changes: 80 additions & 0 deletions examples/stable/mysql/6.x/mysql-blueprint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
apiVersion: cr.kanister.io/v1alpha1
kind: Blueprint
metadata:
name: mysql-blueprint
actions:
backup:
type: StatefulSet
outputArtifacts:
mysqlCloudDump:
keyValue:
s3path: "{{ .Phases.dumpToObjectStore.Output.s3path }}"
phases:
- func: KubeTask
name: dumpToObjectStore
objects:
mysqlSecret:
kind: Secret
name: '{{ index .Object.metadata.labels "release" | toString }}'
namespace: '{{ .StatefulSet.Namespace }}'
args:
image: kanisterio/mysql-sidecar:0.43.0
namespace: "{{ .StatefulSet.Namespace }}"
command:
- bash
- -o
- errexit
- -o
- pipefail
- -c
- |
s3_path="/mysql-backups/{{ .StatefulSet.Namespace }}/{{ index .Object.metadata.labels "release" | toString }}/{{ toDate "2006-01-02T15:04:05.999999999Z07:00" .Time | date "2006-01-02T15-04-05" }}/dump.sql.gz"
root_password="{{ index .Phases.dumpToObjectStore.Secrets.mysqlSecret.Data "mysql-root-password" | toString }}"
mysqldump --column-statistics=0 -u root --password=${root_password} -h {{ index .Object.metadata.labels "release" | toString }} --single-transaction --all-databases | gzip - | kando location push --profile '{{ toJson .Profile }}' --path ${s3_path} -
kando output s3path ${s3_path}
restore:
type: StatefulSet
inputArtifactNames:
- mysqlCloudDump
phases:
- func: KubeTask
name: restoreFromBlobStore
objects:
mysqlSecret:
kind: Secret
name: '{{ index .Object.metadata.labels "release" | toString }}'
namespace: '{{ .StatefulSet.Namespace }}'
args:
image: kanisterio/mysql-sidecar:0.43.0
namespace: "{{ .StatefulSet.Namespace }}"
command:
- bash
- -o
- errexit
- -o
- pipefail
- -c
- |
s3_path="{{ .ArtifactsIn.mysqlCloudDump.KeyValue.s3path }}"
root_password="{{ index .Phases.restoreFromBlobStore.Secrets.mysqlSecret.Data "mysql-root-password" | toString }}"
kando location pull --profile '{{ toJson .Profile }}' --path ${s3_path} - | gunzip | mysql -u root --password=${root_password} -h {{ index .Object.metadata.labels "release" | toString }}
delete:
type: Namespace
inputArtifactNames:
- mysqlCloudDump
phases:
- func: KubeTask
name: deleteFromBlobStore
args:
image: kanisterio/mysql-sidecar:0.43.0
namespace: "{{ .Namespace.Name }}"
command:
- bash
- -o
- errexit
- -o
- pipefail
- -c
- |
s3_path="{{ .ArtifactsIn.mysqlCloudDump.KeyValue.s3path }}"
kando location delete --profile '{{ toJson .Profile }}' --path ${s3_path}
8 changes: 4 additions & 4 deletions examples/stable/mysql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ $ helm repo update
# Install the MySQL database (Helm Version 3)
$ kubectl create namespace mysql-test
$ helm install mysql-release bitnami/mysql --namespace mysql-test \
--set root.password='asd#45@mysqlEXAMPLE'
--set auth.rootPassword='asd#45@mysqlEXAMPLE'

```

The command deploys a MySQL instance in the `mysql-test` namespace.

By default a random password will be generated for the root user. For setting your own password, use the `root.password` param as shown above.
By default a random password will be generated for the root user. For setting your own password, use the `auth.rootPassword` param as shown above.

You can retrieve your root password by running the following command. Make sure to replace [YOUR_RELEASE_NAME] and [YOUR_NAMESPACE]:

Expand Down Expand Up @@ -77,7 +77,7 @@ Once MySQL is running, you can populate it with some data. Let's add a table cal

```bash
# Connect to MySQL by running a shell inside MySQL's pod
$ kubectl exec -ti $(kubectl get pods -n mysql-test --selector=release=mysql-release -o=jsonpath='{.items[0].metadata.name}') -n mysql-test -- bash
$ kubectl exec -ti $(kubectl get pods -n mysql-test --selector=app.kubernetes.io/instance=mysql-release -o=jsonpath='{.items[0].metadata.name}') -n mysql-test -- bash

# From inside the shell, use the mysql CLI to insert some data into the test database
# Create "test" db
Expand Down Expand Up @@ -138,7 +138,7 @@ $ kubectl --namespace kanister describe actionset backup-rslmb
Let's say someone accidentally deleted the test database using the following command:
```bash
# Connect to MySQL by running a shell inside MySQL's pod
$ kubectl exec -ti $(kubectl get pods -n mysql-test --selector=app=mysql-release -o=jsonpath='{.items[0].metadata.name}') -n mysql-test -- bash
$ kubectl exec -ti $(kubectl get pods -n mysql-test --selector=app.kubernetes.io/instance=mysql-release -o=jsonpath='{.items[0].metadata.name}') -n mysql-test -- bash

$ mysql --user=root --password=asd#45@mysqlEXAMPLE

Expand Down

0 comments on commit 5305b92

Please sign in to comment.