暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

PAF-Azure VM 教程

原创 sg1234 2023-07-13
298

Azure VM 教程

在本指南中,我们将创建一个主节点和辅助 Postgres 节点并设置 最多pg_auto_failover在它们之间复制数据。我们将模拟失败 主节点,并查看系统如何顺利切换(故障转移) 到次要。

为了进行说明,我们将在 Azure 中的虚拟机上运行数据库 平台,但这里的技术与任何云提供商或 本地网络。我们将使用四个虚拟机:一个主数据库,一个 辅助数据库、监视器和“应用程序”。监视器监视 其他节点的运行状况,管理全局状态,并为节点分配其角色。

创建虚拟网络

我们的数据库机器需要相互通信并与监视节点通信,因此 让我们创建一个虚拟网络。

az group create \
  --name ha-demo \
  --location eastus

az network vnet create \
  --resource-group ha-demo \
  --name ha-demo-net \
  --address-prefix 10.0.0.0/16

我们需要在机器之间打开端口 5432(Postgres)和 22 (SSH),并且 也让我们自己从我们的远程 IP 访问。我们将通过网络来做到这一点 安全组和子网。

az network nsg create \
  --resource-group ha-demo \
  --name ha-demo-nsg

az network nsg rule create \
  --resource-group ha-demo \
  --nsg-name ha-demo-nsg \
  --name ha-demo-ssh-and-pg \
  --access allow \
  --protocol Tcp \
  --direction Inbound \
  --priority 100 \
  --source-address-prefixes `curl ifconfig.me` 10.0.1.0/24 \
  --source-port-range "*" \
  --destination-address-prefix "*" \
  --destination-port-ranges 22 5432

az network vnet subnet create \
  --resource-group ha-demo \
  --vnet-name ha-demo-net \
  --name ha-demo-subnet \
  --address-prefixes 10.0.1.0/24 \
  --network-security-group ha-demo-nsg

最后添加四个虚拟机(ha-demo-a、ha-demo-b、ha-demo-monitor 和 哈演示应用程序)。为了提高速度,我们将进程后台并运行 它们并行:az vm create

# create VMs in parallel
for node in monitor a b app
do
az vm create \
  --resource-group ha-demo \
  --name ha-demo-${node} \
  --vnet-name ha-demo-net \
  --subnet ha-demo-subnet \
  --nsg ha-demo-nsg \
  --public-ip-address ha-demo-${node}-ip \
  --image debian \
  --admin-username ha-admin \
  --generate-ssh-keys &
done
wait

为了在以后的步骤中更轻松地通过 SSH 连接到这些 VM,让我们创建一个 shell 检索其 IP 地址的功能:

# run this in your local shell as well

vm_ip () {
az vm list-ip-addresses -g ha-demo -n ha-demo-$1 -o tsv \
  --query '[] [] .virtualMachine.network.publicIpAddresses[0].ipAddress'
}

# for convenience with ssh

for node in monitor a b app
do
ssh-keyscan -H `vm_ip $node` >> ~/.ssh/known_hosts
done

让我们回顾一下到目前为止我们创建的内容。

az resource list --output table --query \
"[?resourceGroup=='ha-demo'].{ name: name, flavor: kind, resourceType: type, region: location }"

这将显示以下资源:

Name                             ResourceType                                           Region
------------------------------- ----------------------------------------------------- --------
ha-demo-a                       Microsoft.Compute/virtualMachines                     eastus
ha-demo-app                     Microsoft.Compute/virtualMachines                     eastus
ha-demo-b                       Microsoft.Compute/virtualMachines                     eastus
ha-demo-monitor                 Microsoft.Compute/virtualMachines                     eastus
ha-demo-appVMNic                 Microsoft.Network/networkInterfaces                   eastus
ha-demo-aVMNic                   Microsoft.Network/networkInterfaces                   eastus
ha-demo-bVMNic                   Microsoft.Network/networkInterfaces                   eastus
ha-demo-monitorVMNic             Microsoft.Network/networkInterfaces                   eastus
ha-demo-nsg                     Microsoft.Network/networkSecurityGroups               eastus
ha-demo-a-ip                     Microsoft.Network/publicIPAddresses                   eastus
ha-demo-app-ip                   Microsoft.Network/publicIPAddresses                   eastus
ha-demo-b-ip                     Microsoft.Network/publicIPAddresses                   eastus
ha-demo-monitor-ip               Microsoft.Network/publicIPAddresses                   eastus
ha-demo-net                     Microsoft.Network/virtualNetworks                     eastus



安装“pg_autoctl”可执行文件

本指南使用 Debian Linux,但类似的步骤也适用于其他 分布。所有不同的是包和路径。请参阅安装pg_auto_failover

pg_auto_failover系统作为单个二进制文件分发 使用子命令来初始化和管理复制的 PostgreSQL 服务。 我们将在所有 节点。它将帮助我们运行和观察PostgreSQL。pg_autoctl

for node in monitor a b app
do
az vm run-command invoke \
  --resource-group ha-demo \
  --name ha-demo-${node} \
  --command-id RunShellScript \
  --scripts \
    "sudo touch /home/ha-admin/.hushlogin" \
    "curl https://install.citusdata.com/community/deb.sh | sudo bash" \
    "sudo DEBIAN_FRONTEND=noninteractive apt-get install -q -y postgresql-common" \
    "echo 'create_main_cluster = false' | sudo tee -a /etc/postgresql-common/createcluster.conf" \
    "sudo DEBIAN_FRONTEND=noninteractive apt-get install -q -y postgresql-11-auto-failover-1.4" \
    "sudo usermod -a -G postgres ha-admin" &
done
wait


运行监视器

pg_auto_failover监视器是要运行的第一个组件。它定期 尝试联系其他节点并观察其运行状况。它还 维护全局状态,每个节点上的“守护者”都会咨询以确定其 在系统中自己的角色。

# on the monitor virtual machine

ssh -l ha-admin `vm_ip monitor` -- \
pg_autoctl create monitor \
  --auth trust \
  --ssl-self-signed \
  --pgdata monitor \
  --pgctl /usr/lib/postgresql/11/bin/pg_ctl

此命令在指向的位置初始化 PostgreSQL 集群 通过选项。省略时,尝试使用环境变量。如果一个PostgreSQL 实例已存在于目标目录中,此命令 会将其配置为充当监视器。--pgdata``--pgdata``pg_autoctl``PGDATA

pg_auto_failover`,安装 Postgres 扩展,以及 向新用户授予访问权限。`pgautofailover``autoctl_node

在快速入门中,我们使用 避免复杂的安全设置。 Postgres信任身份验证方法不被认为是合理的 生产环境的选择。请考虑使用该选项,或者自己设置密码。--auth trust``--skip-pg-hba``--auth scram-sha-256

此时,将创建监视器。现在我们将它作为服务安装 systemd,以便在虚拟机重新启动时恢复。

ssh -T -l ha-admin `vm_ip monitor` << CMD
pg_autoctl -q show systemd --pgdata ~ha-admin/monitor > pgautofailover.service
sudo mv pgautofailover.service /etc/systemd/system
sudo systemctl daemon-reload
sudo systemctl enable pgautofailover
sudo systemctl start pgautofailover
CMD

Bring up the nodes

We’ll create the primary database using the subcommand.pg_autoctl create

ssh -l ha-admin `vm_ip a` -- \
pg_autoctl create postgres \
  --pgdata ha \
  --auth trust \
  --ssl-self-signed \
  --username ha-admin \
  --dbname appdb \
  --hostname ha-demo-a.internal.cloudapp.net \
  --pgctl /usr/lib/postgresql/11/bin/pg_ctl \
  --monitor 'postgres://autoctl_node@ha-demo-monitor.internal.cloudapp.net/pg_auto_failover?sslmode=require'

Notice the user and database name in the monitor connection string – these are what monitor init created. We also give it the path to pg_ctl so that the keeper will use the correct version of pg_ctl in future even if other versions of postgres are installed on the system.

In the example above, the keeper creates a primary database. It chooses to set up node A as primary because the monitor reports there are no other nodes in the system yet. This is one example of how the keeper is state-based: it makes observations and then adjusts its state, in this case from “init” to “single.”

Also add a setting to trust connections from our “application” VM:

ssh -T -l ha-admin `vm_ip a` << CMD
echo 'hostssl "appdb" "ha-admin" ha-demo-app.internal.cloudapp.net trust' \
  >> ~ha-admin/ha/pg_hba.conf
CMD

此时,监视器和主节点已创建并运行。接下来我们 需要运行守门员。这是一个独立的过程,因此它可以继续 即使 PostgreSQL 进程在节点上终止,也会运行。我们会 使用 systemd 将其作为服务安装,以便在 VM 重新启动时恢复。

ssh -T -l ha-admin `vm_ip a` << CMD
pg_autoctl -q show systemd --pgdata ~ha-admin/ha > pgautofailover.service
sudo mv pgautofailover.service /etc/systemd/system
sudo systemctl daemon-reload
sudo systemctl enable pgautofailover
sudo systemctl start pgautofailover
CMD

接下来连接到节点 B 并执行相同的过程。我们将同时执行这两个步骤:

ssh -l ha-admin `vm_ip b` -- \
pg_autoctl create postgres \
  --pgdata ha \
  --auth trust \
  --ssl-self-signed \
  --username ha-admin \
  --dbname appdb \
  --hostname ha-demo-b.internal.cloudapp.net \
  --pgctl /usr/lib/postgresql/11/bin/pg_ctl \
  --monitor 'postgres://autoctl_node@ha-demo-monitor.internal.cloudapp.net/pg_auto_failover?sslmode=require'

ssh -T -l ha-admin `vm_ip b` << CMD
pg_autoctl -q show systemd --pgdata ~ha-admin/ha > pgautofailover.service
sudo mv pgautofailover.service /etc/systemd/system
sudo systemctl daemon-reload
sudo systemctl enable pgautofailover
sudo systemctl start pgautofailover
CMD

它从监视器中发现主数据库存在,然后切换自己的主数据库 状态为热备用并开始从主数据库流式传输 WAL 内容。

节点通信

为方便起见,pg_autoctl修改每个节点的文件以允许 要相互连接的节点。例如,pg_autoctl添加了 节点 A 的以下行:pg_hba.conf

# automatically added to node A

hostssl "appdb" "ha-admin" ha-demo-a.internal.cloudapp.net trust
hostssl replication "pgautofailover_replicator" ha-demo-b.internal.cloudapp.net trust
hostssl "appdb" "pgautofailover_replicator" ha-demo-b.internal.cloudapp.net trust

在监控节点上pg_autoctl检查本地网络 并对要允许的子网进行最佳猜测。在我们的例子中,它猜到了 正确:pg_hba.conf

# automatically added to the monitor

hostssl "pg_auto_failover" "autoctl_node" 10.0.1.0/24 trust

如果工作线程节点具有更多临时地址并且不在同一子网中,则 最好在创建过程中使用命令行选项禁用pg_autoctl对pg_hba的自动修改。然后,您将需要 手动编辑 HBA 文件。手动编辑的另一个原因是使用 特殊的身份验证方法。--skip-pg-hba

观看复制

首先,让我们验证监视器是否知道我们的节点,看看是什么 声明它已分配它们:

ssh -l ha-admin `vm_ip monitor` pg_autoctl show state --pgdata monitor

Name | Node |                           Host:Port |       LSN | Reachable |       Current State |     Assigned State
-------+-------+--------------------------------------+-----------+-----------+---------------------+--------------------
node_1 |     1 | ha-demo-a.internal.cloudapp.net:5432 | 0/3000060 |       yes |             primary |             primary
node_2 |     2 | ha-demo-b.internal.cloudapp.net:5432 | 0/3000060 |       yes |           secondary |           secondary

这看起来不错。我们可以将数据添加到主数据库,稍后会看到它出现在 二 次。我们将从“应用程序”虚拟机内部连接到数据库, 使用从监视器获取的连接字符串。

ssh -l ha-admin `vm_ip monitor` pg_autoctl show uri --pgdata monitor

    Type |   Name | Connection String
-----------+---------+-------------------------------
  monitor | monitor | postgres://autoctl_node@ha-demo-monitor.internal.cloudapp.net:5432/pg_auto_failover?sslmode=require
formation | default | postgres://ha-demo-b.internal.cloudapp.net:5432,ha-demo-a.internal.cloudapp.net:5432/appdb?target_session_attrs=read-write&sslmode=require

