×

The 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 the Service Binding Operator to create a binding connection between the application and the database service.

Prerequisites

  • You have access to an OpenShift Container Platform cluster using an account with cluster-admin permissions.

  • You have installed the oc CLI.

  • You have installed PostgreSQL psql CLI.

  • You have installed the Service Binding Operator from OperatorHub.

Deploying a PostgreSQL Operator

  • To deploy the Dev4Devs PostgreSQL Operator in the my-postgresql namespace run the following command in shell:

$ oc apply -f - << EOD
---
apiVersion: v1
kind: Namespace
metadata:
  name: my-postgresql
---
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  name: postgres-operator-group
  namespace: my-postgresql
---
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
  name: ibm-multiarch-catalog
  namespace: openshift-marketplace
spec:
  sourceType: grpc
  image: quay.io/ibm/operator-registry-<architecture> (1)
  imagePullPolicy: IfNotPresent
  displayName: ibm-multiarch-catalog
  updateStrategy:
    registryPoll:
      interval: 30m
---
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: postgresql-operator-dev4devs-com
  namespace: openshift-operators
spec:
  channel: alpha
  installPlanApproval: Automatic
  name: postgresql-operator-dev4devs-com
  source: ibm-multiarch-catalog
  sourceNamespace: openshift-marketplace
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: database-view
  labels:
    servicebinding.io/controller: "true"
rules:
  - apiGroups:
      - postgresql.dev4devs.com
    resources:
      - databases
    verbs:
      - get
      - list
EOD
1 The Operator image.
  • For IBM Power Systems: quay.io/ibm/operator-registry-ppc64le:release-4.9

  • For IBM Z and LinuxONE: quay.io/ibm/operator-registry-s390x:release-4.8

After the operator is installed, list the operator subscriptions in openshift-operators namespace:

$ oc get subs -n openshift-operators
Example output
NAME                               PACKAGE                            SOURCE                  CHANNEL
postgresql-operator-dev4devs-com   postgresql-operator-dev4devs-com   ibm-multiarch-catalog   alpha
rh-service-binding-operator        rh-service-binding-operator        redhat-operators        stable

Creating a PostgreSQL database instance

To create a PostgreSQL database instance, you must create a Database custom resource (CR) and configure the database.

Procedure
  1. Create the Database CR and the my-postgresql namespace by running the following command in shell:

    $ oc apply -f - << EOD
    apiVersion: postgresql.dev4devs.com/v1alpha1
    kind: Database
    metadata:
      name: sampledatabase
      namespace: my-postgresql
      annotations:
        host: sampledatabase
        type: postgresql
        port: "5432"
        service.binding/database: 'path={.spec.databaseName}'
        service.binding/port: 'path={.metadata.annotations.port}'
        service.binding/password: 'path={.spec.databasePassword}'
        service.binding/username: 'path={.spec.databaseUser}'
        service.binding/type: 'path={.metadata.annotations.type}'
        service.binding/host: 'path={.metadata.annotations.host}'
    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: registry.redhat.io/rhel8/postgresql-96:latest
      databaseStorageClassName: nfs-storage-provisioner
      size: 1
    EOD

    The annotations added in this Database CR enable the service binding connection and trigger the Operator reconciliation.

    The output verifies that the database instance is created:

    Example output
    database.postgresql.dev4devs.com/sampledatabase created
  2. After you have created the database instance, ensure that all the pods in the 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
    sampledatabase-cbc655488-74kss            0/1     Running        0       32s

    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.

  3. 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=sampledb
    export cluster_namespace=my-postgresql
    export pgo_cluster_username=sampleuser
    nohup oc -n "\${cluster_namespace}" port-forward svc/sampledatabase 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 OpenShift Container Platform cluster, you must use a deployment configuration and configure your local environment to be able to test the application.

Procedure
  1. Deploy the spring-petclinic-rest application with the PostgresCluster 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/service-binding/spring-petclinic-rest:latest
              env:
              - name: SPRING_PROFILES_ACTIVE
                value: postgresql,spring-data-jpa
              - name: org.springframework.cloud.bindings.boot.enable
                value: "true"
              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
    $ oc get pods -n my-postgresql

    The output verifies that the database is created:

    Example output
    NAME                                      READY    STATUS      RESTARTS   AGE
    sampledatabase-cbc655488-6n25f             0/1     Running     0          1m
    spring-petclinic-rest-7659d5b774-zkjpg     2/2     Running     0          2m
  2. 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
  3. 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"
    Example output
    {"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
  1. 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: postgresql.dev4devs.com
          version: v1beta1
          kind: Database (2)
          name: sampledatabase
          version: v1alpha1
        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
  2. 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.

  3. Once this is created, you can go to the topology to see the visual connection.

    img power
    Figure 1. Connecting spring-petclinic-rest to sampledatabase
  4. 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
  5. Access http://localhost:9966/petclinic.

    You can now remotely access the Spring PetClinic sample application at localhost:9966.

  6. 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.