V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Songxwn
V2EX  ›  程序员

猪圈 Pigsty-PG 私有 RDS 集群搭建教程

  •  
  •   Songxwn · 274 天前 · 1990 次点击
    这是一个创建于 274 天前的主题,其中的信息可能已经有所发展或是发生改变。

    博客

    https://songxwn.com/

    简介

    Pigsty 是一个更好的本地自建且开源 RDS for PostgreSQL 替代,具有以下特点:

    • 开箱即用的 PostgreSQL 发行版,深度整合地理、时序、分布式、图、向量、分词、AI 等 150 余个扩展插件

    • 运行于裸操作系统之上,无需容器支持,支持主流操作系统:EL7/8/9 及其衍生发行版,Ubuntu 20.04/22.04 以及 Debian 11/12 。(推荐使用 Rocky Linux)

    • 基于现代的 PrometheusGrafana 技术栈,提供令人惊艳,无可比拟的数据库观测能力:画廊 & 演示站点

    • 基于 patronihaproxy, 与etcd,打造故障自愈的高可用架构:硬件故障自动切换,流量无缝衔接。

    • 基于 pgBackRest 与可选的 MinIO 集群提供开箱即用的 PITR 时间点恢复,为软件缺陷与人为删库兜底。

    • 基于 Ansible 提供声明式的 API 对复杂度进行抽象,以 Database-as-Code 的方式极大简化了日常运维管理操作。

    • Pigsty 用途广泛,可用作完整应用运行时,开发演示数据/可视化应用,大量使用 PG 的软件可用 Docker 模板一键拉起。

    • 提供基于 Vagrant 的本地开发测试沙箱环境,与基于 Terraform 的云端自动部署方案,开发测试生产保持环境一致。

    • 部署并监控专用的 Redis(主从,哨兵,集群),MinIO ,Etcd ,Haproxy ,MongoDB (FerretDB ) 集群

    官方文档:https://pigsty.cc/doc/#/zh/README

    项目地址:https://github.com/Vonng/pigsty

    本教程说明

    一个非常简单的入门教程,用于构建一个三节点的 PG 集群(开启 VIP ),且支持扩展时序数据库 timescaledb ,主要用于 Zabbix 的后端数据库。

    基于 Pigsty 2.5.1 、Rocky Linux 9.3 编写。

    安装

    初始化元节点(管理监控节点)

    准备一个全新的符合要求 的 Linux x86_64 ,使用带有 root 权限或有 sudo 权限的用户执行安装脚本。

    (官方推荐使用 Rocky Linux 8.8 ,配置建议 2C4G 100G 硬盘)

    curl https://get.pigsty.cc/latest | bash
    

    PS:安装后会移除系统自带 yum 源,建议提前安装所需软件。

    该命令会下载并解压 Pigsty 源码至用户 Home ,按提示完成 准备,配置,安装三个步骤即可完成安装。

    cd ~/pigsty     
     # 进入 Pigsty 源码目录,完成后续 准备、配置、安装 三个步骤
    ./bootstrap      
    # 确保 Ansible 正常安装,如果存在 /tmp/pkg.tgz 离线软件包,便使用它。
    ./configure      
    # 执行环境检测,并生成相应的推荐配置文件,如果你知道如何配置 Pigsty 可以跳过。
    ./install.yml    
    # 根据生成的配置文件开始在当前节点上执行安装,使用离线安装包大概需要 10 分钟完成。
    # 可以在里面修改默认信息 pigsty.yml ,如域名和默认密码等。
    

    安装完成后,您可以通过域名或 80/443 端口通过 Nginx 访问 WEB 界面,通过 5432 端口访问元节点默认的 PostgreSQL 数据库服务。

    IP 地址规划

    IP 地址 主机名 角色
    172.18.77.33 pg-meta-1 元节点
    172.18.77.101 pg-cu1-1 PG 集群主机节点
    172.18.77.102 pg-cu1-2 PG 集群主机节点
    172.18.77.103 pg-cu1-3 PG 集群主机节点
    172.18.77.99 vip Keepalived 虚拟 IP

    PS:Keepalived 集群需要在同一广播域。(其实就是基于 VRRP 协议)

    DNS 解析配置

    组件 端口 域名 说明 官方 Demo 地址
    Nginx 80 h.pigsty Web 服务总入口,本地 YUM 源 home.pigsty.cc
    AlertManager 9093 a.pigsty 告警聚合/屏蔽页面 a.pigsty.cc
    Grafana 3000 g.pigsty Grafana 监控面板 demo.pigsty.cc
    Prometheus 9090 p.pigsty Prometheus 管理界面 p.pigsty.cc

    你需要修改 hosts 文件,增加以上解析。或者在内网 dns 配置上述解析。解析的 IP 为元节点 IP 即可

    Pigsty 会自动给纳入管理的节点填写 hosts 文件。

    172.18.77.33 h.pigsty a.pigsty p.pigsty g.pigsty # pigsty dns
    #示例
    

    访问 Web 界面

    主页域名为 h.pigsty ,g.pigsty 为 Grafana ,全局应用默认账号密码为 admin/pigsty 。

    (如果自己电脑要用浏览器访问,注意配置 DNS 解析或 hosts 文件)

    部署三节点 PG 高可用集群

    编辑 Pigsty 配置文件,增加主机节点信息

    cd ~/pigsty  
    # 进入 pigsty 主目录,所有操作都在此目录执行。
    vim pigsty.yml 
    # 编辑配置文件,增加三台主节点和集群配置。
    

    增加 PG 集群和 VIP 配置信息

    1 、集群名字为 pg-cu1

    2 、配置 172.18.77.101 为默认主节点,其他为从节点。

    3 、开启 keepalived 配置,配置 VIP 地址为 172.18.22.99 。配置每台关联 VIP 的网卡为 ens33 。(网卡名字注意修改)

    4 、此段配置在 children 下增加,与默认的 pg-meta 同级别。

    5 、VRRP 的 id 为 35 ,注意不要冲突。

        pg-cu1:
          hosts:
            172.18.77.101: { pg_seq: 1, pg_role: primary }
            172.18.77.102: { pg_seq: 2, pg_role: replica }
            172.18.77.103: { pg_seq: 3, pg_role: replica }
          vars: 
            pg_cluster: pg-cu1
            vip_enabled: true            # enable vip on this node cluster?
            vip_address: 172.18.77.99       # node vip address in ipv4 format, required if vip is enabled
            vip_vrid: 35        # required, integer, 1-254, should be unique among same VLAN
            vip_role: backup                  # optional, `master/backup`, backup by default, use as init role
            vip_preempt: true               # optional, `true/false`, false by default, enable vip preemption
            vip_interface: ens33              # node vip network interface to listen, `eth0` by default
            vip_dns_suffix: ''                # node vip dns name suffix, empty string by default
            vip_exporter_port: 9650           # keepalived exporter listen port, 9650 by default
    

    增加 PG 数据库、用户、HBA 配置。

    1 、增加 zabbix 、grafana 数据库,Zabbix 开启 timescaledb 扩展,并配置所属用户。并与 pgbouncer 同步创建。

    2 、增加 zabbix 、grafana 用户并配置密码、角色。并与 pgbouncer 同步创建。

    3 、配置用户的 HBA 规则,允许任意 IP 访问,并配置 pgbouncer 和 HBA

    4 、pg_libs 配置 PG 加载的插件列表,这里加载了 timescaledb 插件。

        pg-cu1:
          hosts:
            172.18.77.101: { pg_seq: 1, pg_role: primary } 
            172.18.77.102: { pg_seq: 2, pg_role: replica } 
            172.18.77.103: { pg_seq: 3, pg_role: replica } 
          vars: 
            pg_cluster: pg-cu1
            pg_databases:
              - name: zabbix                    # 必选,`name` 是数据库定义的唯一必选字段
                pgbouncer: true                 # 可选,是否将此数据库添加到 pgbouncer 数据库列表?默认为 true
                extensions:                     # 可选,要安装的附加扩展: 扩展对象的数组
                  - { name: timescaledb }       # 例如有的扩展会创建并使用固定的模式,就不需要指定模式。
                owner: zabbix                   # 可选,数据库所有者,默认为 postgres
              - name: grafana                   # 必选,`name` 是数据库定义的唯一必选字段
                pgbouncer: true                 # 可选,是否将此数据库添加到 pgbouncer 数据库列表?默认为 true
                owner: grafana                  # 可选,数据库所有者,默认为 postgres
            pg_users:    
              - name: zabbix                    # 数据库用户名,必需,`name` 是用户定义的唯一必选字段
                password: Passwd.zabbix         # 可选,密码,可以是 scram-sha-256 哈希字符串或明文
                pgbouncer: true                 # 可选,默认为 false ,将此用户添加到 pgbouncer 用户列表
                roles: [dbrole_admin]
                comment: Zabbix                 # 可选,此用户/角色的说明与备注字符串
              - name: grafana                   # 数据库用户名,必需,`name` 是用户定义的唯一必选字段
                password: 
                pgbouncer: true                 # 可选,默认为 false ,将此用户添加到 pgbouncer 用户列表
                roles: [dbrole_admin]
                comment: grafana                # 可选,此用户/角色的说明与备注字符串
            pg_hba_rules:
              - { user: 'zabbix'  ,db: all ,addr: 0.0.0.0/0    ,auth: pwd ,title: 'zabbix 用户不限制登录'}
              - { user: 'grafana' ,db: all ,addr: 0.0.0.0/0    ,auth: pwd ,title: 'grafana 用户不限制登录'}
            pgb_hba_rules: 
              - { user: 'zabbix'  ,db: all  ,addr: 0.0.0.0/0   ,auth: pwd ,title: 'zabbix 用户不限制登录'}
              - { user: 'grafana' ,db: all  ,addr: 0.0.0.0/0   ,auth: pwd ,title: 'grafana 用户不限制登录'}
            pg_libs: 'timescaledb, pg_stat_statements, auto_explain' # 加载时序数据库插件
            vip_enabled: true            # enable vip on this node cluster?
            vip_address: 172.18.77.99       # node vip address in ipv4 format, required if vip is enabled
            vip_vrid: 35        # required, integer, 1-254, should be unique among same VLAN
            vip_role: backup                  # optional, `master/backup`, backup by default, use as init role
            vip_preempt: true               # optional, `true/false`, false by default, enable vip preemption
            vip_interface: ens33              # node vip network interface to listen, `eth0` by default
            vip_dns_suffix: ''                # node vip dns name suffix, empty string by default
            vip_exporter_port: 9650           # keepalived exporter listen port, 9650 by default
    

    全部配置展示(仅参考) 用于 Zabbix 服务器的时序数据库

    1 、注意全局密码已经修改为 PG-PWD-01

    all:
      children:
        # infra cluster for proxy, monitor, alert, etc..
        infra: { hosts: { 172.18.77.33: { infra_seq: 1 } } }
        # etcd cluster for ha postgres
        etcd: { hosts: { 172.18.77.33: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }
        # minio cluster, optional backup repo for pgbackrest
        #minio: { hosts: { 172.18.77.33: { minio_seq: 1 } }, vars: { minio_cluster: minio } }
        # postgres cluster 'pg-meta' with single primary instance
        pg-meta:
          hosts: { 172.18.77.33: { pg_seq: 1, pg_role: primary } }
          vars:
            pg_cluster: pg-meta
            pg_databases: [ { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [ pigsty ] ,extensions: [{name: postgis, schema: public}] }]
            pg_users:
              - { name: dbuser_meta ,password: DBUser.Meta   ,pgbouncer: true ,roles: [ dbrole_admin ]    ,comment: pigsty admin user }
              - { name: dbuser_view ,password: DBUser.Viewer ,pgbouncer: true ,roles: [ dbrole_readonly ] ,comment: read-only viewer for meta database }
            pg_libs: 'pg_stat_statements, auto_explain' # add extra extensions to shared_preload_libraries
            node_crontab: [ '00 03 * * * postgres /pg/bin/pg-backup full' ] # make a full backup every 1am
        bj-zjy-pg-cu1:
          hosts:
            172.18.77.101: { pg_seq: 1, pg_role: primary } 
            172.18.77.102: { pg_seq: 2, pg_role: replica } 
            172.18.77.103: { pg_seq: 3, pg_role: replica } 
          vars: 
            pg_cluster: pg-cu1
            pg_databases:
              - name: zabbix                    # 必选,`name` 是数据库定义的唯一必选字段
                pgbouncer: true                 # 可选,是否将此数据库添加到 pgbouncer 数据库列表?默认为 true
                extensions:                     # 可选,要安装的附加扩展: 扩展对象的数组
                  - { name: timescaledb }       # 例如有的扩展会创建并使用固定的模式,就不需要指定模式。
                owner: zabbix                   # 可选,数据库所有者,默认为 postgres
              - name: grafana                   # 必选,`name` 是数据库定义的唯一必选字段
                pgbouncer: true                 # 可选,是否将此数据库添加到 pgbouncer 数据库列表?默认为 true
                owner: grafana                  # 可选,数据库所有者,默认为 postgres
            pg_users:    
              - name: zabbix                    # 数据库用户名,必需,`name` 是用户定义的唯一必选字段
                password: Passwd.Zabbix  # 可选,密码,可以是 scram-sha-256 哈希字符串或明文
                pgbouncer: true                 # 可选,默认为 false ,将此用户添加到 pgbouncer 用户列表
                roles: [dbrole_admin]
                comment: Zabbix                 # 可选,此用户/角色的说明与备注字符串
              - name: grafana                    # 数据库用户名,必需,`name` 是用户定义的唯一必选字段
                password: Passwd.grafana  # 可选,密码,可以是 scram-sha-256 哈希字符串或明文
                pgbouncer: true                 # 可选,默认为 false ,将此用户添加到 pgbouncer 用户列表
                roles: [dbrole_admin]
                comment: grafana                 # 可选,此用户/角色的说明与备注字符串
            pg_hba_rules:
              - { user: 'zabbix'  ,db: all ,addr: 0.0.0.0/0    ,auth: pwd ,title: 'zabbix 用户不限制登录'}
              - { user: 'grafana' ,db: all ,addr: 0.0.0.0/0    ,auth: pwd ,title: 'grafana 用户不限制登录'}
            pgb_hba_rules: 
              - { user: 'zabbix'  ,db: all  ,addr: 0.0.0.0/0   ,auth: pwd ,title: 'zabbix 用户不限制登录'}
              - { user: 'grafana' ,db: all  ,addr: 0.0.0.0/0   ,auth: pwd ,title: 'grafana 用户不限制登录'}
            pg_libs: 'timescaledb, pg_stat_statements, auto_explain' # 加载时序数据库插件        
            vip_enabled: true            # enable vip on this node cluster?
            vip_address: 172.18.77.99       # node vip address in ipv4 format, required if vip is enabled
            vip_vrid: 35                    # required, integer, 1-254, should be unique among same VLAN
            vip_role: backup                # optional, `master/backup`, backup by default, use as init role
            vip_preempt: true               # optional, `true/false`, false by default, enable vip preemption
            vip_interface: ens33              # node vip network interface to listen, `eth0` by default
            vip_dns_suffix: ''                # node vip dns name suffix, empty string by default
            vip_exporter_port: 9650           # keepalived exporter listen port, 9650 by default
      vars:                               # global parameters
        version: v2.5.1                   # pigsty version string
        admin_ip: 172.18.77.33            # admin node ip address
        region: china                     # upstream mirror region: default,china,europe
        infra_portal:                     # domain names and upstream servers
          home         : { domain: h.pigsty }
          grafana      : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
          prometheus   : { domain: p.pigsty ,endpoint: "${admin_ip}:9090" }
          alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9093" }
          blackbox     : { endpoint: "${admin_ip}:9115" }
          loki         : { endpoint: "${admin_ip}:3100" }
          #minio        : { domain: sss.pigsty  ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
        # if you want to use minio as backup repo instead of local fs, uncomment minio related lines
        # don't forget to configure pgbackrest_repo and change credentials there!
        #pgbackrest_method: minio
        # if disabled, original /etc/yum.repos.d will be kept
        repo_remove: true       # remove existing repo on admin node during repo bootstrap
        node_repo_remove: true  # remove existing node repo for node managed by pigsty
        # WARNING: CHANGE THESE PASSWORDS
        #grafana_admin_username: admin
        grafana_admin_password: PG-PWD-01
        #pg_admin_username: dbuser_dba
        pg_admin_password: PG-PWD-01
        #pg_monitor_username: dbuser_monitor
        pg_monitor_password: PG-PWD-01
        #pg_replication_username: replicator
        pg_replication_password: PG-PWD-01
        #patroni_username: postgres
        patroni_password: PG-PWD-01
        #haproxy_admin_username: admin
        haproxy_admin_password: PG-PWD-01
        # this config template assume you are using pre-packed offline packages
        # If you wish to download upstream yum packages directly from internet,
        # consider using ad hoc `el7.yml`, `el8.yml`, `el9.yml` config instead.
    ...
    

    配置元节点密钥免密登录主机节点

    Pigsty 会在元节点自动生成一对公私钥,将其拷贝到所有主机节点。

    ssh-copy-id 172.18.77.101
    # 执行后输入 yes ,然后再手动输入主机节点的登录密码即可。
    ssh 172.18.77.101
    # 确认可直接登录即可,所有主机节点都要操作。
    

    将集群节点纳入 Pigsty 管理并部署 PG 集群

    节点纳入管理

    bin/node-add   pg-cu1    
     # 将集群 pg-test1 的 3 个主机节点纳入 Pigsty 管理
    

    PG 集群初始化部署(注意:会根据 CPU 内存等配置自动优化 PG 参数,建议提前固定好虚拟机配置)

    bin/pgsql-add  pg-cu1      # 初始化一个 3 节点的 pg-cu1 可用 PG 集群
    # 执行后不到 10 分钟,就将拥有一个服务接入,监控,备份 PITR ,高可用配置齐全的 PostgreSQL 数据库集群。
    

    PG 集群架构图

    PG-HA 示例图

    硬件故障由 patroni 、etcd 和 Haproxy 提供的自愈高可用架构来兜底,在主库故障的情况下,默认会在 30 秒内执行自动故障转移( Failover )。 客户端无需修改配置重启应用:Haproxy 利用 patroni 健康检查进行流量分发,读写请求会自动分发到新的集群主库中,并避免脑裂的问题。 这一过程十分丝滑,例如在从库故障,或主动切换( switchover )的情况下,客户端只有一瞬间的有感知查询闪断。

    软件故障、人为错误和 数据中心级灾难由 pgbackrest 和可选的 MinIO 集群来兜底。这为您提供了本地/云端的 PITR 能力,并在数据中心爆炸的情况下提供了跨地理区域复制,与异地容灾功能。

    管理和使用

    默认用户

    Pigsty 也有四个默认用户(系统用户):

    • 超级用户 (postgres),集群的所有者和创建者,与操作系统 dbsu 名称相同。

    • 复制用户 (replicator),用于主-从复制的系统用户。

    • 监控用户 (dbuser_monitor),用于监控数据库和连接池指标的用户。

    • 管理用户 (dbuser_dba),执行日常操作和数据库更改的管理员用户。

    这 4 个默认用户的用户名/密码通过 4 对专用参数进行定义,并在很多地方引用:

    • pg_dbsu:操作系统 dbsu 名称,默认为 postgres ,最好不要更改它

    • pg_dbsu_password:dbsu 密码,默认为空字符串意味着不设置 dbsu 密码,最好不要设置。

    • pg_replication_username:postgres 复制用户名,默认为 replicator

    • pg_replication_password:postgres 复制密码,默认为 DBUser.Replicator

    • pg_admin_username:postgres 管理员用户名,默认为 dbuser_dba

    • pg_admin_password:postgres 管理员密码的明文,默认为 DBUser.DBA

    • pg_monitor_username:postgres 监控用户名,默认为 dbuser_monitor

    • pg_monitor_password:postgres 监控密码,默认为 DBUser.Monitor

    在生产部署中记得更改这些密码,不要使用默认值! 在部署前,可以在 pigsty.yml 里面修改。

    配置用户

    bin/pgsql-user <cls> <username>    # pgsql-user.yml -l <cls> -e username=<username>
    

    配置 HBA

    bin/pgsql-hba <cls>                 # 重新加载指定集群 `<cls>` 的 hba 规则
    bin/pgsql-hba <cls> ip1 ip2...      # 重新加载特定实例的 hba 规则
    

    创建数据库

    bin/pgsql-db <cls> <dbname>    # pgsql-db.yml -l <cls> -e dbname=<dbname>
    

    数据库集群访问端口说明

    组件 端口 描述 状态 备注
    Postgres 5432 Pigsty CMDB 默认启用
    Pgbouncer 6432 Pgbouncer 连接池服务 默认启用
    Patroni 8008 Patroni 高可用组件 默认启用
    Haproxy Primary 5433 主连接池:读/写服务 默认启用
    Haproxy Replica 5434 副本连接池:只读服务 默认启用
    Haproxy Default 5436 主直连服务* 默认启用
    Haproxy Offline 5438 离线直连:离线读服务 默认启用
    Haproxy service 543x PostgreSQL 定制服务 按需定制
    Haproxy Admin 9101 监控指标和流量管理 默认启用
    PG Exporter 9630 PG 监控指标导出器 默认启用
    PGBouncer Exporter 9631 PGBouncer 监控指标导出器 默认启用
    Node Exporter 9100 节点监控指标导出器 默认启用
    Promtail 9080 收集数据库组件与主机日志 默认启用
    vip-manager - 将 VIP 绑定到主节点 按需启用
    Docker Daemon 9323 Docker 守护进程 按需启用
    keepalived - 为整个集群绑定 L2 VIP 按需启用
    Keepalived Exporter 9650 Keepalived 指标导出器 按需启用

    PS:个人推荐使用 5436 端口,并通过 VIP 地址访问数据库集群。(绕过 pgbouncer )

    使用 pgbouncer 则可以使用 5433 端口,并通过 VIP 地址访问集群

    默认管理员账号为 dbuser_dba 。

    3 条回复    2024-03-01 08:31:19 +08:00
    defunct9
        1
    defunct9  
       274 天前
    以前启用了 postgres 的 timescale 时序功能,把 prometheus 的时序信息保存到 postgres 做长期备份,本地 prometheus 的只保留 1 个月,结果磁盘占用量 postgres 过大了,随放弃。
    coinbase
        2
    coinbase  
       262 天前
    为什么不用 Docker 容器化呢?
    coinbase
        3
    coinbase  
       262 天前
    coinbase@MacBook-Pro ~/pigsty> ./bootstrap

    bootstrap pigsty v2.5.1 begin
    [ OK ] region = china
    [FAIL] kernel = Darwin, not supported, Linux only

    macOS 上测试都没法测试😂
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5571 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 05:54 · PVG 13:54 · LAX 21:54 · JFK 00:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.