基于Docker快速搭建 PostgreSQL 高可用方案

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介: 基于Docker快速搭建 PostgreSQL 高可用方案

基于Docker快速搭建 PostgreSQL 高可用方案

什么是 PostgreSQL HA?

此 PostgreSQL 集群解决方案包括 PostgreSQL 复制管理器(replication manager),这是一种用于管理 PostgreSQL 集群上的复制(replication)和故障转移(failover)的开源工具。

获取此镜像

获取 Bitnami PostgreSQL HA Docker 镜像的推荐方法是从 Docker Hub Registry 中提取预构建的镜像。

docker pull bitnami/postgresql-repmgr:latest
 docker pull bitnami/postgresql-repmgr:9.6.21

要使用特定版本,你可以拉取版本化标签。 你可以在 Docker Hub Registry 中查看可用版本的列表

docker pull bitnami/postgresql-repmgr:[TAG]

如果你愿意,你也可以自己构建镜像。

docker build -t bitnami/postgresql-repmgr:latest 'https://github.com/bitnami/bitnami-docker-postgresql-repmgr.git#master:14/debian-10'

持久化你的应用程序

如果删除容器,所有数据都将丢失,下次运行镜像时,数据库将重新初始化。 为避免这种数据丢失,你应该挂载一个即使在容器被删除后仍将持续存在的卷。

对于持久性,你应该在 /bitnami/postgresql 路径上挂载一个目录。 如果挂载的目录是空的,它将在第一次运行时被初始化。

docker run \
    -v /path/to/postgresql-repmgr-persistence:/bitnami/postgresql \
    bitnami/postgresql-repmgr:latest

此存储库中的 docker-compose.yml 文件已经配置了持久性。

注意:由于这是一个非 root 容器,因此挂载的文件和目录必须具有 UID 1001 的适当权限。

连接到其他容器

使用 Docker 容器网络,你的应用程序容器可以轻松访问在容器内运行的 PostgreSQL 服务器,反之亦然。

连接到同一网络的容器可以使用容器名称作为主机名相互通信。

使用命令行

在此示例中,我们将创建一个 PostgreSQL 客户端实例,该实例将连接到与客户端在同一 docker 网络上运行的服务器实例。

Step 1: 创建 network
docker network create my-network --driver bridge
Step 2: 在你的 network 中启动 postgresql-repmgr 容器

使用 docker run 命令的 --network <NETWORK> 参数将容器附加到 my-network 网络。

docker run --detach --rm --name pg-0 \
  --network my-network \
  --env REPMGR_PARTNER_NODES=pg-0 \
  --env REPMGR_NODE_NAME=pg-0 \
  --env REPMGR_NODE_NETWORK_NAME=pg-0 \
  --env REPMGR_PRIMARY_HOST=pg-0 \
  --env REPMGR_PASSWORD=repmgrpass \
  --env POSTGRESQL_PASSWORD=secretpass \
  bitnami/postgresql-repmgr:latest
Step 3: 运行你的 PostgreSQL client 实例

最后,我们创建一个新的容器实例来启动 PostgreSQL client 并连接到上一步中创建的服务器:

docker run -it --rm \
  --network my-network \
  bitnami/postgresql:10 \
  psql -h pg-0 -U postgres

使用 Docker Compose

如果未指定,Docker Compose 会自动设置一个新网络并将所有已部署的服务附加到该网络。 但是,我们将明确定义一个名为 my-network 的新 bridge 网络。 在此示例中,我们假设你希望从你自己的自定义应用程序镜像连接到 PostgreSQL 服务器,该镜像在以下代码段中由服务名称 myapp 标识。

version: '2'
networks:
  my-network:
    driver: bridge
services:
  pg-0:
    image: 'bitnami/postgresql-repmgr:latest'
    networks:
      - my-network
    environment:
      - POSTGRESQL_PASSWORD=custompassword
      - REPMGR_PASSWORD=repmgrpassword
      - REPMGR_PRIMARY_HOST=pg-0
      - REPMGR_NODE_NETWORK_NAME=pg-0
      - REPMGR_NODE_NAME=pg-0
      - REPMGR_PARTNER_NODES=pg-0
  myapp:
    image: 'YOUR_APPLICATION_IMAGE'
    networks:
      - my-network

重要的:

  1. 请使用你的应用程序镜像更新上述代码段中的 YOUR_APPLICATION_IMAGE 占位符
  2. 在你的应用程序容器中,使用主机名 pg-0 连接到 PostgreSQL 服务器

使用以下命令启动容器:

docker-compose up -d

配置

初始化一个新实例

第一次执行容器时,它将执行位于 /docker-entrypoint-initdb.d 的扩展名为 .sh.sql.sql.gz 的文件。

为了将你的自定义文件放入 docker 镜像中,你可以将它们挂载为卷。

在首次运行时设置 root 和 repmgr 密码

