Deploying a PostgreSQL DB on IBM Hyper Protect Virtual Server for VPC

Dr. Clemen Chiang
Dr. Clemen Chiang

*CTO’s Notes: Building on our previous experiences, this article discusses our evolved strategy for deploying a PostgreSQL database on IBM Hyper Protect Virtual Servers. We transitioned to a more sophisticated approach, utilizing Docker for database deployment – a method that not only streamlined the process but also enhanced security and scalability. Here, we share the intricate details of this deployment method and the significant advantages it offers.

Today, we would like to walk you through the journey of building your PostgreSQL DB docker container image in an IBM Z Virtual server instance(zVSI) on IBM Cloud and then deploying the image in a contract as an IBM Hyper Protect Virtual Server instance.

There are 6 steps in this journey:

Step 1: Launch an IBM Z Virtual server instance(zVSI) on IBM Cloud

Step 2: SSH into your zVSI and create your docker-compose and Dockerfile for your PostgreSQL DB

Step 3: Test your docker container image by running docker-compose up in your zVSI to ensure it runs well in s390x architecture

Step 4: Build your container image for s390x architecture and push it into IBM Container Registry

Step 5: Create the contract using Terraform

Step 6: Initialize your IBM Hyper Protect Virtual Server instance with the contract from Step 5

Before you begin,

You need to meet the following prerequisites:

  1. Create an IBM Cloud account.
  2. Create an API key for your user identity.
  3. Install IBM Cloud CLI and the container registry CLI plug-in.
  4. Install Git, Terraform, OpenSSL, PostgreSQL, Docker and Docker buildx
  5. Create a VPC and a subnet with a public gateway and a security group with rules that allow at least inbound IP connections on port 5432 and all outbound IP connections.
  6. Create a Log Analysis instance on IBM Cloud. Make a note of the ingestion host and the ingestion key.

Step 1: Launch an IBM Z Virtual server instance(zVSI) on IBM Cloud

Go to the IBM Cloud catalog and select "Virtual Server for VPC"

Choose your preferred location. For example, if you are in Singapore, select "Asia Pacific," and then choose the "Tokyo" region.

Give your instance a name.

Select your preferred image. Under the Architecture section, ensure that you select the s390x architecture "IBM Z, LinuxONE".

Next, select your profile.

Choose an SSH key to use for accessing the instance. If you don't have an SSH key, you can follow the instructions to generate one.

Optionally, add data volumes on top of the boot volume.

Configure your VPC (Virtual Private Cloud) and request a floating IP address for your instance.

Click the "Create virtual server" button. Your new virtual server will be provisioned and available for use shortly.

After your virtual server has been provisioned, assign a floating IP address to the new virtual server instance and click Save because you will need to SSH in the next step.

Step 2: SSH into your zVSI and create your docker-compose and Dockerfile for your PostgreSQL DB

Once your instance is provisioned, you can access it by SSH using the floating IP address and the SSH key you selected during the setup earlier.

ssh -i your-ssh-key.pem root@floating-ip-address

Create a new working directory

COPYCOPY

mkdir postgres-db

Cd to the new working directory

COPYCOPY

cd postgres-db

Create your Dockerfile

COPYCOPY

# Use the official PostgreSQL image from Docker Hub
FROM postgres:latest

# Environment variables
ENV POSTGRES_DB=<postgres_db>
ENV POSTGRES_USER=<postgres_user>
ENV POSTGRES_PASSWORD=<postgres_user_password>

# Expose the default PostgreSQL port
EXPOSE 5432

where

<postgres_db> is the name of your database

<postgres_user> is the username which you will be using to access the database

<postgres_user_password> is the password of the username which you will be using to access the database

Create your docker-compose.file

COPYCOPY

version: '3'

services:
  postgres:
    image: postgres:14-alpine
    ports:
      - 5432:5432
    volumes:
      - ~/apps/postgres:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=<postgres_user_password>
      - POSTGRES_USER=<postgres_user>
      - POSTGRES_DB=<postgres_db>

Step 3: Test your docker container image by running docker-compose up in your zVSI to ensure it runs well in s390x architecture

In the same working directory which contains your Dockerfile and docker-compose.yml, run the command:

COPYCOPY

docker-compose up

Verify that the docker-compose up command is run successfully by running the docker ps -a command:

COPYCOPY

$ docker ps -a
CONTAINER ID   IMAGE                        COMMAND                  CREATED          STATUS                    PORTS                                       NAMES
94d146cce7bb   postgres:14-alpine           "docker-entrypoint.s…"   37 minutes ago   Up 36 minutes             0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   postgres-db_postgres_1

It is important to ensure that your docker container is running well in your zVSI on s390x architecture. Similarly, you may try to connect to your Postgres DB using the command:

COPYCOPY

$ psql -h localhost -U <postgres_user> -d <postgres_db> -p 5432
Password for user spiking_user: <postgres_user_password>

where

<postgres_db> is the name of your database

<postgres_user> is the username

<postgres_user_password> is the password of the username

