如何在 Vagrant 上自动化 PostgreSQL 和 repmgr 您所在的位置:网站首页 witness怎么安装 如何在 Vagrant 上自动化 PostgreSQL 和 repmgr

如何在 Vagrant 上自动化 PostgreSQL 和 repmgr

2023-03-24 02:50| 来源: 网络整理| 查看: 265

我经常被问到是否可以使用 PostgreSQL 构建一个弹性系统。

考虑到弹性应该具有集群高可用性、容错性和自我修复功能,这并不是一个简单的答案。但是关于这一点有很多话要说。

到今天为止,我们无法像 MongoDB 内置功能那样轻松地实现这种弹性水平。但是让我们看看在 repmgr 和其他一些工具的帮助下我们实际上可以做什么。

在本练习结束时,我们将实现一些派上用场的东西,例如:

几个可重用于生产的 Ansible 角色

用于单命令集群部署的 Vagrantfile

更真实的开发环境;接近生产状态有利于预见“生产专有问题”

物镜

搭建具有容错能力的本地开发环境PostgreSQL集群;

开发配置管理代码以在生产中重用。

先决条件

安装Vagrant,VirtualBox和Ansible

sudo apt install vagrant sudo apt install virtualbox && sudo apt install virtualbox-dkms sudo apt install ansible

进入全屏模式 退出全屏模式

注意:在主机上安装 Ansible 的替代方法是使用ansible-localVagrant 提供程序,它需要在生成的虚拟机上安装 Ansible。

配置 1\。写一个 Vagrantfile

您可以使用vagrant init来生成文件或简单地创建它并插入我们的第一个块。

Vagrant.configure("2") do |config| (1..3).each do |n| config.vm.define "node#{n}" do |define| define.ssh.insert_key = false define.vm.box = "ubuntu/bionic64" define.vm.hostname = "node#{n}" define.vm.network :private_network, ip: "172.16.1.1#{n}" define.vm.provider :virtualbox do |v| v.cpus = 2 v.memory = 1024 v.name = "node#{n}" end end end end

进入全屏模式 退出全屏模式

让我们逐块进行:

第一个区块是我们设置 Vagrant 版本的地方;

在第 2 块,我们迭代下面的代码,所以我们重用它来生成 3 个相等的 VM;

操作系统、主机名和网络设置在第 3 块中设置;

第 4 块包含 VirtualBox 特定设置。

您可以使用以下命令创建服务器:

# create all 3 VMs vagrant up # or create only a specific VM vagrant up node1

进入全屏模式 退出全屏模式

2\。添加佣金

仅通过第一步,我们已经可以启动 3 个工作虚拟机。有点令人兴奋,但最好的还没有到来。

启动虚拟机是 Vagrant 的一个不错的功能,但我们希望这些服务器配置 PostgreSQL 和 repmgr,所以我们将使用配置管理软件来帮助我们。这是 Ansible 走进来让我们惊叹的时刻。

Vagrant 支持多个提供者,其中两个是Ansible和Ansible Local。它们之间的区别在于 Ansible 运行的位置,或者换句话说,它必须安装在哪里。根据 Vagrant 的术语,Ansible 提供程序在主机(您的计算机)上运行,而 Ansible Local 提供程序在客户机(虚拟机)上运行。由于我们已经在先决条件部分安装了 Ansible,我们将使用第一个选项。

让我们在Vagrantfile中为这个配置器添加一个块。

Vagrant.configure("2") do |config| (1..3).each do |n| config.vm.define "node#{n}" do |define| define.ssh.insert_key = false define.vm.box = "ubuntu/bionic64" define.vm.hostname = "node#{n}" define.vm.network :private_network, ip: "172.16.1.1#{n}" define.vm.provider :virtualbox do |v| v.cpus = 2 v.memory = 1024 v.name = "node#{n}" end if n == 3 define.vm.provision :ansible do |ansible| ansible.limit = "all" ansible.playbook = "provisioning/playbook.yaml" ansible.host_vars = { "node1" => {:connection_host => "172.16.1.11", :node_id => 1, :role => "primary" }, "node2" => {:connection_host => "172.16.1.12", :node_id => 2, :role => "standby" }, "node3" => {:connection_host => "172.16.1.13", :node_id => 3, :role => "witness" } } end end end end end

