跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

模块:ETCD

Pigsty 可部署 etcd 模块,作为 DCS 为 PostgreSQL 高可用提供可靠的分布式配置存储支持。

ETCD 是一个分布式的、可靠的键-值存储,用于存放系统中最为关键的配置数据。

Pigsty 使用 etcd 作为 DCS(分布式配置存储),它对于 PostgreSQL 的高可用性与自动故障转移至关重要。

ETCD 模块依赖 NODE 模块,同时被 PGSQL 模块依赖。因此在安装 ETCD 模块之前,您需要安装 NODE 模块将节点纳管。 在部署任何 PGSQL 集群之前,你必须先部署一套 ETCD 集群,因为 PostgreSQL 高可用所需的 patronivip-manager 会依赖 etcd 实现高可用与 L2 VIP 主库绑定。

flowchart LR
    subgraph PGSQL [PGSQL]
        patroni[Patroni]
        vip[VIP Manager]
    end
    
    subgraph ETCD [ETCD]
        etcd[DCS 服务]
    end
    
    subgraph NODE [NODE]
        node[软件仓库]
    end
    
    PGSQL -->|依赖| ETCD -->|依赖| NODE
    
    style PGSQL fill:#3E668F,stroke:#2d4a66,color:#fff
    style ETCD fill:#5B9CD5,stroke:#4178a8,color:#fff
    style NODE fill:#FCDB72,stroke:#d4b85e,color:#333
    
    style patroni fill:#2d4a66,stroke:#1e3347,color:#fff
    style vip fill:#2d4a66,stroke:#1e3347,color:#fff
    style etcd fill:#4178a8,stroke:#2d5a7a,color:#fff
    style node fill:#d4b85e,stroke:#b89a4a,color:#333

在一套 Pigsty 部署中,只需要一套 etcd 集群。同一套 etcd 集群可以为多套 PostgreSQL 集群提供 DCS 服务支持。 Pigsty 中的 etcd 默认启用 RBAC,不同 PostgreSQL 集群使用独立的用户名与密码访问 etcd,从而实现多租户管理隔离。 管理员使用 etcd root 用户,拥有对所有 PostgreSQL 集群的管理权限。

1 - 集群配置

根据需求场景选择合适的 Etcd 集群规模,并对外提供可靠的接入。

在部署 Etcd 之前,你需要在 配置清单 中定义一个 Etcd 集群,通常来说,你可以选择:

  • 单节点:没有高可用性,适用于开发、测试、演示,或者依赖外部 S3 备份进行 PITR 的无高可用单机部署
  • 三节点:具有基本的高可用性,可以容忍一个节点的故障,适用于中小规模的生产环境
  • 五节点:具有更好的高可用性,可以容忍两个节点的故障,适用于大规模生产环境

偶数成员的 Etcd 集群在技术上有效,但不会比少一个成员的奇数集群提高故障容忍数,反而会增加部署与仲裁成本。 因此,生产环境通常采用单节点、三节点或五节点;超过五节点的集群并不常见。

集群规模 仲裁数 容忍故障数 适用场景
1 节点 1 0 开发、测试、演示
3 节点 2 1 中小规模生产环境
5 节点 3 2 大规模生产环境
7 节点 4 3 特殊高可用需求

单节点

在 Pigsty 中,定义一个单例 Etcd 实例非常简单,只需要一行配置即可:

etcd: { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }

在 Pigsty 提供的所有单机配置模板中,都有这样一项,其中的占位 IP 地址:10.10.10.10 默认会被替换为当前管理节点的 IP。

除了 IP 地址外,这里唯一必要的参数是 etcd_seqetcd_cluster,它们会唯一标识每一个 Etcd 实例。


三节点

三节点的 Etcd 集群最为常见,它可以容忍一个节点的故障,适用于中小规模的生产环境。

例如,Pigsty 的三节点模板:triosafe 就使用了三节点的 Etcd 集群,如下所示:

etcd: 
  hosts:
    10.10.10.10: { etcd_seq: 1 }  # etcd_seq (etcd实例号)是必须指定的身份参数
    10.10.10.11: { etcd_seq: 2 }  # 实例号是正整数,一般从 0 或 1 开始依次分配
    10.10.10.12: { etcd_seq: 3 }  # 实例号应当终生不可变,一旦分配就不再回收使用。
  vars: # 集群层面的参数
    etcd_cluster: etcd    # 默认情况下,etcd 集群名就叫 etcd, 除非您想要部署多套 etcd 集群,否则不要改这个名字
    etcd_safeguard: false # 是否打开 etcd 的防误删安全保险? 在生产环境初始化完成后,可以考虑打开这个选项,避免误删。

五节点

五节点的 Etcd 集群可以容忍两个节点的故障,适用于大规模生产环境。

例如,Pigsty 的生产仿真模板:ha/simu 中就使用了一个五节点的 Etcd 集群:

etcd:
  hosts:
    10.10.10.21 : { etcd_seq: 1 }
    10.10.10.22 : { etcd_seq: 2 }
    10.10.10.23 : { etcd_seq: 3 }
    10.10.10.24 : { etcd_seq: 4 }
    10.10.10.25 : { etcd_seq: 5 }
  vars: { etcd_cluster: etcd    }

使用 etcd 的服务

目前 Pigsty 中使用 etcd 的服务有:

服务 用途 配置文件
Patroni PostgreSQL 高可用,存储集群状态和配置 /etc/patroni/patroni.yml
VIP-Manager 在 PostgreSQL 集群上绑定 L2 VIP /etc/default/vip-manager.yml

当 etcd 集群的成员信息发生永久性变更时,您应当 重载相关服务的配置,以确保服务能够正确访问 Etcd 集群。

更新 Patroni 的 etcd 端点引用

./pgsql.yml -t pg_conf                            # 重新生成 patroni 配置
ansible all -f 1 -b -a 'systemctl reload patroni' # 重新加载 patroni 配置

更新 VIP-Manager 的 etcd 端点引用(仅当使用 PGSQL L2 VIP 时需要):

./pgsql.yml -t pg_vip_config                           # 重新生成 vip-manager 配置
ansible all -f 1 -b -a 'systemctl restart vip-manager' # 重启 vip-manager

RBAC 认证配置

Pigsty 自 v4.0 起默认启用 etcd 的 RBAC 认证机制。相关配置参数:

参数 说明 默认值
etcd_root_password etcd root 用户密码 Etcd.Root
pg_etcd_password Patroni 连接 etcd 的密码 空(使用集群名)

生产环境建议

all:
  vars:
    etcd_root_password: 'YourSecureEtcdPassword'  # 修改默认密码

etcd:
  hosts:
    10.10.10.10: { etcd_seq: 1 }
    10.10.10.11: { etcd_seq: 2 }
    10.10.10.12: { etcd_seq: 3 }
  vars:
    etcd_cluster: etcd
    etcd_safeguard: true    # 生产环境开启防误删保护

文件系统布局

etcd 模块在目标主机上创建以下目录和文件:

路径 用途 权限
/etc/etcd/ 配置目录 0750, etcd:etcd
/etc/etcd/etcd.conf 主配置文件 0644, etcd:etcd
/etc/etcd/etcd.pass root 密码文件 0640, root:etcd
/etc/etcd/ca.crt CA 证书 0644, etcd:etcd
/etc/etcd/server.crt 服务器证书 0644, etcd:etcd
/etc/etcd/server.key 服务器私钥 0600, etcd:etcd
/var/lib/etcd/ 备用数据目录 0770, etcd:etcd
/data/etcd/ 主数据目录(可配置) 0700, etcd:etcd
/etc/profile.d/etcdctl.sh 客户端环境变量 0644, root:root
/etc/systemd/system/etcd.service Systemd 服务定义 0644, root:root

2 - 参数列表

ETCD 模块提供了 13 个配置参数,用于精细控制集群的行为表现。

ETCD 模块的参数列表,共有 13 个参数,分为两个部分:

  • ETCD:10 个参数,用于 etcd 集群的部署与配置
  • ETCD_REMOVE:3 个参数,控制 etcd 集群的移除
架构变化:Pigsty v3.6+

自 Pigsty v3.6 起,etcd.yml 剧本不再包含移除功能,移除相关参数已迁移至独立的 etcd_remove 角色。v4.0 起默认启用 RBAC 认证,新增 etcd_root_password 参数。


参数概览

ETCD 参数组用于 etcd 集群的部署与配置,包括实例标识、集群名称、数据目录、端口以及认证密码。

参数 类型 级别 说明
etcd_seq int I etcd 实例标识符,必填
etcd_cluster string C etcd 集群名,默认固定为 etcd
etcd_learner bool I/A 是否以 learner 模式初始化 etcd 实例?
etcd_data path C etcd 数据目录,默认为 /data/etcd
etcd_port port C etcd 客户端端口,默认为 2379
etcd_peer_port port C etcd 同伴端口,默认为 2380
etcd_init enum C etcd 初始集群状态,新建或已存在
etcd_election_timeout int C etcd 选举超时,默认为 1000ms
etcd_heartbeat_interval int C etcd 心跳间隔,默认为 100ms
etcd_root_password password G etcd root 用户密码,用于 RBAC 认证

