= Kubernetes Simple Database Provisioner
:toc:
[link=http://www.apache.org/licenses/LICENSE-2.0.txt]
image::.images/license-apache.svg[License: Apache License 2.0]
image::.images/simple-database-provisioner.svg[alt=Simple Database Provisioner,width=200]
The simple database provisioner allows to create and remove databases and user credentials (secretes) via
kubernetes ressources on an existing DBMS server.
It was created as a simpler and more resilient alternative to setting up databases with OSBA.
== Status
**CURRENT STATUS: ALPHA**
Not intended for production use yet. Tests, refactoring
and updating the documentation are missing.
== Concept
* DBMS servers have to be created by some other tool (e.g. manually, or terraform)
* DBMS servers are identified in the config via a unique name and a secret with
the connection information
* DBMS management is (currently) static and requires a pod restart
* Database Instance and Binding management is dynamic via two Custom Resource Definitions
== Installation
There is a helm chart provided so you can easily install it in your
cluster.
1. Set up a postgres database server manually somehow and have the
credentials ready. The user must be able to create databases and
roles.
2. Create a secret with these credentials. (all values are base64
encoded, as usual). See `examples/dev-postgres-secret.yaml` for
an example kubernetes resource definition. The **metadata -> name**
will be the identifier with which you can later assign some databases
onto that dbms server.
3. Enter the directory `helm/simple-database-provisioner` and execute
helm -n sdp sync --name "simple-database-provisioner" .
Now watch the logs and create/delete some resources (e.g. from the `examples` folder, to verify functionality and to get used to it.
== Configuration
=== Application Config File
**config.yaml**
```yaml
dbmsServers:
dev-postgres:
secret: dev-postgres-secret
persistence:
type: file
location: ./sdp.db.yaml
```
=== Database Format (DRAFT)
The database format currently is only a rough draft and might
change during development according to the needs (e.g. list instead
of map, etc.).
```yaml
namespaces:
master:
instances:
mynamespace-myservice-database:
dbmsServer: dev-postgres
databaseName: mynamespace-myservice
bindings:
mynamespace-myservice-binding:
instanceName: mynamespace-myservice-database
secretName: mynamespace-myservice-database-secret
```
=== DBMS Secret
```yaml
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: dbms-dev-postgres-secret
data:
database: cG9zdGdyZXM=
host: cG9zdGdyZXMtcG9zdGdyZXNxbA==
password: WkthNWE4Y0w0Yg==
port: NTQzMg==
ssl: ZmFsc2U=
user: cG9zdGdyZXM=
```
== Custom Resource Definitions
==== CDR: SimpleDatabaseInstance
```yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: simpledatabaseinstances.simpledatabaseprovisioner.k8s.ecodia.de
spec:
group: simpledatabaseprovisioner.k8s.ecodia.de
version: v1alpha1
scope: Namespaced
conditions:
stored_versions: []
names:
plural: simpledatabaseinstances
singular: simpledatabaseinstance
kind: SimpleDatabaseInstance
shortNames:
- sdi
```
**Example**
```yaml
apiVersion: simpledatabaseprovisioner.k8s.ecodia.de/v1alpha1
kind: SimpleDatabaseInstance
metadata:
name: sample-application-database
spec:
dbmsServer: dbms-dev-postgres
databaseName: sample-application-database
```
==== CDR: SimpleDatabaseBinding
```yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: simpledatabasebindings.simpledatabaseprovisioner.k8s.ecodia.de
spec:
group: simpledatabaseprovisioner.k8s.ecodia.de
version: v1alpha1
scope: Namespaced
names:
plural: simpledatabasebindings
singular: simpledatabasebinding
kind: SimpleDatabaseBinding
shortNames:
- sdb
```
**Example**
```yaml
apiVersion: simpledatabaseprovisioner.k8s.ecodia.de/v1alpha1
kind: SimpleDatabaseBinding
metadata:
name: sample-application-binding
spec:
instanceName: sample-application-database
secretName: sample-application-database-secret
```
== Development
This controller is based on the kubernetes samplecontroller:
https://github.com/kubernetes/sample-controller
=== Hands on
Let's jump right into some hands on commands
==== Run the controller
* The controller automatically detects if it is run inside a
cluster or can connect to a cluster via the kubernetes api
* start minikube
* run controller.py , then load the example resources and watch
how events are read
kubectl apply -f examples/sdi-example.yaml
kubectl apply -f examples/sdb-example.yaml
==== Delete databases and bindings
For testing purposes it might be necessary to remove the instances and bindings:
kubectl delete sdi/sample-application-database
kubectl delete sdb/sample-application-binding
==== Delete Custom Resource Definitions
For testing purposes it might be necessary to remove the custom resource definitions:
kubectl delete crd/simpledatabasebindings.simpledatabaseprovisioner.k8s.ecodia.de
kubectl delete crd/simpledatabaseinstances.simpledatabaseprovisioner.k8s.ecodia.de
=== Run tests
To run the tests you need minikube and a postgres database
with the correct user credentials:
minikube start
docker run --rm --name sdp-postgres-testdb -p 5432:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres postgres
Then start the tests with:
go test simple-database-provisioner...
=== Generate custom resource types
The simple-database-provisioner controller is based on https://github.com/kubernetes/sample-controller .
It makes use of the generators in k8s.io/code-generator to generate a typed client, informers, listers and deep-copy functions. You can do this yourself using the ./hack/update-codegen.sh script.