进入全屏模式 退出全屏模式

Ansible 允许我们同时配置多个服务器。要在 Vagrant 上利用此功能,我们添加ansible.limit = "all"并且必须等到所有 3 个 VM 都启动。 Vagrant 知道它们都是因为条件if n == 3而创建的,这使得 Ansible 仅在 Vagrant 迭代 3 次后运行。

ansible.playbook是配置入口点,ansible.host_vars包含要在我们即将创建的任务和模板上使用的 Ansible 主机变量。

3\。创建有组织的 Ansible 文件夹结构

如果您已经熟悉 Ansible,则在本节中无需学习。对于那些不是,它不会变得太复杂。

首先,我们有一个存放所有 Ansible 文件的文件夹,命名为provisioning。在这个文件夹中,我们有前面提到的入口点playbook.yaml、一个存放 Ansible 组变量的group_vars文件夹和一个roles文件夹。

我们可以在playbook.yaml内拥有所有 Ansible 任务,但角色文件夹结构有助于组织。您可以阅读Ansible 文档以了解最佳实践。下面,您将找到本教程的文件夹结构。

project_root | provisioning | | group_vars | | | all.yaml | | roles | | | postgres_12 | | | registration | | | repmgr | | | ssh | | playbook.yaml | Vagrantfile

进入全屏模式 退出全屏模式

4\。 Ansible 角色 4.1 PostgreSQL 角色

要在 PostgreSQL 上配置repmgr,我们需要编辑两个众所周知的 PostgreSQL 配置文件:postgresql.conf和pg_hba.conf。然后我们将编写任务以将配置应用到tasks/main.yaml。我将 PostgreSQL 角色文件夹命名为postgres_12,但您可以轻松使用其他版本如果你想。

postgres_12 | tasks | | main.yaml | templates | | pg_hba.conf.j2 | | pg_hba.conf.j2

进入全屏模式 退出全屏模式

您可以重复使用 PostgreSQL 安装附带的默认文件,并将以下几行添加到来自受信任 VM 的白名单repmgr数据库会话中。创建一个 Ansible 模板文件(Jinja2 格式),如下所示:

# default configuration (...) # repmgr local replication repmgr trust host replication repmgr 127.0.0.1/32 trust host replication repmgr {{ node1_ip }}/32 trust host replication repmgr {{ node2_ip }}/32 trust host replication repmgr {{ node3_ip }}/32 trust local repmgr repmgr trust host repmgr repmgr 127.0.0.1/32 trust host repmgr repmgr {{ node1_ip }}/32 trust host repmgr repmgr {{ node2_ip }}/32 trust host repmgr repmgr {{ node3_ip }}/32 trust

进入全屏模式 退出全屏模式

以与pg_hba.conf相同的方式,您可以重用postgresql.conf默认文件并在文件底部添加更多与复制相关的设置:

# default configuration (...) # repmgr listen_addresses = '*' shared_preload_libraries = 'repmgr' wal_level = replica max_wal_senders = 5 wal_keep_segments = 64 max_replication_slots = 5 hot_standby = on wal_log_hints = on

进入全屏模式 退出全屏模式

以下任务将安装 PostgreSQL 并应用我们的配置。他们的名字是不言自明的。

- name: Add PostgreSQL apt key apt_key: url: https://www.postgresql.org/media/keys/ACCC4CF8.asc - name: Add PostgreSQL repository apt_repository: # ansible_distribution_release = xenial, bionic, focal repo: deb http://apt.postgresql.org/pub/repos/apt/ {{ ansible_distribution_release }}-pgdg main - name: Install PostgreSQL 12 apt: name: postgresql-12 update_cache: yes - name: Copy database configuration template: src: full_postgresql.conf.j2 dest: /etc/postgresql/12/main/postgresql.conf group: postgres mode: '0644' owner: postgres - name: Copy user access configuration template: src: pg_hba.conf.j2 dest: /etc/postgresql/12/main/pg_hba.conf group: postgres mode: '0640' owner: postgres

进入全屏模式 退出全屏模式

4.2 SSH服务器配置 ssh | files | | keys | | | id_rsa | | | id_rsa.pub | tasks | | main.yaml

进入全屏模式 退出全屏模式