ETCD_REMOVE 参数组控制 etcd 集群的移除行为,包括防误删保险、数据清理以及软件包卸载。

参数 类型 级别 说明
etcd_safeguard bool G/C/A true 时无条件拒绝移除操作
etcd_rm_data bool G/C/A 移除时是否删除 etcd 数据?默认为 true
etcd_rm_pkg bool G/C/A 移除时是否卸载 etcd 软件包?默认为 false

ETCD

本节包含 etcd 角色的参数, 这些是 etcd.yml 剧本使用的操作标志参数。

相关参数定义于 roles/etcd/defaults/main.yml

#etcd_seq: 1                      # etcd 实例标识符,需要显式指定(必填)
etcd_cluster: etcd                # etcd 集群和组名称,默认为 etcd
etcd_learner: false               # etcd 实例是否以 learner 模式运行?默认为 false
etcd_data: /data/etcd             # etcd 数据目录,默认为 /data/etcd
etcd_port: 2379                   # etcd 客户端端口,默认为 2379
etcd_peer_port: 2380              # etcd 对等端口,默认为 2380
etcd_init: new                    # etcd 初始集群状态,new 或 existing
etcd_election_timeout: 1000       # etcd 选举超时,默认为 1000ms
etcd_heartbeat_interval: 100      # etcd 心跳间隔,默认为 100ms
etcd_root_password: Etcd.Root     # etcd root 用户密码,用于 RBAC 认证(请修改!)

etcd_seq

参数名称: etcd_seq, 类型: int, 层次:I

etcd 实例标号, 这是必选参数,必须为每一个 etcd 实例指定一个唯一的标号。

以下是一个3节点 etcd 集群的示例,分配了 1 ~ 3 三个标号。

etcd: # dcs service for postgres/patroni ha consensus
  hosts:  # 1 node for testing, 3 or 5 for production
    10.10.10.10: { etcd_seq: 1 }  # etcd_seq required
    10.10.10.11: { etcd_seq: 2 }  # assign from 1 ~ n
    10.10.10.12: { etcd_seq: 3 }  # use odd numbers
  vars: # cluster level parameter override roles/etcd
    etcd_cluster: etcd  # mark etcd cluster name etcd
    etcd_safeguard: false # safeguard against purging

etcd_cluster

参数名称: etcd_cluster, 类型: string, 层次:C

etcd 集群 & 分组名称,默认值为硬编码值 etcd

当您想要部署另外的 etcd 集群备用时,可以修改此参数并使用其他集群名。

etcd_learner

参数名称: etcd_learner, 类型: bool, 层次:I/A

是否以 learner 模式初始化 etcd 实例?默认值为 false

当设置为 true 时,etcd 实例将以 learner(学习者)模式初始化,这意味着该实例不能在 etcd 集群中参与投票选举。

使用场景

  • 集群扩容:向现有集群添加新成员时,使用 learner 模式可以避免在数据同步完成前影响集群的仲裁
  • 安全迁移:在滚动升级或迁移场景中,先以 learner 模式加入,确认数据同步完成后再提升

操作流程

  1. 设置 etcd_learner: true,以 learner 模式初始化新成员
  2. 等待数据同步完成(通过 etcdctl endpoint status 检查)
  3. 使用 etcdctl member promote <member_id> 将其提升为正式成员
注意

Learner 实例不计入集群仲裁成员数。例如,3 节点集群中有 1 个 learner,实际投票成员数为 2,不能容忍任何节点故障。

etcd_data

参数名称: etcd_data, 类型: path, 层次:C

etcd 数据目录,默认为 /data/etcd

etcd_port

参数名称: etcd_port, 类型: port, 层次:C

etcd 客户端端口号,默认为 2379

etcd_peer_port

参数名称: etcd_peer_port, 类型: port, 层次:C

etcd peer 端口,默认为 2380

etcd_init

参数名称: etcd_init, 类型: enum, 层次:C

etcd 初始集群状态,可以是 newexisting,默认值:new

可选值说明

说明 使用场景
new 创建新的 etcd 集群 首次部署、集群重建
existing 加入现有 etcd 集群 集群扩容、添加新成员

重要说明

扩容时必须使用 existing

向现有 etcd 集群添加新成员时,必须 设置 etcd_init=existing。否则新实例会尝试创建独立的新集群,导致脑裂或初始化失败。

使用示例

# 创建新集群(默认行为)
./etcd.yml

# 向现有集群添加新成员
./etcd.yml -l <new_ip> -e etcd_init=existing

# 或使用便捷脚本(自动设置 etcd_init=existing)
bin/etcd-add <new_ip>

etcd_election_timeout

参数名称: etcd_election_timeout, 类型: int, 层次:C

etcd 选举超时,默认为 1000 (毫秒),也就是 1 秒。

etcd_heartbeat_interval

参数名称: etcd_heartbeat_interval, 类型: int, 层次:C

etcd 心跳间隔,默认为 100 (毫秒)。

etcd_root_password

参数名称: etcd_root_password, 类型: password, 层次:G

etcd root 用户密码,用于 RBAC 认证,默认值为 Etcd.Root

Pigsty 自 v4.0 起默认启用 etcd 的 RBAC(基于角色的访问控制)认证机制。在集群初始化时,etcd_auth 任务会自动创建 root 用户并启用认证。

密码存储位置

  • 密码存储在 /etc/etcd/etcd.pass 文件中
  • 文件权限为 0640(root 所有,etcd 组可读)
  • etcdctl 环境变量脚本 /etc/profile.d/etcdctl.sh 会自动读取此文件

与其他组件的配合

  • Patroni 通过 pg_etcd_password 参数配置连接 etcd 的密码
  • 如果 pg_etcd_password 为空,Patroni 会使用集群名称作为密码(不推荐)
  • VIP-Manager 也需要使用相同的认证信息连接 etcd

安全建议

生产环境安全

在生产环境中,强烈建议修改默认密码 Etcd.Root。可以在全局配置或集群配置中设置:

etcd_root_password: 'YourSecurePassword'

使用 configure -g 参数可以自动生成并替换 etcd_root_password


ETCD_REMOVE

本节包含 etcd_remove 角色的参数, 这些是 etcd-rm.yml 剧本使用的操作标志参数。

相关参数定义于 roles/etcd_remove/defaults/main.yml

etcd_safeguard: false             # 为 true 时无条件拒绝移除操作
etcd_rm_data: true                # 移除时是否删除 etcd 数据和配置文件?
etcd_rm_pkg: false                # 移除时是否卸载 etcd 软件包?

etcd_safeguard

参数名称: etcd_safeguard, 类型: bool, 层次:G/C/A

防误删保险参数,默认值为 false。设置为 true 时,etcd-rm.yml 会在注销、退群、停服和删除之前直接中止;它是静态布尔开关,不会探测实例是否正在运行。 需要显式使用命令行参数 -e etcd_safeguard=false 才能覆盖。

使用建议

环境 建议值 说明
开发/测试 false 方便快速重建和测试
生产环境 true 防止误操作导致服务中断

紧急情况下,可以使用命令行参数覆盖配置:

./etcd-rm.yml -l etcd -e etcd_safeguard=false # 覆盖保险并移除目标 Etcd 集群

etcd_rm_data

参数名称: etcd_rm_data, 类型: bool, 层次:G/C/A

移除时是否删除 etcd 数据和配置文件?默认值为 true