在上述命令中,你可能已经注意到 POSTGRESQL_PASSWORDREPMGR_PASSWORD 环境变量的使用。 第一次运行镜像时传递 POSTGRESQL_PASSWORD 环境变量会将 postgres 用户的密码设置为 POSTGRESQL_PASSWORD 的值(或 POSTGRESQL_PASSWORD_FILE 中指定的文件内容)。同样,传递 REPMGR_PASSWORD 环境变量将 repmgr 用户的密码设置为 REPMGR_PASSWORD 的值(或 REPMGR_PASSWORD_FILE 中指定的文件内容)。

docker run --name pg-0 --env REPMGR_PASSWORD=repmgrpass --env POSTGRESQL_PASSWORD=secretpass bitnami/postgresql-repmgr:latest

或通过修改此存储库中存在的 docker-compose.yml 文件:

...
services:
  pg-0:
  ...
    environment:
-      - POSTGRESQL_PASSWORD=adminpassword
+      - POSTGRESQL_PASSWORD=password123
-      - REPMGR_PASSWORD=repmgrpassword
+      - REPMGR_PASSWORD=password123
  ...
  pg-1:
  ...
  environment:
-      - POSTGRESQL_PASSWORD=adminpassword
+      - POSTGRESQL_PASSWORD=password123
-      - REPMGR_PASSWORD=repmgrpassword
+      - REPMGR_PASSWORD=password123
...

Note!postgresrepmgr 用户都是超级用户,并且对 PostgreSQL 数据库具有完全的管理访问权限。

如果要为 postgres 用户设置非特权用户和密码,请参阅在首次运行时创建数据库用户。

首次运行时创建数据库

通过在第一次运行镜像时传递 POSTGRESQL_DATABASE 环境变量,将创建一个数据库。 如果你的应用程序要求数据库已经存在,这将非常有用,你不必使用 PostgreSQL 客户端手动创建数据库。

docker run --name pg-0 --env POSTGRESQL_DATABASE=my_database bitnami/postgresql-repmgr:latest

首次运行时创建数据库用户

你还可以创建一个受限数据库用户,该用户仅对使用 POSTGRESQL_DATABASE 环境变量创建的数据库具有权限。 为此,请提供 POSTGRESQL_USERNAME 环境变量。

docker run --name pg-0 --env POSTGRESQL_USERNAME=my_user --env POSTGRESQL_PASSWORD=password123 --env POSTGRESQL_DATABASE=my_database bitnami/postgresql-repmgr:latest

此存储库中的 docker-compose.yml 文件已配置此设置。

Note!指定 POSTGRESQL_USERNAME 时,不会为 postgres 用户分配密码,因此你无法以 postgres 用户身份远程登录 PostgreSQL 服务器。如果你仍想使用用户 postgres 访问,请设置 POSTGRESQL_POSTGRES_PASSWORD 环境变量(或 POSTGRESQL_POSTGRES_PASSWORD_FILE 中指定的文件内容)。

使用流复制和 repmgr 设置 HA PostgreSQL 集群

使用以下环境变量,可以使用 Bitnami PostgreSQL HA Docker 镜像轻松设置具有[流复制](Streaming replication)和 repmgrHA PostgreSQL 集群:

  • POSTGRESQL_PASSWORD:postgres 用户的密码。没有默认值。
  • POSTGRESQL_PASSWORD_FILE:包含 postgres 用户密码的文件的路径。 这将覆盖 POSTGRESQL_PASSWORD 中指定的值。 没有默认值。
  • REPMGR_USERNAMErepmgr 用户的用户名。默认为 repmgr
  • REPMGR_PASSWORD_FILE:包含 repmgr 用户密码的文件的路径。这将覆盖 REPMGR_PASSWORD 中指定的值。 没有默认值。
  • REPMGR_PASSWORDrepmgr 用户的密码。没有默认值。
  • REPMGR_USE_PASSFILE:配置 repmgr 以在其配置中使用 passfilePGPASSFILE 而不是纯文本密码。
  • REPMGR_PASSFILE_PATH:密码文件的位置,如果它不存在,它将使用 REPMGR 凭据创建。
  • REPMGR_PRIMARY_HOST:初始主节点的主机名。没有默认值。
  • REPMGR_PARTNER_NODES:集群中的伙伴节点的逗号分隔列表。没有默认值。
  • REPMGR_NODE_NAME:节点名称。没有默认值。
  • REPMGR_NODE_NETWORK_NAME:节点主机名。没有默认值。
  • REPMGR_PGHBA_TRUST_ALL:这将在生成的 pg_hba.conf 中设置 auth-method。仅当你使用带有 LDAP 身份验证的 pgpool 时才将其设置为 yes。默认为 no

HA PostgreSQL 集群中,你可以拥有一个主节点和零个或多个备用节点。主节点处于读写模式,而备用节点处于只读模式。为获得最佳性能,建议将读取限制在备用节点。

