使用 PgBouncer

PgBouncer 這是一個用於 PostgreSQL 的輕量級連線池管理工具。 它維持少量資料庫連線,並讓多個應用程式客戶端共用這些連線,這有助於您的部署在 連線限制內 運作,並避免為每個客戶端開啟新連線所產生的開銷。

IBM Cloud® Databases for PostgreSQL 部署版本內建對 PgBouncer's auth_query 的驗證功能。 每次部署都會提供一個 public.pgbouncer_lookup 函式和一個 pgbouncer_auth 角色,因此您所執行的 PgBouncer 實例可直接根據您的部署來驗證資料庫使用者。 您無需為資料庫使用者維護本機密碼清單,且密碼變更會立即生效,無需重新啟動或重新載入 PgBouncer。

Databases for PostgreSQL 並未託管或營運 PgBouncer。 您需在自己的基礎架構(例如虛擬伺服器、Kubernetes 叢集或應用程式 sidecar)上安裝、執行、強化安全性並更新 PgBouncer。 如需有關連線管理的更多資訊,請參閱「管理連線」。

開始之前

您需要:

  • 一個 已設定管理員密碼 的 Databases for PostgreSQL 部署環境。
  • 您應用程式的資料庫使用者 ,可透過使用者介面(UI)、命令列介面(CLI)或 API 建立。
  • PgBouncer 1.11.0 或更高版本,且支援 SCRAM 驗證,並安裝在您所控制的基礎架構上。 若您計劃在交易池模式下使用協定層級的預先準備陳述式,請使用 PgBouncer 1.21.0 或更新版本。
  • 一個 psql 的客戶。
  • 您的部署連線資訊:
    • 主機名稱和埠號,取自連線[字串] ……
    • CA 憑證,透過 ibmcloud cdb deployment-cacert 取得。

對 pgbouncer_lookup 的支援正逐步在各部署中推出。 若要確認您的部署環境是否具備此功能,請以 admin 身分連線至 psql,並執行 \df public.pgbouncer_lookup。 如果結果為空,您的部署將在下次維護更新時收到該函式。

建立專用的驗證使用者

PgBouncer 若以單一指定登入角色執行 auth_query,其 auth_user。 建立一個專門用於此目的的角色。 一個不擁有任何資料且不執行其他任何作業的專用角色,是遵循「最小權限原則」的最佳選擇。

以「admin」使用者身分連線至 psql,接著建立該角色並授予其「pgbouncer_auth」權限:

CREATE ROLE pool_auth WITH LOGIN PASSWORD '<POOL_AUTH_PASSWORD>';
GRANT pgbouncer_auth TO pool_auth;

pgbouncer_auth 角色僅具備一項權限:執行 pgbouncer_lookup 函式的權限。 admin 使用者擁有 pgbouncer_auth 並具備「管理員」權限,因此您可以自行授予或撤銷成員資格。 若您希望該使用者出現在服務憑證中,也可以透過 ibmcloud cdb user-create 建立該使用者;但 透過此方式建立的使用者會成為 ibm-cloud-base-user 的成員,並能建立使用者和資料庫,這已超出認證使用者所需的權限範圍。

僅向專用的驗證使用者授予 pgbouncer_auth 權限。 該角色的任何成員都能讀取您其他資料庫使用者的儲存密碼驗證碼,因此每增加一名成員,都會擴大憑證遭洩露所造成的影響範圍。

若要停用某個授權使用者,請撤銷其會員資格:

REVOKE pgbouncer_auth FROM pool_auth;

設定 PgBouncer

連線至 Databases for PostgreSQL 部署時,必須設定以下 PgBouncer 設定:

  • auth_type = scram-sha-256,因為部署環境會儲存 SCRAM-SHA-256 的密碼驗證器。
  • auth_query = SELECT * FROM public.pgbouncer_lookup($1),因為 PgBouncer's 預設 auth_query 會直接讀取 pg_authid,而您的資料庫使用者無法讀取該檔案。
  • 伺服器端 TLS,因為部署環境僅接受 TLS 連線。 將 server_tls_sslmode = verify-full 設定為適當值,並將透過 ` `ibmcloud cdb deployment-cacert` ` 取得之憑證儲存至您在 ` `server_tls_ca_file 中設定的路徑。

PgBouncer 會從 auth_file 讀取其自身 auth_user 的憑證,因此在此設定下,userlist.txt 僅包含 auth_user 的憑證。 每兩位使用者中就有一位是透過 auth_query 進行解析的。 將檔案的權限限制為「PgBouncer」程序的所有者,例如設定為模式 0600。

