This topic describes how to enable Tanzu Application Platform (TAP) or Tanzu Application Services (TAS) applications to connect and utilize VMware Postgres Operator database services.

Binding an Application to a Postgres Instance using TAP workflow

The Postgres API provided by VMware Postgres Operator adheres to the Kubernetes Service Binding specification which allows Postgres to be a Provisioned Service for Tanzu Application Platform (TAP) applications. This allows VMware Postgres Operator instances to be part of TAP Service Offerings, via the Services Toolkit, that eliminates the manual management of the configuration steps needed to securely, and successfully bind a TAP Workload to a VMware Postgres Operator deployment.

This feature adds the .status.binding.name field in the VMware Postgres Operator API, which points to a Secret in the same namespace. The Secret contains required credentials and connectivity information for the resource.

This topic covers the steps to provision VMware Postgres Operator using a TAP workload. For a similar process and updated TAP information, refer to Consuming services on Tanzu Application Platform.

Prerequisites

Setup Postgres with Services Toolkit

The Services Toolkit offers a set of modular tools used to provide a self-service experience to application owners, who require Service Resources running on Tanzu.

Review Service Resource Claims for details on ResourceClaim, ResourceClaimPolicy, and RBAC ClusterRole.

  • The Services Toolkit controller manager requires permissions to access Postgres resources. Create a ClusterRole with the Role-based access control (RBAC), and save it in a file like resource-claims-postgres.yaml:

    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: resource-claims-postgres
      labels:
        servicebinding.io/controller: "true"
    rules:
    - apiGroups: ["sql.tanzu.vmware.com"]
      resources: ["postgres"]
      verbs: ["get", "list", "watch"]
    

    and then run:

    kubectl apply -f resource-claims-postgres.yaml
    

    The Services Toolkit will now be able to claim Postgres instances.

  • To make the Postgres instances discoverable via the Services Toolkit, create a ClusterInstanceClass that refers to the Postgres API and save it in a file like cluster-instance-class-postgres.yaml:

    ---
    apiVersion: services.apps.tanzu.vmware.com/v1alpha1
    kind: ClusterInstanceClass
    metadata:
      name: postgres
    spec:
      description:
        short: It's a Postgres database!
      pool:
        group: sql.tanzu.vmware.com
        kind: Postgres
    

    and then run:

    kubectl apply -f cluster-instance-class-postgres.yaml
    

    Use the Services Toolkit plugin command tanzu service claimable list --class postgres to return the previously created Postgres instance.

  • (Optional) If you are consuming the Postgres instance from a Workload in another namespace, you will have to enable cross-namespace claims via a ResourceClaimPolicy. If your Postgres instance resides in the default namespace, save the following in a file like resource-claim-policy-postgres.yaml:

    ---
    apiVersion: services.apps.tanzu.vmware.com/v1alpha1
    kind: ResourceClaimPolicy
    metadata:
      name: postgres-cross-namespace
      namespace: default
    spec:
      consumingNamespaces:
      - '*' # consumable from all namespaces
      subject:
        group: sql.tanzu.vmware.com
        kind: Postgres
    

    and then run:

    kubectl apply -f resource-claim-policy-postgres.yaml
    

Create a Postgres Claim

Resource Claims allow Application teams to "claim" resources, and Service Operators to provide resources to be "claimed". This provides a self-service experience for the developer, but gives the Service Operators ultimate control of the Service Resources.

To claim a Postgres instance:

  1. Find the information needed to make a resource claim by running:

    tanzu service claimable list --class postgres
    #! `--class` is the name of the ClusterInstanceClass defined in the previous step
    

    With an output similar to:

    NAME           NAMESPACE  KIND      APIVERSION
    POSTGRES-NAME  default    Postgres  sql.tanzu.vmware.com/v1
    

    where POSTGRES-NAME is the name of the previously created Postgres instance.

    See Discover claimable service instances for more information on the different flags and options available.

  2. Create a claim for the Postgres instance from the namespace of your Workload by running:

    tanzu service claims create CLAIM-NAME \ 
        --resource-name POSTGRES-NAME \ 
        --resource-namespace default \
        --resource-kind Postgres \ 
        --resource-api-version sql.tanzu.vmware.com/v1 \ 
        --namespace WORKLOAD_NAMESPACE
    

    where:

    • POSTGRES-NAME is the name of the previously created Postgres instance.
    • CLAIM-NAME is the name you want to give to the resource claim instance.
    • WORKLOAD_NAMESPACE is the namespace of your Workload.

    The next section shows how to inspect the claim and use it to bind to an application Workload.

    Use tanzu service claims create --help for further usage and help information.

Bind a TAP Workload with Postgres

This topic covers:

Bind a new TAP Workload

To create an application Workload bound to a Postgres instance:

  1. Inspect the claims in your workload namespace to find the value to pass to --service-ref command by running:

    tanzu services claims list -n default
    

    Expected output:

    NAME           READY  REASON
    CLAIM-NAME     True   Ready
    

    Where CLAIM-NAME is the name of the previously created resource claim instance.

    See Listing and getting Resource Claims for more information on the different flags and options available.

  2. Retrieve detailed information about the claim by running:

    tanzu services claims get CLAIM-NAME
    

    where CLAIM-NAME is the name of the previously created resource claim instance.

    The output is similar to:

    Name: CLAIM-NAME
    Status:
      Ready: True
    Namespace: default
    Claim Reference: services.apps.tanzu.vmware.com/v1alpha1:ResourceClaim:CLAIM-NAME
    Resource to Claim:
      Name: POSTGRES-NAME
      Namespace: default
      Group: sql.tanzu.vmware.com
      Version: v1
      Kind: Postgres
    

    Where:

    • POSTGRES-NAME is the name of the previously created Postgres instance.
    • CLAIM-NAME is the name of the previously created resource claim instance.

    See Listing and getting Resource Claims for more information on the different flags and options available.

  3. Record the value of Claim Reference and pass it to --service-ref to create the application Workload by running:

    tanzu apps workload create WORKLOAD-NAME [create flags] \
      --service-ref "db=services.apps.tanzu.vmware.com/v1alpha1:ResourceClaim:CLAIM-NAME" \
      --annotation autoscaling.knative.dev/minScale=1
    

    where:

    • WORKLOAD-NAME is the name that will be given to the workload.
    • [create flags] are the appropriate flags to build the workload from source control, registry image, or local file.
    • --service-ref is the reference to the service using the format {key-name}={apiVersion}:{kind}:{instance-name}.
      • CLAIM-NAME is the name of the previously created resource claim instance.
      • key-name is a unique name given to service binding for the Workload.
    • --annotation value of autoscaling.knative.dev/minScale: "1" prevents the auto-scaling down of pods done by the TAP components. This can help with debugging the Workload.

    See Tanzu apps workload create for more information on the different flags and options available.

Example Workload

You can also create a Workload yaml file where you can specify environment variables, build parameters, etc. that are required by your application to be built and run successfully. The example Workload yaml below shows a spring-petclinic application that binds to a claim of a Postgres instance via a resource claim claim-1.

---
apiVersion: carto.run/v1alpha1
kind: Workload
metadata:
  name: pet-clinic
  labels:
    apps.tanzu.vmware.com/workload-type: web
    app.kubernetes.io/part-of: pet-clinic
    apps.tanzu.vmware.com/has-tests: "true"
spec:
  params:
  - name: annotations
    value:
      autoscaling.knative.dev/minScale: "1"
  build:
    env:
    - name: BP_MAVEN_POM_FILE
      value: skip-pom.xml
  env:
  - name: SPRING_PROFILES_ACTIVE
    value: postgres
  serviceClaims:
  - name: db
    ref:
      apiVersion: services.apps.tanzu.vmware.com/v1alpha1
      kind: ResourceClaim
      name: CLAIM-NAME
  source:
    git:
      ref:
        branch: main
      url: https://github.com/spring-projects/spring-petclinic

where:

  • BP_MAVEN_POM_FILE needs to be set to some non-existent value (in this example, skip-pom.xml) in order to build the upstream spring-petclinic app correctly. Refer to this open issue for more details.
  • SPRING_PROFILES_ACTIVE is set to Postgres to override the default application configuration.
  • CLAIM-NAME is claim-1 for this example.
  • The annotation autoscaling.knative.dev/minScale: "1" prevents the auto-scaling down of Pods done by the TAP components. This can help with debugging the Workload.

Save the above content in workload.yaml file and then run kubectl apply -f workload.yaml

IMPORTANT: This example creates a workload with the sample Spring application spring-petclinic that is available on GitHub. The sample application is subject to change and may face issues during build and run steps in the TAP workflow. Consider specifying a commit sha to use an older state of the sample application as needed for demo and test purposes.

Bind an existing TAP workload

To update an existing TAP Workload to connect and utilize a Postgres database instance, run a command similar to:

tanzu apps workload update WORKLOAD-NAME [update flags] --service-ref "db=services.apps.tanzu.vmware.com/v1alpha1:ResourceClaim:CLAIM-NAME"

