Connect to a Postgres Cluster
It’s one thing to create a Postgres cluster; it’s another thing to connect to it. Let’s explore how PGO makes it possible to connect to a Postgres cluster!
Background: Services, Secrets, and TLS
PGO creates a series of Kubernetes Services to provide stable endpoints for connecting to your Postgres databases. These endpoints make it easy to provide a consistent way for your application to maintain connectivity to your data. To inspect what services are available, you can run the following command:
kubectl -n postgres-operator get svc --selector=postgres-operator.crunchydata.com/cluster=hippo
will yield something similar to:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hippo-ha ClusterIP 10.103.73.92 <none> 5432/TCP 3h14m
hippo-ha-config ClusterIP None <none> <none> 3h14m
hippo-pods ClusterIP None <none> <none> 3h14m
hippo-primary ClusterIP None <none> 5432/TCP 3h14m
hippo-replicas ClusterIP 10.98.110.215 <none> 5432/TCP 3h14m
You do not need to worry about most of these Services, as they are used to help manage the overall health of your Postgres cluster. For the purposes of connecting to your database, the Service of interest is called hippo-primary
. Thanks to PGO, you do not need to even worry about that, as that information is captured within a Secret!
When your Postgres cluster is initialized, PGO will bootstrap a database and Postgres user that your application can access. This information is stored in a Secret named with the pattern <clusterName>-pguser-<userName>
. For our hippo
cluster, this Secret is called hippo-pguser-hippo
. This Secret contains the information you need to connect your application to your Postgres database:
user
: The name of the user account.password
: The password for the user account.dbname
: The name of the database that the user has access to by default.host
: The name of the host of the database. This references the Service of the primary Postgres instance.port
: The port that the database is listening on.uri
: A PostgreSQL connection URI that provides all the information for logging into the Postgres database.jdbc-uri
: A PostgreSQL JDBC connection URI that provides all the information for logging into the Postgres database via the JDBC driver.
All connections are over TLS. PGO provides its own certificate authority (CA) to allow you to securely connect your applications to your Postgres clusters. This allows you to use the verify-full
“SSL mode” of Postgres, which provides eavesdropping protection and prevents MITM attacks. You can also choose to bring your own CA, which is described later in this tutorial in the Customize Cluster section.
Modifying Service Type
By default, PGO deploys Services with the ClusterIP
Service type. Based on how you want to expose your database, you may want to modify the Services to use a different Service type.
You can modify the Services that PGO manages from the following attributes:
spec.service
- this manages the Service for connecting to a Postgres primary.spec.proxy.pgBouncer.service
- this manages the Service for connecting to the PgBouncer connection pooler.
For example, to set the Postgres primary to use a NodePort
service, you would add the following to your manifest:
spec:
service:
type: NodePort
For our hippo
cluster, you would see the Service type modification in the . For example:
kubectl -n postgres-operator get svc --selector=postgres-operator.crunchydata.com/cluster=hippo
will yield something similar to:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hippo-ha NodePort 10.96.17.210 <none> 5432:32751/TCP 2m37s
hippo-ha-config ClusterIP None <none> <none> 2m37s
hippo-pods ClusterIP None <none> <none> 2m37s
hippo-primary ClusterIP None <none> 5432/TCP 2m37s
hippo-replicas ClusterIP 10.96.151.53 <none> 5432/TCP 2m37s
(Note that if you are exposing your Services externally and are relying on TLS verification, you will need to use the custom TLS features of PGO).
Connect an Application
For this tutorial, we are going to connect Keycloak, an open source
identity management application. Keycloak can be deployed on Kubernetes and is backed by a Postgres
database. While we provide an example of deploying Keycloak and a PostgresCluster
in the Postgres Operator examples
repository, the manifest below deploys it using our hippo
cluster that is already running:
kubectl apply --filename=- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak
namespace: postgres-operator
labels:
app.kubernetes.io/name: keycloak
spec:
selector:
matchLabels:
app.kubernetes.io/name: keycloak
template:
metadata:
labels:
app.kubernetes.io/name: keycloak
spec:
containers:
- image: quay.io/keycloak/keycloak:latest
args: ["start-dev"]
name: keycloak
env:
- name: DB_VENDOR
value: "postgres"
- name: DB_ADDR
valueFrom: { secretKeyRef: { name: hippo-pguser-hippo, key: host } }
- name: DB_PORT
valueFrom: { secretKeyRef: { name: hippo-pguser-hippo, key: port } }
- name: DB_DATABASE
valueFrom: { secretKeyRef: { name: hippo-pguser-hippo, key: dbname } }
- name: DB_USER
valueFrom: { secretKeyRef: { name: hippo-pguser-hippo, key: user } }
- name: DB_PASSWORD
valueFrom: { secretKeyRef: { name: hippo-pguser-hippo, key: password } }
- name: KEYCLOAK_ADMIN
value: "admin"
- name: KEYCLOAK_ADMIN_PASSWORD
value: "admin"
- name: KC_PROXY
value: "edge"
ports:
- name: http
containerPort: 8080
- name: https
containerPort: 8443
readinessProbe:
httpGet:
path: /realms/master
port: 8080
restartPolicy: Always
EOF
Notice this part of the manifest:
- name: DB_ADDR
valueFrom: { secretKeyRef: { name: hippo-pguser-hippo, key: host } }
- name: DB_PORT
valueFrom: { secretKeyRef: { name: hippo-pguser-hippo, key: port } }
- name: DB_DATABASE
valueFrom: { secretKeyRef: { name: hippo-pguser-hippo, key: dbname } }
- name: DB_USER
valueFrom: { secretKeyRef: { name: hippo-pguser-hippo, key: user } }
- name: DB_PASSWORD
valueFrom: { secretKeyRef: { name: hippo-pguser-hippo, key: password } }
The above manifest shows how all of these values are derived from the hippo-pguser-hippo
Secret. This means that we do not need to know any of the connection credentials or have to insecurely pass them around – they are made directly available to the application!
Using this method, you can tie application directly into your GitOps pipeline that connect to Postgres without any prior knowledge of how PGO will deploy Postgres: all of the information your application needs is propagated into the Secret!
Next Steps
Now that we have seen how to connect an application to a cluster, let’s learn how to create a high availability Postgres cluster!