"pool_auth" "<POOL_AUTH_PASSWORD>"

一個完整的最小配置,其中 和 取自您的 連線字串:

[databases]
ibmclouddb = host=<HOSTNAME> port=<PORT> dbname=ibmclouddb
[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
auth_user = pool_auth
auth_query = SELECT * FROM public.pgbouncer_lookup($1)
server_tls_sslmode = verify-full
server_tls_ca_file = /etc/pgbouncer/ca-certificate.crt
pool_mode = session
max_client_conn = 200
default_pool_size = 20

請勿設定 auth_dbname = postgres``。 postgres 資料庫中未安裝查找函式。 請勿設定 auth_dbname ,以便認證查詢能在客戶端所連線的資料庫中執行。 您日後建立的資料庫會自動包含此功能。

有關各項設定的說明,請參閱 PgBouncer 中的設定參考文件。

驗證設定

  1. 請確認此查詢能解析為您的其中一位資料庫使用者。 以 admin 身分連線至 psql,並執行:

    SELECT usename, passwd IS NOT NULL AS can_authenticate
      FROM public.pgbouncer_lookup('<APP_USERNAME>');
    

    結果是一行,內容為 can_authenticate = t。 此查詢的寫法是為了不顯示密碼驗證視窗。 服務保留的使用者(包括 admin )不會返回任何資料列。

  2. 請以資料庫使用者「PgBouncer」的身分進行連線:

    psql "host=127.0.0.1 port=6432 dbname=ibmclouddb user=<APP_USERNAME>"
    

    若連線成功,PgBouncer 將透過 auth_query 正確地對使用者進行驗證。

  3. 請定期更換資料庫使用者的密碼,然後使用新密碼透過 PgBouncer 重新連線:

    ibmcloud cdb user-password <DEPLOYMENT_NAME_OR_CRN> <APP_USERNAME> <NEW_PASSWORD>
    

    新密碼會立即生效。 無需重新啟動 PgBouncer、重新載入,或變更 userlist.txt 設定。

安全性模型的運作方式

pgbouncer_lookup 函式僅公開 PgBouncer 進行驗證所需之資訊。

  • 此函式會搭配 SECURITY DEFINER 並將 search_path 設為固定,同時會代您讀取 pg_catalog.pg_authid。 直接存取 pg_authid 和 pg_shadow 的功能仍遭封鎖。
  • 它會傳回經過雜湊處理的 SCRAM 驗證碼,絕不會傳回明文密碼。
  • 僅會解析允許登入的角色。 服務保留的使用者(例如 admin 以及內部複製和運作使用者)永遠不會被解析。
  • 如果某個角色的 VALID UNTIL 時間戳記位於過去,該函式會傳回 NULL 密碼,因此驗證會失敗,且密碼過期規則仍會繼續執行。
  • PUBLIC 執行該函式的權限已被撤銷,僅授予 admin 以及 pgbouncer_auth 的成員。

PgBouncer's 預設情況下,auth_query 會直接讀取 pg_authid,而您的資料庫使用者無法執行此操作。 針對這種情況,PgBouncer 的文件建議改由非超級使用者來呼叫 SECURITY DEFINER 函式。 pgbouncer_lookup 函式即為該函式,但會排除該服務的保留使用者。

限制與注意事項

  • PgBouncer 不會觸發您部署的 max_connections。 請調整 default_pool_size 的數值,以確保所有 PgBouncer 實例的伺服器連線總數維持在連線限制範圍內。 若達到上限,請參閱「增加最大連線數」一節。
  • admin 使用者無法透過 auth_query 進行驗證。 進行管理任務時,請以 admin 身分直接連線至部署環境,而非透過 PgBouncer。
  • postgres 資料庫不具備查找功能,因此切勿設定 auth_dbname = postgres``。
  • 在交易匯總模式(pool_mode = transaction )下,諸如 SET 變數、暫存表、諮詢鎖以及 LISTEN 通道等會話狀態,不會在不同交易之間傳遞。 協議層級的預先準備陳述式需要 max_prepared_statements 以及 PgBouncer 1.21.0 或更高版本。 如需更多資訊,請參閱 PgBouncer features。
  • 在 進行就地主要版本升級 期間,您的部署會經歷一段短暫的停機時間,且所有開啟的連線將會被終止(SQLSTATE 57P01 )。 PgBouncer 會自動重新建立伺服器連線,但您的應用程式必須重新嘗試中斷的交易,並重新準備陳述式。
  • 唯讀使用者無法連線至主要端點。 為了整合這些連線,請新增一個獨立的 [databases] 條目,並將其指向您的唯讀副本。

下一步