InfoQ|一次近乎完美的PostgreSQL版本大升级实践( 三 )


开始接收流量 , 借此可以尽量减少停机时间 。
使用在维护期间和升级前的磁盘快照恢复其他节点
升级中的所有步骤都在用于运行项目的模板中有详细说明
pg_upgrade 运行原理
pg_upgrade 让我们可以在不用 dump/reload 策略 , 不用更多停机时间的情况下 , 将 PostgreSQL 数据文件升级到日后的主要版本 。
正如在 PostgreSQL 官方文档 中所写 , pg_upgrade 工具通过避免执行 dump/restore 的方法来升级 PostgreSQL 版本 。 这里有几点细节需要注意:PostgreSQL 的主要版本会添加新功能 , 这些新功能经常会改变系统表的布局 , 但内部数据存储格式基本会保持不变 。 如果某次主要版本升级改变了数据格式 , 那么就不能继续用 pg_upgrade 了 。 因此 , 我们必须要先验证这些版本之间都有什么变化 。
还有一点很重要 , 任何外部模块都必须兼容二进制 , 虽然你并不能通过 pg_upgrade 来检查这点 。 对 GitLab 的更新来说 , 我们在升级前先卸载了 postgres_exporter 等视图及拓展 , 以便在升级后重新创建 , 出于兼容性考虑 , 还要稍作修改 。
在更新之前 , 必须先安装新版本的二进制文件 。 新的 PostgreSQL 二进制文件及拓展文件都装在需要升级的主机中 。
pg_upgrade 在使用时有很多选项 。 我们选择在 Leader 节点上使用 pg_upgrade 的链接模式 , 因为维护窗口很短暂 , 只有两个小时 。 这种模式可以通过 inode 硬链接文件 , 避免了复制 6TB 文件的麻烦 。 缺点则是旧数据集群无法回滚到 9.6 版本 。 我们保存了 9.6 版本的副本和 GCP 快照作为后备计划的回滚路径 。 因为从头开始重建副本是不可能 , 所以我们选择使用 rsync 增量功能来进行升级 。 pg_upgrade 的官方文档也有写:“从主服务器上位于旧数据库集群目录和新数据库集群目录上方的目录中 , 在每个备用服务器的 primary 上运行此命令 。 ”
ansible-playbook 对于这一步的实现 , 是通过从 leader 节点到每一个副本都有一个任务 , 在新旧数据目录中的父目录中触发 rsync 命令 。
回归测试的基准
任何的迁移或数据库升级都需要在最终的生产升级前进行回归测试 。 对团队来说 , 数据库测试在升级过程中是至关重要的一步 , 根据生产过程中的查询数额来进行性能测试 , 将结果存到 pg_stat_statement 表中 。 这些都是在同一个数据集中运行的 , 一次是在 9.6 版本 , 一次是在 11 版本的迭代 。 这一步过程可以在下面这个公共的 issue 中找到:
工具的准备
创建测试环境
计算容量
使用 JMeter 工具运行基准测试
最后 , 根据 OnGres 在这一基准测试上的工作 , GitLab 将在未来跟进新的基准测试 。
主要生产数据库集群的能力评估
数据库容量及饱和度分析
升级过程:全自动就完事了
在升级项目中 , 升级团队坚持使用自动化和基础架构及代码工具(IaC) 。 所有流程必须全部自动化 , 以减少在维护窗口的人为失误 。 pg_upgrade 所有的运行步骤都可以在这个 GitLab 的 pg_upgrade 的模板 issue 上找到详细说明 。
GitLab.com 的环境由 Terraform 和 Chef 共同管理 , 所有的升级自动化都是用 Ansible 2.9 的 playbook 和 roles 编写的 , 我们用了两个 ansible-playbook 来完成升级自动化:
一个 ansible-playbook 控制流量和应用:
将 Cloudflare 设置为维护状态 , 不接受流量:
停止 HA-proxy
停止访问数据库的中间件:Sidekiq、Workhorse、WEB-API
另一个 ansible-playbook 运行升级过程:
协调所有数据库和连接池的流量
控制 Patroni 集群和 Consul 实例
在主节点和次级节点上执行升级
收集升级后的统计数据


推荐阅读