Skip to content

PgBouncer 連線池(Kubernetes 部署)

在 Kubernetes 上部署 PgBouncer 作為 PostgreSQL 連線池,支援 TLS 加密、SCRAM-SHA-256 認證與 Prometheus 監控。

概述

PgBouncer 是輕量級的 PostgreSQL 連線池(connection pooler),置於應用程式與 PostgreSQL 之間,負責管理、複用資料庫連線。當應用端連線數遠超 PostgreSQL 的最佳承載量時,PgBouncer 能有效降低資料庫端的連線開銷,提升整體吞吐量。

在 Kubernetes 環境中,PgBouncer 以 Deployment 形式部署(支援多副本),透過 Azure Internal LoadBalancer 對內網暴露服務。應用程式連線至 PgBouncer 的 6432 埠,PgBouncer 再以連線池方式與後端 PostgreSQL(5432 埠)溝通。認證機制採用 SCRAM-SHA-256,透過 auth_query 向 PostgreSQL 即時查詢帳號密碼,免去手動維護所有使用者密碼的負擔。

核心內容

連線池模式選擇

PgBouncer 提供三種連線池模式:

  • Session Mode:連線在整個 session 生命週期內綁定同一後端連線,相容性最高但池化效率最低。
  • Transaction Mode(本部署採用):連線在交易完成後歸還連線池,適合大多數 Web 應用場景,大幅提升連線複用率。
  • Statement Mode:每條 SQL 執行完即歸還,限制最嚴格(不支援多語句交易)。

本部署選用 transaction 模式,搭配 default_pool_size=20max_client_conn=1000 的配置,可讓最多 1000 個客戶端連線共享少量的後端資料庫連線。

認證架構設計

本部署採用 auth_query 認證模式,這是 PgBouncer 較進階的認證方式:

  1. PgBouncer 收到客戶端登入請求時,使用 pgbouncer_auth(具 SUPERUSER 權限)連線至 PostgreSQL 執行 auth_query
  2. 該查詢從 pg_authid 系統表取得使用者的密碼雜湊值
  3. PgBouncer 用查詢結果驗證客戶端提供的密碼

這種設計的優點是新增 PostgreSQL 使用者時,不需要在 PgBouncer 端額外設定,認證資訊自動同步。userlist.txt 僅需維護 PgBouncer 自身的管理帳號。

TLS 加密設定

部署同時啟用了 client-side 與 server-side TLS:

  • Client → PgBouncer:使用自簽憑證,client_tls_sslmode=require 強制加密
  • PgBouncer → PostgreSQLserver_tls_sslmode=require 確保後端連線也加密

憑證透過 Kubernetes TLS Secret 掛載至 Pod 內。

資料庫路由設定

PgBouncer 的 [databases] 區段定義了可連線的資料庫清單,每個條目指定後端 PostgreSQL 的 host、port、dbname 及可選的 pool_size未列入此區段的資料庫無法透過 PgBouncer 存取,這是常見的踩坑點。需要新增資料庫時,必須更新 ConfigMap 並重啟 Pod。

關鍵要點

  • 採用 Transaction 連線池模式,1000 客戶端連線共享 20 條預設後端連線
  • auth_query + SUPERUSER 實現自動認證同步,免手動維護密碼清單
  • [databases] 區段是白名單機制,未列入的資料庫無法連線
  • Client 與 Server 端均啟用 TLS 加密
  • 2 副本部署搭配 Azure Internal LoadBalancer 提供高可用性

實際應用

本 PgBouncer 部署作為 AKS 叢集中所有需要連線 PostgreSQL 的應用程式的統一入口。應用程式連線至 10.30.196.60:6432,PgBouncer 根據目標資料庫名稱路由至後端 PostgreSQL 10.30.197.13:5432。目前配置了 poland、sourcer_helper、maisy、scmdb、resource_buddy 等多個業務資料庫的連線池。

部署設定參考

以下為實際部署時使用的完整設定,供日後查詢與複製使用。

環境參數

項目
PostgreSQL 主機10.30.197.13
PostgreSQL 埠號5432
PgBouncer Load Balancer IP10.30.196.60
PgBouncer 對外埠號6432
Kubernetes Namespaceingress-basic
容器映像edoburu/pgbouncer:latest
副本數2
連線池模式transaction
最大客戶端連線數1000
預設後端連線池大小20

建立 TLS 憑證

bash
# 產生自簽憑證(有效期 10 年)
openssl req -new -x509 -days 3650 -nodes \
  -out pgbouncer.crt \
  -keyout pgbouncer.key \
  -subj "/CN=pgbouncer/O=pgbouncer"

