将本地 PostgreSQL 集群迁移到 Google Cloud

本文介绍了如何将本地 PostgreSQL 集群迁移到 Google Cloud。此方法使用 PgBouncer 作为连接池程序,这可以最大限度地减少应用停机时间,并有助于设置用于监控结果的工具。本文的目标受众是在 Linux 环境中工作的 PostgreSQL 管理员和系统管理员。

在下图中,PgBouncer 实例位于本地主实例的前面。

位于本地主实例前面的 PgBouncer 实例的架构。

有了连接池,客户端便会在故障转移到 Google Cloud 时路由到替代节点,而无需重新部署应用配置或进行应用级更改。

下图演示了迁移过程。

到 Google Cloud 的迁移的架构。

如需执行迁移,请关停当前主实例,然后将从属 Google Cloud 副本提升为主实例。PgBouncer 会将流量重新路由到 Google Cloud 上的新主节点。

费用

本教程使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计用量来估算费用。

目标

  • 在 Google Cloud 中设置 PostgreSQL。
  • 在 Compute Engine 上设置复制功能。
  • 将数据播种 (seed) 至新实例。
  • 在 Google Cloud 上设置 PostgreSQL 集群。
  • 切换到新服务器。
  • 实现监控功能。

准备工作

本教程使用 gcloudgsutil 命令,您可以通过从 Cloud Console 启动的 Cloud Shell 实例运行这些命令。如果要在本地工作站上使用 gcloudgsutil,请安装 Cloud SDK。本教程介绍的是如何在 Cloud Shell 中运行命令;如果您在工作站上使用 Cloud SDK,请相应调整指令。

  1. 登录您的 Google Cloud 帐号。如果您是 Google Cloud 新手,请创建一个帐号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到“项目选择器”

  3. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  4. 启用 Compute Engine API。

    启用 API

  5. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到“项目选择器”

  6. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  7. 启用 Compute Engine API。

    启用 API

设置环境

首先执行以下任务:

  • 在 Google Cloud 中设置 PostgreSQL。
  • 在 Compute Engine 上设置复制功能。

然后,在开始复制主实例之前,将数据播种到新实例。

在 Google Cloud 中设置 PostgreSQL

请按照如何设置 PostgreSQL 以通过热备用模式实现高可用性和复制功能中所述的步骤操作,只需几分钟即可在 Google Cloud 上设置好 PostgreSQL。您可在 Compute Engine 上的 Ubuntu 虚拟机实例中配置 PostgreSQL。

在 Compute Engine 上设置复制功能

请按照如何在 Google Compute Engine 上设置 PostgreSQL 中所述的步骤配置 PostgreSQL,使其在 Compute Engine 上以热备用模式运行。您需要使用两个 Compute Engine 实例。一个实例用于运行主 PostgreSQL 服务器,另一个实例用于运行备用服务器。

尽管用于配置 PostgreSQL 的属性在主实例和从属实例之间有所不同,但属性文件应当相同,以便实现无缝故障转移。

PostgreSQL 集群中的从属实例通过 recovery.conf 文件的存在来表示。

在大多数情况下,都有必要分离数据库的数据目录与启动磁盘。在本例中,数据库文件存储在 /database 处装载的目录中。

如需修改主实例上的 postgresql.conf 文件以设置复制功能,请使用以下命令:

wal_level = 'hot_standby'
archive_mode = on
archive_command = 'test ! -f /postgresql/archivedir/%f && cp %p /postgresql/archivedir/%f'
max_wal_senders = 3
listen_addresses = '*'
wal_keep_segments = 8

如需修改副本上的 postgresql.conf 文件,请使用以下命令:

hot_standby = on
standby_mode = on
primary_conninfo = 'host=${PRIMARY_IP} port=5432 user=repuser'

向副本发送 Read 请求可以减轻主实例的负载。

播种数据