生成一个密钥对以在我们的虚拟机中使用以允许访问它们。如果你不知道怎么做,这个链接可以帮助。只需确保密钥文件路径与下一步中的路径匹配即可。

以下任务将安装 OpenSSH 服务器并应用我们的配置。他们的名字是不言自明的。

- name: Install OpenSSH apt: name: openssh-server update_cache: yes state: present - name: Create postgres SSH directory file: mode: '0755' owner: postgres group: postgres path: /var/lib/postgresql/.ssh/ state: directory - name: Copy SSH private key copy: src: "keys/id_rsa" dest: /var/lib/postgresql/.ssh/id_rsa owner: postgres group: postgres mode: '0600' - name: Copy SSH public key copy: src: "keys/id_rsa.pub" dest: /var/lib/postgresql/.ssh/id_rsa.pub owner: postgres group: postgres mode: '0644' - name: Add key to authorized keys file authorized_key: user: postgres state: present key: "{{ lookup('file', 'keys/id_rsa.pub') }}" - name: Restart SSH service service: name: sshd enabled: yes state: restarted

进入全屏模式 退出全屏模式

4.3 repmgr 安装 repmgr | tasks | | main.yaml | templates | | repmgr.conf.j2

进入全屏模式 退出全屏模式

我们在repmgr.conf内配置诸如升级命令、跟随命令、超时和重试计数等设置。我们将此文件复制到其默认目录/etc以避免一直在repmgr命令上传递-f参数。

以下任务将安装repmgr并应用我们的配置。他们的名字是不言自明的。

- name: Download repmgr repository installer get_url: dest: /tmp/repmgr-installer.sh mode: 0700 url: https://dl.2ndquadrant.com/default/release/get/deb - name: Execute repmgr repository installer shell: /tmp/repmgr-installer.sh - name: Install repmgr for PostgreSQL {{ pg_version }} apt: name: postgresql-{{ pg_version }}-repmgr update_cache: yes - name: Setup repmgr user and database become_user: postgres ignore_errors: yes shell: | createuser --replication --createdb --createrole --superuser repmgr && psql -c 'ALTER USER repmgr SET search_path TO repmgr_test, "$user", public;' && createdb repmgr --owner=repmgr - name: Copy repmgr configuration template: src: repmgr.conf.j2 dest: /etc/repmgr.conf - name: Restart PostgreSQL systemd: name: postgresql enabled: yes state: restarted

进入全屏模式 退出全屏模式

4.4 repmgr节点注册

最后,我们到达了建立容错的时刻。

registration | tasks | | main.yaml

进入全屏模式 退出全屏模式

node_id = {{ node_id }} node_name = 'node{{ node_id }}' conninfo = 'host={{ connection_host }} user=repmgr dbname=repmgr' data_directory = '/var/lib/postgresql/{{ pg_version }}/main' use_replication_slots = yes reconnect_attempts = 5 reconnect_interval = 1 failover = automatic pg_bindir = '/usr/lib/postgresql/{{ pg_version }}/bin' promote_command = 'repmgr standby promote -f /etc/repmgr.conf' follow_command = 'repmgr standby follow -f /etc/repmgr.conf' log_level = INFO log_file = '/var/log/postgresql/repmgr.log'

进入全屏模式 退出全屏模式

此角色是根据repmgr文档构建的,它可能是最复杂的角色,因为它需要:

以 root 身份运行某些命令,以 Postgres 身份运行其他命令;

在重新配置之间停止服务;

主、备、支持有不同的任务见证角色配置(如果你想让node3也成为备用节点,只需在Vagrantfileansible.host_vars中分配role: standby)

- name: Register primary node become_user: postgres shell: repmgr primary register ignore_errors: yes when: role == "primary" - name: Stop PostgreSQL systemd: name: postgresql state: stopped when: role == "standby" - name: Clean up PostgreSQL data directory become_user: postgres file: path: /var/lib/postgresql/{{ pg_version }}/main force: yes state: absent when: role == "standby" - name: Clone primary node data become_user: postgres shell: repmgr -h {{ node1_ip }} -U repmgr -d repmgr standby clone ignore_errors: yes when: role == "standby" - name: Start PostgreSQL systemd: name: postgresql state: started when: role == "standby" - name: Register {{ role }} node become_user: postgres shell: repmgr {{ role }} register -F ignore_errors: yes when: role != "primary" - name: Start repmgrd become_user: postgres shell: repmgrd ignore_errors: yes

