Skip to content

Instantly share code, notes, and snippets.

@baijum
Forked from trisberg/three-bindings.adoc
Created October 24, 2020 13:56
Show Gist options
  • Save baijum/bf1230889748ceb2f8990550964aecfc to your computer and use it in GitHub Desktop.
Save baijum/bf1230889748ceb2f8990550964aecfc to your computer and use it in GitHub Desktop.
A tale of three database backing service bindings

A tale of three database backing service bindings

Important

This document is deprecated, you want to look at A tale of four backing service bindings instead.

Introduction

How does Cody connect his function or app to a backing service? First off, what do we mean by backing service?

A backing service is any service the app consumes over the network as part of its normal operation. Examples include datastores (such as MySQL or CouchDB), messaging/queueing systems (such as RabbitMQ or Beanstalkd), SMTP services for outbound email (such as Postfix), and caching systems (such as Memcached).
https://12factor.net/backing-services

Cody can provision a backing service in a variety of ways and we might have to adjust how we bind to them based on the way they actually are provisioned.

To allow for several ways of provisioning the service we can introduce a Binding object to hold the information that is needed for a succesfull binding and we can populate this object in different ways depending on the way the service was provisioned.

The Binding object might contain fields like:

- name
- uri
- jdbcUrl
- databaseName
- username
- secretReference
- passwordKey

The Binding resource might look something like this:

apiVersion: service.projectriff.io/v1alpha1
kind: Binding
metadata:
  name: mypets
  namespace: demo
spec:
  connection:
    uri: mysql://mypets-mysql.demo.svc.cluster.local:3306/petclinic
    username: riff
  secretReference:
    name: mypets-mysql
    passwordKey: mysql-password

Most of the work is going to be in the area of mapping and providing the connection properties needed by the app based on data provided by the service bindings and secrets and any additional info provided by the user.

Service Provisioning and Binding

Helm

Cody can create a new database using the following Helm command:

helm install --name mypets --namespace demo \
  --set mysqlUser=riff --set mysqlDatabase=petclinic stable/mysql

We can see the following in the NOTES section when the chart is executed :

MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
mypets-mysql.demo.svc.cluster.local

This gives us most of the info we need to bind to the new database. The uri can be constructed by using mysql://<service-host>:<service-port>/<database>

The only missing piece is the generated password. When the chart is executed it also creates a secret named mypets-mysql with mysql-password and mysql-root-password keys, so this should give us all that we need.

Now Cody can create the service binding:

riff binding create mypets --namespace demo --secret-ref mypets-mysql \
  --uri mysql://mypets-mysql.demo.svc.cluster.local:3306/petclinic \
  --username riff \
  --password-key mysql-password

Service Catalog with ksm-broker

Note

We are using a slightly modified MySQL chart for this example. Starting with tke kibosh-sample mysql chart we are then adding database name and username to the binding/secret that is generated.

Cody can provision the database using the svcat CLI:

svcat provision mypets --namespace demo --class mysql --plan small \
  --params-json '{"mysqlUser": "riff", "mysqlDatabase": "petclinic"}'

He can then check on the status:

$ svcat get instances --namespace demo
   NAME    NAMESPACE   CLASS   PLAN    STATUS
+--------+-----------+-------+-------+--------+
  mypets   demo        mysql   small   Ready

Next Cody creates the Service Catalog binding:

svcat bind mypets --name mypets --namespace demo

This command creates a servicebinding.servicecatalog.k8s.io object as well as a regular Secret named mypets in the demo namespace.

Depending on the broker and offer that was used to provision the service there might be enough information available in the ServiceBinding to connect to the service, but if there is not we can use the Secret and create a binding.service.projectriff.io object that has all the information.

riff binding create mypets --namespace demo --secret-ref mypets \
  --uri-key uri \
  --jdbc-url-key jdbcUrl \
  --username-key username \
  --password-key password

Crossplane

Crossplane provides a way to provision a database in addition to all other features that it provides. We’ll provision a MySQL database using GCP Cloud SQL in this example.

Note
We’ll use the experimental "xpl" CLI generated by Mark Fisher

Alana has already configured Crossplane so Cody can now simply provision a database:

xpl resource create mypets -t mysql -c standard -n demo

This command should create a MySQLInstance resource like this:

apiVersion: storage.crossplane.io/v1alpha1
kind: MySQLInstance
metadata:
  name: mypets
  namespace: demo
spec:
  classReference:
    name: standard-mysql
    namespace: crossplane-system
  engineVersion: "5.7"

This also creates a secret that has the following content:

apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: mypets-database
  namespace: demo
data:
  endpoint: MTAuMTEuMTIuMTM=
  password: ZYbnFQVnZ180UnlSQXI4MlBuTk44OWlmQWdB
  username: cm9vdA==

Using the information in the secret Cody can create the following binding:

riff binding create mypets --namespace demo --secret-ref mypets-database \
  --host-key endpoint \
  --port 3306 \
  --username-key username \
  --password-key password

What about ISM?

We’ll add some coverage of ISM once that project gets to an alpha release.

What about other types of services?

Yes, we’ll need to add some coverage of services like MongoDB, Redis, Rabbit MQ etc.

Deploying Functions and Apps

When Cody deploys a function or an app he can simply reference the binding that he created earlier. Let’s see what Binding resources we have available:

$ kubectl get bindings.service.projectriff.io
NAME     URI                                                          SECRET
mypets   mysql://mypets-mysql.demo.svc.cluster.local:3306/petclinic   mypets-mysql
Note

The binding-type defines how the connection properties are bound. Selecting vcap would create a VCAP_SERVICES environment variable similar to what is currently provided in Cloud Foundry Application Runtime. Selecting spring-boot will create Spring Boot style environment variables like SPRING_DATASOURCE_USERNAME, SPRING_DATASOURCE_PASSWORD etc. for the connection properties.

Since Codey is deploying a Spring Boot based function he selects spring-boot as the binding type.

riff handler create pets --namespace demo \
  --function-ref pets \
  --binding-ref mypets \
  --binding-type spring-boot

Cody should now have the pets function deployed and connected to the provisioned database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment