使用 Docker swarm 构建 PostgreSQL 集群

又是一个渣翻,Copyright belongs to the original text。

原文地址

背景

PostgreSQL 在 9.0 版本已经开始持续接收大量的增强,包括:

  1. 异步拓展
  2. 同步拓展
  3. 仲裁提交
  4. 级联拓展
  5. 逻辑拓展

PostgreSQL 文档也提供了一个 overview 以及 不同拓展方法的比较。详见PostgreSQL 集群策略比较

用于部署 PostgreSQL 的拓展的主拓展的方法论,是一个重要的工具来为你的数据库集群创建高可用的环境。需要一个合适的部署策略来确保你的数据被保存到不同磁盘,以及不同的数据中心。

拓展不是一个“安装然后忘记”的操作。在生产系统中,你想要确定你对实例有合适的监控,来了解你所有的在线的拓展,或者了解一个拓展有多少数据需要与主节点进行同步。

当主节点配置好以后,安装就很容易了。但幸运的是,使用 Docker 可以使得这个过程更加轻松。

环境安装

想要部署这个环境,你至少需要 Docker 1.12版本。

要想开始,提供一个 Docker 集群。例如,一个开发集群,你可以在每一个机器上加载 Dokcer,来使用 Swarm。这个方法将使用如下的架构:

PostgreSQL Docker Swarm Architecture

每一个系统都需要安装 Docker 以及启动。

Swarm 安装

从1.12版本开始,Docker就已经集成了Swarm。

容器编排

高可用 PostgresSQL 集群配置需要两个以上的主机。主节点和从节点需要运行在不同的 worker 节点上,来使得可用性最高。

为了部署 Crunchy PostgreSQL containers 到多个集群,你需要使用 node labels。

标注主机对于使用 PostgreSQL 容器有几个好处:

  • 将服务散步到许多 worker 上,来提高可用性
  • 主机可以针对读(从)写(主)操作进行优化(例如使用高性能磁盘)

记住:对于PostgreSQL 10,主节点可以同时被允许读写,但是从节点仅仅允许被读。

为了允许容器被放在指定的 worker 节点上,增加一个元数据标签到 Swarm 节点上。

node1_id=$(docker node list | grep worker1 | awk '{print $1}')
docker node update --label-add type=primary ${node1_id?}

在上述例子中,一个被称为 primary 的标签,加入了 worker1。通过使用这个标签,我们可以应用一些约束到 Docker swarm 的 PostgreSQL Stack 部署上。

注意:我们没有对从节点增加约束,我们可以简单的使用一条 inverse 约束:

node.labels.type != primary

PostgreSQL stack 定义

通过 Swarm 部署以及 worker 节点正确的标记,我们可以部署 PostgreSQL stack了。

PostgreSQL stack 是通过一个主节点以及从节点组成的。下面是服务定义:

docker-compose.yml

---
version: "3.3"

services:
  primary:
    hostname: 'primary'
    image: crunchydata/crunchy-postgres:centos7-10.3-1.8.2
    environment:
    - PGHOST=/tmp
    - MAX_CONNECTIONS=10
    - MAX_WAL_SENDERS=5
    - PG_MODE=primary
    - PG_PRIMARY_USER=primaryuser
    - PG_PRIMARY_PASSWORD=password
    - PG_DATABASE=testdb
    - PG_USER=testuser
    - PG_PASSWORD=password
    - PG_ROOT_PASSWORD=password
    - PG_PRIMARY_PORT=5432
    volumes:
    - pg-primary-vol:/pgdata
    ports:
    - "5432"
    networks:
    - crunchynet
    deploy:
      placement:
        constraints:
        - node.labels.type == primary
        - node.role == worker
  replica:
    image: crunchydata/crunchy-postgres:centos7-10.3-1.8.2
    environment:
    - PGHOST=/tmp
    - MAX_CONNECTIONS=10
    - MAX_WAL_SENDERS=5
    - PG_MODE=replica
    - PG_PRIMARY_HOST=primary
    - PG_PRIMARY_PORT=5432
    - PG_PRIMARY_USER=primaryuser
    - PG_PRIMARY_PASSWORD=password
    - PG_DATABASE=testdb
    - PG_USER=testuser
    - PG_PASSWORD=password
    - PG_ROOT_PASSWORD=password
    volumes:
    - pg-replica-vol:/pgdata
    ports:
    - "5432"
    networks:
    - crunchynet
    deploy:
      placement:
        constraints:
        - node.labels.type != primary
        - node.role == worker
networks:
  crunchynet:

volumes:
  pg-primary-vol:
  pg-replica-vol:

注意,主服务定义了一个 hostname,但是 replica 服务没有。Replica 需要一个 hostname 来启动 replication。通过提供一个静态的 hostname 给主节点,replica就可以连接主节点,而不需要发现主容器。

replica,没有一个 hostname,这允许 replica 服务拓展到多个节点。(待会儿展示一下)。

primary 和 replica 服务的主要区别,是 PG_MODE 环境变量。这个变量配置容器是主节点,还是从节点。

部署 STACK

保存这个文件到 docker-compose.yml 之后,我们可以通过 Docker 进行部署了。

docker stack deploy --compose-file=./docker-compose.yml pg-stack

这个 stack 部署,将会创建一个 PostgreSQL 集群,就像是下图一样:

PostgreSQL Docker Swarm Primary Replica Cluster

测试集群

检查服务是否运行,运行下面的命令:

docker service ls
docker service ps pg-stack_primary
docker service ps pg-stack_replica

如果想要提升 replicas 的数量,运行下列命令:

docker service scale pg-stack_replica=2
docker service ps pg-stack_replica

为了确保 replicas 是流式的,在 worker1 节点上查询 PostgreSQL 主节点,使用下列命令:

docker exec -it $(docker ps -q) psql -U postgres -x -c 'table pg_stat_replication' postgres

示例代码

下面是实例代码:

https://github.com/CrunchyData/crunchy-containers/tree/master/examples/docker/swarm-service

结论

Docker 以及 Docker swarm 提供了工具,来使得容器部署进入了更高的层次。我们希望这个提议证明了 PostgreSQL 集群是如何的容易部署。

打赏

发表评论

电子邮件地址不会被公开。 必填项已用*标注