注意:对于 9.6 版之前的 Postgresql,REPMGR_USE_PASSFILE 和 REPMGR_PASSFILE_PATH 将被忽略。

使用 REPMGR_PASSFILE_PATH 挂载外部密码文件时,还需要相应地配置 REPMGR_PASSWORD 和 REPMGR_USERNAME。

Step 1: 创建 network
docker network create sharednet --driver bridge
Step 2: 创建初始主节点

第一步是启动初始主节点:

docker run --detach --name pg-0 -p 5433:5432 \
  --network sharednet \
  --env REPMGR_PARTNER_NODES=pg-0,pg-1 \
  --env REPMGR_NODE_NAME=pg-0 \
  --env REPMGR_NODE_NETWORK_NAME=pg-0 \
  --env REPMGR_PRIMARY_HOST=pg-0 \
  --env REPMGR_PASSWORD=repmgrpass \
  --env POSTGRESQL_DATABASE=registry \
  --env POSTGRESQL_PASSWORD=secretpass \
  bitnami/postgresql-repmgr:9.6.21
Step 3: 创建备用节点

接下来我们启动一个备用节点:

docker run --detach --name pg-1 -p 5455:5432 \
  --network sharednet \
  --env REPMGR_PARTNER_NODES=pg-0,pg-1 \
  --env REPMGR_NODE_NAME=pg-1 \
  --env REPMGR_NODE_NETWORK_NAME=pg-1 \
  --env REPMGR_PRIMARY_HOST=pg-0 \
  --env REPMGR_PASSWORD=repmgrpass \
  --env POSTGRESQL_PASSWORD=secretpass \
  bitnami/postgresql-repmgr:9.6.21

使用这三个命令,你现在可以启动并运行一个两节点 PostgreSQL 主备流复制集群。 你可以通过添加/删除备用节点来扩展集群,而不会导致任何停机时间。

注意:集群会完整地复制主节点,其中包括所有用户和数据库。

