Skip to content

yusufnar/pgpool-docker-lb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

25 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Pgpool-II PostgreSQL Read Load Balancing Setup

This project demonstrates read load balancing for PostgreSQL using Pgpool-II and Docker Compose. It distributes SELECT queries across multiple streaming replicas while directing all write operations to the primary server.

Note: This setup focuses on read scaling and connection pooling. It does not include automatic primary failover (promoting a replica to primary).

πŸ—οΈ Architecture

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   Application   β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                             β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚    Pgpool-II    β”‚ ← Port 5433 (Load Balancer)
                    β”‚  (Connection    β”‚
                    β”‚   Pooler +      β”‚
                    β”‚   Read LB)      β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚                   β”‚                   β”‚
         β–Ό                   β–Ό                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   pg-primary    β”‚ β”‚   pg-replica1    β”‚ β”‚   pg-replica2    β”‚
β”‚  (Write Only)   β”‚ β”‚   (Read Only)    β”‚ β”‚   (Read Only)    β”‚
β”‚   weight = 0    β”‚ β”‚   weight = 1     β”‚ β”‚   weight = 1     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

✨ Features

  • βš–οΈ Read Load Balancing: SELECT queries distributed across replicas (primary has weight 0)
  • πŸ”„ Streaming Replication: WAL-based replication using physical replication slots
  • πŸ₯ Health Check: Backend health monitoring every 1 second
  • πŸ•’ Replication Lag Detection: Replicas with lag > 1 second are excluded from load balancing
  • πŸ” Auto Failback: Recovered replicas automatically re-added to the read pool
  • 🏊 Connection Pooling: 64 child processes, 2 connections per backend each (max 384 connections)
  • 🐳 Custom Dockerfile: Full control over Pgpool configuration

🐳 Container Images

Container Image Description
pg-primary postgres:17 Official PostgreSQL 17 image (primary)
pg-replica1 postgres:17 Official PostgreSQL 17 image (streaming replica)
pg-replica2 postgres:17 Official PostgreSQL 17 image (streaming replica)
pgpool-read Custom build postgres:17-alpine + pgpool (ARM64/AMD64 compatible)

Why Custom Pgpool Image?

  • Official pgpool/pgpool: Only AMD64, not ARM64 compatible (fails on M1/M2 Macs)
  • Bitnami bitnami/pgpool: Discontinued from Docker Hub (Aug 2025)
  • Our solution: Custom Dockerfile based on postgres:15-alpine with pgpool package

Pgpool-Read Dockerfile

FROM postgres:17-alpine
RUN apk add --no-cache pgpool pgpool-openrc bash
COPY pgpool.conf pool_hba.conf pool_passwd pcp.conf /etc/pgpool-II/
EXPOSE 5432 9898

This provides:

  • Full control over pgpool.conf
  • ARM64 & AMD64 compatibility
  • No dependency on third-party images

πŸ“‹ Prerequisites

  • Docker & Docker Compose
  • psql client (for test scripts)

πŸš€ Getting Started

1. Start the Cluster

docker-compose up -d

This starts:

  • pg-primary - Primary PostgreSQL (Port 5432)
  • pg-replica1 - Streaming replica
  • pg-replica2 - Streaming replica
  • pgpool-read - Custom-built Pgpool-II load balancer (Port 5433)

2. Check Cluster Status

PGPASSWORD=secret psql -h localhost -p 5433 -U postgres -d appdb -c "SHOW POOL_NODES"

πŸ“‘ Connection

# Via Pgpool (recommended)
PGPASSWORD=secret psql -h localhost -p 5433 -U postgres -d appdb

# Direct to Primary
PGPASSWORD=secret psql -h localhost -p 5432 -U postgres -d appdb

πŸ§ͺ Test & Monitor Scripts

Script Description
./monitor_load_balancing.sh Real-time query distribution monitor
./monitor_connections.sh Backend connection stats (idle/active)
./check_lag.sh Detailed replication lag info
./check_replication.sh Full replication test
./check_pgpool_nodes.sh Pgpool node status
./test_failover_timing.sh Failover detection timing
./test_artificial_lag.sh Test lag detection on one replica
./test_replica_down.sh Test replica down scenario
./test_both_replicas_down.sh Test all replicas down
./test_both_replicas_lag.sh Test lag on all replicas

βš™οΈ Configuration

Pgpool Settings (pgpool/pgpool.conf)

Parameter Value Description
num_init_children 64 Max concurrent client connections
max_pool 2 Connections per backend per child
connection_life_time 600 Connection lifetime (10 min)
health_check_period 1 Health check interval (seconds)
health_check_max_retries 1 Retries before marking down
sr_check_period 1 Replication lag check interval
delay_threshold_by_time 1000 Max allowed lag (1 second = 1000ms)
prefer_lower_delay_standby on Prefer replica with lower lag
auto_failback on Auto re-add recovered replicas

Backend Weights

Primary has weight 0 = read queries only go to replicas:

backend_weight0 = 0  # pg-primary (write only)
backend_weight1 = 1  # pg-replica1 (read)
backend_weight2 = 1  # pg-replica2 (read)

πŸ“ Project Structure

pgpool/
β”œβ”€β”€ docker-compose.yml          # Container orchestration
β”œβ”€β”€ README.md
β”‚
β”œβ”€β”€ pg-primary/                 # Primary PostgreSQL
β”‚   β”œβ”€β”€ init.sql                # Replication user, slots, test table
β”‚   β”œβ”€β”€ 01_hba.sh               # pg_hba.conf settings
β”‚   └── postgresql.conf
β”‚
β”œβ”€β”€ replica/                    # Replica configuration
β”‚   β”œβ”€β”€ init_replica.sh         # Base backup and replication setup
β”‚   β”œβ”€β”€ postgresql.conf
β”‚   └── recovery.conf
β”‚
β”œβ”€β”€ pgpool/                     # Custom Pgpool-Read build
β”‚   β”œβ”€β”€ Dockerfile              # Custom ARM64-compatible image
β”‚   β”œβ”€β”€ entrypoint.sh           # Startup script
β”‚   β”œβ”€β”€ pgpool.conf             # Full configuration
β”‚   β”œβ”€β”€ pool_hba.conf           # Client authentication
β”‚   β”œβ”€β”€ pool_passwd             # User passwords
β”‚   └── pcp.conf                # PCP admin config
β”‚
└── scripts (root)
    β”œβ”€β”€ monitor_load_balancing.sh   # Real-time LB monitor
    β”œβ”€β”€ monitor_connections.sh      # Connection stats monitor
    β”œβ”€β”€ check_lag.sh                # Replication lag check
    β”œβ”€β”€ check_replication.sh        # Full replication test
    β”œβ”€β”€ check_pgpool_nodes.sh       # Pool nodes status
    β”œβ”€β”€ test_failover_timing.sh     # Failover timing test
    β”œβ”€β”€ test_artificial_lag.sh      # Lag detection test
    β”œβ”€β”€ test_replica_down.sh        # Replica down test
    β”œβ”€β”€ test_both_replicas_down.sh  # All replicas down test
    └── test_both_replicas_lag.sh   # All replicas lag test

πŸ”§ Troubleshooting

View Logs

docker-compose logs -f pgpool-read
docker-compose logs -f pg-primary

Reset Everything

docker-compose down -v
docker-compose up -d --build

Check Replication Slots

docker exec pg-primary psql -U postgres -c "SELECT * FROM pg_replication_slots;"

πŸ“š References

πŸ“„ License

This project is intended for educational and development purposes.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published