# 建立 Kubernetes TLS Secret
kubectl create secret tls pgbouncer-tls \
  --cert=pgbouncer.crt \
  --key=pgbouncer.key -n ingress-basic

pgbouncer.ini 完整設定檔

ini
[databases]
poland = host=10.30.197.13 port=5432 dbname=poland pool_size=40
sourcer_helper = host=10.30.197.13 port=5432 dbname=sourcer_helper
maisy = host=10.30.197.13 port=5432 dbname=maisy pool_size=40
scmdb = host=10.30.197.13 port=5432 dbname=scmdb
resource_buddy = host=10.30.197.13 port=5432 dbname=resource_buddy

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 5432

auth_type = scram-sha-256
auth_query = SELECT rolname, CASE WHEN rolvaliduntil < now() THEN NULL ELSE rolpassword END FROM pg_authid WHERE rolname=$1 AND rolcanlogin
auth_user = pgbouncer_auth
auth_file = /etc/pgbouncer/userlist.txt

server_tls_sslmode = require
client_tls_sslmode = require
client_tls_key_file = /etc/pgbouncer/tls/pgbouncer.key
client_tls_cert_file = /etc/pgbouncer/tls/pgbouncer.crt
client_tls_ca_file = /etc/pgbouncer/tls/pgbouncer.crt

admin_users = pgbouncer_admin

; 連線池設定
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20
min_pool_size = 5

; 逾時與資源管理
client_idle_timeout = 600.0
server_idle_timeout = 600.0
query_timeout = 600.0
query_wait_timeout = 120.0
client_login_timeout = 60.0
server_lifetime = 3600.0
server_connect_timeout = 15.0

; 日誌
log_connections = 1
log_disconnections = 1
log_pooler_errors = 1

; 監控帳號
stats_users = pgbouncer_stats

ignore_startup_parameters = extra_float_digits

userlist.txt

text
"pgbouncer_auth" "Lz4zwwuXVh"
"pgbouncer_admin" "gnJ8YCvK36"

帳號角色說明

帳號用途建立位置
pgbouncer_auth認證查詢用超級使用者,查詢 PostgreSQL 帳密PostgreSQL
pgbouncer_adminPgBouncer 管理用 admin userPgBouncer only
pgbouncer_statsPrometheus exporter 監控用帳號PgBouncer config

在 PostgreSQL 上建立認證用超級使用者:

sql
CREATE ROLE pgbouncer_auth LOGIN SUPERUSER PASSWORD 'Lz4zwwuXVh';

建立 ConfigMap 與 Secret

bash
# ConfigMap — pgbouncer.ini
kubectl create configmap pgbouncer-config \
  --from-file=pgbouncer.ini=pgbouncer.ini \
  -n ingress-basic \
  --dry-run=client -o yaml | kubectl apply -f -

# Secret — userlist.txt
kubectl create secret generic pgbouncer-users \
  --from-file=userlist.txt=userlist.txt -n ingress-basic \
  --dry-run=client -o yaml | kubectl apply -f -

Deployment YAML

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pgbouncer
  namespace: ingress-basic
spec:
  replicas: 2
  selector:
    matchLabels:
      app: pgbouncer
  template:
    metadata:
      labels:
        app: pgbouncer
    spec:
      containers:
      - name: pgbouncer
        image: edoburu/pgbouncer:latest
        ports:
        - containerPort: 5432
        volumeMounts:
        - name: config
          mountPath: /etc/pgbouncer/pgbouncer.ini
          subPath: pgbouncer.ini
        - name: userlist
          mountPath: /etc/pgbouncer/userlist.txt
          subPath: userlist.txt
        - name: tls
          mountPath: /etc/pgbouncer/tls/pgbouncer.crt
          subPath: pgbouncer.crt
        - name: tls
          mountPath: /etc/pgbouncer/tls/pgbouncer.key
          subPath: pgbouncer.key
      volumes:
      - name: config
        configMap:
          name: pgbouncer-config
      - name: userlist
        secret:
          secretName: pgbouncer-users
      - name: tls
        secret:
          secretName: pgbouncer-tls

Service YAML(Internal Load Balancer)

yaml
apiVersion: v1
kind: Service
metadata:
  name: pgbouncer-service
  namespace: ingress-basic
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"
    service.beta.kubernetes.io/azure-load-balancer-ipv4: 10.30.196.60
spec:
  type: LoadBalancer
  ports:
  - port: 6432
    targetPort: 5432
    protocol: TCP
    name: pgbouncer
  selector:
    app: pgbouncer

操作指令

管理連線(使用 pgbouncer_admin):

bash
psql -h 10.30.196.60 -p 6432 -U pgbouncer_admin pgbouncer

相關概念

來源