由于主数据库有事务日志限额,因此大多数 PostgreSQL 迁移都需要将数据种子设定为新实例,然后才能开始复制主实例。可通过以下某种方式播种数据:

  • 使用 Pg_dump 将单个数据库转储为一个脚本或归档文件。
  • 使用 Pg_basebackup 获取正在运行的数据库集群的二进制副本。
  • 使用 rsync 将数据文件夹复制到副本。
  • 将旧备份恢复到副本。

在上述方式中,推荐的方式是将旧备份恢复到副本。采用这种解决方案时,系统性能不会因传输数据量大而受到影响,并且当前集群仍能够继续正常运行。

在数据库的初始种子设定完成之后,您可以使用 rsync 命令将更改馈送到执行备份后生成的副本;该命令会同步两个实例之间的数据目录。如果备份比主实例滞后太多,无法通过正常复制与之同步,那么这步操作非常重要。

在 Google Cloud 上设置 PostgreSQL 集群

您可以使用级联复制功能创建 PostgreSQL 集群。首先迁移数据库,如下图所示。

迁移到 Google Cloud 的当前环境的架构。

迁移数据库

  1. 从正在运行的主服务器获取完整备份(label 可以是任何标签):

    echo "select pg_start_backup('label',true);" |sudo su - postgres -c psql
    sudo tar cvfz postgresql_AAAAMMDD.tar.gz $PGDATA
    

    $PGDATA 是 PostgreSQL 的主数据目录。

  2. 在 Google Cloud 项目中创建一个名为 gs://pg-repo/ 的存储分区。

  3. 将备份转移到刚刚创建的存储分区:

    master$ gsutil cp postgresql_AAAAMMDD.tar.gz gs://pg-repo/
    
  4. 将备份文件转移到 Google Cloud 主实例:

    new_master$ gsutil cp gs://pg-repo/postgresql_AAAAMMDD.tar.gz
    
  5. 将备份文件恢复到 Google Cloud 主实例:

    new_master$ (cd / ; tar xvf postgresql_AAAAMMDD.tar.gz)
    
  6. $PG_DATA 目录中创建一个包含以下内容的 recovery.conf 文件:

    standby_mode     = 'on'
    primary_conninfo = 'port=5432 host=${running_master_ip} user=${replication_user} application_name=cloud_master'
    trigger_file     = '/tmp/failover.postgresql.5432'
    
  7. 启动 PostgreSQL 服务:

    sudo service postgresql start
    
  8. 等待 Google Cloud 主服务器与正在运行的主实例同步。在日志中,您可以看到如下所示的内容:

    tail -f /var/log/postgresql/postgresql*log
    ...
    2018-09-22 17:59:54 UTC LOG:  consistent recovery state reached at 0/230000F0
    2018-09-22 17:59:54 UTC LOG:  database system is ready to accept read only connections
    ...
    

    此外,您可以搜索 master pg_stat_replication 来确定新的从属实例(称为 cloud_master)是否已连接:

    postgres=# \x
    Expanded display is on.
    postgres=# select * from pg_stat_replication where application_name='cloud_master';
    -[ RECORD 1 ]----+------------------------------
    pid              | 16940
    usesysid         | 16402
    usename          | repmgr
    application_name | cloud_master
    ...
    

