1. Answers
  2. Managing PostgreSQL connection pools in a Kubernetes cluster

How do I manage PostgreSQL connection pools in a Kubernetes cluster?

In this guide, we will set up and manage PostgreSQL connection pools in a Kubernetes cluster using Pulumi. This involves deploying a PostgreSQL database and configuring a connection pool manager such as PgBouncer to optimize database connections.

The steps include:

  1. Setting up a PostgreSQL database.
  2. Deploying PgBouncer for connection pooling.
  3. Configuring Kubernetes services and deployments for PostgreSQL and PgBouncer.
import * as pulumi from "@pulumi/pulumi";
import * as k8s from "@pulumi/kubernetes";

// Define the PostgreSQL deployment
const postgresDeployment = new k8s.apps.v1.Deployment("postgres-deployment", {
    spec: {
        selector: { matchLabels: { app: "postgres" } },
        replicas: 1,
        template: {
            metadata: { labels: { app: "postgres" } },
            spec: {
                containers: [{
                    name: "postgres",
                    image: "postgres:13",
                    ports: [{ containerPort: 5432 }],
                    env: [
                        { name: "POSTGRES_DB", value: "mydatabase" },
                        { name: "POSTGRES_USER", value: "myuser" },
                        { name: "POSTGRES_PASSWORD", value: "mypassword" }
                    ],
                    volumeMounts: [{
                        name: "postgres-storage",
                        mountPath: "/var/lib/postgresql/data"
                    }]
                }],
                volumes: [{
                    name: "postgres-storage",
                    persistentVolumeClaim: {
                        claimName: "postgres-pvc"
                    }
                }]
            }
        }
    }
});

// Define the PostgreSQL service
const postgresService = new k8s.core.v1.Service("postgres-service", {
    spec: {
        selector: { app: "postgres" },
        ports: [{ port: 5432, targetPort: 5432 }]
    }
});

// Define the PersistentVolumeClaim for PostgreSQL
const postgresPVC = new k8s.core.v1.PersistentVolumeClaim("postgres-pvc", {
    spec: {
        accessModes: ["ReadWriteOnce"],
        resources: {
            requests: {
                storage: "10Gi"
            }
        }
    }
});

// Define the PgBouncer deployment
const pgbouncerDeployment = new k8s.apps.v1.Deployment("pgbouncer-deployment", {
    spec: {
        selector: { matchLabels: { app: "pgbouncer" } },
        replicas: 1,
        template: {
            metadata: { labels: { app: "pgbouncer" } },
            spec: {
                containers: [{
                    name: "pgbouncer",
                    image: "edoburu/pgbouncer",
                    ports: [{ containerPort: 6432 }],
                    env: [
                        { name: "DATABASE_URL", value: "postgres://myuser:mypassword@postgres-service:5432/mydatabase" }
                    ],
                    volumeMounts: [{
                        name: "pgbouncer-config",
                        mountPath: "/etc/pgbouncer"
                    }]
                }],
                volumes: [{
                    name: "pgbouncer-config",
                    configMap: {
                        name: "pgbouncer-config"
                    }
                }]
            }
        }
    }
});

// Define the PgBouncer service
const pgbouncerService = new k8s.core.v1.Service("pgbouncer-service", {
    spec: {
        selector: { app: "pgbouncer" },
        ports: [{ port: 6432, targetPort: 6432 }]
    }
});

// Define the ConfigMap for PgBouncer configuration
const pgbouncerConfigMap = new k8s.core.v1.ConfigMap("pgbouncer-config", {
    data: {
        "pgbouncer.ini": `
[databases]
mydatabase = host=postgres-service port=5432 dbname=mydatabase user=myuser password=mypassword

[pgbouncer]
listen_addr = *
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = session
max_client_conn = 100
default_pool_size = 20
`
    }
});

// Define the Secret for PgBouncer userlist
const pgbouncerSecret = new k8s.core.v1.Secret("pgbouncer-secret", {
    stringData: {
        "userlist.txt": `"myuser" "mypassword"`
    }
});

export const postgresServiceName = postgresService.metadata.name;
export const pgbouncerServiceName = pgbouncerService.metadata.name;

Key Points

  • PostgreSQL Deployment: Defines a PostgreSQL database instance with environment variables for database name, user, and password.
  • PostgreSQL Service: Exposes the PostgreSQL database internally within the cluster.
  • PersistentVolumeClaim: Ensures persistent storage for PostgreSQL data.
  • PgBouncer Deployment: Sets up PgBouncer, a lightweight connection pooler for PostgreSQL.
  • PgBouncer Service: Exposes PgBouncer internally within the cluster.
  • ConfigMap and Secret: Configures PgBouncer with database connection details and user credentials.

Summary

We have successfully set up a PostgreSQL database and a PgBouncer connection pooler in a Kubernetes cluster using Pulumi. This setup ensures efficient management of database connections, improving the performance and scalability of your applications.

Deploy this code

Want to deploy this code? Sign up for a free Pulumi account to deploy in a few clicks.

Sign up

New to Pulumi?

Want to deploy this code? Sign up with Pulumi to deploy in a few clicks.

Sign up