Postgres

Preparation

As we want to make use of the database from all kinds of clients - particualarly arm clients that don’t have mass storage (e.g. raspberry pi) - we will put the database data files on external persistent storage which was created before.

Prerequisites are:

Install postgres

cd ~/homekube/src/postgres
. ./install.sh

Once installed the postgres namespace should look like

root@homekube:~# kubectl get all -n postgres
NAME             READY   STATUS    RESTARTS      AGE
pod/postgres-0   1/1     Running   1 (19h ago)   21h

NAME                          TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/postgres-service-np   NodePort   10.152.183.37   <none>        5432:30100/TCP   21h

NAME                        READY   AGE
statefulset.apps/postgres   1/1     21h

Checking container-local availability

# Step into the postgres container with a bash shell
kubectl exec -it -n postgres postgres-0 -- bash 
# Connect with the postgres (or homekube) database
psql -U admin -d postgres

As an admin user with local admin permissions connect with the postgres (or homekube) database and execute \l for a list of existing databases. Then \q will quit psql.
NOTE that we don’t need to specify a host as localhost is the default and we don’t need to authenticate as long as 1) the user exist with sufficient privileges (We created user admin during installation of postgres ) 2) Trust authentication is configured for local access (default)

root@postgres-0:/# psql -U admin -d postgres
psql (16.3 (Debian 16.3-1.pgdg120+1))
Type "help" for help.

postgres=# \l
                                                   List of databases
   Name    | Owner | Encoding | Locale Provider |  Collate   |   Ctype    | ICU Locale | ICU Rules | Access privileges 
-----------+-------+----------+-----------------+------------+------------+------------+-----------+-------------------
 homekube  | admin | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | 
 postgres  | admin | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | 
 template0 | admin | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | =c/admin         +
           |       |          |                 |            |            |            |           | admin=CTc/admin
 template1 | admin | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | =c/admin         +
           |       |          |                 |            |            |            |           | admin=CTc/admin
(4 rows)

postgres=# \q
root@postgres-0:/# 

Checking cluster-local availability

Now lets do another check to confirm that we can connect to the database from inside the cluster. For this we install another instance of postgres. Actually we only need the psql client but its just simpler to use the same image.

kubectl run -it postgres-client --image=postgres:16 --restart=Never -- bash
# then execute
psql -U admin postgresql://postgres-service-np.postgres/homekube

We connect with user admin via the postgresql driver to the service instance postgres-service-np in the namespace postgres to the database homekube.
As this is cluster-local in contrast to container-local Trust authentication doesn’t kick in and we need to supply credentials for authorization.

root@postgres-client:/# psql -U admin postgresql://postgres-service-np.postgres/homekube
Password for user admin: 
psql (16.3 (Debian 16.3-1.pgdg120+1))
Type "help" for help.

homekube=# \l
                                                   List of databases
   Name    | Owner | Encoding | Locale Provider |  Collate   |   Ctype    | ICU Locale | ICU Rules | Access privileges 
-----------+-------+----------+-----------------+------------+------------+------------+-----------+-------------------
 homekube  | admin | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | 
 postgres  | admin | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | 
 template0 | admin | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | =c/admin         +
           |       |          |                 |            |            |            |           | admin=CTc/admin
 template1 | admin | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | =c/admin         +
           |       |          |                 |            |            |            |           | admin=CTc/admin
(4 rows)

homekube=# \q
root@postgres-client:/# 
# cleanup - remove the helper pod
kubectl delete po postgres-client

Checking local network availability

Local network availability is a very useful option for deeper inspection of the database during development. For this we need to install the postgres client on our developer machine in the local network. Or as an alternative we can use a client wih a visual ui. There a various options and I’m using “official” postgres frontend pgAdmin. It offers numerous installation option for the different os and a web based version too.

Lets first check the ip address of our lxc container containing our homekube cluster in the local network:

ubuntu@pi1:~$ lxc list homekube
+----------+---------+-----------------------------+------+-----------+-----------+
| NAME     |  STATE  |            IPV4             | IPV6 |   TYPE    | SNAPSHOTS |
+----------+---------+-----------------------------+------+-----------+-----------+
| homekube | RUNNING | 192.168.1.100 (eth0)        |      | CONTAINER | 0         |
|          |         | 10.1.103.192 (vxlan.calico) |      |           |           |
+----------+---------+-----------------------------+------+-----------+-----------+

Install the client on your developer machine following the instructions Create a server with the following properties:

1) On the General tab name the service as you like, e.g. “Homekube”
2) On the Connection tab fill in the values from our configuration.
2.1) The hostname/address is the IP of the clusters host in your local network (e.g. 192.168.1.100)
2.2) The port is the nodePort (30100) we configured during database creation
2.3) As the maintenance database we can either specify postgres or homekube
2.4) Username is admin as given during installation
2.5) Password is the ${HOMEKUBE_PG_PASSWORD} from your environment settings during installation

Cleanup

kubectl delete ns postgres
kubectl delete pv postgres-pv

Useful tips

Create a scram-sha-256 hash

This is useful to avoid using plain text passwords. Postgres supports md5 and scram-sha-256 hashes. It is a better approach to use passwords in environment variables. Thats what we do in our install.sh scripts. This is an alternative way (which is considered less safe) to supply passwords. Here is an easy way to create one.

# psql into our homekube database with admin permissions
root@homekube:~# kubectl exec -it -n postgres postgres-0 -- psql -U admin -d homekube
psql (16.3 (Debian 16.3-1.pgdg120+1))
Type "help" for help.

homekube=# 

Lets create a user ‘test’ and assign a password of your choice (e.g. ‘your_password’)

show password_encryption; -- should be 'scram-sha-256' (default from Postgres version 14) or older 'md5'
-- SET password_encryption  = 'scram-sha-256'; -- or ALTER SYSTEM SET password_encryption = 'scram-sha-256';
CREATE USER test with password 'your_password';
SELECT rolpassword FROM pg_catalog.pg_authid WHERE rolname = 'test';
drop user test;
\q

Use the rolpassword from console output

CREATE ROLE
                                                              rolpassword                                                              
---------------------------------------------------------------------------------------------------------------------------------------
 SCRAM-SHA-256$4096:tTGGLga+/GtT1SeNTvE84w==$omR6+uiZE2VQlW6afdI/Q1+5P9i+G3ush3YqSeXn46I=:7JYgIBChLnwjIHpmjkflyUTWnp97laRChQRxdex5to8=
(1 row)

Use the whole prompt as password e.g.
SCRAM-SHA-256$4096:tTGGLga+/GtT1SeNTvE84w==$omR6+uiZE2VQlW6afdI/Q1+5P9i+G3ush3YqSeXn46I=:7JYgIBChLnwjIHpmjkflyUTWnp97laRChQRxdex5to8=