创建从属数据库

  1. 关停数据库和服务器:

    sudo service postgresql stop
    sudo shutdown -h now
    
  2. 如需验证服务已经停止,请运行以下命令:

    gcloud compute instances describe master-instance-name | grep status
    

    在输出中,实例的状态将显示为 TERMINATED

    status: TERMINATED
    

    接下来,创建数据磁盘的快照以帮助创建新的从属实例。

  3. 在 Cloud Console 中,转到快照页面。

    转到“快照”页面

  4. 基于 PostgreSQL 磁盘新建一个快照。

  5. 启动 Google Cloud 主服务器。

  6. 转到虚拟机实例页面,点击 master-instance-name,然后点击启动

    PostgreSQL 服务即会自动启动。

  7. 如需检查这一点,请运行以下命令:

    ps ax | grep postgres
    

    结果应该类似如下所示:

     1398 ?     S   0:00 /usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main -c config_file=/etc/postgresql/9.3/main/postgresql.conf
     1454 ?     Ss  0:00 postgres: checkpointer process
     1455 ?     Ss  0:00 postgres: writer process
     1456 ?     Ss  0:00 postgres: wal writer process
     1457 ?     Ss  0:00 postgres: stats collector process
    
  8. 在 Cloud Console 中,转到虚拟机实例页面,然后点击创建实例

  9. 对于启动磁盘,选择 Ubuntu 14.04

  10. 点击管理、磁盘、网络、SSH 密钥,然后根据您之前创建的快照添加新的磁盘。

  11. 启动新服务器并装载该磁盘:

    sudo mkdir /database && sudo mount /dev/sdb1 /database
    
  12. 安装 PostgreSQL:

    sudo apt-get install postgresql && sudo service postgresql stop
    
  13. 配置数据目录和复制值。从 Google Cloud 主实例中复制 postgresql.conf 文件和 pg_hba.conf 文件,然后修改 recovery.conf 文件以包含以下内容:

    standby_mode = 'on'
    primary_conninfo = 'port=5432 host=${cloud_master_ip} user=${replication_user} application_name=cloud_slave_${identifier}'
    recovery_target_timeline = 'latest'
    
  14. 使用新的配置文件启动 PostgreSQL 服务,使其指向 Google Cloud 主实例:

    sudo service postgresql restart
    
  15. 验证服务正在运行:

    ps ax | grep postgres
    
  16. 使用以下查询检查 Google Cloud 主服务器:

    postgres=# \x
    Expanded display is on.
    postgres=# select * from pg_stat_replication where application_name like 'cloud_slave%';
    -[ RECORD 1 ]----+-----------------------------
    pid              | 2466
    usesysid         | 16402
    usename          | repmgr
    application_name | cloud_slave_1
    ...
    
  17. 重复上述步骤来创建更多从属实例。

切换到新服务器

  1. 将 PgBouncer 中的配置文件更改为指向新的 Google Cloud 主服务器。
  2. 在 PgBouncer 实例中,关停 PgBouncer,使用 failover.postgresql.5432 触发器文件提升新的主实例,然后重启 PgBouncer:

    service pgbouncer stop ; ssh ${cloud_master_ip} 'touch /tmp/failover.postgresql.5432' ; service pgbouncer start
    

设置监控功能

Google 已与 Blue Medora 携手合作,共同提供 PostgreSQL 指标。您可以从现有的 PostgreSQL 实例和新的 Google Cloud 实例收集指标和日志。

如需详细了解 Blue Medora 的 PostgreSQL 监控支持,请访问相应的使用入门页面。

查询示例

检查服务器上的所有并发连接数:

 select * from pg_stat_activity;

(主实例)检查复制状态:

select * from pg_stat_replication;

(主实例)检查副本应用数据的延迟情况:

select pg_xlog_location_diff(write_location, replay_location) from pg_stat_replication;

(主实例)检查复制的字节延迟情况:

select client_hostname, client_addr, pg_xlog_location_diff(pg_stat_replication.sent_location,
  pg_stat_replication.replay_location)AS byte_lag from pg_stat_replication;

(从属实例)检查数据库是否为副本:

select pg_is_in_recovery();

(从属实例)检查上次从主实例接收的数据:

select pg_last_xlog_receive_location();

(从属实例)检查上次从主实例应用的数据:

select pg_last_xlog_replay_location();

(从属实例)检查复制延迟时间(以秒为单位):

select now() - pg_last_xact_replay_timestamp();

清理

删除项目

  1. 在 Cloud Console 中,转到管理资源页面。

    转到“管理资源”

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

后续步骤

  • 探索有关 Google Cloud 的参考架构、图表、教程和最佳做法。查看我们的云架构中心
  • 了解如何使用 Google Cloud 产品构建端到端解决方案