which you have created in the Dockerfile and docker-compose.yml previously

Step 4: Build your container image for s390x architecture and push it into IBM Container Registry

Now that we have ensured that our docker container is working well in zVSI on s390x architecture, we are ready to push the container image into the IBM Container Registry.

In the same working directory which contains your Dockerfile and docker-compose.yml, build the container image for the s390x architecture and tag the container image with the following command:

COPYCOPY

docker buildx build --platform linux/s390x -t jp.icr.io/hpvs-spiking/postgres-db .

where

jp.icr.io is the region of your IBM container registry

hpvs-spiking is a namespace in your IBM container registry

postgres-db is your application name

Log in to the IBM Cloud Container Registry with the following commands:

COPYCOPY

$ ibmcloud login -u iamapikey --apikey <your API Key>
API endpoint: https://cloud.ibm.com
Region: jp-tok
Authenticating...
OK

where

<your API Key> is the API Key of the IAM user you have created in your IBM cloud account

I have selected Japan-Tokyo as the region of my IBM container registry

You may use the command below to switch to another region e.g. us-south:

COPYCOPY

ibmcloud target -r us-south

Lastly, run the command:

COPYCOPY

ibmcloud cr login --client docker

Create a namespace and push the container image by running the following commands:

COPYCOPY

ibmcloud cr namespace-add hpvs-spiking

where

hpvs-spiking is a namespace in your IBM container registry

Push the container image you created earlier by using the command:

COPYCOPY

docker push jp.icr.io/hpvs-spiking/postgres-db

Display the container image digest. You can view and note the container image digest in your container registry, or alternatively use the following command:

COPYCOPY

docker inspect jp.icr.io/hpvs-spiking/postgres-db | grep -A 1 RepoDigests

Step 5: Create the contract using Terraform

To provision the IBM Hyper Protect Virtual Server instance in the next step, you would need to first create a contract. You may create a contract manually or use Terraform which aids in reducing the time needed for contract creation.

Follow the steps below to use Terraform to create a contract:

Use Git to clone the repo

Move to the following directory with the command:

COPYCOPY

cd linuxone-vsi-automation-samples\terraform-hpvs\create-contract-dynamic-registry

Update the docker-compose.yml file in the compose folder. You need to specify your container image digest and the exposed ports. See the following example of a docker-compose.yml file:

COPYCOPY

version: "3"
services:
  tradegpt:
    image: ${REGISTRY}/hpvs-spiking/postgres-db@sha256:<sha256>
    ports:
      - "5432:5432"

where

<sha256> is the image digest in your container registry

Set the required Terraform variables. To do so, you need to copy the file my-settings.auto.tfvars-template to my-settings.auto.tfvars, edit the copied file, and adapt the variable values. See the following example:

COPYCOPY

registry="jp.icr.io"
pull_username="iamapikey"
pull_password="<your API key>"
logdna_ingestion_key="<the ingestion key of your log instance>"
logdna_ingestion_hostname="syslog-a.jp-tok.logging.cloud.ibm.com"

where

jp.icr.io is the region of your IBM container registry

jp-tok is the region of your logging instance

<your API Key> is the API Key of the IAM user you have created in your IBM cloud account

<the ingestion key of your log instance> which you can retrieve on IBM cloud for your respective logging instance

To initialize Terraform, run the following command:

COPYCOPY

terraform init

Create the contract by using Terraform:

COPYCOPY

terraform apply

Display the contract that is created with the Terraform script by running the following command:

COPYCOPY

cat build/contract.yml

💡Copy the displayed contract. You need to paste the copied contract into the User Data text field in the next step.

Step 6: Initialize your IBM Hyper Protect Virtual Server instance with the contract from Step 5

  1. Log in to IBM Cloud.
  2. Go to the provisioning page for IBM Hyper Protect Virtual Server for VPC on the IBM Cloud catalog.

3. Name the virtual server instance

4. Ensure that the image is an IBM Hyper Protect image running on s390x Architecture

5. Paste the created contract information into User data.

6. Under the Networking, select your VPC and subnet.

7. Click Create Virtual Server.

8. Assign a floating IP address to the IBM Hyper Protect Virtual Server Instance and click Save.

9. Under your security group, ensure that you allow at least inbound IP connections on port 5432 and all outbound IP connections so that in the very last step, you will be able to connect to your PostgreSQL DB via <floating-ip-address> and the default PostgreSQL port of 5432

10. View the logs in the Log Analysis instance dashboard.

11. Ensure that there's no error in the logs and that the IBM Hyper Protect Virtual Server is started successfully

12. Copy and paste the <floating-ip-address> and you may connect to your Postgres DB on the IBM Hyper Protect Virtual Server instance using the command:

$ psql -h <floating-ip-address> -U <postgres_user> -d <postgres_db> -p 5432
Password for user spiking_user: <postgres_user_password>

Continue to our subsequent article to explore how we applied these improved deployment strategies to launch a React Web Application on IBM Hyper Protect Virtual Servers.