-
Notifications
You must be signed in to change notification settings - Fork 148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mongodb percona #1742
base: master
Are you sure you want to change the base?
Mongodb percona #1742
Changes from all commits
722edf6
6b7ed64
ba86d6c
716a42a
53a9a69
26e6a0b
8de0fdc
84e697c
2e8d1c4
5ac5f79
74bdfb8
2b7e55b
e1e26fd
42dbcc9
be6d991
15129e1
0258d01
9c960c5
a5fc6f7
7cd5982
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,318 @@ | ||||
# MongoDB | ||||
|
||||
[MongoDB](https://www.mongodb.com/) is a cross-platform document-oriented | ||||
database. Classified as a NoSQL database, MongoDB eschews the traditional | ||||
table-based relational database structure in favor of JSON-like documents with | ||||
dynamic schemas, making the integration of data in certain types of | ||||
applications easier and faster. | ||||
|
||||
## Prerequisites | ||||
|
||||
* Kubernetes 1.20+ | ||||
* PV support on the underlying infrastructure | ||||
* Kanister controller version 0.84.0 installed in your cluster | ||||
* Kanctl CLI installed (https://docs.kanister.io/tooling.html#kanctl) | ||||
|
||||
## Operator Details | ||||
|
||||
We will be using [percona operator for Mongodb](https://docs.percona.com/percona-operator-for-mongodb/index.html). | ||||
The blueprint follows backup and restore workflows as described in the | ||||
[backup/restore documentation](https://docs.percona.com/percona-operator-for-mongodb/backups.html) of the operator. | ||||
|
||||
## Limitations | ||||
|
||||
For simplicity, we did not patch the `PerconaServerMongoDB` object with the | ||||
`profiles.cr.kanister.io` to define the backup target. Instead, we can use the | ||||
`storages` section to define it along with a secret reference to a secret that | ||||
defines the `AWS_ACCESS_KEY_ID` and the `AWS_SECRET_ACCESS_KEY` keys: | ||||
```yaml | ||||
storages: | ||||
my-s3-storage: | ||||
type: s3 | ||||
s3: | ||||
bucket: my-bucket | ||||
credentialsSecret: s3-secret | ||||
region: eu-west-3 | ||||
prefix: "mongodb/my-cluster-name/" | ||||
uploadPartSize: 10485760 | ||||
maxUploadParts: 10000 | ||||
storageClass: STANDARD | ||||
insecureSkipTLSVerify: false | ||||
``` | ||||
|
||||
Those values need to be defined (this section and the s3-secret) before | ||||
executing the blueprint. | ||||
|
||||
## Install the Operator and Create a Cluster | ||||
|
||||
Edit the `cr.yaml` to ensure the backup/storages section (line 443) is | ||||
consistent with your s3 target. The following may be changed: | ||||
- the region | ||||
- the bucket name | ||||
- the endpoint | ||||
- the prefix | ||||
- ... | ||||
|
||||
Also, define the ENV variables for `AWS_S3_ACCESS_KEY_ID` and | ||||
`AWS_SECRET_ACCESS_KEY` according to requirements. | ||||
|
||||
These values can't be obtained from a Kanister profile as they need to be | ||||
defined in the `PerconaServerMongoDB` object itself before running any Kanister | ||||
actions (see Limitations). | ||||
|
||||
```bash | ||||
kubectl create namespace mongodb | ||||
kubectl config set-context --current --namespace=mongodb | ||||
kubectl apply -f https://raw.githubusercontent.com/percona/percona-server-mongodb-operator/v1.13.0/deploy/bundle.yaml | ||||
kubectl create secret generic s3-secret --from-literal AWS_ACCESS_KEY_ID=$AWS_S3_ACCESS_KEY_ID --from-literal AWS_SECRET_ACCESS_KEY=$AWS_S3_SECRET_ACCESS_KEY | ||||
kubectl apply -f cr.yaml | ||||
``` | ||||
|
||||
Check the status of the mongodb cluster | ||||
```bash | ||||
kubectl get psmdb | ||||
``` | ||||
|
||||
**NOTE:** | ||||
|
||||
We can also enable point-in-time restore (PITR) for this cluster | ||||
|
||||
```yaml | ||||
pitr: | ||||
enabled: true | ||||
compressionType: gzip | ||||
compressionLevel: 6 | ||||
``` | ||||
|
||||
## Integrating with Kanister | ||||
|
||||
If the operator is deployed with a name other than `my-cluster-name`, and a | ||||
namespace other than `mongodb`, modify the commands used below to use the | ||||
correct 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 mongodb | ||||
``` | ||||
|
||||
**NOTE:** | ||||
|
||||
The 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. | ||||
|
||||
**NOTE:** | ||||
|
||||
The profile is actually useless in this case but mandatory for executing kanister action. | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, this is no longer the case |
||||
|
||||
|
||||
### Create Blueprint | ||||
Create Blueprint in the same namespace as the controller | ||||
|
||||
```bash | ||||
$ kubectl create -f psmdb-bp.yaml -n kasten-io | ||||
``` | ||||
|
||||
Once MongoDB is running, populate it with some data. Let's add a collection | ||||
called "ticker": | ||||
|
||||
```bash | ||||
MONGODB_DATABASE_ADMIN_PASSWORD=$(kubectl get secret my-cluster-name-secrets -ojsonpath='{.data.MONGODB_DATABASE_ADMIN_PASSWORD}'|base64 -d) | ||||
MONGODB_DATABASE_ADMIN_USER=$(kubectl get secret my-cluster-name-secrets -ojsonpath='{.data.MONGODB_DATABASE_ADMIN_USER}'|base64 -d) | ||||
kubectl run -i --rm --tty percona-client \ | ||||
--image=percona/percona-server-mongodb:4.4.16-16 \ | ||||
--env=MONGODB_DATABASE_ADMIN_PASSWORD=$MONGODB_DATABASE_ADMIN_PASSWORD \ | ||||
--env=MONGODB_DATABASE_ADMIN_USER=$MONGODB_DATABASE_ADMIN_USER \ | ||||
--restart=Never \ | ||||
-- bash -il | ||||
mongo "mongodb://$MONGODB_DATABASE_ADMIN_USER:$MONGODB_DATABASE_ADMIN_PASSWORD@my-cluster-name-mongos.mongodb.svc.cluster.local/admin?ssl=false" | ||||
``` | ||||
|
||||
Insert some data | ||||
```bash | ||||
db.createCollection("ticker") | ||||
db.ticker.insert( {createdAt: new Date(), randomdata: "qstygshgqsfxxtqsfgqfhjqhsj"} ) | ||||
db.ticker.insert( {createdAt: new Date(), randomdata: "qstygshgqsfxxtqsfgqfhjqhsj"} ) | ||||
db.ticker.insert( {createdAt: new Date(), randomdata: "qstygshgqsfxxtqsfgqfhjqhsj"} ) | ||||
db.ticker.insert( {createdAt: new Date(), randomdata: "qstygshgqsfxxtqsfgqfhjqhsj"} ) | ||||
db.ticker.find({}).sort({createdAt:-1}).limit(1) | ||||
``` | ||||
|
||||
In order to test Point-In-Time Restore (PITR), create a ticker pod that adds | ||||
a new entry every second. | ||||
|
||||
```bash | ||||
MONGODB_DATABASE_ADMIN_PASSWORD=$(kubectl get secret my-cluster-name-secrets -ojsonpath='{.data.MONGODB_DATABASE_ADMIN_PASSWORD}'|base64 -d) | ||||
MONGODB_DATABASE_ADMIN_USER=$(kubectl get secret my-cluster-name-secrets -ojsonpath='{.data.MONGODB_DATABASE_ADMIN_USER}'|base64 -d) | ||||
kubectl run percona-ticker \ | ||||
--image=percona/percona-server-mongodb:4.4.16-16 \ | ||||
--env=MONGODB_DATABASE_ADMIN_PASSWORD=$MONGODB_DATABASE_ADMIN_PASSWORD \ | ||||
--env=MONGODB_DATABASE_ADMIN_USER=$MONGODB_DATABASE_ADMIN_USER \ | ||||
-- bash -c "while true; do mongo \"mongodb://$MONGODB_DATABASE_ADMIN_USER:$MONGODB_DATABASE_ADMIN_PASSWORD@my-cluster-name-mongos.mongodb.svc.cluster.local/admin?ssl=false\" --eval 'db.ticker.insert( {createdAt: new Date(), randomdata: \"qstygshgqsfxxtqsfgqfhjqhsj\"} )'; sleep 1; done" | ||||
``` | ||||
|
||||
Reuse the percona-client to check if a new entry is created every second. | ||||
Execute this command multiple times. | ||||
```bash | ||||
db.ticker.find({}).sort({createdAt:-1}).limit(1) | ||||
``` | ||||
|
||||
**NOTE:** | ||||
|
||||
If the storage name is changed to something other than `my-s3-storage` in the | ||||
`cr.yaml` file, change this name in the blueprint accordingly. | ||||
|
||||
## Protect the Application | ||||
|
||||
The MongoDB data can be backed up using an ActionSet defining backup for this | ||||
application. Create an ActionSet in the same namespace as the controller. | ||||
|
||||
```bash | ||||
$ kubectl get profiles.cr.kanister.io -n mongodb | ||||
NAME AGE | ||||
s3-profile-bvc8k 2h | ||||
Comment on lines
+174
to
+176
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We may not need this |
||||
|
||||
$ kanctl create actionset \ | ||||
--action backup --namespace kasten-io \ | ||||
--blueprint psmdb-bp \ | ||||
--profile mongodb/s3-profile-bvc8k \ | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
--objects psmdb.percona.com/v1/perconaservermongodbs/mongodb/my-cluster-name | ||||
|
||||
$ kubectl --namespace kasten-io get actionsets.cr.kanister.io | ||||
NAME AGE | ||||
backup-vvskw 2h | ||||
|
||||
# View the status of the actionset | ||||
$ kubectl --namespace kasten-io describe actionset backup-vvskw | ||||
``` | ||||
|
||||
### Disaster Strikes! | ||||
|
||||
Let's say someone accidentally deleted the mongo cluster and all the PVCs: | ||||
```bash | ||||
kubectl delete psmdb my-cluster-name | ||||
kubectl delete po percona-ticker | ||||
kubectl delete pvc --all | ||||
``` | ||||
|
||||
All the pods and PVCs are now gone. Recreate the cluster | ||||
```bash | ||||
kubectl apply -f cr.yaml | ||||
``` | ||||
|
||||
Check if the cluster is now ready | ||||
```bash | ||||
kubectl get psmdb | ||||
``` | ||||
|
||||
The data in the database is no longer there: | ||||
```bash | ||||
MONGODB_DATABASE_ADMIN_PASSWORD=$(kubectl get secret my-cluster-name-secrets -ojsonpath='{.data.MONGODB_DATABASE_ADMIN_PASSWORD}'|base64 -d) | ||||
MONGODB_DATABASE_ADMIN_USER=$(kubectl get secret my-cluster-name-secrets -ojsonpath='{.data.MONGODB_DATABASE_ADMIN_USER}'|base64 -d) | ||||
kubectl run -i --rm --tty percona-client \ | ||||
--image=percona/percona-server-mongodb:4.4.16-16 \ | ||||
--env=MONGODB_DATABASE_ADMIN_PASSWORD=$MONGODB_DATABASE_ADMIN_PASSWORD \ | ||||
--env=MONGODB_DATABASE_ADMIN_USER=$MONGODB_DATABASE_ADMIN_USER \ | ||||
--restart=Never \ | ||||
-- bash -il | ||||
mongo "mongodb://$MONGODB_DATABASE_ADMIN_USER:$MONGODB_DATABASE_ADMIN_PASSWORD@my-cluster-name-mongos.mongodb.svc.cluster.local/admin?ssl=false" | ||||
``` | ||||
|
||||
There should be no output when trying to query the ticker collections | ||||
```bash | ||||
db.ticker.find({}).sort({createdAt:-1}).limit(1) | ||||
``` | ||||
|
||||
|
||||
### Restore the Application | ||||
|
||||
To restore the missing data, use the backup created earlier. An easy way to do | ||||
this is to leverage `kanctl`, a command-line tool that helps create ActionSets | ||||
that depend on other ActionSets: | ||||
|
||||
|
||||
```bash | ||||
$ kanctl --namespace kasten-io create actionset --action restore --from "backup-vvskw" | ||||
actionset restore-backup-vvskw-sfpm6 created | ||||
|
||||
# View the status of the ActionSet | ||||
kubectl --namespace kasten-io describe actionset restore-backup-vvskw-sfpm6 | ||||
``` | ||||
|
||||
The data should now be successfully restored to MongoDB! | ||||
|
||||
```bash | ||||
db.ticker.find({}).sort({createdAt:-1}).limit(1) | ||||
{ "_id" : ObjectId("637372caf98744ac5a6e4aae"), "createdAt" : ISODate("2022-11-15T11:06:50.296Z"), "randomdata" : "qstygshgqsfxxtqsfgqfhjqhsj" } | ||||
``` | ||||
|
||||
#### Point-In-Time Restore | ||||
|
||||
Let's say the backup was at 15th Nov 2022 at 15:11 and we want to restore at a | ||||
specific point in time after the backup at 15:13:10 the same day | ||||
|
||||
```bash | ||||
kanctl --namespace kasten-io create actionset --action restore --from "backup-vvskw" --options pitr="2022-11-15 15:13:10" | ||||
``` | ||||
|
||||
### Delete the Artifacts | ||||
|
||||
The artifacts created by the backup action can be cleaned up using the | ||||
following command: | ||||
|
||||
```bash | ||||
$ kanctl --namespace kasten-io create actionset --action delete --from "backup-vvskw" | ||||
actionset delete-backup-vvskw-xh29t created | ||||
|
||||
# View the status of the ActionSet | ||||
$ kubectl --namespace kasten-io describe actionset delete-backup-vvskw-xh29t | ||||
``` | ||||
|
||||
**NOTE:** | ||||
|
||||
To have the delete action working, we need the operator up and running. | ||||
|
||||
### Troubleshooting | ||||
|
||||
In case of issues with the above commands, check the logs of the controller | ||||
using: | ||||
|
||||
```bash | ||||
$ kubectl --namespace kasten-io logs -l app=kanister-operator | ||||
``` | ||||
|
||||
Check events of the ActionSet | ||||
|
||||
```bash | ||||
$ kubectl describe actionset restore-backup-vvskw-sfpm6 -n kasten-io | ||||
``` | ||||
|
||||
## Uninstalling the Operator and the Blueprint | ||||
|
||||
To uninstall/delete the mongodb cluster and the operator: | ||||
|
||||
```bash | ||||
kubectl delete psmdb my-cluster-name | ||||
kubectl delete po percona-ticker | ||||
kubectl delete pvc --all | ||||
kubectl delete -f https://raw.githubusercontent.com/percona/percona-server-mongodb-operator/v1.13.0/deploy/bundle.yaml | ||||
kubectl delete ns mongodb | ||||
``` | ||||
|
||||
The command removes all the Kubernetes components associated with the operator | ||||
and deletes the `mongodb` namespace. | ||||
|
||||
Delete Blueprint and Profile CR | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will change if we remove the profile requirement |
||||
|
||||
```bash | ||||
$ kubectl delete blueprints.cr.kanister.io psmdb-bp -n kasten-io | ||||
|
||||
$ kubectl get profiles.cr.kanister.io -n mongodb | ||||
NAME AGE | ||||
s3-profile-bvc8k 2h | ||||
|
||||
$ kubectl delete profiles.cr.kanister.io s3-profile-bvc8k -n mongodb | ||||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@michaelcourcy we can skip this section IIUC. We are defining the storage section in the database backup spec, right?
I verified that we have removed the requirement to define a profile to execute actionset
^^ this is during rendering the action - ref:
param.go:fetchProfile()
Let me know if you are seeing an error. May be this is a downstream restriction but Kanister should work without one 🤔