back to all blogsSee all blog posts

Bind an operator-managed PostgreSQL database to a JPA application in a Kubernetes cluster

image of author
Edward Mezarina on Sep 17, 2021

Binding your microservice application to operator-based services, such as a database, is now easier, thanks to the Service Binding Operator and OpenShift Do (odo). These frameworks enable the automatic collection of service data and easier resource data sharing, while abstracting resource configuration and deployment details.

In this post, we’ll use the Open Liberty devfile stack, Openshift odo, and the Service Binding Operator to easily deploy an application that uses the Java Persistence API (JPA) and bind a PostgreSQL database to the application.

Open Liberty devfile stack

The Open Liberty devfile stack provides much of the infrastructure (Open Liberty, Maven/Gradle, Open J9, etc.) needed to start developing applications that use Maven or Gradle, and it is made available as Maven and Gradle development images. The devfiles that are provided by the stack use these images as a base to build and run your applications.

The Open Liberty devfile stack provides two fully configured devfiles: A Maven-based devfile and a Gradle-based devfile. These devfiles define the environment and steps to build and deploy your application using the Open Liberty runtime.

OpenShift Do (odo)

Odo is a simple CLI tool to create devfile-based components that interact directly with your Kubernetes cluster. With odo, you can set up the environment, and also build, deploy, access, and debug your application. Directives to manage the environment and application are provided by a component’s devfile.

Service Binding Operator

The Service Binding Operator makes it easier for developers to bind operator-managed services such as databases to applications. The operator generates a binding secret for the purpose of storing information from the routes, services, secrets, and configMaps owned by the backing service.

Try it out

To begin, you need three things:

  • Kubernetes cluster. For this blog, an OpenShift cluster is used. Be sure to log in. Odo will interact with your Kubernetes cluster.

  • OpenShift Do. If you have not already installed odo, do so now by following the instructions outlined in the odo documentation. Be sure to install version 2.2.4 and above.

  • An application that uses a PostgreSQL database. For this post, we’ll use the Open Liberty stack sample JPA application.

Install the needed operators

If you have the right privileges, you can use the OpenShift console to install these operators. You do this by navigating to Operators→OperatorHub and searching/selecting/installing a couple of operators from the catalog.

  • Service Binding Operator (provided by Red Hat)

Use the OpenShift console (Operators→OperatorHub) to install this operator. Be sure to install version 0.9.1 and above.

  • PostgreSQL Operator (provided by Dev4Ddevs.com)

Before installing this operator, create the project/namespace under which the application will be deployed. This operator is namespace scoped, so it needs to be installed in the same namespace where the application will be deployed.

odo project create service-binding-demo

Use the OpenShift console (Operators→OperatorHub) to install this operator. Be sure to pick service-binding-demo as the namespace in which to install it.

Provide service resource access to the Service Binding Operator

Starting with v0.10.0, the Service Binding Operator requires explicit permissions to access service resources.

Grant the Service Binding Operator’s controller permission to get/list Database custom resource instances. The Database custom resource is provided by the Dev4Devs PostgreSQL operator you installed in the previous step.

cat <<EOF | kubectl apply -f-
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: sbo-service-view
  labels:
    service.binding/controller: "true"
rules:
  - apiGroups:
      - postgresql.dev4devs.com
    resources:
      - databases
    verbs:
      - get
      - list
EOF

Create a Java Open Liberty-based component and the database resource service

Clone the application repository.

git clone https://github.com/OpenLiberty/application-stack-samples.git && \
cd application-stack-samples/jpa

Create a Java Open Liberty component.

odo create java-openliberty mysboproj

Display the service providers and services available in the cluster.

odo catalog list services

Output:

Services available through Operators
NAME                                CRDs
...
postgresql-operator.v0.1.1          Backup, Database
...

Generate the postgresql-operator.v0.1.1 Database custom resource yaml and store it in a file. The data is stored in a file because some entries will be customized.

odo service create postgresql-operator.v0.1.1/Database --dry-run > db.yaml

Open db.yaml and do the following:

Customize the database name, username, and password values under the spec section as shown:

spec:
  databaseName: "sampledb"
  databasePassword: "samplepwd"
  databaseUser: "sampleuser"

Customize the resource instance name and add the needed annotations under the metadata section as shown:

