Setup
:一个 Docker Swarm,包含一个管理器节点和一个工作节点(两个虚拟机)。其中docker-stack.yml
包含两个服务
primary
:bitnami/postgresql图像设置为主 postgres 服务器。- 已安装一个本地目录(
./docker/primary/data
在管理器节点上)来保存来自主 postgres 服务的数据。 - 仅有 1 个实例正在运行。
- 已安装一个本地目录(
replica
:bitnami/postgresql图像设置为复制的 postgres 服务器。- 未挂载任何卷。这意味着复制的数据是短暂的,重新启动容器将导致
replica
服务实例上的数据丢失。 - 有 5 个实例通过
replicas: 5
键deploy:
运行docker-stack.yml
。
- 未挂载任何卷。这意味着复制的数据是短暂的,重新启动容器将导致
- 此设置有效,并
select * from pg_stat_replication;
显示 5 个 wal 接收器primary
。 - swarm 中的两个虚拟机都在我的 Debian 计算机上本地运行。在实际生产环境中,这两台机器将是两个单独的 ec2 实例。我只是在本地运行它来学习 HA 部署。
Goal
:将“副本”服务的每个复制实例的数据保存到单独的目录中(可能在本地工作节点本身的唯一目录中,或者在 aws s3 存储桶中进行备份;对于上述设置,每个“副本”服务复制实例总共应该有 5 个唯一备份)。
Problem
:
replica
如果我以与为我的服务安装相同的方式在服务上安装本地卷primary
。我认为这会导致写入竞争,因为服务的每个“副本”实例都会尝试写入同一个文件夹,并且本地文件夹不能保证在群集中存在工作节点和管理器节点。您如何克服这个问题?- 如果上述本地备份有效,那么您如何获取该本地目录并将其备份到 aws s3 存储桶?
Research
:我搜索了这个问题并得出的结论是,swarm 在状态全复制方面并不擅长,而 swarm 更多地是为给定服务的无状态复制而设计的。
docker-stack.yml
version: "3.9"
# temporary env vars.
services:
primary:
image: "bitnami/postgresql:latest"
environment:
postgresql_username: "primary"
postgresql_password: "password"
postgresql_database: "lune"
postgresql_replication_mode: "master"
postgresql_replication_user: "replica"
postgresql_replication_password: "password"
postgresql_synchronous_commit_mode: "on"
postgresql_num_synchronous_replicas: "1"
volumes:
- ./docker/primary/data:/bitnami/postgresql
ports:
- 5432:5432
networks:
- backend
deploy:
restart_policy:
condition: on-failure
replica:
image: "bitnami/postgresql:latest"
depends_on:
- primary
environment:
postgresql_password: "password"
postgresql_replication_mode: "slave"
postgresql_replication_user: "replica"
postgresql_replication_password: "password"
postgresql_master_host: "primary"
postgresql_master_port_number: "5432"
ports:
- 5433:5432
networks:
- backend
deploy:
replicas: 5
restart_policy:
condition: on-failure
networks:
backend: