四月 29, 2026
摘要:在本教程中,您将学习如何为 Patroni 和 PostgreSQL 设置 etcd。
目录
为什么选择 etcd?
分布式配置存储(DCS)是整个 Patroni 集群的通信与状态核心。因此必须先安装 etcd 并确认其正常运行。etcd 是 Patroni 集群默认且最常用的部署组件,同时也是 Kubernetes 默认的键值存储系统,足以满足我们的可靠性需求。
关于 etcd 的更多详细信息,请参考 etcd 官方文档。
搭建准备
若要跟随本教程实操,你需要准备:
- 准备 3 台虚拟机
- 3 台运行 Debian 13 稳定版的虚拟机
- 每台虚拟机均支持 root 权限的 SSH 访问
本教程优先基于 Debian 系统操作,若你习惯使用 RedHat 系系统,可替换对应命令;熟悉 Linux 操作的话,大部分步骤可适配任意 Linux 发行版。
为简化操作,可在虚拟机的/etc/hosts文件中添加节点映射,用易记名称替代 IP 地址,示例如下:
192.168.8.20 pg1
192.168.8.21 pg2
192.168.8.22 pg3
无特殊说明时,以下命令需在所有 3 台虚拟机上执行。
虚拟机初始化配置
安装 etcd 前,先创建专用系统用户etcd,用于管理服务及相关数据,执行命令:
sudo useradd --system --create-home -s /bin/bash -d /var/lib/etcd etcd
需将该用户创建为系统用户,因为 Systemd 对系统用户的管理规则与普通用户不同。
安装 etcd
首先需注意:这类工具大多没有官方维护的最新 .deb 或 .rpm 安装包,etcd 官方仅提供压缩包(zip、tar.gz)与源码。因此第一步需访问 etcd 的 GitHub 发布页,获取最新版本的下载地址。
获取地址后,执行以下命令安装:
export DL_FILE=etcd-v3.6.7-linux-amd64.tar.gz
wget https://github.com/etcd-io/etcd/releases/download/v3.6.7/${DL_FILE}
sudo tar -xf ${DL_FILE} -C /usr/local
sudo chown -R root:root /usr/local/etcd-v3.6.7-linux-amd64
sudo ln -s etcd-v3.6.7-linux-amd64 /usr/local/etcd
接着通过 Debian alternatives 系统简化二进制文件调用:
sudo update-alternatives \
--install /usr/sbin/etcd etcd /usr/local/etcd/etcd 100
sudo update-alternatives \
--install /usr/bin/etcdctl etcdctl /usr/local/etcd/etcdctl 100
最后创建 systemd 服务文件,用于管控 etcd 服务:
cat<<EOF|sudo tee /etc/systemd/system/etcd.service
[Unit]
Description=etcd key-value store
Documentation=https://github.com/etcd-io/etcd
After=network.target
[Service]
User=etcd
Type=notify
Environment=ETCD_DATA_DIR=/var/lib/etcd
Environment=ETCD_NAME=%m
ExecStart=/usr/sbin/etcd --config-file /etc/etcd/etcd.yaml
Restart=always
RestartSec=10s
LimitNOFILE=40000
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
暂不启动服务,此时尚未完成配置。
配置 etcd
etcd 的核心难点是配置参数准确,需重点关注以下参数:name、advertise-client-urls、initial-advertise-peer-urls、listen-client-urls、listen-peer-urls,这些参数必须对应当前服务器的主机名或 IP 地址。最简单的方式是通过环境变量配置,示例如下:
sudo mkdir /etc/etcd
sudo chown etcd:etcd /etc/etcd
# 需根据当前节点修改以下变量
export MY_HOST=pg1
export MY_IP=192.168.8.20
cat<<EOF|sudo tee /etc/etcd/etcd.yaml
name: ${MY_HOST}
advertise-client-urls: http://${MY_HOST}:2379
data-dir: /var/lib/etcd/postgresql
initial-advertise-peer-urls: http://${MY_HOST}:2380
initial-cluster: pg1=http://pg1:2380,pg2=http://pg2:2380,pg3=http://pg3:2380
initial-cluster-state: new
initial-cluster-token: patroni_cluster
listen-client-urls: http://${MY_IP}:2379,http://127.0.0.1:2379
listen-peer-urls: http://${MY_IP}:2380
dial-timeout: 20s
read-timeout: 20s
write-timeout: 20s
EOF
监听 URL 需使用 IP 地址,因为 etcd 对该参数配置主机名时会尝试解析,易出现异常。
所有节点配置文件完成后,启用并启动 etcd 服务:
sudo systemctl enable etcd
sudo systemctl start etcd
配置文件标记集群为new(新建),因此需所有 3 台节点上线并互联后,集群才会完成初始化,等待 1-2 分钟再继续操作。
服务验证
所有节点启动 etcd 后,需验证其正常运行,再对接 Patroni。首先通过etcdctl查看集群成员列表,应包含全部 3 个节点:
etcdctl member list
11be7ea7eac6dbc8, started, pg2, http://pg2:2380, http://pg2:2379, false
2a0c85329dcad4bd, started, pg3, http://pg3:2380, http://pg3:2379, false
608fb0f2dfc0e470, started, pg1, http://pg1:2380, http://pg1:2379, false
该命令仅显示节点已加入集群,无法判断运行状态,需执行以下命令检查:
etcdctl endpoint health --cluster
http://pg1:2379 is healthy: successfully committed proposal: took = 1.69574ms
http://pg2:2379 is healthy: successfully committed proposal: took = 1.774651ms
http://pg3:2379 is healthy: successfully committed proposal: took = 1.80241ms
节点离线时的异常返回示例:
etcdctl endpoint health --cluster
http://pg1:2379 is healthy: successfully committed proposal: took = 1.50183ms
http://pg3:2379 is healthy: successfully committed proposal: took = 3.106761ms
http://pg2:2379 is unhealthy: failed to commit proposal: context deadline exceeded
最后通过键值读写验证集群一致性:
# 在节点1执行
etcdctl put testkey "Hello World"
OK
# 在节点2执行
etcdctl get testkey
testkey
Hello World
# 在节点3执行
etcdctl del testkey
1
完整的读写删除流程证明 etcd 正常运行,所有节点工作正常,可对接 Patroni。
结语
至此你已完成 3 台虚拟机的 etcd 服务部署,本部分到此结束。之所以采用 3 节点架构,是因为这是具备实际意义的最小高可用集群规模。
理论上可搭建双节点集群,但共识机制要求多数节点正常才能保证数据一致性,节点异议会被判定为异常,需重新同步主流节点数据。双节点集群必须保持两台节点同时在线,否则不可靠;而三节点集群允许单节点离线,剩余两台仍可维持共识。
因此生产环境无小于 3 节点的 etcd 集群。注意该规则仅适用于 etcd 层!参考以下架构:
flowchart TB
%% Nodes
HAProxy["HAProxy"]
DCS["DCS"]
subgraph 数据层
%% Nodes
Patroni1["Patroni"]
Patroni2["Patroni"]
Primary[("主节点")]
Replica1[("副本")]
%% Edge connections between nodes
Patroni1 --> Primary
Patroni2 --> Replica1
end
%% Edge connections between nodes
HAProxy <--> Primary
HAProxy <--> Replica1
Patroni1 <--> DCS
Patroni2 <--> DCS
该架构仅部署 2 个 PostgreSQL + Patroni 节点,完全可行,因为 etcd 层已保障共识,无需对 PostgreSQL 或 Patroni 强制三节点要求。理论上可借助外部管理的 DCS,在不同区域运行 2 个 PostgreSQL 节点。
本教程未采用该架构,若要将 Patroni 与 etcd 解耦,需 5 节点集群:3 个 etcd 节点和 2 个 Patroni + PostgreSQL 节点。该架构更适合复杂场景,多个 Patroni 集群可共享一套 etcd 资源。