Page
Create the PostgreSQL instance, ConfigMap, and Deployment objects
Your first step in building and populating your database is to create the PostgreSQL instance, ConfigMap, and Deployment objects.
Step 0: Log in to your Developer Sandbox at the command line
If you’re unsure of how to do this, you can find instructions here: Access your Developer Sandbox from the command line.
Step 1: Get the code from GitHub
Download or clone the following repo: https://github.com/redhat-developer-demos/getfood
Then, move it into the directory where the code lands.
Step 2: Create the PostgreSQL instance
Run the following command to create an instance of PostgreSQL running in your sandbox. Note: This is an ephemeral instance; the data is lost when the pod is stopped:
oc new-app openshift/postgresql-ephemeral -p DATABASE_SERVICE_NAME=postgresql -e POSTGRESQL_USER=postgres -e POSTGRESQL_PASSWORD=postgres --labels=app.kubernetes.io/part-of=foods,systemname=foods,tier=database,database=postgresql,foods=database
Step 3: Make the files available
There are several pieces of information that need to be available inside your OpenShift cluster in order to create a database, create a table, and fill that table with data. The method used to get the scripts and data into the OpenShift cluster is by using a ConfigMap object. The ConfigMap is then mounted as a volume in the init containers. In other words, the files appear as files on a drive, in a given file path. For example, /etc/scripts/build_database.sql
.
The files we will use are in the /configmap directory of this activity. Here’s a listing:
Directory: C:\Users\dschenck\src\getfood\configmap
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 11/29/2023 1:29 PM 631 build_tables.sql
-a--- 11/29/2023 1:07 PM 22 create_database.sql
-a--- 11/17/2023 2:13 PM 421163 fooddisplaytable.csv
The *.sql
files are PostgreSQL commands to create the database and the table. The file fooddisplaytable.csv
contains the data that will be imported into the table. These three files need to be combined into one ConfigMap object. Fortunately, there’s a command to do that.
Move into your Git repo top-level directory (getfood
) and run the following command to create the ConfigMap object YAML file on your local PC:
oc create configmap db-config --from-file=./configmap --dry-run=client -o yaml > db-configmap.yaml
The result is the file db-configmap.yam
l that contains the contents of all three of the files in the ./configmap
subdirectory. Those files are in the data
section of the created ConfigMap YAML. Here’s a snippet:
apiVersion: v1
data:
build_tables.sql: "CREATE TABLE IF NOT EXISTS food (\r\n\tfood_code int,\r\n\tdisplay_name
vaRcHaR( 80 ),\r\n\tportion_default int,\r\n\tportion_amount numeric,\r\n\tportion_display_name
vaRcHaR( 40 ),\r\n\tfactor numeric,\r\n\tincrement numeric,\r\n\tmultiplier numeric,\r\n\tgrains
numeric,\r\n\twhole_grains numeric,\r\n\tvegetables numeric,\r\n\torange_vegetables
numeric,\r\n\tdrkgreen_vegetables numeric,\r\n\tstarchy_vegetables
numeric,\r\n\tother_vegetables
numeric,\r\n\tfruits numeric,\r\n\tmilk numeric,\r\n\tmeats numeric,\r\n\tsoy
numeric,\r\n\tdrybeans_peas numeric,\r\n\toils numeric,\r\n\tsolid_fats numeric,\r\n\tadded_sugars
numeric,\r\n\talcohol numeric,\r\n\tcalories numeric,\r\n\tsaturated_fats numeric\r\n);"
create_database.sql: CREATE DATABASE foods;
fooddisplaytable.csv: "Food_Code,Display_Name,Portion_Default,Portion_Amount,Portion_Display_Name,Factor,Increment,Multiplier,Grains,Whole_Grains,Vegetables,Orange_Vegetables,Drkgreen_Vegetables,Starchy_vegetables,Other_Vegetables,Fruits,Milk,Meats,Soy,Drybeans_Peas,Oils,Solid_Fats,Added_Sugars,Alcohol,Calories,Saturated_Fats\r\n12350000,Sour
cream dip,1,.25000,cup,.25000,.25000,1.00000,.04799,.00000,.04070,.00000,.00000,.00000,.04070,.00000,.00000,.00000,.00000,.00000,.00000,105.64850,1.57001,.00000,133.65000,7.36898\r\n13110100,\"Ice
cream, regular\",1,1.00000,cup,1.0000
This means we can reference the files by name—e.g., build_tables.sql
from our init containers. With this YAML file created, we can create the ConfigMap object in our cluster. Run the following command to create the ConfigMap:
oc create -f db-configmap.yaml
Here’s an example:
> oc create -f .\db-configmap.yaml
configmap/db-config created
At this point, the ConfigMap object exists in your cluster. It doesn’t do anything; it simply exists. But, it exists with the files we need inside of it. That is, the files are available for us to use. Referencing those files from the init containers is how we make use of it.
The next step is to create a Deployment object that includes init container objects that reference these files.
Create a Deployment object
In the Git repo home directory, this Deployment object is defined in the file mydeploy.yaml
. Rather than recreate the contents here, you can view the Kubernetes documentation for Init Containers to see how they work. Likewise, you can view the Kubernetes documentation related to configuring a pod to use a ConfigMap.
When those two pieces of knowledge are combined, you get a deployment that, in our case, includes the following (an explanation follows this section of the YAML file):
spec:
initContainers:
- name: init-createdb
image: postgres:14
command: ["psql", "postgresql://postgres:postgres@postgresql", "-f", "/etc/rsalbums/create_database.sql"]
volumeMounts:
- name: albums-volume
mountPath: /etc/rsalbums
- name: init-builddb
image: postgres:14
command: ["psql", "postgresql://postgres:postgres@postgresql/foods", "-f", "/etc/rsalbums/build_tables.sql"]
volumeMounts:
- name: albums-volume
mountPath: /etc/rsalbums
- name: init-populatedb
image: postgres:14
command: ["psql", "postgresql://postgres:postgres@postgresql/foods", "-c", "\\copy food FROM '/etc/rsalbums/fooddisplaytable.csv' CSV HEADER;"]
volumeMounts:
- name: albums-volume
mountPath: /etc/rsalbums
containers:
- name: getfood
image: quay.io/rhdevelopers/food-service:latest
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 8443
protocol: TCP
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext: {}
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
volumes:
- name: albums-volume
configMap:
name: db-config
In this deployment (mydeploy.yaml
) are three init containers and the container we want, eventually, to be up and running as our microservice (getfood
). The init containers use the image postgres:14
to run their commands. Why? Because the command being run is the PostgreSQL command-line tool, psql
, which allows us to run scripts and other commands against the PostgreSQL database instance that we created in Step 2.
Once those three init containers run, the getfood
container is started using the image specified. The food-service program reads from the database and returns a JSON array representing the entire table.
Congratulations! You've created an instance, a ConfigMap, and deployment objects. Now it’s time to deploy the application.