Quick Start Guide
The goal of this quick start guide is to:
-
Provide an overview of Service Binding Operator.
-
Provide a list of prerequisites to be configured on your Kubernetes cluster.
-
Create a PostgreSQL database instance
-
Deploy the application
-
Connect the application to the database with Service Binding
For this quick start, we are using a PostgreSQL database and a simple application using the Spring Boot REST API server sample. This will allow you to understand how Service Binding Operator can be used to simplify the connection between a service, like a database and the application.
To illustrate what we are going to do, here is a visual representation of the application we are going to setup.
In this configuration, we leverage the service binding operator, to collect the binding data from the PostgreSQL database and project them into the sample application.
Before starting, we invite you to refer to the Prerequisites section to make sure you have all the needed components configured on your K8s cluster.
The quick start consists of three main steps:
Prerequisites
In order to follow the quick start, you’ll need the following tools installed and configured:
-
Kubernetes cluster
-
PostgreSQL client (
psql
CLI tool)
Create a PostgreSQL database instance
The application is going to use to a PostgreSQL database backend which
can be setup using the v5
channel of
Crunchy PostgreSQL operator
from OperatorHub.io. We just need to make sure that the operator is
availabe in our my-postgresql
namespace.
The installation of the operator doesn’t create a database instance itself, so we need to create one.
-
To create a database instance, you need to create custom resource
PostgresCluster
and that will trigger the operator reconciliation. For convenience, run this command to createPostgresCluster
custom resource: -
Once the database is created, we need to ensure all the pods in
my-postgresql
namespace are running (it will take few minutes):kubectl get pod -n my-postgresql
You should see output something like this:
NAME READY STATUS RESTARTS AGE hippo-backup-6th6--1-28849 0/1 Completed 0 1m hippo-instance1-sl4r-0 2/2 Running 0 2m hippo-pgbouncer-8454474bc7-lhcn9 2/2 Running 0 2m pgo-84b9679484-79c6m 1/1 Running 0 3m
The database has been created and is empty at this stage. We now need to set its schema and we will also project a sample data set, so we can play around with the application.
-
You can initialize the database with the schema and sample data using this command:
We have now finished to configured the database for the application. We are ready to deploy the sample application and connect it to the database.
Deploy the sample application
In this section, we are going to deploy the application on our kubernetes cluster. For that, we will use a deployment configuration and do the configuration of our local environment to be able to test the application.
-
Deploy the
spring-petclinic-rest
app with thisDeployment
configuration: -
Let’s now setup the port forwarding from the application port so we can access it from our local environment
kubectl port-forward --address 0.0.0.0 svc/spring-petclinic-rest 9966:80 -n my-postgresql
-
You should be able to open http://localhost:9966/petclinic and see a Swagger UI where you can play with the API.
At this stage, the application is not yet connected to the database. So, if you try to play around the APIs, you’ll see errors returned by the application.
For example, if you try to access the list of all pets, you can see an error like this:
curl -X GET "http://localhost:9966/petclinic/api/pets" -H "accept: application/json"
{"className":"org.springframework.transaction.CannotCreateTransactionException","exMessage":"Could
not open JPA EntityManager for transaction; nested exception is
org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC
Connection"}
Now, we are going to see how you can use Service Binding to easily connect the application to the database.
Connect the application to the database
Suppose the Service Binding operator is not present. In that case, the application’s admin needs to extract all the configuration details and create a Secret resource and expose it to the application through volume mount in Kubernetes. The steps would be something like this:
-
Identify the required values for connecting the application to the database
-
Locate the resources where the values are present
-
Take the values from different resources and create a Secret resource
-
Mount the Secret resource into the application
-
Depending on the application requirement the values should be exposed as env var or file.
In this quick start, we are going to leverage Service Binding as a way to easily and safely connect the application to the database service. In order to do that, we’ll need to create a Service Binding resource which will trigger the Service Binding Operator to project the binding datas into the application.
-
Create the ServiceBinding resource to project the binding data:
The
.spec
has two sections. The first is a list of service resources (.spec.services
), and the second one is the application (.spec.application
). The services resources points to the database’s service resources. How the values are exposed from service resources are explained Introduction section. The application points to aDeployment
or any resource that is PodSpec compatible.apiVersion: binding.operators.coreos.com/v1alpha1 kind: ServiceBinding metadata: name: spring-petclinic-rest namespace: my-postgresql spec: services: - group: postgres-operator.crunchydata.com version: v1beta1 kind: PostgresCluster name: hippo application: name: spring-petclinic-rest group: apps version: v1 resource: deployments
For simplicity, you can copy/paste the following command to create the resource:
To check if the binding was successful you can check the binding resource status conditions by the following command:
kubectl get servicebindings spring-petclinic-rest -n my-postgresql -o jsonpath-as-json='{.status.conditions}'
You should see output something like:
[ [ { "lastTransitionTime": "2021-09-06T13:42:28Z", "message": "", "reason": "DataCollected", "status": "True", "type": "CollectionReady", }, { "lastTransitionTime": "2021-09-06T13:42:28Z", "message": "", "reason": "ApplicationUpdated", "status": "True", "type": "InjectionReady", }, { "lastTransitionTime": "2021-09-06T13:42:28Z", "message": "", "reason": "ApplicationsBound", "status": "True", "type": "Ready", }, ], ]
To learn more about creating service bindings, you can find more information on the following document
By creating this
Service Binding
resource, we now have values from the database’s binding data projected into the application container as files (that’s the default behavior, but you can also project environment variables if you prefer). If you check under/bindings/spring-petclinic-rest
directory you’ll see all the values from the secret resource projected there. In the above example, you’ll findusername
andpassword
. And the values pointed out through the annotation are also projected which includesdatabase
,host
, andport
. Finallytype
is also projected which is required for connectity.. The application looks forSERVICE_BINDING_ROOT
env var to find the location of/bindings
directory. The Spring Boot application used here is built using Spring Cloud Bindings and it looks forSERVICE_BINDING_ROOT
to get the projected binding data. See the using projected binding data section about how the values can be used from the application.To verify that binding was successful and that the files in the application contain the expected content, you can use the following script to inspect the deployment:
for i in username password host port type; do kubectl exec -it deploy/spring-petclinic-rest -n my-postgresql -- /bin/bash -c 'find /bindings/*/'$i' -exec echo -n {}:" " \; -exec cat {} \;'; echo done
You should see output something like:
/bindings/spring-petclinic-rest/username: hippo /bindings/spring-petclinic-rest/password: w0ZB<0j1W|K;+4*TlK7-w^z/ /bindings/spring-petclinic-rest/host: hippo-pgbouncer /bindings/spring-petclinic-rest/port: 5432 /bindings/spring-petclinic-rest/type: postgresql
-
Let’s now check how the application is behaving and setup the port forwarding of the application port to access it from our local environment
kubectl port-forward --address 0.0.0.0 svc/spring-petclinic-rest 9966:80 -n my-postgresql
-
Open http://localhost:9966/petclinic, you should see a Swagger UI where you can play with the API.
If you try to access list of all pets, you can see the application is now connected to the database and see the sample data initially configured:
$ curl -X GET "http://localhost:9966/petclinic/api/pets" -H "accept: application/json" [{"id":1,"name":"Leo","birthDate":"2000/09/07","type":{"id":1,"name":"cat"}, "owner":{"id":1,"firstName":"George","lastName":"Franklin","address":"110...
Next Steps
In this sample, we setup a database and connected it to an application using the Service Binding operator to collect the connection metadata and expose them to the application.
By using service bindings, developers are able to more easily leverage the services available to them on a Kubernetes cluster. This method provides consistency accross different services and is repeatable for the developers. By remove the usual manual and error prone configuration, they benefit from a unified way to do application-to-service linkage.
You can continue to learn more about Service Binding by: