With this tutorial, you can try out Tanzu Postgres in a Minikube Kubernetes development environment running on your MacOS or Linux laptop.


In this tutorial, you will deploy the Postgres operator, create a Postgres instance, and build and deploy the Spring Music web app to a Minikube Kubernetes cluster. Minikube is a one-node Kubernetes cluster that runs in a virtual machine on your workstation.

The Postgres operator is a controller for Postgres instance resources. You install the Postgres operator using the Helm package manager. The operator is responsible for managing Postgres instances.

A Postgres instance is a container with a VMware Postgres installation. The Postgres operator provisions two persistent volumes for a Postgres instance, one for database data, and another for backups. The Postgres operator creates a user database named testdb, where the Spring Music app creates its data table.

The Spring Music app is a sample web application built with Spring Framework and Spring Boot. It is configured to use the Postgres instance named my-postgres for its database service.

This following figure illustrates the resources deployed to the Minikube Kubernetes node in this example.

quick start minikube

The Postgres operator and the Spring Music app are deployments managing replica sets (one-replica each) for the Postgres operator image, Postgres instances, and Spring Music services.

The Postgres instance and Spring Music services provide access to the database and web app on their Cluster IP (internal) addresses. The External IPs are greyed out in this illustration because Minikube does not automatically set up routes for External IPs. On a production Kubernetes cluster, an External IP would be allocated to allow access from outside the cluster.


To run this tutorial you must have installed Docker, Minikube, kubectl, and Helm 3 on your system. These links will take you to installation instructions.

  • Docker - install and start Docker.
  • Minikube - install kubectl, Minikube, and, if needed, a hypervisor such as VirtualBox. On MacOS systems you can use the built-in Hyperkit hypervisor by installing the Minikube Hyperkit driver.
  • Helm 3 - install the Helm 3 CLI.

Download and Extract VMware Tanzu SQL for Postgres

  1. Download Tanzu Postgres from VMware Tanzu Network. The name of the download file is in the format postgres-for-kubernetes-v<version>.tar.gz, where <version> is the Tanzu Postgres version number.

  2. Extract the download file.

    $ tar xfz postgres-for-kubernetes-v<version>.tar.gz

    The contents of the download file are extracted into the directory postgres-for-kubernetes-v<version>.

  3. Change into the postgres-for-kubernetes-v<version> directory.

    $ cd postgres-for-kubernetes-v*

Run Minikube and Set Up the Environment

  1. Start Minikube.

    $ minikube start --cpus 4 --memory 4G
    😄  minikube v1.5.2 on Darwin 10.15.3
    ✨  Automatically selected the 'hyperkit' driver (alternates: [virtualbox])
    🔥  Creating hyperkit VM (CPUs=4, Memory=4000MB, Disk=20000MB) ...
    🐳  Preparing Kubernetes v1.16.2 on Docker '18.09.9' ...
    🚜  Pulling images ...
    🚀  Launching Kubernetes ...
    ⌛  Waiting for: apiserver
    🏄  Done! kubectl is now configured to use "minikube"

    Minikube automatically selects a hypervisor. If you want to specify a different hypervisor add --vm-driver=<driver> to the minikube start command, for example --vm-driver=virtualbox.

  2. Set the Docker environment to use Minikube.

    $ eval $(minikube docker-env)
  3. Install Cert Manager. The Postgres operator requires Cert Manager.

    $ kubectl apply --validate=false \
      -f https://github.com/jetstack/cert-manager/releases/download/v0.15.0/cert-manager.yaml
  4. Tanzu Postgres provides two images: the Postgres operator and the Postgres instance. You must load both into your Docker registry so that Helm can deploy them to the cluster.

    $ docker load -i ./images/postgres-operator
    c8be1b8f4d60: Loading layer [==================================================>]  65.58MB/65.58MB
    977183d4e999: Loading layer [==================================================>]  991.2kB/991.2kB
    6597da2e2e52: Loading layer [==================================================>]  15.87kB/15.87kB
    16542a8fc3be: Loading layer [==================================================>]  3.072kB/3.072kB
    b5ad6316ad03: Loading layer [==================================================>]    406kB/406kB
    59717e88b76f: Loading layer [==================================================>]  40.88MB/40.88MB
    Loaded image: postgres-operator:v0.3.0
    $ docker load -i ./images/postgres-instance
    f18c8721f59c: Loading layer [==================================================>]  31.87MB/31.87MB
    012e544fc273: Loading layer [==================================================>]  5.632kB/5.632kB
    a5988d6bd81b: Loading layer [==================================================>]  2.048kB/2.048kB
    f25939fc235a: Loading layer [==================================================>]    332MB/332MB
    9859d37be96a: Loading layer [==================================================>]  60.42kB/60.42kB
    Loaded image: postgres-instance:v0.3.0

Create a Postgres Operator Release

This task creates a Postgres operator release in the Kubernetes cluster. The Postgres operator is the controller for Postgres instances in the cluster.

  1. Install the Postgres operator into the cluster using helm.

    $ helm install postgres-operator operator/
    $ helm install postgres-operator operator/
    NAME: postgres-operator
    LAST DEPLOYED: Mon May  4 11:07:04 2020
    NAMESPACE: default
    STATUS: deployed
    TEST SUITE: None
  2. Verify that the Postgres operator pod has been created and its status is "Running".

    $ watch kubectl get all
    Every 2.0s: kubectl get all                                                                                     MBP-Pivotal: Thu May  7 16:49:50 2020
    NAME                                     READY   STATUS    RESTARTS   AGE
    pod/postgres-operator-5475ff58b4-hxlw8   1/1     Running   0          49s
    NAME                                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    service/kubernetes                          ClusterIP       <none>        443/TCP   6m41s
    service/postgres-operator-webhook-service   ClusterIP   <none>        443/TCP   49s
    NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/postgres-operator   1/1     1            1           49s
    NAME                                           DESIRED   CURRENT   READY   AGE
    replicaset.apps/postgres-operator-5475ff58b4   1         1         1       49s

    Press Ctrl-C to break out of watch.

Create a Postgres Instance

A Postgres instance is defined in a Kubernetes configuration file. The Tanzu Postgres distribution includes a sample configuration file named pg-instance-example.yaml that defines a Postgres instance named my-postgres.

  1. Create the my-postgres instance.

    $ kubectl create -f pg-instance-example.yaml
    postgres.sql.tanzu.vmware.com/my-postgres created
  2. Check the status of the instance to verify that it was created and its status is Running.

    $ kubectl get postgres/my-postgres
    NAME          STATUS    AGE
    my-postgres   Running   99s
  3. Use the kubectl exec command to start the psql utility on the Postgres pod and check that you can connect to Postgres.

    kubectl exec -it my-postgres-0 -- bash -c psql
    psql (11.7 (VMware Postgres 11.7.1))
    Type "help" for help.
    postgres=# \c
    You are now connected to database "postgres" as user "postgres".

    Enter \q to exit the psql utility.

Build and Run the Spring Music App

The Spring Music app is a simple web application that manages a table named album in the testdb database.

  1. Change to the sample-app directory and build the app.

    $ cd sample-app
    $ docker build . -t spring-music:latest -f Dockerfile
    ... build output is omitted
  2. Create the Spring Music deployment using the spring-music.yaml Kubernetes configuration file.

    $ kubectl create -f spring-music.yaml
    deployment.apps/spring-music created
    service/spring-music-service created
  3. List the deployments, pods, and services in the Kubernetes cluster.

    $ kubectl get deployments
    NAME                READY   UP-TO-DATE   AVAILABLE   AGE
    postgres-operator   1/1     1            1           16m
    spring-music        0/1     1            0           14s
    $ kubectl get pods
    NAME                                 READY   STATUS    RESTARTS   AGE
    my-postgres-0                        1/1     Running   0          15m
    postgres-operator-6677b8f95c-rqfcj   1/1     Running   0          17m
    spring-music-56f78fd987-s9nkk        1/1     Running   0          69s
    $ kubectl get services
    NAME                                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
    kubernetes                          ClusterIP       <none>        443/TCP          11m
    my-postgres                         LoadBalancer   <pending>     5432:31861/TCP   4m2s
    postgres-operator-webhook-service   ClusterIP   <none>        443/TCP          5m44s
    spring-music-service                LoadBalancer   <pending>     80:30253/TCP     50s
  4. Verify that the Spring Music app has created the album table in the testdb database in your Postgres instance.

    $ kubectl exec -it my-postgres-0 -- psql -d testdb
    testdb=# SELECT COUNT(*) FROM album;
    (1 row)
    testdb=# \q
  5. Access the Spring Music app in your browser at the internal ip of the spring-music-service service. You can use the following commands to find the URL for the app.

    $ host=$(minikube ip)
    $ port=$(kubectl get service spring-music-service -o jsonpath='{.spec.ports[0].nodePort}')
    $ echo "Connect to the Spring Music app at http://$host:$port"

    Note: In a full Kubernetes cluster, you would use the LoadBalancer's external IP and port, but Minikube does not set up LoadBalancer routes automatically.

    Using the Spring Music app, you can sort, change the view, and add or delete albums. Changes you make in the browser UI are saved in the albums table in your my-postgres-0 Postgres instance.

    Spring Music

Clean Up

  1. Run minikube delete to destroy your Minikube environment.

    $ minikube delete
    🔥  Removing /home/<user>/.minikube/machines/minikube ...
    💀  Removed all traces of the "minikube" cluster.
check-circle-line exclamation-circle-line close-line
Scroll to top icon