Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

How to use Quarkus with the Service Binding Operator

December 22, 2021
Ioannis Kanellos
Related topics:
KubernetesOperatorsQuarkus
Related products:
Red Hat OpenShift

Share:

    In the seven years since Kubernetes was released, there have been various efforts to simplify the process of consuming and binding to services from Kubernetes clusters. While discovering a service isn't much of an issue if you employ a well-known set of conventions, getting the credentials and other details required to access that service is sometimes trickier.

    The Kubernetes Service Catalog was an attempt to simplify provisioning and binding to services, but it seems to have lost momentum. The lack of uniformity between providers, differences in how each service communicates binding information, and the fact that developers tend to favor operators for provisioning services all made the Service Catalog hard to use in practice.

    The Service Binding Operator for Kubernetes and Red Hat OpenShift is a more recent initiative. It stays out of the way of service provisioning, leaving that to operators. Instead, it focuses on how to best communicate binding information to the application. An interesting part of the specification is the workload projection, which defines a directory structure that will be mounted to the application container when binding occurs in order to pass all the required binding information: type, URI, and credentials

    Other parts of the specification are related to the ServiceBinding resource, which controls which services are bound to which application, and how.

    Quarkus, which already supports the workload-projection part of the Service Binding specification, recently received enhancements for service binding. In this article, you'll learn how to automatically generate a ServiceBinding resource, then go through the whole process from installing operators to configuring and deploying an application.

    A note about the example

    In the example, you will use kind to install the Service Binding Operator and the Postgres Operator from Crunchy Data. After that, you will create a PostgreSQL cluster, and finally create a simple todo application, deploying it and binding it to the provisioned cluster. Before you begin, you may want to take a look at the Service Binding Operator Quick Start Guide.

    Set up your clusters

    Begin by creating a new cluster with kind. (If you've already created one, or don't use kind at all, you can skip this step.)

    kind create cluster

    You'll install both of the operators used in our example through the OperatorHub.

    Install the Operator Lifecycle Manager

    The first step is to install the Operator Lifecycle Manager:

    curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.19.1/install.sh | bash -s v0.19.1
    
    

    Install the Service Binding Operator

    Next, you'll install the Service Binding Operator:

    kubectl create -f https://operatorhub.io/install/service-binding-operator.yaml
    

    Before moving to the next step, verify the installation with the following command:

    kubectl get csv -n operators -w
    

    When the phase of the Service Binding Operator is Succeeded, you can proceed.

    Install the Postgres Operator

    Use the following command to install the Postgres Operator from Crunchy Data:

    kubectl create -f https://operatorhub.io/install/postgresql.yaml 

    As you did before, you'll want to verify the installation:

    kubectl get csv -n operators -w

    When the phase of the operator is Succeeded, you can move to the next stage.

    Create a PostgreSQL cluster

    To begin this process, create a new namespace where you'll install your cluster and application:

    kubectl create ns demo kubectl config set-context --current --namespace=demo

    To create the cluster, you need to apply the following custom resource:

    
    apiVersion: postgres-operator.crunchydata.com/v1beta1
    kind: PostgresCluster
    metadata:
      name: pg-cluster
      namespace: demo
    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
    
    

    This resource has been borrowed from the Service Binding Operator Quick Start Guide. Save that file as pg-cluster.yml and apply it using kubectl:

    kubectl apply -f ~/pg-cluster.yml

    Now check the pods to verify the installation:

    kubectl get pods -n demo

    Create the Quarkus application

    Next, you'll create a simple Quarkus todo application that will connect to PostgreSQL via Hibernate and Panache. The todo application is a simple rest API for creating, reading, and deleting todo entries in a PostgreSQL database. It is heavily inspired by Clement Escoffier's Quarkus todo app but focuses less on presentation and more on the binding aspect.

    Generate the application using the following Maven command:

    mvn io.quarkus.platform:quarkus-maven-plugin:2.5.0.Final:create -DprojectGroupId=org.acme -DprojectArtifactId=todo-example -DclassName="org.acme.TodoResource" -Dpath="/todo"
    
    

    Next, add all of the required extensions for connecting to PostgreSQL, generate the required Kubernetes resources, and build a container image for the application using Docker:

    ./mvnw quarkus:add-extension -Dextensions="resteasy-jackson,jdbc-postgresql,hibernate-orm-panache,kubernetes,kubernetes-service-binding,container-image-docker"
    

    At this point, you need to create a simple entity:

    package org.acme;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    
    import io.quarkus.hibernate.orm.panache.PanacheEntity;
    
    @Entity
    public class Todo extends PanacheEntity {
    
        @Column(length = 40, unique = true)
        public String title;
    
        public boolean completed;
    
        public Todo() {
        }
    
        public Todo(String title, Boolean completed) {
            this.title = title;
        }
    }
    

    Then, expose it via REST:

    package org.acme;
    
    import javax.transaction.Transactional;
    import javax.ws.rs.*;
    import javax.ws.rs.core.Response;
    import javax.ws.rs.core.Response.Status;
    import java.util.List;
    
    @Path("/todo")
    public class TodoResource {
    
        @GET
        @Path("/")
        public List<Todo> getAll() {
          return Todo.listAll();
        }
    
        @GET
        @Path("/{id}")
        public Todo get(@PathParam("id") Long id) {
            Todo entity = Todo.findById(id);
            if (entity == null) {
                throw new WebApplicationException("Todo with id of " + id + " does not exist.", Status.NOT_FOUND);
            }
            return entity;
        }
    
        @POST
        @Path("/")
        @Transactional
        public Response create(Todo item) {
            item.persist();
            return Response.status(Status.CREATED).entity(item).build();
        }
    
        @GET
        @Path("/{id}/complete")
        @Transactional
        public Response complete(@PathParam("id") Long id) {
            Todo entity = Todo.findById(id);
            entity.id = id;
            entity.completed = true;
            return Response.ok(entity).build();
        }
    
    
        @DELETE
        @Transactional
        @Path("/{id}")
        public Response delete(@PathParam("id") Long id) {
            Todo entity = Todo.findById(id);
            if (entity == null) {
                throw new WebApplicationException("Todo with id of " + id + " does not exist.", Status.NOT_FOUND);
            }
            entity.delete();
            return Response.noContent().build();
        }
    }
    

    Bind to the target cluster

    In order to bind the PostgreSQL service to the application, you must either provide a ServiceBinding resource or have it generated. To have the binding generated for you, you need to provide the following service coordinates:

    • apiVersion: postgres-operator.crunchydata.com/v1beta1
    • Kind: PostgresCluster
    • Name: pg-cluster, prefixed with quarkus.kubernetes-service-binding.services.<id>

    You can see these coordinates in the following listing:

    quarkus.kubernetes-service-binding.services.my-db.api-version=postgres-operator.crunchydata.com/v1beta1
    quarkus.kubernetes-service-binding.services.my-db.kind=PostgresCluster
    quarkus.kubernetes-service-binding.services.my-db.name=pg-cluster 

    Note that the id is just used to group properties together and can be any text.

    You also need to configure the datasource:

    quarkus.datasource.db-kind=postgresql
    quarkus.hibernate-orm.database.generation=drop-and-create
    quarkus.hibernate-orm.sql-load-script=import.sql
    

    This sample application will not push the image to a registry, but just loads it to the cluster, so use IfNotPresent as the image pull policy:

    quarkus.kubernetes.image-pull-policy=IfNotPresent

    The application properties file should look like this:

    quarkus.kubernetes-service-binding.services.my-db.api-version=postgres-operator.crunchydata.com/v1beta1
    quarkus.kubernetes-service-binding.services.my-db.kind=PostgresCluster
    quarkus.kubernetes-service-binding.services.my-db.name=pg-cluster
    
    quarkus.datasource.db-kind=postgresql
    quarkus.hibernate-orm.database.generation=drop-and-create
    quarkus.hibernate-orm.sql-load-script=import.sql
    
    quarkus.kubernetes.image-pull-policy=IfNotPresent
    

    Prepare for deployment

    Before you deploy, you need to perform a container image build, load the image to the cluster, and generate the resource.

    First, build the container image:

    mvn clean install -Dquarkus.container-image.build=true -DskipTests
    

    Note that this instruction assumes that you have Docker up and running.

    Next, you'll load the Docker image to the cluster:

    kind load docker-image iocanel/todo-example:1.0.0-SNAPSHOT
    
    

    If you're using minikube instead of Docker, execute the following to rebuild the image:

    eval $(minikube docker-env)
    
    

    When using tools like kind or minikube, it is generally a good idea to change the image pull policy to IfNotPresent as you did in this example. Doing this avoids unnecessary pulls, because most of the time the image will be loaded from the local Docker daemon.

    Deploy the application

    Next, generate the deployment manifest, including the ServiceBinding, and apply them on Kubernetes:

    mvn clean install -Dquarkus.kubernetes.deploy=true -DskipTests
    

    Now, verify that everything is up and running:

    kubectl get pods -n demo -w

    Verify the installation

    The simplest way to verify that everything works as expected is to port forward to a local HTTP port and access the /todo endpoint:

    kubectl port-forward service/todo-example 8080:80

    Point your browser to http://localhost:8080/todo and enjoy!

    A look ahead

    I am very excited about recent progress on the service binding front. In the near future, we may be able to reduce the amount of configuration necessary with the use of smart conventions (such as assuming that the custom resource name is the same as the database name unless explicitly specified otherwise) and a reasonable set of defaults (such as assuming that for PostgreSQL the default operator is Crunchy Data's Postgres Operator). In such a scenario, you could bind to services with no configuration without sacrificing flexibility or customizability. I hope you are as excited as I am by this prospect!

    See the following resources to learn more about service binding and the Service Binding Operator:

    • Announcing Service Binding Operator 1.0 GA
    • Service Binding Operator: The Operator in action
    • How to use service binding with RabbitMQ
    Last updated: September 20, 2023

    Related Posts

    • Announcing Service Binding Operator 1.0 GA

    • Service Binding Operator: The Operator in action

    • How to use service binding with RabbitMQ

    • Connect Node.js applications to Red Hat OpenShift Streams for Apache Kafka with Service Binding

    Recent Posts

    • GuideLLM: Evaluate LLM deployments for real-world inference

    • Unleashing multimodal magic with RamaLama

    • Integrate Red Hat AI Inference Server & LangChain in agentic workflows

    • Streamline multi-cloud operations with Ansible and ServiceNow

    • Automate dynamic application security testing with RapiDAST

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue