I realized there were a few mistakes here after posting this question...
I used PostgreSQL 11 for replication prior so I assumed they worked the same way (which of course is wrong, there are some changes). The
recovery.confis omitted from PostgreSQL 12 and it gave this error messageFATAL: XX000: using recovery command file "recovery.conf" is not supportedwhen I had it. so I had to remove it from my ConfigMap.I confused about Docker's
Entrypoint & Commandto Kubernetes'Command & Args. After being corrected by my senior that KubernetesCommandwill override the DockerEntrypoint, I'm going to need and use onlyArgsafterwards.
The following are the changes I made to my ConfigMap and Deployment.
apiVersion: v1
kind: ConfigMap
metadata:
name: pg-replica
labels:
app: postgres
name: pg-replica
data:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: mypassword
pg_hba.conf: |
# Contents
postgresql.conf: |
data_directory = '/var/lib/postgresql/data'
# the contents from recovery.conf are integrated into postgresql.conf
primary_conninfo = # host address and authentication credentials
promote_trigger_file = # trigger file path
extra.sh: |
#!/bin/sh
postgres -D /var/lib/postgresql
---
apiVersion: v1
kind: Service
metadata:
name: pg-replica
labels:
app: postgres
name: pg-replica
spec:
type: NodePort
ports:
- nodePort: 31000
port: 5432
selector:
app: postgres
name: pg-replica
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: pg-replica
spec:
selector:
matchLabels:
app: postgres
name: pg-replica
replicas: 1
template:
metadata:
labels:
app: postgres
name: pg-replica
spec:
containers:
- name: pg-replica
image: postgres:latest
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 5432
envFrom:
- configMapRef:
name: pg-replica
volumeMounts:
- name: pg-replica
mountPath: /var/lib/postgresql/data
- name: replica-config
mountPath: /var/lib/postgresql/postgresql.conf
subPath: postgresql.conf
- name: replica-config
mountPath: /var/lib/postgresql/pg_hba.conf
subPath: pg_hba.conf
- name: replica-config
mountPath: /docker-entrypoint-initdb.d/extra.sh
subPath: extra.sh
args:
- "-c"
- "config_file=/var/lib/postgresql/postgresql.conf"
- "-c"
- "hba_file=/var/lib/postgresql/pg_hba.conf"
volumes:
- name: pg-replica
persistentVolumeClaim:
claimName: pv-replica-claim
- name: replica-config
configMap:
name: pg-replica
The arguments in Args will set the location of the .conf files to where I specified.
For further steps in Replication:
After the pod is up, I manually ran the pod's shell with
kubectl exec.I removed all the files from the
data-directoryfor step 3 (to copy files from master pod).
rm -rf /var/lib/postgresql/data/*
- Use
pg_basebackupto backup data from master node.
pg_basebackup -h <host IP> --port=<port number used> -D /var/lib/postgresql/data -P -U replica -R -X stream
And that's it. Now I managed to have my pg-replica pod replicating my master pod.
As mentioned in comments, I really encorage you to use the Postgres Helm chart to setup yout environment.
The way you solved the issue could work, but if the pod died for some reason, all work you have done will be lost and you'll need to reconfigure everything again.
Here you can found all information about how to create a postgres deployment with high availability and replication.
To install HELM you can follow this guide.
You can use Kubernetes postStart lifecycle hook to create your schema on given Postgres DB. Just update your deployment file with the lifecycle block.
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: postgres
name: postgres
spec:
containers:
- image: postgres:10.4
name: postgres
resources: {}
lifecycle:
postStart:
exec:
command: ["/bin/bash","-c","sleep 20 && PGPASSWORD=$POSTGRES_PASSWORD psql $POSTGRES_DB -U $POSTGRES_USER -c \'CREATE SCHEMA IF NOT EXISTS key;\'"]
envFrom:
- configMapRef:
name: postgres-config
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: data
dnsPolicy: ClusterFirst
restartPolicy: Never
volumes:
- name: data
emptyDir: {}
status: {}
For your use-case, it is better to setup PostgreSQL using Helm charts, for e.g.:
helm install stable/postgresql \
--set global.postgresql.postgresqlDatabase=postgresdb \
--set global.postgresql.postgresqlUsername=postgresadmin \
--set global.postgresql.postgresqlPassword=admin123 \
--set global.postgresql.servicePort=5432 \
--set initdbScripts."init\.sql"="CREATE SCHEMA IF NOT EXISTS key;"