进入全屏模式 退出全屏模式

5\。设置组变量

创建一个文件group_vars/all.yaml来设置你的虚拟机 IP 地址和你想使用的 PostgreSQL 版本。就像在Vagrantfile上设置的host_vars一样,这些变量将被放置在模板占位符中。

client_ip: "172.16.1.1" node1_ip: "172.16.1.11" node2_ip: "172.16.1.12" node3_ip: "172.16.1.13" pg_version: "12"

进入全屏模式 退出全屏模式

6\。将所有部分与剧本放在一起

唯一缺少的是剧本本身。创建一个名为playbook.yaml的文件并调用我们一直在开发的角色。gather_facts是一个 Ansible 属性,用于获取操作系统数据,例如分布 (ansible_distribution_release) 以及其他有用的变量。您还可以使用Ansible 设置模块读取这些变量。

- hosts: all gather_facts: yes become: yes roles: - postgres_12 - ssh - repmgr - registration

进入全屏模式 退出全屏模式

7\。启动集群

都结束了。您现在可以使用vagrant up启动集群,然后执行连接和故障转移测试。

测试集群故障转移

现在我们的集群已经启动并配置好了,您可以从关闭备用节点开始:

# save standby state and shut it down ungracefully vagrant suspend node2

进入全屏模式 退出全屏模式

您会看到集群运行正常。带回备用节点,它将保持这种状态。

# bring standby back online after suspension vagrant resume node1

进入全屏模式 退出全屏模式

把主节点拿下来怎么样?

# save primary state and shut it down ungracefully vagrant suspend node1

进入全屏模式 退出全屏模式

此时,由于启用了repmgrd,备用节点将按照配置的次数(reconnect_attempts = 5)重试连接到主节点,如果没有响应,则会将自己提升为主节点并接管 PostgreSQL 集群上的写入操作。成功!

要再次加入集群,旧的主节点将不得不丢失其当前数据,克隆新的主数据,并注册为新的备用节点。

vagrant resume node1 vagrant ssh node1 service postgresql stop rm -r /var/lib/postgresql/12/main repmgr -h 172.16.1.12 -U -d repmgr standby clone service postgresql start repmgr standby register -F repmgrd repmgr service status

进入全屏模式 退出全屏模式

最后一条命令向我们展示了集群工作正常,但角色颠倒了。

postgres@node1:~$ repmgr service status ID | Name | Role | Status | Upstream | repmgrd | PID | Paused? | Upstream last seen ----+-------+---------+-----------+----------+---------+-------+---------+-------------------- 1 | node1 | standby | running | node2 | running | 22490 | no | n/a 2 | node2 | primary | * running | | running | 22548 | no | 0 second(s) ago 3 | node3 | witness | * running | node2 | running | 22535 | no | 0 second(s) ago

进入全屏模式 退出全屏模式

这没有错,但是让我们让这些节点切换它们的角色。

# ssh in and out just to add host key to known_hosts file ssh -o StrictHostKeyChecking=no exit # trigger switchover on current standby repmgr standby switchover --siblings-follow

进入全屏模式 退出全屏模式

我们又回到了初始状态。

postgres@node1:~$ repmgr service status ID | Name | Role | Status | Upstream | repmgrd | PID | Paused? | Upstream last seen ----+-------+---------+-----------+----------+---------+-------+---------+-------------------- 1 | node1 | primary | * running | | running | 22490 | no | n/a 2 | node2 | standby | running | node1 | running | 22548 | no | 0 second(s) ago 3 | node3 | witness | * running | node1 | running | 22535 | no | 0 second(s) ago

进入全屏模式 退出全屏模式

结论

我们设法使用 Vagrant 和 Ansible 构建了一个容错 PostgreSQL 集群。

高可用性是一个巨大的挑战。就像生活本身的事情一样,只有当我们适应挑战的条件时,我们才会为最大的挑战做好准备。

生产环境特有的问题是自然而然的,难以猜测。弥合开发和生产之间的差距是防止部署/生产问题的一种方法。我们可以朝着这个目标做出一些努力,而这正是我们刚刚通过这种高可用性数据库设置实现的目标。

你可以在这里找到本教程的源代码。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有