启用此选项后,etcd-rm.yml 剧本在移除集群或成员时会同时删除以下内容:

  • /etc/etcd/ - 配置目录(包括证书和密码文件)
  • /var/lib/etcd/ - 备用数据目录
  • {{ etcd_data }} - 主数据目录(默认 /data/etcd
  • /etc/systemd/system/etcd.service - Systemd 服务单元文件
  • /etc/profile.d/etcdctl.sh - 客户端环境变量脚本
  • /etc/vector/etcd.yaml - Vector 日志采集配置

使用场景

场景 建议值 说明
彻底移除 true(默认) 完全清理,释放磁盘空间
仅停止服务 false 保留数据,便于故障排查或恢复
# 仅停止服务,保留数据
./etcd-rm.yml -l etcd -e etcd_rm_data=false

etcd_rm_pkg

参数名称: etcd_rm_pkg, 类型: bool, 层次:G/C/A

移除时是否卸载 etcd 软件包?默认值为 false

启用此选项后,etcd-rm.yml 剧本在移除集群或成员时会同时卸载 etcd 软件包。

使用场景

场景 建议值 说明
常规移除 false(默认) 保留软件包,便于快速重建
彻底清理 true 完全卸载,节省磁盘空间
# 移除时同时卸载软件包
./etcd-rm.yml -l etcd -e etcd_rm_pkg=true
提示

通常不需要卸载 etcd 软件包。保留软件包可以加快后续的重新部署速度,因为不需要重新下载和安装。

3 - 管理预案

etcd 集群管理 SOP:创建,销毁,扩缩容,更新配置,RBAC 配置的详细说明。

以下是一些常见的 etcd 管理任务 SOP(预案):

  • 创建集群:如何初始化 etcd 集群?
  • 销毁集群:如何销毁 etcd 集群?
  • 环境变量:如何配置 etcd 客户端,以访问 etcd 服务器集群?
  • RBAC 认证:如何使用 etcd 的 RBAC 认证?
  • 重载配置:如何更新客户端使用的 etcd 服务器成员列表?
  • 添加成员:如何向现有 etcd 集群添加新成员?
  • 移除成员:如何从 etcd 集群移除老成员?
  • 便捷脚本:使用 bin/etcd-addbin/etcd-rm 简化操作

更多问题请参考 FAQ:ETCD


创建集群

要创建一个集群,首先需要在 配置清单 中定义 etcd 集群:

etcd:
  hosts:
    10.10.10.10: { etcd_seq: 1 }
    10.10.10.11: { etcd_seq: 2 }
    10.10.10.12: { etcd_seq: 3 }
  vars: { etcd_cluster: etcd }

执行 etcd.yml 剧本即可。

./etcd.yml  # 初始化 etcd 集群
架构变化:Pigsty v3.6+

自 Pigsty v3.6 起,etcd.yml 剧本专注于集群安装和成员添加,不再包含移除功能。所有移除操作请使用独立的 etcd-rm.yml 剧本。

对于已初始化的生产环境 etcd 集群,可以打开防误删保护 etcd_safeguard,避免误删现有的 etcd 实例。


销毁集群

要销毁一个 Etcd 集群,请使用独立的 etcd-rm.yml 剧本。默认的 etcd_rm_data: true 会删除本机数据与配置;请先确认没有 PostgreSQL 集群仍将它用作 DCS,并核验近期备份和精确目标名。

./etcd-rm.yml -l etcd                            # 确认后销毁整个 etcd 集群
./etcd-rm.yml -l etcd -e etcd_safeguard=false   # 仅在清单已启用保险时显式覆盖

或使用便捷脚本:

bin/etcd-rm                           # 移除整个 etcd 集群

移除剧本会尊重 etcd_safeguard 防误删保险的配置。如果该参数设置为 true,剧本将在退群、注销、停服和删除之前中止;其默认值为 false,不能把未显式覆盖保险当作一次确认。

注意

在移除 etcd 集群之前,请确保没有 PostgreSQL 集群正在使用该 etcd 作为 DCS 服务。否则会导致 PostgreSQL 高可用功能失效。


环境变量

Pigsty 默认使用 etcd v3 API(v3.6+ 已移除 v2 API 支持)。Pigsty 会在 etcd 节点上自动配置环境变量脚本 /etc/profile.d/etcdctl.sh,登录后会自动加载。

以下是 etcd 客户端配置环境变量的示例:

alias e="etcdctl"
alias em="etcdctl member"
export ETCDCTL_ENDPOINTS=https://10.10.10.10:2379
export ETCDCTL_CACERT=/etc/etcd/ca.crt
export ETCDCTL_CERT=/etc/etcd/server.crt
export ETCDCTL_KEY=/etc/etcd/server.key

Pigsty 自 v4.0 起为 etcd 默认启用 RBAC 认证,当前版本仍需配置用户认证:

export ETCDCTL_USER="root:$(cat /etc/etcd/etcd.pass)"

配置好客户端环境变量后,你可以使用以下命令进行 etcd CRUD 操作:

e put a 10 ; e get a; e del a   # 基本 KV 操作
e member list                    # 列出集群成员
e endpoint health                # 检查端点健康状态
e endpoint status                # 查看端点状态

RBAC 认证

Pigsty 自 v4.0 起默认启用 etcd 的 RBAC(基于角色的访问控制)认证机制。在集群初始化时,etcd_auth 任务会自动创建 root 用户并启用认证。

root 用户密码etcd_root_password 参数指定,默认值为 Etcd.Root。密码存储在 /etc/etcd/etcd.pass 文件中,权限为 0640(root 所有,etcd 组可读)。

在生产环境中,强烈建议修改默认密码

etcd:
  hosts:
    10.10.10.10: { etcd_seq: 1 }
    10.10.10.11: { etcd_seq: 2 }
    10.10.10.12: { etcd_seq: 3 }
  vars:
    etcd_cluster: etcd
    etcd_root_password: 'YourSecurePassword'  # 修改默认密码

客户端认证方式

# 方式一:使用环境变量(推荐,已自动配置在 /etc/profile.d/etcdctl.sh)
export ETCDCTL_USER="root:$(cat /etc/etcd/etcd.pass)"

# 方式二:在命令行中指定
etcdctl --user root:YourSecurePassword member list

重载配置

如果 etcd 集群的成员发生变化(添加或移除成员),我们需要刷新对 etcd 服务端点的引用。目前 Pigsty 中有以下几处 etcd 引用需要更新:

配置位置 配置文件 更新方式
etcd 成员配置 /etc/etcd/etcd.conf ./etcd.yml -t etcd_conf
etcdctl 环境变量 /etc/profile.d/etcdctl.sh ./etcd.yml -t etcd_config
Patroni DCS 配置 /etc/patroni/patroni.yml ./pgsql.yml -t pg_conf
VIP-Manager 配置 /etc/default/vip-manager.yml ./pgsql.yml -t pg_vip_config

刷新 etcd 成员配置文件

./etcd.yml -t etcd_conf                           # 刷新 /etc/etcd/etcd.conf
ansible etcd -f 1 -b -a 'systemctl restart etcd'  # 可选:逐一重启 etcd 实例

刷新 etcdctl 客户端环境变量

./etcd.yml -t etcd_config                         # 刷新 /etc/profile.d/etcdctl.sh

更新 Patroni DCS 端点配置

./pgsql.yml -t pg_conf                            # 重新生成 patroni 配置
ansible all -f 1 -b -a 'systemctl reload patroni' # 重新加载 patroni 配置

更新 VIP-Manager 端点配置(仅当使用 PGSQL L2 VIP 时需要):

./pgsql.yml -t pg_vip_config                           # 重新生成 vip-manager 配置
ansible all -f 1 -b -a 'systemctl restart vip-manager' # 重启 vip-manager
提示

使用 bin/etcd-addbin/etcd-rm 便捷脚本时,脚本会在操作完成后提示您需要执行的配置刷新命令。


添加成员

ETCD 参考: 添加成员

推荐方式:使用便捷脚本

使用 bin/etcd-add 脚本是向现有 etcd 集群添加新成员的 推荐方式

# 首先在配置清单中添加新成员定义,然后执行:
bin/etcd-add <ip>              # 添加单个新成员
bin/etcd-add <ip1> <ip2> ...   # 添加多个新成员

脚本会自动完成以下操作:

  • 验证 IP 地址有效性
  • 执行 etcd.yml 剧本(自动设置 etcd_init=existing
  • 提供安全警告和倒计时
  • 操作完成后提示配置刷新命令

手动方式:分步操作

向现有的 etcd 集群添加新成员需要以下步骤:

  1. 更新配置清单:将新实例添加到 etcd
  2. 通知集群:执行 etcdctl member add 命令(可选,剧本会自动执行)
  3. 初始化新成员:使用 etcd_init=existing 参数运行剧本
  4. 提升成员:将学习者提升为正式成员(可选,使用 etcd_learner=true 时需要)
  5. 重载配置:更新所有客户端的 etcd 端点引用
# 配置清单更新后,初始化新成员
./etcd.yml -l <new_ins_ip> -e etcd_init=existing

# 如果使用 learner 模式,需要手动提升
etcdctl member promote <new_ins_server_id>
重要

添加新成员时必须使用 etcd_init=existing 参数,否则新实例会尝试创建新集群而非加入现有集群。

详细步骤:向 etcd 集群添加成员

下面是具体操作的详细细节,让我们从一个单实例 etcd 集群开始:

etcd:
  hosts:
    10.10.10.10: { etcd_seq: 1 } # <--- 集群中原本存在的唯一实例
    10.10.10.11: { etcd_seq: 2 } # <--- 将此新成员定义添加到清单中
  vars: { etcd_cluster: etcd }

使用便捷脚本添加新成员(推荐):

$ bin/etcd-add 10.10.10.11

或者手动操作。首先使用 etcdctl member add 向现有 etcd 集群宣告新的学习者实例 etcd-2 即将到来:

$ etcdctl member add etcd-2 --learner=true --peer-urls=https://10.10.10.11:2380
Member 33631ba6ced84cf8 added to cluster 6646fbcf5debc68f

ETCD_NAME="etcd-2"
ETCD_INITIAL_CLUSTER="etcd-2=https://10.10.10.11:2380,etcd-1=https://10.10.10.10:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://10.10.10.11:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

使用 etcdctl member list(或 em list)检查成员列表,我们可以看到一个 unstarted 新成员:

33631ba6ced84cf8, unstarted, , https://10.10.10.11:2380, , true       # 这里有一个未启动的新成员
429ee12c7fbab5c1, started, etcd-1, https://10.10.10.10:2380, https://10.10.10.10:2379, false

接下来使用 etcd.yml 剧本初始化新的 etcd 实例 etcd-2,完成后,我们可以看到新成员已经启动:

$ ./etcd.yml -l 10.10.10.11 -e etcd_init=existing    # 一定要添加 existing 参数
...
33631ba6ced84cf8, started, etcd-2, https://10.10.10.11:2380, https://10.10.10.11:2379, true
429ee12c7fbab5c1, started, etcd-1, https://10.10.10.10:2380, https://10.10.10.10:2379, false

新成员初始化完成并稳定运行后,可以将新成员从学习者提升为追随者:

$ etcdctl member promote 33631ba6ced84cf8   # 将学习者提升为追随者
Member 33631ba6ced84cf8 promoted in cluster 6646fbcf5debc68f

$ em list                # 再次检查,新成员已提升为正式成员
33631ba6ced84cf8, started, etcd-2, https://10.10.10.11:2380, https://10.10.10.11:2379, false
429ee12c7fbab5c1, started, etcd-1, https://10.10.10.10:2380, https://10.10.10.10:2379, false

新成员添加完成,请不要忘记 重载配置,让所有客户端也知道新成员的存在。

重复以上步骤,可以添加更多成员。记住,生产环境中至少要使用 3 个成员。


移除成员

推荐方式:使用便捷脚本

使用 bin/etcd-rm 脚本是从 etcd 集群移除成员的 推荐方式

bin/etcd-rm <ip>              # 移除指定成员
bin/etcd-rm <ip1> <ip2> ...   # 移除多个成员
bin/etcd-rm                   # 移除整个 etcd 集群

脚本会依次尝试以下操作:

  • 从集群中优雅地移除成员
  • 停止并禁用 etcd 服务
  • 清理数据和配置文件
  • 从监控系统中注销

底层移除角色会容忍部分退群与清理错误,因此脚本结束后仍必须核对 etcdctl member list、端点健康、剩余仲裁,以及目标服务和数据目录的实际状态。

手动方式:分步操作

要从 etcd 集群中删除一个成员实例,通常需要以下步骤:

  1. 保持成员仍在配置清单中:移除剧本需要清单里的 etcd_seq、集群成员和连接端点信息
  2. 清理实例:对目标运行 etcd-rm.yml;剧本会先尝试 member remove,再停服并按参数清理
  3. 更新配置清单:成功后再从配置清单中注释或删除该实例
  4. 重载引用:按 重载配置 刷新其余 etcd 成员及 Patroni/VIP-Manager 的端点
# 此时 <ip> 必须仍在 etcd 清单组中
./etcd-rm.yml -l <ip>                  # 自动退出集群并清理实例
# 成功后编辑 pigsty.yml 删除该成员,再刷新其余成员与客户端配置

不要在运行移除剧本前先从清单删除目标;etcd-rm.ymlhosts: etcd 将无法再选中它,也无法从清单推导实例身份和集群端点。 也不需要在移除剧本前后额外重复执行 etcdctl member remove

详细步骤:从 etcd 集群移除成员

让我们以一个 3 节点的 etcd 集群为例,从中移除 3 号实例。

方法一:使用便捷脚本(推荐)

$ bin/etcd-rm 10.10.10.12

脚本会尝试从集群中移除成员、停止服务并清理数据;结束后仍需按上文检查成员列表、仲裁与目标文件状态。

方法二:手动操作

首先保持待删除成员仍在清单中,使用移除剧本:

$ ./etcd-rm.yml -l 10.10.10.12

剧本会依次尝试以下操作:

  1. 获取成员列表并找到对应的成员 ID
  2. 执行 etcdctl member remove 从集群中踢除
  3. 停止 etcd 服务
  4. 清理数据和配置文件

剧本会自动查询成员 ID 并执行 member remove。只有在排障时需要手工完成这一步:

$ etcdctl member list
429ee12c7fbab5c1, started, etcd-1, https://10.10.10.10:2380, https://10.10.10.10:2379, false
33631ba6ced84cf8, started, etcd-2, https://10.10.10.11:2380, https://10.10.10.11:2379, false
93fcf23b220473fb, started, etcd-3, https://10.10.10.12:2380, https://10.10.10.12:2379, false  # <--- 移除这个

$ etcdctl member remove 93fcf23b220473fb  # 从集群中踢除
Member 93fcf23b220473fb removed from cluster 6646fbcf5debc68f

手工踢除后仍需在目标尚存于清单时运行 ./etcd-rm.yml -l 10.10.10.12 完成停服、注销和清理;其退出步骤找不到已删除的成员时会跳过。

确认成员已经离开现场集群、剩余成员保持仲裁且目标服务与文件符合预期后,才从配置清单中删除 10.10.10.12,并按 重载配置 刷新其余 Etcd 成员和所有客户端引用,移除成员至此完成。

重复以上步骤,可以移除更多成员,与 添加成员 配合使用,可以对 etcd 集群进行滚动升级搬迁。


便捷脚本

Pigsty v3.6+ 提供了便捷脚本简化 etcd 集群的扩容和缩容操作:

bin/etcd-add

向现有 etcd 集群添加新成员:

bin/etcd-add <ip>              # 添加单个新成员
bin/etcd-add <ip1> <ip2> ...   # 添加多个新成员

脚本功能:

  • 验证 IP 地址格式
  • 自动设置 etcd_init=existing 参数
  • 执行 etcd.yml 剧本完成成员添加
  • 操作完成后提示配置刷新命令

bin/etcd-rm

从 etcd 集群移除成员或整个集群:

bin/etcd-rm <ip>              # 移除指定成员
bin/etcd-rm <ip1> <ip2> ...   # 移除多个成员
bin/etcd-rm                   # 移除整个 etcd 集群

脚本功能:

  • 提供安全警告和确认倒计时
  • 自动执行 etcd-rm.yml 剧本
  • 优雅地从集群中移除成员
  • 清理数据和配置文件

管理 Etcd 密码

etcd_root_password 参数定义了 etcd 集群的 root 用户密码。

要修改此密码,你需要访问到 etcd 端点,例如在 INFRA节点ETCD节点 上使用 管理用户 执行:

e user passwd root  # 修改 etcd root 用户密码

然后你应该刷新所有对 etcd root 密码的引用,包括 INFRA 节点上的 Patroni 客户端配置与 etcdctl 客户端环境变量:

./infra.yml -t env_patroni    # 刷新 /infra/conf/patronictl.yml 对 etcd root 密码的引用
./etcd.yml  -t etcd_conf      # 刷新 /etc/etcd/etcd.pass 与 /etc/profile.d/etcdctl.sh

4 - 预置剧本

如何使用预置的 ansible 剧本来管理 Etcd 集群,常用管理命令速查。

Etcd 模块提供了两个核心剧本:etcd.yml 用于安装与配置 Etcd 集群,etcd-rm.yml 用于移除 Etcd 集群或成员。

架构变化:Pigsty v3.6+

自 Pigsty v3.6 起,etcd.yml 剧本专注于集群安装和成员添加,所有移除操作已迁移至独立的 etcd-rm.yml 剧本和 etcd_remove 角色。


etcd.yml

剧本原始文件:etcd.yml

执行本剧本,将会在硬编码的固定分组 etcd 上安装配置 Etcd 集群,并启动 etcd 服务。

etcd.yml 中,提供了以下是可用的任务子集:

  • etcd_assert:验证 etcd 身份参数(etcd_seq 必须定义且为非负整数)
  • etcd_install:安装 etcd 软件包
  • etcd_dir:创建 etcd 数据和配置目录
  • etcd_config:生成 etcd 配置
    • etcd_conf:生成 etcd 主配置文件 /etc/etcd/etcd.conf
    • etcd_cert:生成 etcd TLS 证书(CA、服务器证书、私钥)
  • etcd_member:将新成员添加到现有集群(仅当 etcd_init=existing 时执行)
  • etcd_launch:启动 etcd 服务
  • etcd_auth:启用 RBAC 认证(创建 root 用户并启用认证)
  • etcd_register:将 etcd 注册到 VictoriaMetrics 监控

etcd-rm.yml

剧本原始文件:etcd-rm.yml

用于移除 Etcd 集群或单个成员的专用剧本。在 etcd-rm.yml 中,提供了以下可用的任务子集:

  • etcd_safeguard:检查防误删保险,如果启用则中止执行
  • etcd_pause:暂停 3 秒,允许用户使用 Ctrl-C 中止执行
  • etcd_deregister:从 VictoriaMetrics 监控目标中移除 etcd 注册
  • etcd_leave:在清理前尝试优雅地离开 etcd 集群
  • etcd_svc:使用 systemd 停止并禁用 etcd 服务
  • etcd_data:移除 etcd 数据(可通过 etcd_rm_data=false 禁用)
  • etcd_pkg:卸载 etcd 软件包(需通过 etcd_rm_pkg=true 显式启用)

移除剧本使用 etcd_remove 角色,支持以下可配置参数:

  • etcd_safeguard:设置为 true 时阻止意外移除
  • etcd_rm_data:控制是否删除 ETCD 数据(默认:true
  • etcd_rm_pkg:控制是否卸载 ETCD 软件包(默认:false
危险操作

etcd_safeguard 默认是 falseetcd_rm_data 默认是 true。因此,完整执行 etcd-rm.yml 会尝试将目标退群、注销并停服,随后删除本机 Etcd 数据、配置、单元和客户端环境文件。 剧本会忽略部分退群与清理错误,也不会证明剩余成员仍有仲裁;每次都应使用精确的 -l,并核对近期备份、成员列表与剩余仲裁。


执行演示

asciicast


命令速查

Etcd 安装与配置:

./etcd.yml                                      # 初始化 etcd 集群
./etcd.yml -t etcd_launch                       # 重启整个 etcd 集群
./etcd.yml -t etcd_conf                         # 使用最新状态刷新 /etc/etcd/etcd.conf
./etcd.yml -t etcd_cert                         # 重新生成 etcd TLS 证书
./etcd.yml -l 10.10.10.12 -e etcd_init=existing # 扩容节点:添加新成员到现有集群

Etcd 移除与清理:

./etcd-rm.yml -l 10.10.10.12                     # 退群、注销、停服并默认删除本机数据
./etcd-rm.yml -l 10.10.10.12 -e etcd_rm_data=false # 退群、注销并停服,保留本机数据与配置
./etcd-rm.yml -l 10.10.10.12 -e etcd_rm_pkg=true # 同时卸载 etcd 软件包
./etcd-rm.yml -l etcd                            # 销毁整个 etcd 集群及其本机数据

便捷脚本:

bin/etcd-add <ip>                               # 向现有集群添加新成员(推荐)
bin/etcd-rm <ip>                                # 从集群中移除指定成员(推荐)
bin/etcd-rm                                     # 移除整个 etcd 集群

保护机制

出于防止误删的目的,Pigsty 的 ETCD 模块提供了防误删保险,由 etcd_safeguard 参数控制,默认为 false,即默认不打开防误删保护。

对于生产环境已经初始化好的 etcd 集群,建议打开防误删保护,避免误删现有的 etcd 实例:

etcd:
  hosts:
    10.10.10.10: { etcd_seq: 1 }
    10.10.10.11: { etcd_seq: 2 }
    10.10.10.12: { etcd_seq: 3 }
  vars:
    etcd_cluster: etcd
    etcd_safeguard: true  # 打开防误删保护

etcd_safeguard 设置为 true 时,etcd-rm.yml 会在任何注销、退群、停服或删除动作前直接中止;它是布尔保护开关,并不探测实例是否存活。您可以使用命令行参数来覆盖这一行为:

./etcd-rm.yml -l <exact-target> -e etcd_safeguard=false  # 仅在确认目标与备份后覆盖保险

无论保护开关取值如何,真实运行后都要重新检查 etcdctl member list、端点健康和剩余仲裁;任务返回成功不能替代这些运行态验收。

5 - 监控告警

etcd 监控面板,指标,以及告警规则。

监控面板

ETCD 模块提供了一个监控面板:Etcd Overview。

ETCD Overview Dashboard

ETCD Overview:ETCD 集群概览

这个监控面板提供了 ETCD 状态的关键信息:最值得关注的是 ETCD Aliveness,它显示了 ETCD 集群整体的服务状态。

红色的条带标识着实例不可用的时间段,而底下蓝灰色的条带标识着整个集群处于不可用的时间段。

etcd-overview.jpg


告警规则

Pigsty 针对 Etcd 提供了以下五条预置告警规则,定义于 files/victoria/rules/etcd.yml

  • EtcdServerDown:Etcd 节点宕机,严重警报
  • EtcdNoLeader:Etcd 集群没有领导者,严重警报
  • EtcdQuotaFull:Etcd 配额使用超过 90%,警告
  • EtcdNetworkPeerRTSlow:Etcd 网络时延缓慢,提醒
  • EtcdWalFsyncSlow:Etcd 磁盘刷盘缓慢,提醒

以下片段原样反映当前规则源码。当前只随 Pigsty 提供 etcd-overview 仪表盘;两条延迟告警注释中的 /ui/d/etcd-instance 目标并不存在,应改用 /ui/d/etcd-overview 查看集群状态。这是规则注释中的已知源码偏差,不影响告警表达式本身。

#==============================================================#
#                         Aliveness                            #
#==============================================================#
# etcd server instance down
- alert: EtcdServerDown
  expr: etcd_up < 1
  for: 1m
  labels: { level: 0, severity: CRIT, category: etcd }
  annotations:
    summary: "CRIT EtcdServerDown {{ $labels.ins }}@{{ $labels.instance }}"
    description: |
      etcd_up[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value }} < 1
      /ui/d/etcd-overview

#==============================================================#
#                         Error                                #
#==============================================================#
# Etcd no Leader triggers a P0 alert immediately
# if dcs_failsafe mode is not enabled, this may lead to global outage
- alert: EtcdNoLeader
  expr: min(etcd_server_has_leader) by (cls) < 1
  for: 15s
  labels: { level: 0, severity: CRIT, category: etcd }
  annotations:
    summary: "CRIT EtcdNoLeader: {{ $labels.cls }} {{ $value }}"
    description: |
      etcd_server_has_leader[cls={{ $labels.cls }}] = {{ $value }} < 1
      /ui/d/etcd-overview?from=now-5m&to=now&var-cls={{$labels.cls}}

#==============================================================#
#                        Saturation                            #
#==============================================================#
- alert: EtcdQuotaFull
  expr: etcd:cls:quota_usage > 0.90
  for: 1m
  labels: { level: 1, severity: WARN, category: etcd }
  annotations:
    summary: "WARN EtcdQuotaFull: {{ $labels.cls }}"
    description: |
      etcd:cls:quota_usage[cls={{ $labels.cls }}] = {{ $value | printf "%.3f" }} > 90%

#==============================================================#
#                         Latency                              #
#==============================================================#
# etcd network peer rt p95 > 200ms for 1m
- alert: EtcdNetworkPeerRTSlow
  expr: etcd:ins:network_peer_rt_p95_5m > 0.200
  for: 1m
  labels: { level: 2, severity: INFO, category: etcd }
  annotations:
    summary: "INFO EtcdNetworkPeerRTSlow: {{ $labels.cls }} {{ $labels.ins }}"
    description: |
      etcd:ins:network_peer_rt_p95_5m[cls={{ $labels.cls }}, ins={{ $labels.ins }}] = {{ $value }} > 200ms
      /ui/d/etcd-instance?from=now-10m&to=now&var-cls={{ $labels.cls }}

# Etcd wal fsync rt p95 > 50ms
- alert: EtcdWalFsyncSlow
  expr: etcd:ins:wal_fsync_rt_p95_5m > 0.050
  for: 1m
  labels: { level: 2, severity: INFO, category: etcd }
  annotations:
    summary: "INFO EtcdWalFsyncSlow: {{ $labels.cls }} {{ $labels.ins }}"
    description: |
      etcd:ins:wal_fsync_rt_p95_5m[cls={{ $labels.cls }}, ins={{ $labels.ins }}] = {{ $value }} > 50ms
      /ui/d/etcd-instance?from=now-10m&to=now&var-cls={{ $labels.cls }}

6 - 指标列表

Pigsty ETCD 模块提供的完整监控指标列表与释义

本页快照记录 ETCD 模块的 177 类监控指标;实际运行时的指标集合会随软件包版本、启用的采集器和目标状态变化。

Metric Name Type Labels Description
etcd:ins:backend_commit_rt_p95_5m Unknown cls, ins, instance, job, ip N/A
etcd:ins:wal_fsync_rt_p95_5m Unknown cls, ins, instance, job, ip N/A
etcd:ins:network_peer_rt_p95_5m Unknown cls, To, ins, instance, job, ip N/A
etcd_cluster_version gauge cls, cluster_version, ins, instance, job, ip Which version is running. 1 for ‘cluster_version’ label with current cluster version
etcd_debugging_auth_revision gauge cls, ins, instance, job, ip The current revision of auth store.
etcd_debugging_disk_backend_commit_rebalance_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_disk_backend_commit_rebalance_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_disk_backend_commit_rebalance_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_disk_backend_commit_spill_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_disk_backend_commit_spill_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_disk_backend_commit_spill_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_disk_backend_commit_write_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_disk_backend_commit_write_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_disk_backend_commit_write_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_lease_granted_total counter cls, ins, instance, job, ip The total number of granted leases.
etcd_debugging_lease_renewed_total counter cls, ins, instance, job, ip The number of renewed leases seen by the leader.
etcd_debugging_lease_revoked_total counter cls, ins, instance, job, ip The total number of revoked leases.
etcd_debugging_lease_ttl_total_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_lease_ttl_total_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_lease_ttl_total_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_compact_revision gauge cls, ins, instance, job, ip The revision of the last compaction in store.
etcd_debugging_mvcc_current_revision gauge cls, ins, instance, job, ip The current revision of store.
etcd_debugging_mvcc_db_compaction_keys_total counter cls, ins, instance, job, ip Total number of db keys compacted.
etcd_debugging_mvcc_db_compaction_last gauge cls, ins, instance, job, ip The unix time of the last db compaction. Resets to 0 on start.
etcd_debugging_mvcc_db_compaction_pause_duration_milliseconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_mvcc_db_compaction_pause_duration_milliseconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_db_compaction_pause_duration_milliseconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_db_compaction_total_duration_milliseconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_mvcc_db_compaction_total_duration_milliseconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_db_compaction_total_duration_milliseconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_events_total counter cls, ins, instance, job, ip Total number of events sent by this member.
etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_keys_total gauge cls, ins, instance, job, ip Total number of keys.
etcd_debugging_mvcc_pending_events_total gauge cls, ins, instance, job, ip Total number of pending events to be sent.
etcd_debugging_mvcc_range_total counter cls, ins, instance, job, ip Total number of ranges seen by this member.
etcd_debugging_mvcc_slow_watcher_total gauge cls, ins, instance, job, ip Total number of unsynced slow watchers.
etcd_debugging_mvcc_total_put_size_in_bytes gauge cls, ins, instance, job, ip The total size of put kv pairs seen by this member.
etcd_debugging_mvcc_watch_stream_total gauge cls, ins, instance, job, ip Total number of watch streams.
etcd_debugging_mvcc_watcher_total gauge cls, ins, instance, job, ip Total number of watchers.
etcd_debugging_server_lease_expired_total counter cls, ins, instance, job, ip The total number of expired leases.
etcd_debugging_snap_save_marshalling_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_snap_save_marshalling_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_snap_save_marshalling_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_snap_save_total_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_snap_save_total_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_snap_save_total_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_store_expires_total counter cls, ins, instance, job, ip Total number of expired keys.
etcd_debugging_store_reads_total counter cls, action, ins, instance, job, ip Total number of reads action by (get/getRecursive), local to this member.
etcd_debugging_store_watch_requests_total counter cls, ins, instance, job, ip Total number of incoming watch requests (new or reestablished).
etcd_debugging_store_watchers gauge cls, ins, instance, job, ip Count of currently active watchers.
etcd_debugging_store_writes_total counter cls, action, ins, instance, job, ip Total number of writes (e.g. set/compareAndDelete) seen by this member.
etcd_disk_backend_commit_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_disk_backend_commit_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_disk_backend_commit_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_disk_backend_defrag_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_disk_backend_defrag_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_disk_backend_defrag_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_disk_backend_snapshot_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_disk_backend_snapshot_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_disk_backend_snapshot_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_disk_defrag_inflight gauge cls, ins, instance, job, ip Whether or not defrag is active on the member. 1 means active, 0 means not.
etcd_disk_wal_fsync_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_disk_wal_fsync_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_disk_wal_fsync_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_disk_wal_write_bytes_total gauge cls, ins, instance, job, ip Total number of bytes written in WAL.
etcd_grpc_proxy_cache_hits_total gauge cls, ins, instance, job, ip Total number of cache hits
etcd_grpc_proxy_cache_keys_total gauge cls, ins, instance, job, ip Total number of keys/ranges cached
etcd_grpc_proxy_cache_misses_total gauge cls, ins, instance, job, ip Total number of cache misses
etcd_grpc_proxy_events_coalescing_total counter cls, ins, instance, job, ip Total number of events coalescing
etcd_grpc_proxy_watchers_coalescing_total gauge cls, ins, instance, job, ip Total number of current watchers coalescing
etcd_mvcc_db_open_read_transactions gauge cls, ins, instance, job, ip The number of currently open read transactions
etcd_mvcc_db_total_size_in_bytes gauge cls, ins, instance, job, ip Total size of the underlying database physically allocated in bytes.
etcd_mvcc_db_total_size_in_use_in_bytes gauge cls, ins, instance, job, ip Total size of the underlying database logically in use in bytes.
etcd_mvcc_delete_total counter cls, ins, instance, job, ip Total number of deletes seen by this member.
etcd_mvcc_hash_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_mvcc_hash_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_mvcc_hash_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_mvcc_hash_rev_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_mvcc_hash_rev_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_mvcc_hash_rev_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_mvcc_put_total counter cls, ins, instance, job, ip Total number of puts seen by this member.
etcd_mvcc_range_total counter cls, ins, instance, job, ip Total number of ranges seen by this member.
etcd_mvcc_txn_total counter cls, ins, instance, job, ip Total number of txns seen by this member.
etcd_network_active_peers gauge cls, ins, Local, instance, job, ip, Remote The current number of active peer connections.
etcd_network_client_grpc_received_bytes_total counter cls, ins, instance, job, ip The total number of bytes received from grpc clients.
etcd_network_client_grpc_sent_bytes_total counter cls, ins, instance, job, ip The total number of bytes sent to grpc clients.
etcd_network_peer_received_bytes_total counter cls, ins, instance, job, ip, From The total number of bytes received from peers.
etcd_network_peer_round_trip_time_seconds_bucket Unknown cls, To, ins, instance, job, le, ip N/A
etcd_network_peer_round_trip_time_seconds_count Unknown cls, To, ins, instance, job, ip N/A
etcd_network_peer_round_trip_time_seconds_sum Unknown cls, To, ins, instance, job, ip N/A
etcd_network_peer_sent_bytes_total counter cls, To, ins, instance, job, ip The total number of bytes sent to peers.
etcd_server_apply_duration_seconds_bucket Unknown cls, version, ins, instance, job, le, success, ip, op N/A
etcd_server_apply_duration_seconds_count Unknown cls, version, ins, instance, job, success, ip, op N/A
etcd_server_apply_duration_seconds_sum Unknown cls, version, ins, instance, job, success, ip, op N/A
etcd_server_client_requests_total counter client_api_version, cls, ins, instance, type, job, ip The total number of client requests per client version.
etcd_server_go_version gauge cls, ins, instance, job, server_go_version, ip Which Go version server is running with. 1 for ‘server_go_version’ label with current version.
etcd_server_has_leader gauge cls, ins, instance, job, ip Whether or not a leader exists. 1 is existence, 0 is not.
etcd_server_health_failures counter cls, ins, instance, job, ip The total number of failed health checks
etcd_server_health_success counter cls, ins, instance, job, ip The total number of successful health checks
etcd_server_heartbeat_send_failures_total counter cls, ins, instance, job, ip The total number of leader heartbeat send failures (likely overloaded from slow disk).
etcd_server_id gauge cls, ins, instance, job, server_id, ip Server or member ID in hexadecimal format. 1 for ‘server_id’ label with current ID.
etcd_server_is_leader gauge cls, ins, instance, job, ip Whether or not this member is a leader. 1 if is, 0 otherwise.
etcd_server_is_learner gauge cls, ins, instance, job, ip Whether or not this member is a learner. 1 if is, 0 otherwise.
etcd_server_leader_changes_seen_total counter cls, ins, instance, job, ip The number of leader changes seen.
etcd_server_learner_promote_successes counter cls, ins, instance, job, ip The total number of successful learner promotions while this member is leader.
etcd_server_proposals_applied_total gauge cls, ins, instance, job, ip The total number of consensus proposals applied.
etcd_server_proposals_committed_total gauge cls, ins, instance, job, ip The total number of consensus proposals committed.
etcd_server_proposals_failed_total counter cls, ins, instance, job, ip The total number of failed proposals seen.
etcd_server_proposals_pending gauge cls, ins, instance, job, ip The current number of pending proposals to commit.
etcd_server_quota_backend_bytes gauge cls, ins, instance, job, ip Current backend storage quota size in bytes.
etcd_server_read_indexes_failed_total counter cls, ins, instance, job, ip The total number of failed read indexes seen.
etcd_server_slow_apply_total counter cls, ins, instance, job, ip The total number of slow apply requests (likely overloaded from slow disk).
etcd_server_slow_read_indexes_total counter cls, ins, instance, job, ip The total number of pending read indexes not in sync with leader’s or timed out read index requests.
etcd_server_snapshot_apply_in_progress_total gauge cls, ins, instance, job, ip 1 if the server is applying the incoming snapshot. 0 if none.
etcd_server_version gauge cls, server_version, ins, instance, job, ip Which version is running. 1 for ‘server_version’ label with current version.
etcd_snap_db_fsync_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_snap_db_fsync_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_snap_db_fsync_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_snap_db_save_total_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_snap_db_save_total_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_snap_db_save_total_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_snap_fsync_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_snap_fsync_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_snap_fsync_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_up Unknown cls, ins, instance, job, ip N/A
go_gc_duration_seconds summary cls, ins, instance, quantile, job, ip A summary of the pause duration of garbage collection cycles.
go_gc_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
go_gc_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
go_goroutines gauge cls, ins, instance, job, ip Number of goroutines that currently exist.
go_info gauge cls, version, ins, instance, job, ip Information about the Go environment.
go_memstats_alloc_bytes gauge cls, ins, instance, job, ip Number of bytes allocated and still in use.
go_memstats_alloc_bytes_total counter cls, ins, instance, job, ip Total number of bytes allocated, even if freed.
go_memstats_buck_hash_sys_bytes gauge cls, ins, instance, job, ip Number of bytes used by the profiling bucket hash table.
go_memstats_frees_total counter cls, ins, instance, job, ip Total number of frees.
go_memstats_gc_cpu_fraction gauge cls, ins, instance, job, ip The fraction of this program’s available CPU time used by the GC since the program started.
go_memstats_gc_sys_bytes gauge cls, ins, instance, job, ip Number of bytes used for garbage collection system metadata.
go_memstats_heap_alloc_bytes gauge cls, ins, instance, job, ip Number of heap bytes allocated and still in use.
go_memstats_heap_idle_bytes gauge cls, ins, instance, job, ip Number of heap bytes waiting to be used.
go_memstats_heap_inuse_bytes gauge cls, ins, instance, job, ip Number of heap bytes that are in use.
go_memstats_heap_objects gauge cls, ins, instance, job, ip Number of allocated objects.
go_memstats_heap_released_bytes gauge cls, ins, instance, job, ip Number of heap bytes released to OS.
go_memstats_heap_sys_bytes gauge cls, ins, instance, job, ip Number of heap bytes obtained from system.
go_memstats_last_gc_time_seconds gauge cls, ins, instance, job, ip Number of seconds since 1970 of last garbage collection.
go_memstats_lookups_total counter cls, ins, instance, job, ip Total number of pointer lookups.
go_memstats_mallocs_total counter cls, ins, instance, job, ip Total number of mallocs.
go_memstats_mcache_inuse_bytes gauge cls, ins, instance, job, ip Number of bytes in use by mcache structures.
go_memstats_mcache_sys_bytes gauge cls, ins, instance, job, ip Number of bytes used for mcache structures obtained from system.
go_memstats_mspan_inuse_bytes gauge cls, ins, instance, job, ip Number of bytes in use by mspan structures.
go_memstats_mspan_sys_bytes gauge cls, ins, instance, job, ip Number of bytes used for mspan structures obtained from system.
go_memstats_next_gc_bytes gauge cls, ins, instance, job, ip Number of heap bytes when next garbage collection will take place.
go_memstats_other_sys_bytes gauge cls, ins, instance, job, ip Number of bytes used for other system allocations.
go_memstats_stack_inuse_bytes gauge cls, ins, instance, job, ip Number of bytes in use by the stack allocator.
go_memstats_stack_sys_bytes gauge cls, ins, instance, job, ip Number of bytes obtained from system for stack allocator.
go_memstats_sys_bytes gauge cls, ins, instance, job, ip Number of bytes obtained from system.
go_threads gauge cls, ins, instance, job, ip Number of OS threads created.
grpc_server_handled_total counter cls, ins, instance, grpc_code, job, grpc_method, grpc_type, ip, grpc_service Total number of RPCs completed on the server, regardless of success or failure.
grpc_server_msg_received_total counter cls, ins, instance, job, grpc_type, grpc_method, ip, grpc_service Total number of RPC stream messages received on the server.
grpc_server_msg_sent_total counter cls, ins, instance, job, grpc_type, grpc_method, ip, grpc_service Total number of gRPC stream messages sent by the server.
grpc_server_started_total counter cls, ins, instance, job, grpc_type, grpc_method, ip, grpc_service Total number of RPCs started on the server.
os_fd_limit gauge cls, ins, instance, job, ip The file descriptor limit.
os_fd_used gauge cls, ins, instance, job, ip The number of used file descriptors.
process_cpu_seconds_total counter cls, ins, instance, job, ip Total user and system CPU time spent in seconds.
process_max_fds gauge cls, ins, instance, job, ip Maximum number of open file descriptors.
process_open_fds gauge cls, ins, instance, job, ip Number of open file descriptors.
process_resident_memory_bytes gauge cls, ins, instance, job, ip Resident memory size in bytes.
process_start_time_seconds gauge cls, ins, instance, job, ip Start time of the process since unix epoch in seconds.
process_virtual_memory_bytes gauge cls, ins, instance, job, ip Virtual memory size in bytes.
process_virtual_memory_max_bytes gauge cls, ins, instance, job, ip Maximum amount of virtual memory available in bytes.
promhttp_metric_handler_requests_in_flight gauge cls, ins, instance, job, ip Current number of scrapes being served.
promhttp_metric_handler_requests_total counter cls, ins, instance, job, ip, code Total number of scrapes by HTTP status code.
scrape_duration_seconds Unknown cls, ins, instance, job, ip N/A
scrape_samples_post_metric_relabeling Unknown cls, ins, instance, job, ip N/A
scrape_samples_scraped Unknown cls, ins, instance, job, ip N/A
scrape_series_added Unknown cls, ins, instance, job, ip N/A
up Unknown cls, ins, instance, job, ip N/A

7 - 常见问题

Pigsty etcd 模块常见问题答疑

etcd集群起什么作用?

etcd 是一个分布式的、可靠的键-值存储,用于存放系统中最为关键的数据,Pigsty 使用 etcd 作为 Patroni 的 DCS(分布式配置存储)服务,用于存储 PostgreSQL 集群的高可用状态信息。

Patroni 将通过 etcd,实现集群故障检测、自动故障转移、主从切换,集群配置管理等功能。

etcd 对 PostgreSQL 集群的高可用至关重要;其自身的可用性取决于多数派成员持续可达。生产环境通常把成员分散到独立故障域,并采用 3 或 5 个投票成员。


etcd集群使用多大规模合适?

如果超过集群成员数一半(包括正好一半)的 etcd 实例不可用,那么 etcd 集群将进入不可用状态,拒绝对外提供服务。

例如:使用 3 节点的 etcd 集群允许最多一个节点宕机,而其他两个节点仍然可以正常工作;而使用 5 节点的 etcd 集群则可以容忍 2 节点失效。

请注意,etcd 集群中的 学习者(Learner)实例不计入成员数,因此在 3 节点 etcd 集群中,如果有一个学习者实例,那么实际上成员数量为 2,不能容忍任一节点失效。

在生产环境中,我们建议使用奇数个 etcd 实例,对于生产环境,建议使用 3 节点或 5 节点的 etcd 集群部署以确保足够的可靠性。


etcd集群不可用会有什么影响?

如果 etcd 集群不可用,那么会影响 PostgreSQL 的管控平面,但不会影响数据平面 —— 现有的 PostgreSQL 集群将继续运行,但通过 Patroni 进行的管理操作将无法执行。

etcd 故障期间,PostgreSQL 高可用将无法实现自动故障转移,您也无法使用 patronictl 对 PostgreSQL 集群发起管理操作,例如修改配置,执行手动故障转移等。 通过 Ansible 发起的管理命令不受 etcd 故障影响:例如创建数据库,创建用户,刷新 HBA 与 Service 配置等,etcd 故障期间,您依然可以直接操作 PostgreSQL 集群来实现这些功能。

请注意,以上描述的行为仅适用于较新版本的 Patroni (>=3.0,对应 Pigsty >= 2.0)。如果您使用的是较老版本的 Patroni (<3.0,对应 Pigsty 版本为 1.x),则 etcd / consul 故障会引发极为严重的全局性影响: 所有 PostgreSQL 集群将发生降级:主库将降级为从库,拒绝写请求,etcd 故障将放大为全局性 PostgreSQL 故障。在 Patroni 3.0 引入 DCS Failsafe 功能后,这种情况得到了显著改善。


etcd集群中存储着什么数据?

在 Pigsty 的默认用途里,etcd 用作 Patroni 的 DCS,保存 PostgreSQL 高可用所需的领导者租约、成员状态与动态配置等协调数据;Pigsty 本身不会再把业务数据存入其中。

这些 DCS 数据由 Patroni 生成和管理。在受控维护中,Patroni 通常可以依据仍然健康的 PostgreSQL 集群重新建立协调状态,但这并不等于 etcd 没有状态,也不能把直接删除 DCS 数据视作无风险操作。

重建 etcd 会中断自动故障转移和 patronictl 管理能力,并清除当时的 DCS 状态。操作前应先核对 Patroni 拓扑、当前主库、剩余仲裁与近期备份,在维护窗口内按明确的恢复步骤执行。

如果您将 etcd 用于其他目的,例如作为 Kubernetes 的元数据存储,或自行存储其他数据,那么您需要自行备份 etcd 数据,并在 etcd 集群恢复后进行数据恢复。


如何从etcd故障中恢复?

Pigsty 默认只把 etcd 用作 Patroni DCS。服务重启与整簇重建是两种风险完全不同的操作:前者保留 DCS 数据,后者会清除协调状态,并在恢复前使 PostgreSQL 高可用失去 DCS 仲裁。因此应优先诊断并恢复现有成员;只有在确认拓扑、备份和恢复路径后,才考虑整簇重建。

重启 etcd 集群,您可以使用以下 Ansible 命令:

./etcd.yml -t etcd_launch

确需 重置/重建 etcd 集群时,应在维护窗口内先清理再重建,并在完成后核对 etcdctl endpoint healthetcdctl member listpatronictl list

./etcd-rm.yml -l etcd          # 核对备份和目标后清理集群
./etcd.yml -l etcd             # 按清单重新部署 etcd 集群

如果您自行使用 etcd 存储了其他数据,那么通常需要备份 etcd 数据,并在 etcd 集群恢复后进行数据恢复。


维护etcd有什么注意事项?

简单的版本是:不要写爆 etcd 就好

Pigsty 默认启用了 etcd 自动压实(Auto Compact),当前后端存储配额为 8 GiB。通常无需担心写满 etcd,但仍应监控实际用量。

etcd 的 数据模型 使得每一次写入都会产生一个新的版本。 因此如果您的 etcd 集群频繁写入,即使只有极个别的 Key,etcd 数据库的大小也可能会不断增长。 当达到容量上限时,etcd 将会拒绝写入请求,这可能导致依赖 etcd 的 PostgreSQL 高可用机制无法正常工作。

Pigsty 默认的 etcd 配置已包含以下优化:

auto-compaction-mode: periodic      # 周期性自动压缩
auto-compaction-retention: "24h"    # 保留 24 小时历史
quota-backend-bytes: 8589934592     # 8 GiB 配额

更多维护细节请阅读 etcd 官方文档维护指南

提示

对于 Pigsty v2.6 之前的版本,请参照下面的说明手动启用 etcd 自动垃圾回收。


如何启动etcd自动垃圾回收?

如果您使用的早先版本的 Pigsty (v2.0 - v2.5),我们强烈建议您通过以下步骤,在生产环境中启用 etcd 的自动压实功能,从而避免 etcd 容量配额写满导致的 etcd 不可用故障。

在 Pigsty 源码目录中,编辑 etcd 配置文件模板:roles/etcd/templates/etcd.conf,添加以下三条配置项:

auto-compaction-mode: periodic
auto-compaction-retention: "24h"
quota-backend-bytes: 17179869184

然后将所有相关 PostgreSQL 集群设置为 维护模式 后,重新使用 ./etcd.yml 覆盖部署 etcd 集群即可。

该配置会将 etcd 默认的容量配额从 2 GiB 提高到 16 GiB,并确保只保留最近一天的写入历史版本,从而避免了 etcd 数据库大小的无限增长。


etcd中的PostgreSQL高可用数据存储在哪里?

默认情况下,Patroni 使用 pg_namespace 指定的前缀(默认为 /pg)作为所有元数据键的前缀,随后是 PostgreSQL 集群名称。 例如,名为 pg-meta 的 PG 集群,其元数据键将存储在 /pg/pg-meta 下。

etcdctl get /pg/pg-meta --prefix

其中的数据样本如下所示:

/pg/pg-meta/config
{"ttl":30,"loop_wait":10,"retry_timeout":10,"primary_start_timeout":10,"maximum_lag_on_failover":1048576,"maximum_lag_on_syncnode":-1,"primary_stop_timeout":30,"synchronous_mode":false,"synchronous_mode_strict":false,"failsafe_mode":true,"pg_version":16,"pg_cluster":"pg-meta","pg_shard":"pg-meta","pg_group":0,"postgresql":{"use_slots":true,"use_pg_rewind":true,"remove_data_directory_on_rewind_failure":true,"parameters":{"max_connections":100,"superuser_reserved_connections":10,"max_locks_per_transaction":200,"max_prepared_transactions":0,"track_commit_timestamp":"on","wal_level":"logical","wal_log_hints":"on","max_worker_processes":16,"max_wal_senders":50,"max_replication_slots":50,"password_encryption":"scram-sha-256","ssl":"on","ssl_cert_file":"/pg/cert/server.crt","ssl_key_file":"/pg/cert/server.key","ssl_ca_file":"/pg/cert/ca.crt","shared_buffers":"7969MB","maintenance_work_mem":"1993MB","work_mem":"79MB","max_parallel_workers":8,"max_parallel_maintenance_workers":2,"max_parallel_workers_per_gather":0,"hash_mem_multiplier":8.0,"huge_pages":"try","temp_file_limit":"7GB","vacuum_cost_delay":"20ms","vacuum_cost_limit":2000,"bgwriter_delay":"10ms","bgwriter_lru_maxpages":800,"bgwriter_lru_multiplier":5.0,"min_wal_size":"7GB","max_wal_size":"28GB","max_slot_wal_keep_size":"42GB","wal_buffers":"16MB","wal_writer_delay":"20ms","wal_writer_flush_after":"1MB","commit_delay":20,"commit_siblings":10,"checkpoint_timeout":"15min","checkpoint_completion_target":0.8,"archive_mode":"on","archive_timeout":300,"archive_command":"pgbackrest --stanza=pg-meta archive-push %p","max_standby_archive_delay":"10min","max_standby_streaming_delay":"3min","wal_receiver_status_interval":"1s","hot_standby_feedback":"on","wal_receiver_timeout":"60s","max_logical_replication_workers":8,"max_sync_workers_per_subscription":6,"random_page_cost":1.1,"effective_io_concurrency":1000,"effective_cache_size":"23907MB","default_statistics_target":200,"log_destination":"csvlog","logging_collector":"on","log_directory":"/pg/log/postgres","log_filename":"postgresql-%Y-%m-%d.log","log_checkpoints":"on","log_lock_waits":"on","log_replication_commands":"on","log_statement":"ddl","log_min_duration_statement":100,"track_io_timing":"on","track_functions":"all","track_activity_query_size":8192,"log_autovacuum_min_duration":"1s","autovacuum_max_workers":2,"autovacuum_naptime":"1min","autovacuum_vacuum_cost_delay":-1,"autovacuum_vacuum_cost_limit":-1,"autovacuum_freeze_max_age":1000000000,"deadlock_timeout":"50ms","idle_in_transaction_session_timeout":"10min","shared_preload_libraries":"timescaledb, pg_stat_statements, auto_explain","auto_explain.log_min_duration":"1s","auto_explain.log_analyze":"on","auto_explain.log_verbose":"on","auto_explain.log_timing":"on","auto_explain.log_nested_statements":true,"pg_stat_statements.max":5000,"pg_stat_statements.track":"all","pg_stat_statements.track_utility":"off","pg_stat_statements.track_planning":"off","timescaledb.telemetry_level":"off","timescaledb.max_background_workers":8,"citus.node_conninfo":"sslm
ode=prefer"}}}
/pg/pg-meta/failsafe
{"pg-meta-2":"http://10.10.10.11:8008/patroni","pg-meta-1":"http://10.10.10.10:8008/patroni"}
/pg/pg-meta/initialize
7418384210787662172
/pg/pg-meta/leader
pg-meta-1
/pg/pg-meta/members/pg-meta-1
{"conn_url":"postgres://10.10.10.10:5432/postgres","api_url":"http://10.10.10.10:8008/patroni","state":"running","role":"primary","version":"4.0.1","tags":{"clonefrom":true,"version":"16","spec":"8C.32G.125G","conf":"tiny.yml"},"xlog_location":184549376,"timeline":1}
/pg/pg-meta/members/pg-meta-2
{"conn_url":"postgres://10.10.10.11:5432/postgres","api_url":"http://10.10.10.11:8008/patroni","state":"running","role":"replica","version":"4.0.1","tags":{"clonefrom":true,"version":"16","spec":"8C.32G.125G","conf":"tiny.yml"},"xlog_location":184549376,"replication_state":"streaming","timeline":1}
/pg/pg-meta/status
{"optime":184549376,"slots":{"pg_meta_2":184549376,"pg_meta_1":184549376},"retain_slots":["pg_meta_1","pg_meta_2"]}

如何使用一个外部的已经存在的 etcd 集群?

配置清单中硬编码了所使用 etcd 的分组名为 etcd,这个分组里的成员将被用作 PGSQL 的 DCS 服务器。您可以使用 etcd.yml 对它们进行初始化,或直接假设它是一个已存在的外部 etcd 集群。

要使用现有的外部 etcd 集群,只要像往常一样定义它们即可,您可以跳过 etcd.yml 剧本的执行,因为集群已经存在,不需要部署。

但用户必须确保 现有 etcd 集群证书是由 Pigsty 使用的相同 CA 签名颁发的。否则客户端无法使用 Pigsty 自签名 CA 颁发的证书来访问外部的 etcd 集群。


如何向现有etcd集群添加新的成员?

详细过程,请参考 向 etcd 集群添加成员

推荐方式:使用便捷脚本

# 首先在配置清单中添加新成员定义,然后执行:
bin/etcd-add <ip>      # 添加单个新成员
bin/etcd-add <ip1>     # 添加多个新成员

手动方式:

etcdctl member add <etcd-?> --learner=true --peer-urls=https://<new_ins_ip>:2380 # 宣告新成员加入
./etcd.yml -l <new_ins_ip> -e etcd_init=existing                                 # 初始化新成员
etcdctl member promote <new_ins_server_id>                                       # 提升为正式成员

请注意,我们建议一次只添加一个新成员。


如何从现有etcd集群中移除成员?

详细过程,请参考 从 etcd 集群中移除成员

推荐方式:使用便捷脚本

bin/etcd-rm <ip>              # 移除指定成员
bin/etcd-rm                   # 移除整个 etcd 集群

手动方式:

./etcd-rm.yml -l <ins_ip>                    # 退群、停服并默认清理本机数据

etcd-rm.yml 已经包含 etcdctl member remove 步骤,不要在正常流程中前后重复执行。只有排障时才手工 member remove;之后仍可在目标尚存于清单时运行一次移除剧本完成本机停服、注销和清理,并核对剩余仲裁。


如何配置 etcd RBAC 认证?

Pigsty 自 v4.0 起默认启用 etcd 的 RBAC 认证。root 用户密码由 etcd_root_password 参数控制,默认值为 Etcd.Root

在生产环境中,强烈建议修改默认密码

all:
  vars:
    etcd_root_password: 'YourSecurePassword'

客户端认证

# 在 etcd 节点上,环境变量已自动配置
source /etc/profile.d/etcdctl.sh
etcdctl member list

# 手动配置认证
export ETCDCTL_USER="root:YourSecurePassword"
export ETCDCTL_CACERT=/etc/etcd/ca.crt
export ETCDCTL_CERT=/etc/etcd/server.crt
export ETCDCTL_KEY=/etc/etcd/server.key

更多详情请参考 RBAC 认证