如果主节点宕机,repmgr 将确保任何备用节点担任主节点,从而保证高可用性。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MGekHyY3-1655257545300)(https://cdn.jsdelivr.net/gh/Fly0905/note-picture@main/imag/202206081641747.png)]

LOG:  database system is ready to accept read only connections
LOG:  started streaming WAL from primary at 0/5000000 on timeline 1
 done
server started
postgresql-repmgr 08:04:49.98 INFO  ==> ** Starting repmgrd **
[2022-06-08 08:04:49] [NOTICE] repmgrd (repmgrd 5.2.1) starting up
INFO:  set_repmgrd_pid(): provided pidfile is /opt/bitnami/repmgr/tmp/repmgr.pid
[2022-06-08 08:04:50] [NOTICE] starting monitoring of node "pg-1" (ID: 1001)
ERROR:  cannot execute UPDATE in a read-only transaction
STATEMENT:  UPDATE "public"."tag" SET "pull_time" = '2022-06-08 06:47:10' WHERE "id" = 75
FATAL:  could not receive data from WAL stream: server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.
# 1. 发现主机点宕机
LOG:  invalid record length at 0/528F650: wanted 24, got 0
FATAL:  could not connect to the primary server: could not connect to server: Connection refused
    Is the server running on host "pg-0" (172.23.0.2) and accepting
    TCP/IP connections on port 5432?
# 2. 尝试连接主机点(3次)
[2022-06-08 08:40:00] [WARNING] unable to ping "user=repmgr password=repmgrpass host=pg-0 dbname=repmgr port=5432 connect_timeout=5"
[2022-06-08 08:40:00] [DETAIL] PQping() returned "PQPING_NO_ATTEMPT"
[2022-06-08 08:40:00] [WARNING] unable to connect to upstream node "pg-0" (ID: 1000)
[2022-06-08 08:40:00] [WARNING] unable to ping "user=repmgr password=repmgrpass connect_timeout=5 dbname=repmgr host=pg-0 port=5432 fallback_application_name=repmgr"
[2022-06-08 08:40:00] [DETAIL] PQping() returned "PQPING_NO_ATTEMPT"
[2022-06-08 08:40:05] [WARNING] unable to ping "user=repmgr password=repmgrpass connect_timeout=5 dbname=repmgr host=pg-0 port=5432 fallback_application_name=repmgr"
[2022-06-08 08:40:05] [DETAIL] PQping() returned "PQPING_NO_ATTEMPT"
FATAL:  could not connect to the primary server: could not translate host name "pg-0" to address: Name or service not known
FATAL:  could not connect to the primary server: could not translate host name "pg-0" to address: Name or service not known
[2022-06-08 08:40:10] [WARNING] unable to ping "user=repmgr password=repmgrpass connect_timeout=5 dbname=repmgr host=pg-0 port=5432 fallback_application_name=repmgr"
[2022-06-08 08:40:10] [DETAIL] PQping() returned "PQPING_NO_ATTEMPT"
# 3. 尝试连接主机点失败(3次),从备用节点中选主
[2022-06-08 08:40:10] [WARNING] unable to reconnect to node "pg-0" (ID: 1000) after 3 attempts
[2022-06-08 08:40:10] [NOTICE] this node is the only available candidate and will now promote itself
NOTICE: using provided configuration file "/opt/bitnami/repmgr/conf/repmgr.conf"
DEBUG: connecting to: "user=repmgr password=repmgrpass connect_timeout=5 dbname=repmgr host=pg-1 port=5432 fallback_application_name=repmgr options=-csearch_path="
DEBUG: set_config():
  SET synchronous_commit TO 'local'
INFO: connected to standby, checking its state
DEBUG: get_recovery_type(): SELECT pg_catalog.pg_is_in_recovery()
DEBUG: get_node_record():
  SELECT n.node_id, n.type, n.upstream_node_id, n.node_name,  n.conninfo, n.repluser, n.slot_name, n.location, n.priority, n.active, n.config_file, '' AS upstream_node_name, NULL AS attached   FROM repmgr.nodes n  WHERE n.node_id = 1001
DEBUG: get_replication_info():
 SELECT ts,         in_recovery,         last_wal_receive_lsn,         last_wal_replay_lsn,         last_xact_replay_timestamp,         CASE WHEN (last_wal_receive_lsn = last_wal_replay_lsn)           THEN 0::INT         ELSE           CASE WHEN last_xact_replay_timestamp IS NULL             THEN 0::INT           ELSE             EXTRACT(epoch FROM (pg_catalog.clock_timestamp() - last_xact_replay_timestamp))::INT           END         END AS replication_lag_time,         last_wal_receive_lsn >= last_wal_replay_lsn AS receiving_streamed_wal,         wal_replay_paused,         upstream_last_seen,         upstream_node_id    FROM (  SELECT CURRENT_TIMESTAMP AS ts,         pg_catalog.pg_is_in_recovery() AS in_recovery,         pg_catalog.pg_last_xact_replay_timestamp() AS last_xact_replay_timestamp,         COALESCE(pg_catalog.pg_last_xlog_receive_location(), '0/0'::PG_LSN) AS last_wal_receive_lsn,         COALESCE(pg_catalog.pg_last_xlog_replay_location(),  '0/0'::PG_LSN) AS last_wal_replay_lsn,         CASE WHEN pg_catalog.pg_is_in_recovery() IS FALSE           THEN FALSE           ELSE pg_catalog.pg_is_xlog_replay_paused()         END AS wal_replay_paused,         CASE WHEN pg_catalog.pg_is_in_recovery() IS FALSE           THEN -1           ELSE repmgr.get_upstream_last_seen()         END AS upstream_last_seen,         CASE WHEN pg_catalog.pg_is_in_recovery() IS FALSE           THEN -1           ELSE repmgr.get_upstream_node_id()         END AS upstream_node_id           ) q 
INFO: searching for primary node
DEBUG: get_primary_connection():
  SELECT node_id, conninfo,          CASE WHEN type = 'primary' THEN 1 ELSE 2 END AS type_priority     FROM repmgr.nodes    WHERE active IS TRUE      AND type != 'witness' ORDER BY active DESC, type_priority, priority, node_id
INFO: checking if node 1000 is primary
DEBUG: connecting to: "user=repmgr password=repmgrpass connect_timeout=5 dbname=repmgr host=pg-0 port=5432 fallback_application_name=repmgr options=-csearch_path="
ERROR: connection to database failed
DETAIL: 
could not translate host name "pg-0" to address: Name or service not known
DETAIL: attempted to connect using:
  user=repmgr password=repmgrpass connect_timeout=5 dbname=repmgr host=pg-0 port=5432 fallback_application_name=repmgr options=-csearch_path=
INFO: checking if node 1001 is primary
DEBUG: connecting to: "user=repmgr password=repmgrpass connect_timeout=5 dbname=repmgr host=pg-1 port=5432 fallback_application_name=repmgr options=-csearch_path="
DEBUG: set_config():
  SET synchronous_commit TO 'local'
DEBUG: get_recovery_type(): SELECT pg_catalog.pg_is_in_recovery()
DEBUG: get_node_replication_stats():
 SELECT pg_catalog.current_setting('max_wal_senders')::INT AS max_wal_senders,         (SELECT pg_catalog.count(*) FROM pg_catalog.pg_stat_replication) AS attached_wal_receivers,         current_setting('max_replication_slots')::INT AS max_replication_slots,         (SELECT pg_catalog.count(*) FROM pg_catalog.pg_replication_slots WHERE slot_type='physical') AS total_replication_slots,         (SELECT pg_catalog.count(*) FROM pg_catalog.pg_replication_slots WHERE active IS TRUE AND slot_type='physical')  AS active_replication_slots,         (SELECT pg_catalog.count(*) FROM pg_catalog.pg_replication_slots WHERE active IS FALSE AND slot_type='physical') AS inactive_replication_slots,         pg_catalog.pg_is_in_recovery() AS in_recovery
DEBUG: get_active_sibling_node_records():
  SELECT n.node_id, n.type, n.upstream_node_id, n.node_name,  n.conninfo, n.repluser, n.slot_name, n.location, n.priority, n.active, n.config_file, '' AS upstream_node_name, NULL AS attached     FROM repmgr.nodes n    WHERE n.upstream_node_id = 1000      AND n.node_id != 1001      AND n.active IS TRUE ORDER BY n.node_id 
DEBUG: clear_node_info_list() - closing open connections
DEBUG: clear_node_info_list() - unlinking
DEBUG: get_node_record():
  SELECT n.node_id, n.type, n.upstream_node_id, n.node_name,  n.conninfo, n.repluser, n.slot_name, n.location, n.priority, n.active, n.config_file, '' AS upstream_node_name, NULL AS attached   FROM repmgr.nodes n  WHERE n.node_id = 1001
NOTICE: promoting standby to primary
DETAIL: promoting server "pg-1" (ID: 1001) using "/opt/bitnami/postgresql/bin/pg_ctl -o "--config-file="/opt/bitnami/postgresql/conf/postgresql.conf" --external_pid_file="/opt/bitnami/postgresql/tmp/postgresql.pid" --hba_file="/opt/bitnami/postgresql/conf/pg_hba.conf"" -w -D '/bitnami/postgresql/data' promote"
LOG:  received promote request
LOG:  redo done at 0/528F628
LOG:  last completed transaction was at log time 2022-06-08 08:39:58.858907+00
NOTICE: waiting up to 60 seconds (parameter "promote_check_timeout") for promotion to complete
DEBUG: get_recovery_type(): SELECT pg_catalog.pg_is_in_recovery()
LOG:  selected new timeline ID: 2
LOG:  archive recovery complete
LOG:  MultiXact member wraparound protections are now enabled
LOG:  database system is ready to accept connections
LOG:  autovacuum launcher started
DEBUG: get_recovery_type(): SELECT pg_catalog.pg_is_in_recovery()
INFO: standby promoted to primary after 1 second(s)
DEBUG: setting node 1001 as primary and marking existing primary as failed
DEBUG: begin_transaction()
DEBUG: commit_transaction()
NOTICE: STANDBY PROMOTE successful
DETAIL: server "pg-1" (ID: 1001) was successfully promoted to primary
DEBUG: _create_event(): event is "standby_promote" for node 1001
DEBUG: get_recovery_type(): SELECT pg_catalog.pg_is_in_recovery()
DEBUG: _create_event():
   INSERT INTO repmgr.events (              node_id,              event,              successful,              details             )       VALUES ($1, $2, $3, $4)    RETURNING event_timestamp 
DEBUG: _create_event(): Event timestamp is "2022-06-08 08:40:11.867269+00"
DEBUG: _create_event(): command is '/opt/bitnami/repmgr/events/router.sh %n %e %s "%t" "%d"'
INFO: executing notification command for event "standby_promote"
# 4. 产生新的主节点
DETAIL: command is:
  /opt/bitnami/repmgr/events/router.sh 1001 standby_promote 1 "2022-06-08 08:40:11.867269+00" "server \"pg-1\" (ID: 1001) was successfully promoted to primary"
DEBUG: clear_node_info_list() - closing open connections
DEBUG: clear_node_info_list() - unlinking
[2022-06-08 08:40:11] [NOTICE] node 1001 has recovered, reconnecting
[2022-06-08 08:40:12] [NOTICE] monitoring cluster primary "pg-1" (ID: 1001)
# 5. 原来的主节点恢复正常后,会变为备用节点
[2022-06-08 08:48:55] [NOTICE] new standby "pg-0" (ID: 1000) has connected

注意:集群中其他节点的配置需要更新,以便它们知道它们。这将需要重新启动旧节点,以适应 REPMGR_PARTNER_NODES 环境变量。

使用 Docker Compose,可以使用此存储库中的 docker-compose.yml 文件设置 HA PostgreSQL 集群:

version: '2'
services:
  pg-0:
    image: docker.io/bitnami/postgresql-repmgr:14
    ports:
      - 5432
    volumes:
      - pg_0_data:/bitnami/postgresql
    environment:
      - POSTGRESQL_POSTGRES_PASSWORD=adminpassword
      - POSTGRESQL_USERNAME=customuser
      - POSTGRESQL_PASSWORD=custompassword
      - POSTGRESQL_DATABASE=customdatabase
      - REPMGR_PASSWORD=repmgrpassword
      - REPMGR_PRIMARY_HOST=pg-0
      - REPMGR_PRIMARY_PORT=5432
      - REPMGR_PARTNER_NODES=pg-0,pg-1:5432
      - REPMGR_NODE_NAME=pg-0
      - REPMGR_NODE_NETWORK_NAME=pg-0
      - REPMGR_PORT_NUMBER=5432
  pg-1:
    image: docker.io/bitnami/postgresql-repmgr:14
    ports:
      - 5432
    volumes:
      - pg_1_data:/bitnami/postgresql
    environment:
      - POSTGRESQL_POSTGRES_PASSWORD=adminpassword
      - POSTGRESQL_USERNAME=customuser
      - POSTGRESQL_PASSWORD=custompassword
      - POSTGRESQL_DATABASE=customdatabase
      - REPMGR_PASSWORD=repmgrpassword
      - REPMGR_PRIMARY_HOST=pg-0
      - REPMGR_PRIMARY_PORT=5432
      - REPMGR_PARTNER_NODES=pg-0,pg-1:5432
      - REPMGR_NODE_NAME=pg-1
      - REPMGR_NODE_NETWORK_NAME=pg-1
      - REPMGR_PORT_NUMBER=5432
volumes:
  pg_0_data:
    driver: local
  pg_1_data:
    driver: local

或者

curl -sSL https://raw.githubusercontent.com/bitnami/bitnami-docker-postgresql-repmgr/master/docker-compose.yml > docker-compose.yml
 docker-compose up -d

保护 PostgreSQL 流量

PostgreSQL 支持使用 SSL/TLS 协议对连接进行加密。如果你希望启用此可选功能,你可以使用以下环境变量来配置应用程序:

  • POSTGRESQL_ENABLE_TLS:是否为流量启用 TLS。默认为 no
  • POSTGRESQL_TLS_CERT_FILE:包含 TLS 流量证书文件的文件。没有默认值。
  • POSTGRESQL_TLS_KEY_FILE:包含证书密钥的文件。没有默认值。
  • POSTGRESQL_TLS_CA_FILE:包含证书 CA 的文件。如果提供,PostgreSQL 将通过向 TLS/SSL 客户端请求证书来对其进行身份验证(请参阅ref)。没有默认值。
  • POSTGRESQL_TLS_CRL_FILE:包含证书吊销列表的文件。没有默认值。
  • POSTGRESQL_TLS_PREFER_SERVER_CIPHERS:是否使用服务器的 TLS 密码首选项而不是客户端的。默认为 yes

启用 TLS 时,PostgreSQL 默认支持标准流量和加密流量,但更喜欢后者。下面是一些关于如何快速设置 TLS 流量的示例:

  1. 使用 docker run
docker run \
    -v /path/to/certs:/opt/bitnami/postgresql/certs \
    -e POSTGRESQL_ENABLE_TLS=yes \
    -e POSTGRESQL_TLS_CERT_FILE=/opt/bitnami/postgresql/certs/postgres.crt \
    -e POSTGRESQL_TLS_KEY_FILE=/opt/bitnami/postgresql/certs/postgres.key \
    bitnami/postgresql-repmgr:latest
  1. 修改此存储库中存在的 docker-compose.yml 文件:
services:
  pg-0:
  ...
    environment:
      ...
      - POSTGRESQL_ENABLE_TLS=yes
      - POSTGRESQL_TLS_CERT_FILE=/opt/bitnami/postgresql/certs/postgres.crt
      - POSTGRESQL_TLS_KEY_FILE=/opt/bitnami/postgresql/certs/postgres.key
    ...
    volumes:
      ...
      - /path/to/certs:/opt/bitnami/postgresql/certs
  ...

或者,你也可以在自定义配置文件中提供此配置。

配置文件

该镜像在 /opt/bitnami/repmgr/conf//opt/bitnami/postgresql/conf/ 中查找 repmgr.confpostgresql.confpg_hba.conf 文件。你可以在 /bitnami/repmgr/conf/ 挂载一个卷,并复制/编辑 /path/to/custom-conf/ 中的配置文件。 如果 /bitnami/repmgr/conf/ 为空,默认配置将填充到 conf/ 目录。

/path/to/custom-conf/
└── postgresql.conf

由于带有 Replication manager 镜像的 PostgreSQL 是非 root 用户,因此你需要为主机中的挂载目录设置适当的权限:

sudo chgrp -R root /path/to/custom-conf/
 sudo chmod -R g+rwX /path/to/custom-conf/
Step 1: 运行 PostgreSQL 镜像

运行 PostgreSQL 镜像,从你的主机挂载一个目录。

docker run --name pg-0 \
    -v /path/to/custom-conf/:/bitnami/repmgr/conf/ \
    bitnami/postgresql-repmgr:latest

或者使用 Docker Compose

version: '2'
services:
  pg-0:
    image: bitnami/postgresql-repmgr:latest
    ports:
      - '5432:5432'
    volumes:
      - /path/to/custom-conf/:/bitnami/repmgr/conf/
  pg-1:
    image: bitnami/postgresql-repmgr:latest
    ports:
      - '5432:5432'
    volumes:
      - /path/to/custom-conf/:/bitnami/repmgr/conf/
Step 2: 编辑配置

使用你喜欢的编辑器编辑主机上的配置。

vi /path/to/custom-conf/postgresql.conf
Step 3: 重启 PostgreSQL

更改配置后,重新启动 PostgreSQL 容器以使更改生效。

docker restart pg-0

或者使用 Docker Compose

docker-compose restart pg-0
 docker-compose restart pg-1

有关配置选项的完整列表,请参阅服务器配置手册

允许从默认 postgresql.conf 以外的文件加载设置。

除了使用自定义的 repmgr.confpostgresql.confpg_hba.conf,你还可以在 /bitnami/postgresql/conf/ 的卷中包含 conf.d 目录中以 .conf 结尾的文件。为此,默认的 postgresql.conf 包含以下部分:

##------------------------------------------------------------------------------
## CONFIG FILE INCLUDES
##------------------------------------------------------------------------------
## These options allow settings to be loaded from files other than the
## default postgresql.conf.
include_dir = 'conf.d'  # Include files ending in '.conf' from directory 'conf.d'

如果你使用自定义 postgresql.conf,你应该在配置文件中创建(或取消注释)上述部分,在这种情况下,结构应该类似于

/path/to/custom-conf/
└── postgresql.conf
/path/to/extra-custom-conf/
└── extended.conf

请记住为主机中的挂载目录设置适当的权限:

sudo chgrp -R root /path/to/extra-custom-conf/
 sudo chmod -R g+rwX /path/to/extra-custom-conf/
Step 1: 运行 PostgreSQL 镜像

运行 PostgreSQL 镜像,从你的主机挂载一个目录。

docker run --name pg-0 \
    -v /path/to/extra-custom-conf/:/bitnami/postgresql/conf/conf.d/ \
    -v /path/to/custom-conf/:/bitnami/repmgr/conf/ \
    bitnami/postgresql-repmgr:latest

或者使用 Docker Compose

version: '2'
services:
  pg-0:
    image: bitnami/postgresql-repmgr:latest
    ports:
      - '5432:5432'
    volumes:
      - /path/to/extra-custom-conf/:/bitnami/postgresql/conf/conf.d/
      - /path/to/custom-conf/:/bitnami/repmgr/conf/
  pg-1:
    image: bitnami/postgresql-repmgr:latest
    ports:
      - '5432:5432'
    volumes:
      - /path/to/extra-custom-conf/:/bitnami/postgresql/conf/conf.d/
      - /path/to/custom-conf/:/bitnami/repmgr/conf/
Step 2: 编辑配置

使用你喜欢的编辑器编辑主机上的配置。

vi /path/to/extra-custom-conf/extended.conf
Step 3: 重启 PostgreSQL

更改配置后,重新启动 PostgreSQL 容器以使更改生效。

docker restart pg-0

或者使用 Docker Compose:

docker-compose restart pg-0
 docker-compose restart pg-1

环境变量

请在下表中查看 Bitnami PostgreSQL HA 容器中可用的环境变量列表:

Environment Variable Default value
REPMGR_NODE_ID nil
REPMGR_NODE_ID_START_SEED 1000
REPMGR_NODE_NAME nil
REPMGR_NODE_NETWORK_NAME nil
REPMGR_NODE_PRIORITY 100
REPMGR_PARTNER_NODES nil
REPMGR_PRIMARY_HOST nil
REPMGR_NODE_LOCATION default
REPMGR_PRIMARY_PORT 5432
REPMGR_PORT_NUMBER 5432
REPMGR_LOG_LEVEL NOTICE
REPMGR_START_OPTIONS nil
REPMGR_CONNECT_TIMEOUT 5
REPMGR_RECONNECT_ATTEMPTS 3
REPMGR_RECONNECT_INTERVAL 5
REPMGR_USE_REPLICATION_SLOTS 1
REPMGR_MASTER_RESPONSE_TIMEOUT 20
REPMGR_DEGRADED_MONITORING_TIMEOUT 5
REPMGR_USERNAME repmgr
REPMGR_DATABASE repmgr
REPMGR_PASSWORD nil
REPMGR_PASSWORD_FILE nil
REPMGR_FENCE_OLD_PRIMARY no
REPMGR_CHILD_NODES_CHECK_INTERVAL 5
REPMGR_CHILD_NODES_CONNECTED_MIN_COUNT 1
REPMGR_CHILD_NODES_DISCONNECT_TIMEOUT 30
REPMGR_USE_PASSFILE nil
POSTGRESQL_USERNAME postgres
POSTGRESQL_DATABASE nil
POSTGRESQL_PASSWORD nil
POSTGRESQL_PASSWORD_FILE nil
POSTGRESQL_POSTGRES_PASSWORD nil
POSTGRESQL_POSTGRES_PASSWORD_FILE nil
POSTGRESQL_PORT_NUMBER 5432
POSTGRESQL_INITDB_ARGS nil
POSTGRESQL_PGCTLTIMEOUT 60
POSTGRESQL_SHUTDOWN_MODE fast
POSTGRESQL_ENABLE_TLS no
POSTGRESQL_TLS_CERT_FILE nil
POSTGRESQL_TLS_KEY_FILE nil
POSTGRESQL_TLS_CA_FILE nil
POSTGRESQL_TLS_CRL_FILE nil
POSTGRESQL_TLS_PREFER_SERVER_CIPHERS yes

日志

Bitnami PostgreSQL HA Docker 镜像将容器日志发送到 stdout。查看日志:

docker logs pg-0

如果你希望以不同的方式使用容器日志,则可以使用 --log-driver 选项配置容器 logging driver。在默认配置中,docker 使用 json-file driver。

维护

升级这个镜像

Bitnami 提供了 PostgreSQL HA 的最新版本,包括安全补丁,这些补丁在上游发布后很快就会发布。我们建议你按照以下步骤升级容器。

Step 1: 获取更新的镜像
docker pull bitnami/postgresql-repmgr:latest

或者,如果你使用的是 Docker Compose,请将 image 属性的值更新为 bitnami/postgresql-repmgr:latest

Step 2: 停止正在运行的容器

使用命令停止当前运行的容器

docker stop pg-0

或者使用 Docker Compose:

docker-compose stop pg-0
 docker-compose stop pg-1

接下来,使用以下命令对持久卷 /path/to/postgresql-persistence 进行快照:

rsync -a /path/to/postgresql-persistence /path/to/postgresql-persistence.bkp.(date +%Y%m%d-%H.%M.%S)
Step 3: 移除当前运行的容器
docker rm -v pg-0

或者使用 Docker Compose:

docker-compose rm -v pg-0
 docker-compose rm -v pg-1
Step 4: 运行新镜像

从新镜像重新创建容器。

docker run --name pg-0 bitnami/postgresql-repmgr:latest

或者使用 Docker Compose:

docker-compose up pg-0
 docker-compose up pg-1

参考链接

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
4月前
|
负载均衡 Cloud Native Linux
云原生|docker|基于docker部署高可用keepalived集群
云原生|docker|基于docker部署高可用keepalived集群
128 0
|
1月前
|
负载均衡 监控 关系型数据库
PostgreSQL从小白到高手教程 - 第48讲:PG高可用实现keepalived
PostgreSQL技术大讲堂 - 第48讲:PG高可用实现keepalived
65 1
|
1月前
|
关系型数据库 分布式数据库 PolarDB
PolarDB常见问题之安装gms时出现docker如何解决
PolarDB是阿里云推出的下一代关系型数据库,具有高性能、高可用性和弹性伸缩能力,适用于大规模数据处理场景。本汇总囊括了PolarDB使用中用户可能遭遇的一系列常见问题及解答,旨在为数据库管理员和开发者提供全面的问题指导,确保数据库平稳运行和优化使用体验。
|
2月前
|
关系型数据库 数据库 PostgreSQL
Docker安装postgreSql
Docker安装postgreSql步骤
|
2月前
|
消息中间件 运维 应用服务中间件
容器化运维:构建高可用RabbitMQ集群的Docker Compose指南
容器化运维:构建高可用RabbitMQ集群的Docker Compose指南
183 0
|
3月前
|
Java Docker Windows
Windows下部署SpringBoot的实践方案(Docker & Docker Desktop)
Windows下部署SpringBoot的实践方案(Docker & Docker Desktop)
76 0
|
4月前
|
Web App开发 安全 前端开发
百度搜索:蓝易云【Docker WebRTC容器部署方案】
以上是一个简单的Docker WebRTC容器部署方案。在实际应用中,你可能需要根据自己的需求进行更复杂的配置和优化。此外,要确保你的WebRTC应用程序在Docker容器中能够正确运行,可能需要处理一些网络和安全方面的问题。
103 6
|
4月前
|
SQL 关系型数据库 C语言
PostgreSQL【应用 03】Docker部署的PostgreSQL扩展SQL之C语言函数(编写、编译、载入)计算向量余弦距离实例分享
PostgreSQL【应用 03】Docker部署的PostgreSQL扩展SQL之C语言函数(编写、编译、载入)计算向量余弦距离实例分享
45 0
|
4月前
|
关系型数据库 数据库 PostgreSQL
PostgreSQL【应用 01】使用Vector插件实现向量相似度查询(Docker部署的PostgreSQL安装pgvector插件说明)和Milvus向量库对比
PostgreSQL【应用 01】使用Vector插件实现向量相似度查询(Docker部署的PostgreSQL安装pgvector插件说明)和Milvus向量库对比
190 1
|
4月前
|
关系型数据库 数据库 PostgreSQL
Docker【应用 03】给Docker部署的PostgreSQL数据库安装PostGIS插件(安装流程及问题说明)
Docker【应用 03】给Docker部署的PostgreSQL数据库安装PostGIS插件(安装流程及问题说明)
156 0