现在,我们将获取连接字符串并将其存储在本地环境中 变量:

APP_DB_URI=$( \
ssh -l ha-admin `vm_ip monitor` \
  pg_autoctl show uri --formation default --pgdata monitor \
)

连接字符串包含我们的两个节点,逗号分隔,并包括 URL 参数告诉 psql 我们 想要连接到这些服务器中的任何一个支持读取写入。 这将是主服务器。?target_session_attrs=read-write

# connect to database via psql on the app vm and
# create a table with a million rows
ssh -l ha-admin -t `vm_ip app` -- \
psql "'$APP_DB_URI'" \
  -c "'CREATE TABLE foo AS SELECT generate_series(1,1000000) bar;'"

导致故障转移

现在我们已经将数据添加到节点 A,让我们切换哪个被认为是 主要和次要。切换后,我们将再次连接 并查询数据,这次是从节点 B 查询。

# initiate failover to node B
ssh -l ha-admin -t `vm_ip monitor` \
pg_autoctl perform switchover --pgdata monitor

一旦节点B被标记为“主”(或“wait_primary”),我们就可以连接并验证 数据仍然存在:

# connect to database via psql on the app vm
ssh -l ha-admin -t `vm_ip app` -- \
psql "'$APP_DB_URI'" \
  -c "'SELECT count(*) FROM foo;'"

它显示

  count
---------
1000000

导致节点故障

这个剧情太无聊了,是时候介绍个问题了。我们将关闭 VM 的 节点 B(当前是我们上次故障转移后的主节点)和监视节点 A 升职。

在一个终端中,让我们密切关注事件:

ssh -t -l ha-admin `vm_ip monitor` -- \
watch -n 1 -d pg_autoctl show state --pgdata monitor

在另一个终端中,我们将关闭虚拟服务器。

az vm stop \
--resource-group ha-demo \
--name ha-demo-b

在多次尝试与节点 B 通信失败后,监视器确定 节点运行状况不佳,并将其置于“降级”状态。监视器 将节点 A 提升为新的主节点。

  Name |  Node |                            Host:Port |       LSN | Reachable |       Current State |      Assigned State
-------+-------+--------------------------------------+-----------+-----------+---------------------+--------------------
node_1 |     1 | ha-demo-a.internal.cloudapp.net:5432 | 0/6D4E068 |       yes |       wait_primary |       wait_primary
node_2 |     2 | ha-demo-b.internal.cloudapp.net:5432 | 0/6D4E000 |       yes |             demoted |         catchingup

节点 A 不能被视为处于完全“主”状态,因为没有辅助节点 存在,但它仍然可以满足客户端请求。它被标记为“wait_primary” 直到出现辅助数据库,以指示它在没有备份的情况下运行。

让我们在 B 离线时添加一些数据。

# notice how $APP_DB_URI continues to work no matter which node
# is serving as primary
ssh -l ha-admin -t `vm_ip app` -- \
psql "'$APP_DB_URI'" \
  -c "'INSERT INTO foo SELECT generate_series(1000001, 2000000);'"

复活节点 B

运行以下命令以使节点 B 重新联机:

az vm start \
--resource-group ha-demo \
--name ha-demo-b

现在,守护者下次重试其运行状况检查时,它会恢复节点。 节点 B 在更新其数据以匹配时经历状态“追赶” 一个。一旦完成,B 将成为辅助,A 现在再次成为完整的主数据库。

  Name |  Node |                            Host:Port |        LSN | Reachable |       Current State |      Assigned State
-------+-------+--------------------------------------+------------+-----------+---------------------+--------------------
node_1 |     1 | ha-demo-a.internal.cloudapp.net:5432 | 0/12000738 |       yes |             primary |             primary
node_2 |     2 | ha-demo-b.internal.cloudapp.net:5432 | 0/12000738 |       yes |           secondary |           secondary

更重要的是,如果我们再次直接连接到数据库,则所有 200 万行 仍然存在。

ssh -l ha-admin -t `vm_ip app` -- \
psql "'$APP_DB_URI'" \
  -c "'SELECT count(*) FROM foo;'"

它显示

  count
---------
2000000
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论