Overview #
Kubernetes Operator #
A Kubernetes Operator is like a manager, that runs and maintains specific applications in Kubernetes.
Custom Resource Definition (CRD) #
A Custom Resource Definition (CRD) in Kubernetes is a way to extend the built-in Kubernetes API by defining your own custom resources. These resources let you manage more than just the standard Kubernetes objects like Pods, Services, or Deployments.
-
A Custom Resource is like a new type of Kubernetes object. It can represent something specific like a database cluster.
-
The CRD is used to define the application-specific resources that the Operator will manage.
Postgres Operator #
The Postgres Operator is developed and maintained by Zalando.
Prerequisites #
Overview #
I’m using the following K3s Kubernetes cluster and an Ubuntu 22.04 based NFS server:
# Kubernetes Cluster
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ubuntu1 Ready control-plane,master 9m29s v1.30.5+k3s1 192.168.30.10 <none> Ubuntu 24.04.1 LTS 6.8.0-45-generic containerd://1.7.21-k3s2
ubuntu2 Ready worker 8m32s v1.30.5+k3s1 192.168.30.11 <none> Ubuntu 24.04.1 LTS 6.8.0-45-generic containerd://1.7.21-k3s2
ubuntu3 Ready worker 8m25s v1.30.5+k3s1 192.168.30.12 <none> Ubuntu 24.04.1 LTS 6.8.0-45-generic containerd://1.7.21-k3s2
ubuntu4 Ready worker 3m42s v1.30.5+k3s1 192.168.30.13 <none> Ubuntu 24.04.1 LTS 6.8.0-45-generic containerd://1.7.21-k3s2
192.168.30.90 # NFS server
NFS #
NFS Server Setup #
# Create directory for NFS share
sudo mkdir -p /srv/nfs/k8s_nfs-csi
# Open NFS configuration
sudo vi /etc/exports
# Define Kubernetes nodes
/srv/nfs/k8s_nfs-csi 192.168.30.10(rw,sync,no_root_squash)
/srv/nfs/k8s_nfs-csi 192.168.30.11(rw,sync,no_root_squash)
/srv/nfs/k8s_nfs-csi 192.168.30.12(rw,sync,no_root_squash)
/srv/nfs/k8s_nfs-csi 192.168.30.13(rw,sync,no_root_squash)
# Restart NFS server
sudo systemctl restart nfs-server
Install NFS Client on Kubernetes Nodes #
Install the NFS Client on all the Kubernetes nodes:
# Install NFS utilities package and rpcbind package
sudo apt install nfs-common rpcbind -y
Note: The “rpcbind” package is necessary for NFSv3, which relies on remote procedure calls (RPCs) for various operations.
Verify the NFS connectivity from the Kubernetes nodes:
# Verify that the NFS server is correctly configured
/usr/sbin/showmount -e 192.168.30.90
# Shell output:
Export list for 192.168.30.90:
/srv/nfs/k8s_nfs-csi 192.168.30.13,192.168.30.12,192.168.30.11,192.168.30.10
NFS CSI Driver #
Install Helm #
# Install Helm with script
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 &&
chmod +x get_helm.sh &&
./get_helm.sh
# Verify the installation / check version
helm version
CSI Setup #
Add the NFS CSI Helm repository:
# Add Helm repository & update repository index
helm repo add csi-driver-nfs https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts &&
helm repo update
Install CSI NFS Driver:
# Install the CSI NFS Driver
helm install csi-driver-nfs csi-driver-nfs/csi-driver-nfs --namespace kube-system
# Shell output:
NAME: csi-driver-nfs
LAST DEPLOYED: Tue Oct 1 13:18:27 2024
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The CSI NFS Driver is getting deployed to your cluster.
To check CSI NFS Driver pods status, please run:
kubectl --namespace=kube-system get pods --selector="app.kubernetes.io/instance=csi-driver-nfs" --watch
Verify CSI NFS Driver:
# List pods
kubectl --namespace=kube-system get pods --selector="app.kubernetes.io/instance=csi-driver-nfs" --watch
# Shell output: (Wait a while)
NAME READY STATUS RESTARTS AGE
csi-nfs-controller-868b6df87f-pwxcf 4/4 Running 1 (38s ago) 2m15s
csi-nfs-node-6w8t7 3/3 Running 1 (48s ago) 2m15s
csi-nfs-node-jvjrd 3/3 Running 1 (46s ago) 2m15s
csi-nfs-node-kwqxb 3/3 Running 1 (43s ago) 2m15s
csi-nfs-node-sfb8x 3/3 Running 1 (47s ago) 2m15s
Create Storage Class #
# Create a manifest for the storage class
vi csi-nfs-storage-class.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-csi
provisioner: nfs.csi.k8s.io # NFS CSI Driver
parameters:
server: 192.168.30.90
share: /srv/nfs/k8s_nfs-csi
reclaimPolicy: Retain
volumeBindingMode: Immediate
mountOptions:
- nfsvers=3
# Create storage class
kubectl apply -f csi-nfs-storage-class.yml
Verify Storage Class #
# List StorageClasses
kubectl get storageclasses
# Shell output:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 19h
nfs-csi nfs.csi.k8s.io Retain Immediate false 6s
Deploy Postgres Operator #
Add Helm Repository #
# Add postgres-operator repository
helm repo add postgres-operator-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator
# Add postgres-operator-ui repository
helm repo add postgres-operator-ui-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator-ui
# Update all Helm repositories
helm repo update
Install Postgres Operator #
# Install the postgres-operator
helm install postgres-operator postgres-operator-charts/postgres-operator
# Shell output:
NAME: postgres-operator
LAST DEPLOYED: Tue Oct 1 13:22:09 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
To verify that postgres-operator has started, run:
kubectl --namespace=default get pods -l "app.kubernetes.io/name=postgres-operator"
Optional, install the Postgres Operator UI:
# Install the postgres-operator-ui
helm install postgres-operator-ui postgres-operator-ui-charts/postgres-operator-ui
# Shell output:
NAME: postgres-operator-ui
LAST DEPLOYED: Tue Oct 1 13:22:58 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
To verify that postgres-operator has started, run:
kubectl --namespace=default get pods -l "app.kubernetes.io/name=postgres-operator-ui"
Verify the Installation #
# List pods
kubectl --namespace=default get pods -l "app.kubernetes.io/name=postgres-operator"
# Shell output:
NAME READY STATUS RESTARTS AGE
postgres-operator-75c8bb45cd-khcgj 1/1 Running 0 21s
# List pods
kubectl --namespace=default get pods -l "app.kubernetes.io/name=postgres-operator-ui"
# Shell output:
NAME READY STATUS RESTARTS AGE
postgres-operator-ui-659b45d69c-4z54b 0/1 Running 0 24s
Verify the CRDS
# List CRDs
kubectl get crds | grep postgresqls.acid.zalan.do
# Shell output:
postgresqls.acid.zalan.do 2024-10-01T13:22:09Z
Verify the Services:
# List services in the default namespace
kubectl get svc
# Shell ouput:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 19h
postgres-operator ClusterIP 10.43.120.44 <none> 8080/TCP 106s
postgres-operator-ui ClusterIP 10.43.162.216 <none> 80/TCP 57s
Access Postgres Operator UI #
Port Forwarding #
# Create a port forwarding for the Postgres Operator UI service
kubectl port-forward --address 0.0.0.0 svc/postgres-operator-ui 8081:80
# Access the Postgres Operator UI from an external host
http://192.168.30.10:8081
Treafik Ingress #
TLS Certificate #
In this setup I’m using a Let’s Encrypt wildcard certificate.
# Create a Kubernetes secret for the TLS certificate
kubectl create secret tls postgres-operator-tls --cert=./fullchain.pem --key=./privkey.pem
# Shell output:
secret/postgres-operator-tls created
# Verify the secret
kubectl get secrets
# Shell output:
NAME TYPE DATA AGE
postgres-operator-tls kubernetes.io/tls 2 41s
sh.helm.release.v1.postgres-operator-ui.v1 helm.sh/release.v1 1 14m
sh.helm.release.v1.postgres-operator.v1 helm.sh/release.v1 1 15m
# List secret details
kubectl describe secret postgres-operator-tls
# Shell output:
...
Data
====
tls.crt: 3578 bytes
tls.key: 1708 bytes
Deploy Ingress #
# Create a manifest for the ingress
vi postgres-operator-ui-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: postgres-operator-ui
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik
tls:
- hosts:
- "postgress-operator.jklug.work"
secretName: postgres-operator-tls
rules:
- host: "postgress-operator.jklug.work"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: postgres-operator-ui
port:
number: 80
# Deploy the ingress resource
kubectl apply -f postgres-operator-ui-ingress.yaml
# Verify the ingress resource
kubectl get ingress
# Shell output:
NAME CLASS HOSTS ADDRESS PORTS AGE
postgres-operator-ui traefik postgress-operator.jklug.work 192.168.30.10,192.168.30.11,192.168.30.12,192.168.30.13 80, 443 7s
DNS Entry #
# Create a DNS entry for the Postgress Operator UI
192.168.30.10 postgress-operator.jklug.work
Access the Postgres Operator UI #
# Open the Postgres Operator UI
https://postgress-operator.jklug.work/
Create Postgres Cluster #
Clone Postgres Operator Repository #
# Clone the Zalando postgres-operator repository
git clone https://github.com/zalando/postgres-operator.git &&
cd postgres-operator
Adopt the Postgres Cluster Manifest #
# Open the manifest
vi manifests/minimal-postgres-manifest.yaml
Original version:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: acid-minimal-cluster
spec:
teamId: "acid"
volume:
size: 1Gi
numberOfInstances: 2
users:
zalando: # database owner
- superuser
- createdb
foo_user: [] # role for application foo
databases:
foo: zalando # dbname: owner
preparedDatabases:
bar: {}
postgresql:
version: "16"
Add the NFS CSI storage class:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: postgres-cluster-1 # Define a name for the cluster
spec:
teamId: "project-1" # Define organizational name
volume:
size: 2Gi
storageClass: nfs-csi # Add the storage class
numberOfInstances: 3 # Define nodes number
users:
zalando: # database owner
- superuser
- createdb
foo_user: [] # role for application foo
databases:
foo: zalando # dbname: owner
preparedDatabases:
bar: {}
postgresql:
version: "16"
Create Postgres Cluster #
# Create a Postgres cluster
kubectl create -f manifests/minimal-postgres-manifest.yaml
# Shell output:
postgresql.acid.zalan.do/postgres-cluster-1 created
Verify the Postgres Cluster #
Verify the Postgres Cluster:
# Check the cluster deployment
kubectl get postgresql
# Shell output:
NAME TEAM VERSION PODS VOLUME CPU-REQUEST MEMORY-REQUEST AGE STATUS
postgres-cluster-1 project-1 16 3 2Gi 17s Creating
# Shell output: (Wait a view minutes)
NAME TEAM VERSION PODS VOLUME CPU-REQUEST MEMORY-REQUEST AGE STATUS
postgres-cluster-1 project-1 16 3 2Gi 2m28s Running
Verify the Postgres Node Pods:
# Verify the Postgres pods
kubectl get pods -l application=spilo -L spilo-role
# Shell output:
NAME READY STATUS RESTARTS AGE SPILO-ROLE
postgres-cluster-1-0 1/1 Running 0 2m43s master
postgres-cluster-1-1 1/1 Running 0 2m12s replica
postgres-cluster-1-2 1/1 Running 0 99s replica
# List pods in "default" namespace
kubectl get pods
# Shell output:
NAME READY STATUS RESTARTS AGE
postgres-cluster-1-0 1/1 Running 0 2m56s
postgres-cluster-1-1 1/1 Running 0 2m25s
postgres-cluster-1-2 1/1 Running 0 112s
postgres-operator-75c8bb45cd-khcgj 1/1 Running 0 25m
postgres-operator-ui-659b45d69c-4z54b 1/1 Running 0 24m
Verify the Services:
# Verify the services
kubectl get svc -l application=spilo -L spilo-role
# Shell output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SPILO-ROLE
postgres-cluster-1 ClusterIP 10.43.190.173 <none> 5432/TCP 3m7s master
postgres-cluster-1-config ClusterIP None <none> <none> 2m34s
postgres-cluster-1-repl ClusterIP 10.43.45.69 <none> 5432/TCP 3m7s replica
Verify the Persistent Volume Claim #
# List Persistent Volume Claims
kubectl get pvc
# Shell output:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
pgdata-postgres-cluster-1-0 Bound pvc-459c0e99-ee90-4005-88d8-c6dbea13abe8 2Gi RWO nfs-csi <unset> 3m21s
pgdata-postgres-cluster-1-1 Bound pvc-ac08f468-25bd-4e11-98d3-267f59a2b234 2Gi RWO nfs-csi <unset> 2m50s
pgdata-postgres-cluster-1-2 Bound pvc-a71f346f-4dd4-40f9-aa49-8be8b4034172 2Gi RWO nfs-csi <unset> 2m17s
# Verify the volumes on the NFS server
ls -la /srv/nfs/k8s_nfs-csi/
# Shell output:
drwxr-xr-x 3 root root 4096 Oct 1 13:44 pvc-459c0e99-ee90-4005-88d8-c6dbea13abe8
drwxr-xr-x 3 root root 4096 Oct 1 13:45 pvc-a71f346f-4dd4-40f9-aa49-8be8b4034172
drwxr-xr-x 3 root root 4096 Oct 1 13:45 pvc-ac08f468-25bd-4e11-98d3-267f59a2b234
Test the Cluster Failover #
Connect to Master Pod / Node #
Connect to the Postgres master pod and create an example database.
- Create a port forwarding to the master node
# Export master node pod name
export PGMASTER=$(kubectl get pods -o jsonpath={.items..metadata.name} -l application=spilo,cluster-name=postgres-cluster-1,spilo-role=master -n default)
# Create port forwarding
kubectl port-forward $PGMASTER 5432:5432 -n default
- Open another shell:
# Install Postgres client
sudo apt install postgresql-client -y
# Export the password etrieved from the Postgres Kubernetes secret
export PGPASSWORD=$(kubectl get secret postgres.postgres-cluster-1.credentials.postgresql.acid.zalan.do -o 'jsonpath={.data.password}' | base64 -d)
export PGSSLMODE=require
export PGSSLMODE=require
Ensures that the PostgreSQL client will require an SSL connection when connecting to the database
# Connect to Postgres
psql -U postgres -h localhost -p 5432
- Create an example database and some tables
# Create example database "example_database"
create database example_database;
# Connect to "example_database" database
\c example_database
# Create some tables
create table some_table_1(a varchar(100), b timestamp);
create table some_table_2(a varchar(100), b timestamp);
create table some_table_3(a varchar(100), b timestamp);
# Insert some values
insert into some_table_1 values('some value', '2024-01-01 01:01:01');
insert into some_table_2 values('some value', '2024-01-01 01:01:01');
insert into some_table_3 values('some value', '2024-01-01 01:01:01');
- List the tables in the example database
# List and describe object in current database
\d
# Shell output:
List of relations
Schema | Name | Type | Owner
--------+-------------------------+-------+----------
public | pg_stat_kcache | view | postgres
public | pg_stat_kcache_detail | view | postgres
public | pg_stat_statements | view | postgres
public | pg_stat_statements_info | view | postgres
public | some_table_1 | table | postgres
public | some_table_2 | table | postgres
public | some_table_3 | table | postgres
(7 rows)
# Exit
\q
- Stop the port forwarding to the master node pod
Delete Master Node #
List the Postgres pods:
# Verify the Postgres Pods
kubectl get pods -l application=spilo -L spilo-role
# Shell output:
NAME READY STATUS RESTARTS AGE SPILO-ROLE
postgres-cluster-1-0 1/1 Running 0 7m10s master
postgres-cluster-1-1 1/1 Running 0 6m39s replica
postgres-cluster-1-2 1/1 Running 0 6m6s replica
Delete the Master Pod:
# Delete the master pod
kubectl delete pod postgres-cluster-1-0
# Shell output:
pod "postgres-cluster-1-0" deleted
List the Postgres pods: Verify the new replica node
# Verify the Postgres Pods
kubectl get pods -l application=spilo -L spilo-role
# Shell output:
NAME READY STATUS RESTARTS AGE SPILO-ROLE
postgres-cluster-1-0 1/1 Running 0 15s replica
postgres-cluster-1-1 1/1 Running 0 7m21s replica
postgres-cluster-1-2 1/1 Running 0 6m48s master
Check the Logs #
Optional, check the logs:
# List the Postgres Pods / Nodes logs:
kubectl logs postgres-cluster-1-0
kubectl logs postgres-cluster-1-1
kubectl logs postgres-cluster-1-2
Verify Data Persistence #
Verify the data persistence after the failover.
- Create a port forwarding to the master node
# Create port forwarding
kubectl port-forward $PGMASTER 5432:5432 -n default
- Open another shell
# Export the password etrieved from the Postgres Kubernetes secret
export PGPASSWORD=$(kubectl get secret postgres.postgres-cluster-1.credentials.postgresql.acid.zalan.do -o 'jsonpath={.data.password}' | base64 -d)
export PGSSLMODE=require
# Connect to Postgres
psql -U postgres -h localhost -p 5432
# Connect to the "example_database" database
\c example_database
# List and describe object in current database
\d
# Shell output:
List of relations
Schema | Name | Type | Owner
--------+-------------------------+-------+----------
public | pg_stat_kcache | view | postgres
public | pg_stat_kcache_detail | view | postgres
public | pg_stat_statements | view | postgres
public | pg_stat_statements_info | view | postgres
public | some_table_1 | table | postgres
public | some_table_2 | table | postgres
public | some_table_3 | table | postgres
(7 rows)
# Verify the values from table1
select * from some_table_1;
# Shell output:
a | b
------------+---------------------
some value | 2024-01-01 01:01:01
(1 row)
# Exit
\q
Verify the Cluster Status from within a Pod #
Exec Pod Terminal #
# Exec the terminal of one of the Postgres node pods
kubectl exec -it postgres-cluster-1-0 -- /bin/bash
List Postgres Nodes #
# List Postgres nodes
patronictl list
# Shell output:
+ Cluster: postgres-cluster-1 (7420802808068677691) -----+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+----------------------+-----------+---------+-----------+----+-----------+
| postgres-cluster-1-0 | 10.42.2.6 | Replica | streaming | 2 | 0 |
| postgres-cluster-1-1 | 10.42.3.5 | Replica | streaming | 2 | 0 |
| postgres-cluster-1-2 | 10.42.1.4 | Leader | running | 2 | |
+----------------------+-----------+---------+-----------+----+-----------+
-
Patroni
Is a high-availability (HA) solution for PostgreSQL clusters -
patronictl list
- Lists a detailed overview of the current state of the PostgreSQL cluster managed by Patroni.
Connect to Database #
# Switch to the postgres user
su - postgres
# Connect to the default db
psql -d postgres
# List all databases
\l
# Shell output:
List of databases
Name | Owner | Encoding | Locale Provider | Collate | Ctype | ICU Locale | ICU Rules | Access privileges
------------------+-----------+----------+-----------------+-------------+-------------+------------+-----------+-----------------------
bar | bar_owner | UTF8 | libc | en_US.utf-8 | en_US.utf-8 | | |
example_database | postgres | UTF8 | libc | en_US.utf-8 | en_US.utf-8 | | |
foo | zalando | UTF8 | libc | en_US.utf-8 | en_US.utf-8 | | |
postgres | postgres | UTF8 | libc | en_US.utf-8 | en_US.utf-8 | | |
template0 | postgres | UTF8 | libc | en_US.utf-8 | en_US.utf-8 | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | libc | en_US.utf-8 | en_US.utf-8 | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
(6 rows)
# Exit
\q
# Exit the terminal
exit
External Access via Master LoadBalancer #
Adopt the Postgres Cluster Manifest #
# Adopt the Postgres cluster manifest
vi manifests/minimal-postgres-manifest.yaml
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: postgres-cluster-1
spec:
teamId: "project-1"
volume:
size: 2Gi
storageClass: nfs-csi
enableMasterLoadBalancer: true # Enable LoadBalancer
numberOfInstances: 3
users:
zalando:
- superuser
- createdb
foo_user: []
databases:
foo: zalando
preparedDatabases:
bar: {}
postgresql:
version: "16"
# Update the Postgres cluster with the master LB
kubectl apply -f manifests/minimal-postgres-manifest.yaml
Verify the Master LoadBalancer #
# List services
kubectl get svc
# Shell output: Previous output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 20h
postgres-cluster-1 ClusterIP 10.43.190.173 <none> 5432/TCP 21m
postgres-cluster-1-config ClusterIP None <none> <none> 20m
postgres-cluster-1-repl ClusterIP 10.43.45.69 <none> 5432/TCP 21m
postgres-operator ClusterIP 10.43.120.44 <none> 8080/TCP 43m
postgres-operator-ui ClusterIP 10.43.162.216 <none> 80/TCP 42m
# Shell output: Verify the LoadBalancer service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 20h
postgres-cluster-1 LoadBalancer 10.43.190.173 192.168.30.10,192.168.30.11,192.168.30.12,192.168.30.13 5432:31315/TCP 29m
postgres-cluster-1-config ClusterIP None <none> <none> 29m
postgres-cluster-1-repl ClusterIP 10.43.45.69 <none> 5432/TCP 29m
postgres-operator ClusterIP 10.43.120.44 <none> 8080/TCP 52m
postgres-operator-ui ClusterIP 10.43.162.216 <none> 80/TCP 51m
Retrieve Postgres Password #
# List the Postgres cluster secrets
kubectl get secret |grep postgres-cluster-1
# Shell output:
foo-user.postgres-cluster-1.credentials.postgresql.acid.zalan.do Opaque 2 35m
postgres.postgres-cluster-1.credentials.postgresql.acid.zalan.do Opaque 2 35m
standby.postgres-cluster-1.credentials.postgresql.acid.zalan.do Opaque 2 35m
zalando.postgres-cluster-1.credentials.postgresql.acid.zalan.do Opaque 2 35m
# Print Postgres PW to shell
export PGPASSWORD=$(kubectl get secret postgres.postgres-cluster-1.credentials.postgresql.acid.zalan.do -o 'jsonpath={.data.password}' | base64 -d)
echo "PGPASSWORD=$PGPASSWORD"
# Shell output:
PGPASSWORD=iCLGF9PQjbcPhi7XH92YJKEX1znUF4dVYcHumcaUQ4hUo31EhlnlfFJii7kyUiLl
Connect from External Host #
Install Postgres Client #
# Install Postgres client
sudo apt install postgresql-client -y
Export the Postgres PW #
# Export the password on the external host
export PGPASSWORD=iCLGF9PQjbcPhi7XH92YJKEX1znUF4dVYcHumcaUQ4hUo31EhlnlfFJii7kyUiLl
export PGSSLMODE=require
export PGSSLMODE=require
Ensures that the PostgreSQL client will require an SSL connection when connecting to the database
Connect to Postgres DB #
# Connect to the database
psql -U postgres -h 192.168.30.10 -p 31315
# List all databases
\l
# Shell output:
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
------------------+-----------+----------+-------------+-------------+-----------------------
bar | bar_owner | UTF8 | en_US.utf-8 | en_US.utf-8 |
example_database | postgres | UTF8 | en_US.utf-8 | en_US.utf-8 |
foo | zalando | UTF8 | en_US.utf-8 | en_US.utf-8 |
postgres | postgres | UTF8 | en_US.utf-8 | en_US.utf-8 |
template0 | postgres | UTF8 | en_US.utf-8 | en_US.utf-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf-8 | en_US.utf-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(6 rows)
Links #
# Official Documentation
https://github.com/zalando/postgres-operator/blob/master/docs/quickstart.md