metadata:
  name: sampledatabase
  annotations:
    service.binding/db_name: 'path={.spec.databaseName}'
    service.binding/db_password: 'path={.spec.databasePassword}'
    service.binding/db_user: 'path={.spec.databaseUser}'

Adding the annotations ensures that the Service Binding Operator will inject the databaseName, databasePassword and databaseUser spec values into the application. Note that the instance name you configure will be used as part of the name of various artifacts and resource references. Be sure to change it.

Now that we are done customizing the Database resource with bindable data, generate its devfile configuration.

odo service create --from-file db.yaml

The following configuration is automatically added to devfile.yaml:

...
- kubernetes:
    inlined: |
      apiVersion: postgresql.dev4devs.com/v1alpha1
      kind: Database
      metadata:
        annotations:
          service.binding/db_name: path={.spec.databaseName}
          service.binding/db_password: path={.spec.databasePassword}
          service.binding/db_user: path={.spec.databaseUser}
        name: sampledatabase
      spec:
        databaseCpu: 30m
        databaseCpuLimit: 60m
        databaseMemoryLimit: 512Mi
        databaseMemoryRequest: 128Mi
        databaseName: sampledb
        databaseNameKeyEnvVar: POSTGRESQL_DATABASE
        databasePassword: samplepwd
        databasePasswordKeyEnvVar: POSTGRESQL_PASSWORD
        databaseStorageRequest: 1Gi
        databaseUser: sampleuser
        databaseUserKeyEnvVar: POSTGRESQL_USER
        image: centos/postgresql-96-centos7
        size: 1
  name: sampledatabase
...

Push the updates to the cluster.

odo push

So far, two things have taken place:

  • The application was deployed on your cluster. The application was built and deployed using Maven. However, you could have also built and deployed the application using Gradle by using the odo create java-openliberty-gradle mysboproj command instead when creating the Java Open Liberty component.

  • A Dev4Ddevs Database custom resource instance was created. This, in turn, triggered the creation of a PostgreSQL database instance.

However, the application is still not usable because it does not have the data needed to connect to the database. Let’s solve that next.

Bind the application to the PostgreSQL service

List the available services to which the application can be bound. The PostgreSQL database service should be listed.

odo service list

Output:

NAME                        MANAGED BY ODO      STATE      AGE
...
Database/sampledatabase     Yes (mysboproj)     Pushed     50s
...

Generate the service binding devfile configuration.

odo link Database/sampledatabase

The following configuration is automatically added to devfile.yaml:

...
- kubernetes:
    inlined: |
      apiVersion: binding.operators.coreos.com/v1alpha1
      kind: ServiceBinding
      metadata:
        creationTimestamp: null
        name: mysboproj-database-sampledatabase
      spec:
        application:
          group: apps
          name: mysboproj-app
          resource: deployments
          version: v1
        bindAsFiles: false
        detectBindingResources: true
        services:
        - group: postgresql.dev4devs.com
          kind: Database
          name: sampledatabase
          version: v1alpha1
      status:
        secret: ""
  name: mysboproj-database-sampledatabase
...

Push the updates to the cluster.

odo push

That is all. The application is now bound to the PostgreSQL database service. During the binding process, a secret containing the database connection information was created, and the pod hosting the application is restarted with the database connection information contained in the secret. The connection information is set in the application pod as environment variables.

Next, let’s make sure we can use the application.

Use the application

Find the URL to access the application through a browser.

odo url list

Output:

Found the following URLs for component mysboproj
NAME     STATE      URL                                                                      PORT     SECURE     KIND
ep1      Pushed     http://ep1-mysboproj-service-binding-demo.apps.my.os.cluster.ibm.com     9080     false      route

Open a browser and go to the URL shown by the previous step. Click the Create New Person button.

Main Page

Enter a user’s name and age via the form shown on the page and click Save. The data is now persisted in the PostgreSQL database.

Data Input Page

After you save the data to the PostgreSQL database, notice that you are re-directed to the PersonList.xhtml page. The data being displayed was retrieved from the PostgreSQL database.

Data Display Page

You just used Open Liberty devfile stack, Openshift odo, and the Service Binding Operator to deploy an application, bind a PostgreSQL database to the application, and successfully test the interaction between the application and the database.

Learn more

Tags