where:

  • WORKLOAD-NAME is the name of the Workload.
  • [update flags] are the appropriate flags to build the Workload from source control, registry image, or local file.
  • --service-ref is the reference to the service using the format {key-name}={apiVersion}:{kind}:{name}.
    • CLAIM-NAME is the name of the previously created resource claim instance.
    • key-name is a unique name given to service binding for the Workload.

For example:

tanzu apps workload update pet-clinic --service-ref "db=services.apps.tanzu.vmware.com/v1alpha1:ResourceClaim:claim-1"

See Tanzu apps workload update for more information on the different flags available.

Verify a TAP Workload Service Binding

To check if the application has been successfully bound to the VMware Postgres Operator instance:

  • Check that the corresponding ResourceClaim object is ready. The ResourceClaim name follows the format <.metadata.name>-<.spec.serviceClaim[0].name> as given in the Workload yaml as shown above. In this example, it would be pet-clinic-db.

    kubectl get resourceclaims pet-clinic-db
    
    NAME                                                         READY   REASON
    resourceclaim.services.apps.tanzu.vmware.com/pet-clinic-db   True
    
  • Query the database using the Postgres application user .spec.pgConfig.appUser.
    Fetch the corresponding credentials and connection details from the Secret referenced in .status.binding.name field in the instance CR. With a Postgres called postgres-sample, the Secret would be postgres-sample-app-user-db-secret and the data can be verified in the postgres-sample database.

    dbname=$(kubectl get secrets postgres-sample-app-user-db-secret -o jsonpath='{.data.database}' | base64 -D)
    username=$(kubectl get secrets postgres-sample-app-user-db-secret -o jsonpath='{.data.username}' | base64 -D)
    password=$(kubectl get secrets postgres-sample-app-user-db-secret -o jsonpath='{.data.password}' | base64 -D)
    
    host=$(kubectl get secrets postgres-sample-app-user-db-secret -o jsonpath='{.data.host}' | base64 -D)
    port=$(kubectl get secrets postgres-sample-app-user-db-secret -o jsonpath='{.data.port}' | base64 -D)
    

    Using the spring-petclinic app, use a psql query similar to:

    PGPASSWORD=$password psql -h $host -p $port -d $dbname -U $username
    

    which should return an output similar to:

    psql (14.2 (VMware Postgres 14.2.0))
    Type "help" for help.
    
    my-postgres=# SELECT COUNT(1) from vets;
     count
    -------
         6
    (1 row)
    

Binding VMware Postgres Operator to a TAS Application

Prerequisites

  • VMware Postgres Operator has been successfully installed on a Kubernetes cluster.
  • The external public ingress service type of the instance is set to LoadBalancer. See Deploying a Postgres Instance.
  • You have deployed an application to TAS, and the application is able to reach the Kubernetes cluster ingress points.

Binding an Application

  1. Export the environment variables $dbname, $username, $password, $host, and $port, described in Accessing Postgres with External Clients.

  2. (Optional) From your computer validate that the Postgres instance is reachable from the location where TAS is deployed, by using a command similar to:

    # create a CF SSH tunnel, this will hang and you need to leave it open until you're done with this step
    cf ssh <appname> -L 54320:$host:$port
    

    which returns similar to:

    vcap@f00949bd-6601-4731-6f7e-e859:~$
    

    where f00949bd-6601-4731-6f7e-e859 is an example GUID. In a new window or tab, use psql to test the connection:

    PGPASSWORD=$password psql -h 127.0.0.1 -p 54320 -U $username -d $dbname
    
    psql (11.13 (VMware Postgres 11.13.1))
    Type "help" for help.
    
    postgres-sample=#
    
  3. Choose a name and create the user provided service:

    cf create-user-provided-service my-postgres-instance -p "{\"uri\":\"postgres://$username:$password@$host:$port/$dbname?sslmode=require\"}"
    

    For more details, see User-Provided Service Instances.

  4. Bind, restage, and use the service as you would normally with a "cf marketplace" provisioned SQL instance. See Bind a Service Instance to an App for an example of this process, and Restage Your App.

    Like any data service, the application will automatically connect to the database instance depending on the buildpack. If autoconnect is not supported, the application will have to manually make use of the uri service credential to make a connection.

    Bound service credentials are available at runtime to TAS applications via the DATABASE_URL and VCAP_SERVICES environment variables. For further details see DATABASE_URL in TAS for VMs Environment Variables documentation.

check-circle-line exclamation-circle-line close-line
Scroll to top icon