Getting started with service binding
- Creating a PostgreSQL database instance
- Deploying the Spring PetClinic sample application
- Connecting the Spring PetClinic sample application to the PostgreSQL database service
- Additional Resources
Service Binding Operator manages the data plane for workloads and backing services. This guide provides instructions with examples to help you create a database instance, deploy an application, and use Service Binding Operator to create a binding connection between the application and the database service.
Prerequisites
You have access to an OKD cluster using an account with
cluster-admin
permissions.You have installed the
oc
CLI.You have installed PostgreSQL
psql
CLI.You have installed Service Binding Operator from OperatorHub.
You have installed the Crunchy Postgres for Kubernetes Operator from OperatorHub using the v5 Update channel. The installed Operator is available in an appropriate namespace, such as the
my-postgresql
namespace.
Creating a PostgreSQL database instance
To create a PostgreSQL database instance, you must create a PostgresCluster
custom resource (CR) and configure the database.
Procedure
Create the
PostgresCluster
CR and themy-postgresql
namespace by running the following command in shell:$ oc apply -f - << EOD
---
apiVersion: v1
kind: Namespace
metadata:
name: my-postgresql
---
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: hippo
namespace: my-postgresql
annotations:
service.binding: 'path={.metadata.annotations.dbsecret},objectType=Secret'
dbsecret: hippo-pguser-hippo
proxy: hippo-pgbouncer
type: postgresql
service.binding/database: path={.metadata.name}
service.binding/port: path={.spec.port}
service.binding/username: path={.metadata.name}
service.binding/host: path={.metadata.annotations.proxy}
service.binding/type: path={.metadata.annotations.type}
spec:
image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.4-0
postgresVersion: 13
instances:
- name: instance1
dataVolumeClaimSpec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 1Gi
backups:
pgbackrest:
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-2
repos:
- name: repo1
volume:
volumeClaimSpec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 1Gi
- name: repo2
volume:
volumeClaimSpec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 1Gi
proxy:
pgBouncer:
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbouncer:centos8-1.15-2
EOD
The annotations added in this
PostgresCluster
CR help in enabling the service binding connection and trigger the Operator reconciliation.The output verifies that the database instance is created:
Example output
namespace/my-postgresql configured
postgrescluster.postgres-operator.crunchydata.com/hippo created
After you have created the database instance, ensure that all the pods in
my-postgresql
namespace are running (it will take a few minutes):$ oc get pods -n my-postgresql
The output verifies that the database is created:
Example output
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
The new database is empty at this stage. You can set its schema and project a sample data set to interact with the sample application.
Initialize the database with the schema and sample data. To do so, use the following custom shell script by copying the code into the shell and running it:
$ cat << EOD | bash
#!/bin/bash
export pgo_cluster_name=hippo
export cluster_namespace=my-postgresql
export pgo_cluster_username=hippo
export PGPASSWORD=\$(oc -n "\${cluster_namespace}" get secrets \
"\${pgo_cluster_name}-pguser-\${pgo_cluster_username}" -o "jsonpath={.data['password']}" | base64 -d)
nohup oc -n \${cluster_namespace} port-forward svc/hippo-pgbouncer 5432:5432 &
sleep 5
curl -LO https://raw.githubusercontent.com/spring-petclinic/spring-petclinic-rest/master/src/main/resources/db/postgresql/initDB.sql
psql -h localhost -U "\${pgo_cluster_username}" "\${pgo_cluster_name}" -f initDB.sql
curl -LO https://raw.githubusercontent.com/spring-petclinic/spring-petclinic-rest/master/src/main/resources/db/postgresql/populateDB.sql
psql -h localhost -U "\${pgo_cluster_username}" "\${pgo_cluster_name}" -f populateDB.sql
EOD
The output in the terminal shows you that the database is being configured for the application.
After the database is configured, you can deploy the sample application and connect it to the database service.
Deploying the Spring PetClinic sample application
To deploy the Spring PetClinic sample application on an OKD cluster, you must use a deployment configuration and configure your local environment to be able to test the application.
Procedure
Deploy the
spring-petclinic-rest
application with thePostgresCluster
custom resource (CR) by running the following command in shell:$ oc apply -f - << EOD
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-petclinic-rest
namespace: my-postgresql
labels:
app: spring-petclinic-rest
spec:
replicas: 1
selector:
matchLabels:
app: spring-petclinic-rest
template:
metadata:
labels:
app: spring-petclinic-rest
spec:
containers:
- name: application
image: quay.io/baijum/spring-petclinic-rest:latest
env:
- name: SPRING_PROFILES_ACTIVE
value: postgresql,spring-data-jpa
ports:
- name: http
containerPort: 9966
---
apiVersion: v1
kind: Service
metadata:
name: spring-petclinic-rest
namespace: my-postgresql
spec:
ports:
- port: 80
targetPort: 9966
selector:
app: spring-petclinic-rest
EOD
The output verifies that the Spring PetClinic sample application is created and deployed:
Example output
deployment.apps/spring-petclinic-rest created
service/spring-petclinic-rest created
Set up port forwarding from the application port to access the sample application from your local environment:
$ oc port-forward --address 0.0.0.0 svc/spring-petclinic-rest 9966:80 -n my-postgresql
Access http://localhost:9966/petclinic.
You can now remotely access the Spring PetClinic sample application at localhost:9966.
The application is not yet connected to the database service. If you try to interact with the application, it will return errors.
For example, if you try to access the list of all pets using
curl
, you can see an error message similar to the following sample message:$ 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"}
You can now use the Service Binding Operator to connect the application to the database service.
Connecting the Spring PetClinic sample application to the PostgreSQL database service
To connect the sample application to the database service, you must create a ServiceBinding
custom resource (CR) that triggers the Service Binding Operator to project the binding data into the application.
Procedure
Create a
ServiceBinding
CR to project the binding data:$ oc apply -f - << EOD
---
apiVersion: binding.operators.coreos.com/v1alpha1
kind: ServiceBinding
metadata:
name: spring-petclinic-rest
namespace: my-postgresql
spec:
services: (1)
- group: postgres-operator.crunchydata.com
version: v1beta1
kind: PostgresCluster (2)
name: hippo
- group: ""
version: v1
kind: Secret
name: hippo-pguser-hippo
application: (3)
name: spring-petclinic-rest
group: apps
version: v1
resource: deployments
EOD
1 Specifies a list of service resources. 2 The CR of the database. 3 The sample application that points to a Deployment or any other similar resource with an embedded PodSpec. The output verifies that the
ServiceBinding
CR is created to project the binding data into the sample application.Example output
servicebinding.binding.operators.coreos.com/spring-petclinic-rest created
To verify that the binding is successful, check the status conditions of the binding resource:
$ oc get servicebindings spring-petclinic-rest -n my-postgresql -o jsonpath-as-json='{.status.conditions}'
Example output
[
[
{
"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",
},
],
]
By default, the values from the binding data of the database service are projected as files into the workload container that runs the sample application.
To verify that the files in the application contain the projected binding data, use the following command in shell to print out the contents:
$ for i in username password host port type; do oc exec -it deploy/spring-petclinic-rest -n my-postgresql -- /bin/bash -c 'find /bindings/*/'$i' -exec echo -n {}:" " \; -exec cat {} \;'; echo; done
Example output: With all the values from the secret resource
/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
Set up the port forwarding from the application port to access the sample application from your local environment:
$ oc port-forward --address 0.0.0.0 svc/spring-petclinic-rest 9966:80 -n my-postgresql
Access http://localhost:9966/petclinic.
You can now remotely access the Spring PetClinic sample application at localhost:9966.
To verify that the application is now connected to the database service, access the list of all pets:
$ curl -X GET "http://localhost:9966/petclinic/api/pets" -H "accept: application/json"
Example output
[{"id":1,"name":"Leo","birthDate":"2000/09/07","type":{"id":1,"name":"cat"},
"owner":{"id":1,"firstName":"George","lastName":"Franklin","address":"110...
The previous output shows the initially configured sample data and verifies that the application is now connected to the database service.