跳转到主要内容

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

返回本页常规视图.

Pigsty v1.5.1 文档

冻结于 Pigsty v1.5.1 的历史文档。

v1.5.1 中文文档

开箱即用的开源数据库发行版

logo

最新版本: v1.5.1 | Github项目 | 公开Demo

文档地址: 英文文档 | 中文文档 | Github Pages文档

Pigsty是什么?

Pigsty是开箱即用的开源数据库发行版,以 PostgreSQL 为核心,打包TimescaleDBPostGISCitus与上百余+生态扩展插件,整合了大规模生产环境所需的PaaS基础设施数据分析组件:将顶级DBA的经验沉淀为软件,一次性解决使用数据库时会遇到的各类问题。

Pigst还是自动驾驶的运维解决方案,带有全面专业的监控系统,与简单易用的高可用数据库部署管控方案。用户只需声明自己想要什么样的数据库,即可将其一键创建:PostgreSQL / Redis / Greenplum

Pigsty是简单易用的开发者工具箱,无论是下载、安装、还是部署迁移备份恢复扩缩容,都能一键完成。基于Vagrant本地沙箱Terraform的多云部署能力,让Pigsty在所有环境中都能一键拉起,带来统一的使用体验。

Pigsty用途广泛,可支持各类上层SaaS应用或制作大屏/Demo。相比使用云数据库,数据安全自主可控,简运维、低成本、全功能、优体验,可以显著节省数据库运维人力,并节约 50% ~ 80% 的数据库综合成本。对各类企业用户、ISV、个人用户都具有显著的价值与吸引力。

请参考 亮点特性 一节,获取更多关于Pigsty产品功能特点的介绍。

快速上手

准备全新机器节点一台,Linux x86_64 CentOS 7.8,确保您可以登陆该节点并免密码执行sudo命令。

curl -SL https://github.com/Vonng/pigsty/releases/download/v1.5.1/pigsty.tgz | gzip -d | tar -xC ~ # 下载
cd ~/pigsty && ./configure                            # 配置
make install                                          # 安装

更多安装细节,请参考 快速上手

协议

Pigsty基于Apache 2.0协议开源,可以免费用于商业目的,但改装与衍生需遵守Apache License 2.0的显著声明条款。如需帮助或专业支持,请参阅社区交流

关于

作者: 冯若航 ([email protected])

协议: Apache 2.0 License

备案: 浙ICP备15016890-2号

1 - Pigsty入门指南

从 Pigsty v1.5.1 标签恢复的历史文档。

不同的用户有不同的关注点,如果遇到问题,欢迎查阅FAQ,提交Issue,或向社区求助。

新用户

新接触PostgreSQL与Pigsty的用户,可以参阅 亮点特性了解Pigsty的功能,或访问Pigsty演示站点:http://demo.pigsty.cc 进行直观地交互式体验概览其功能。如果您想自己动手试一试,可以按照 快速上手 中的介绍,一键在本地拉起一样的沙箱环境

Pigsty演示中内置了几个典型基于Pigsty开发的数据应用,用于演示此发型版的能力,例如:pglogcovidisddbengworktime等,此外,您还可以参考 Docker应用教程,使用Pigsty部署生产级的SaaS软件服务。

开发者(Dev)

开发者更关注的问题是:如何最快地下载安装接入数据库,请参考 快速上手

Pigsty针对易用性进行了大量优化,在全新CentOS 7.8节点上,无需互联网访问即可完成一键安装。

Pigsty提供了预置的 Vagrant & Terraform 模板,用于在本地x86笔记本/PC或云上一键拉起4台虚拟机,部署沙箱环境

用户也可以自行准备虚拟机,云虚拟机,或生产物理机器来进行标准部署流程。

Pigsty中的数据库,对外以服务的方式交付,用户通过PG连接串进行接入

部署完成后,开发者可以参考教程中的内容,熟悉基本管理操作,并了解访问数据库的方法,如果有问题

如果您想要深入了解Pigsty本身的设计与架构,可以参考概念一章中的主题:

Pigsty中的绝大多数操作都是一键傻瓜式的,而真正的精髓隐藏在配置中。

运维人员 (OPS)

运维人员更关注实施部署的细节,以下教程将介绍Pigsty安装部署的细节:

其中,教程升级Grafana后端数据库展示了一个完整的,具有代表性的案例:搭建并使用一套专供Grafana使用的Postgres数据库集群,将上述主题的内容付诸于实践。

管理员(DBA)

DBA通常更关注监控系统的用法与日常维护的具体方式。

监控系统教程

日常维护管理

专业用户

对于专业用户(深度定制,二次开发),Pigsty提供了丰富的配置项与定制接口。

几乎所有配置项都配置有合理的默认值,无需修改即可使用。专业用户可以参考配置项文档按需自行调整或按需定制

2 - Pigsty 快速上手

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty的安装分为三个步骤:部署准备修改配置执行剧本


Pigsty有两种典型使用模式:单机安装集群管理

  • 单机:在单个节点上安装Pigsty,将其作为开箱即用的Postgres数据库使用(开发测试)
  • 集群:在单机安装的基础上,部署、监控、管理其他节点与多种不同种类的数据库(运维管理)

单机安装

在一台节点上安装Pigsty时,Pigsty会在该节点上部署完整的基础设施运行时 与 一个单节点PostgreSQL数据库集群。对于个人用户、简单场景、小微企业来说,您可以直接开箱使用此数据库。

准备好新装机器(Linux x86_64 CentOS 7.8.2003)一台,配置管理用户ssh本机sudo访问,然后下载Pigsty

curl -SL https://github.com/Vonng/pigsty/releases/download/v1.5.1/pigsty.tgz | gzip -d | tar -xC ~  # 下载最新pigsty源代码
cd ~/pigsty; ./configure                               # 根据当前环境生成配置
./infra.yml                                            # 在当前节点上完成安装

如果您有可用的Macbook/PC/笔记本或云厂商账号,可使用沙箱部署在本机或云端自动创建虚拟机。

执行完毕后,您已经在当前节点完成了Pigsty的安装,上面带有完整的基础设施与一个开箱即用的PostgreSQL数据库实例,当前节点的5432对外提供数据库服务,80端口对外提供所有WebUI类服务。

80端口为所有Web图形界面服务的访问端点。尽管可以绕过Nginx直接使用端口访问各项服务,例如3000端口的Grafana,但强烈建议用户通过在本机配置静态DNS的方式,使用域名访问各项Web子服务。

访问 http://g.pigstyhttp://<primary_ip>:3000 即可浏览 Pigsty监控系统主页 (用户名: admin, 密码: pigsty)


集群管理

Pigsty还可以用作大规模生产环境的集群/数据库管理。您可以从单机安装Pigsty的节点(将作为集群的元节点,或称作元节点/Meta)上发起控制,将更多的 机器节点 纳入Pigsty的管理与监控中。 更重要的是,Pigsty还可以在这些节点上部署并管理各式各样的数据库集群与应用:创建高可用的PostgreSQL数据库集群;创建不同类型的Redis集簇;部署 Greenplum/MatrixDB 数据仓库,并获取关于节点、数据库与应用的实时洞察。

# 在四节点本地沙箱/云端演示环境中,可以使用以下命令在其他三台节点上部署数据库集群
./nodes.yml  -l pg-test      # 初始化集群pg-test包含的三台机器节点(配置节点+纳入监控)
./pgsql.yml  -l pg-test      # 初始化高可用PGSQL数据库集群pg-test
./redis.yml  -l redis-test   # 初始化Redis集群 redis-test
./pgsql-matrixdb.yml -l mx-*  # 初始化MatrixDB集群mx-mdw,mx-sdw

沙箱环境

Pigsty设计了一个标准的,4节点的演示教学环境,称为沙箱环境,您可以参考教程,使用Vagrant或Terraform快速在本机或公有云上拉起所需的四台虚拟机资源,并进行部署测试。跑通流程后稍作修改,便可用于生产环境部署

以默认的沙箱环境为例,假设您已经在10.10.10.10元节点上完成单机Pigsty的安装:

./infra.yml # 在沙箱环境的 10.10.10.10 meta 机器上,完成完整的单机Pigsty安装

主机初始化

现希望将三个节点:10.10.10.11, 10.10.10.12, 10.10.10.13 纳入管理,则可使用 nodes.yml 剧本:

./nodes.yml -l pg-test      # 初始化集群pg-test包含的三台机器节点(配置节点+纳入监控)

执行完毕后,这三台节点已经带有DCS服务,主机监控与日志收集。可以用于后续的数据库集群部署。详情请参考节点 配置剧本

PostgreSQL部署

使用 pgsql.yml 剧本,可以在这三台节点上初始化一主两从的高可用PostgreSQL数据库集群 pg-test

./pgsql.yml  -l pg-test      # 初始化高可用PGSQL数据库集群pg-test

部署完成后,即可从监控系统 中看到新创建的PostgreSQL集群。

详情请参考:PgSQL数据库集群 配置定制剧本

Redis部署

除了标准的PostgreSQL集群,您还可以部署各种其他类型的集群,甚至其他类型的数据库。

例如在沙箱中部署Redis,可以使用Redis数据库集群 配置剧本

./configure -m redis
./nodes.yml    # 配置所有用于安装Redis的节点
./redis.yml    # 在所有节点上按照配置声明Redis

MatrixDB部署

例如在沙箱中部署开源数据仓库MatrixDB(Greenplum7),可以使用以下命令:

./configure -m mxdb  # 使用沙箱环境MatrixDB配置文件模板
./download matrix    # 下载MatrixDB软件包并构建本地源
./infra.yml -e no_cmdb=true  # 如果您准备在meta节点上部署 MatrixDB Master,添加no_cmdb选项,否则正常安装即可。
./nodes.yml                  # 配置所有用于安装MatrixDB的节点
./pgsql-matrixdb.yml          # 在上述节点上安装MatrixDB

3 - Pigsty亮点特性

从 Pigsty v1.5.1 标签恢复的历史文档。

开箱即用的数据库发行版:用得上,用的好,用着简单还省钱!

自动驾驶高可用 / 极致入微可观测 / 简单易用门槛低 / 自由部署体验齐 / 应用广泛生态全 / 自主可控更省钱

PostgreSQL数据库发行版

RedHat for Linux! 开箱即用! 从无到有,让用户用得上

Pigsty将高可用集群部署,扩容缩容,主从复制,故障切换,流量代理,连接池,服务发现,访问控制,监控系统,告警系统,日志采集等生产级成熟解决方案封装为发行版。一次性解决在生产环境与各类场景下使用 世界上最先进的开源关系型数据库 —— PostgreSQL 时会遇到的各种问题,真正做到开箱即用。

智能监控管控运维解决方案

Auto-Pilot for Postgres! 自动驾驶! 从有到优,让用户用的爽

数据库即代码开发者工具箱

HashiCorp for Database! 简单易用!从优到易,让用户省心

  • Pigsty秉持 Infra as Data 的设计理念,用户只需用几行声明式的配置文件描述自己想要的数据库,即可使用幂等剧本,一键将其创建。Just like Kubernetes!

  • Pigsty向开发者交付简单易用的数据库工具箱:一键下载安装,自动配置;一键部署各类开源数据库,一键迁移备份、扩容缩容,极大拉低数据库管理使用门槛,量产DBA!

  • Pigsty能够简化数据库部署与交付、解决环境配置统一的难题:无论是上千套数据库几万核的生产环境,还是本地1C1G的笔记本均可完整运行;基于Vagrant的本地沙箱与基于Terraform的多云部署,云上云下,一键拉起!

开源云数据库PaaS替代方案

Alternative for RDS! 安全可控降本增效!从易到廉,给用户省钱

  • Pigsty相比云厂商RDS,在拥有更低使用⻔槛与更丰富功能的前提下,可节约 50% - 80% 的数据库软硬件成本,初级研发人员即可自主管理成百上千套数据库。

  • Pigsty采用模块化设计,可自由组合,按需定制扩展。可在生产环境部署管理各种数据库,或仅仅将其当成主机监控;可用于开发数据库可视化Demo、或支撑各类SaaS应用

  • 开源免费的生产级数据库解决方案,用于补全云原生生态缺失的最后一块拼图。稳定可靠,经过长时间大规模生产部署验证,提供可选的专业技术支持服务。

自动驾驶高可用

故障自愈,高枕无忧

以PostgreSQL为例,Pigsty创建的数据库集群是分布式高可用数据库集群。只要集群中有任意实例存活,集群就可以对外提供完整的读写服务只读服务

Pigsty的高可用架构久经生产环境考验,Pigsty使用 Patroni + Consul 进行故障检测、Fencing与自动故障切换,通过HAProxy、VIP或DNS实现流量的自动切换,以极低的复杂度代价实现了完整的高可用方案,让主从架构的数据库能用出了布式数据库般的体验。

数据库集群可以自动进行故障检测与主从切换,普通故障能在几秒到几十秒内自愈:主库故障RTO < 1min,只读流量几乎无影响,同步集群 RPO = 0 不丢数据。

数据库集群中的每个数据库实例在使用上都是幂等的,任意实例都可以通过内建负载均衡组件HAProxy提供完整的读写服务。任何一个或多个Haproxy实例都可以作为集群的负载均衡器,并通过健康检查进行流量分发,对外屏蔽集群成员的区别。用户可以通过配置灵活定义服务,并通过多种可选方式接入

极致入微可观测

You can’t manage you don’t measure.

监控系统提供了对系统状态的度量,是运维管理工作的基石。【DEMO

Pigsty带有一个针对大规模数据库集群管理而设计的专业级监控系统,基于业内最佳实践,采用Prometheus、Alertmanager、Grafana、Loki作为监控基础设施。开源开放,定制便利,可复用,可移植,没有厂商锁定。

Pigsty在PostgreSQL监控上做到无可比拟,通过30+监控面板与上千仪表盘综合呈现约1200+类指标,覆盖从全局大盘到单个对象的详细信息,从数据库目录到节点日志全部一览无遗。与同类产品相比在指标的覆盖率与监控面板丰富程度上一骑绝尘,为专业用户提供无可替代的价值。详略得当的层次设计,为业余用户带来直观便捷的管理体验。

Pigsty的监控系统可用于监控原生部署的各类数据库实例:PGSQL,REDIS,GPSQL等,也可以独立使用,监控已有的数据库实例或远端云厂商RDS,或仅仅作为主机监控使用,它还可以用作数据可视化作品的展示平台。

简单易用门槛低

HashiCorp for Database! Database as Code, Infra as Data!

Pigsty采纳 Database as Data 的设计哲学,使用类似 Kubernetes 的声明式配置,通过大量可选的配置选项对数据库与运行环境进行描述,并通过幂等的预置剧本自动创建所需的数据库集群,提供私有云般的使用体验。

用户只需要通过配置文件或图形界面描述“自己想要什么样的数据库”,而无需关心Pigsty如何去创建或修改它。Pigsty会根据用户的配置文件清单,在几分钟内从裸机节点上创造出所需的数据库集群。

例如,在三台机器上创建一主两从的数据库集群pg-test,只需要几行配置与一行命令pgsql.yml -l pg-test,即可创建出如下一节所介绍的高可用数据库集群。

使用更多参数对数据库集群进行定制
#----------------------------------#
# cluster: pg-meta (on meta node)  #
#----------------------------------#
# pg-meta is the default SINGLE-NODE pgsql cluster deployed on meta node (10.10.10.10)
# if you have multiple n meta nodes, consider deploying pg-meta as n-node cluster too

pg-meta:                                # required, ansible group name , pgsql cluster name. should be unique among environment
  hosts:                                # `<cluster>.hosts` holds instances definition of this cluster
    10.10.10.10:                        # INSTANCE-LEVEL CONFIG: ip address is the key. values are instance level config entries (dict)
      pg_seq: 1                         # required, unique identity parameter (+integer) among pg_cluster
      pg_role: primary                  # required, pg_role is mandatory identity parameter, primary|replica|offline|delayed
      pg_offline_query: true            # instance with `pg_offline_query: true` will take offline traffic (saga, etl,...)
      # some variables can be overwritten on instance level. e.g: pg_upstream, pg_weight, etc...
    #---------------
    # mandatory                         # all configuration above (`ip`, `pg_seq`, `pg_role`) and `pg_cluster` are mandatory
    #---------------
  vars:                                 # `<cluster>.vars` holds CLUSTER LEVEL CONFIG of this pgsql cluster
    pg_cluster: pg-meta                 # required, pgsql cluster name, unique among cluster, used as namespace of cluster resources

    #---------------
    # optional                          # all configuration below are OPTIONAL for a pgsql cluster (Overwrite global default)
    #---------------
    pg_version: 14                      # pgsql version to be installed (use global version if missing)
    node_tune: tiny                     # node optimization profile: {oltp|olap|crit|tiny}, use tiny for vm sandbox
    pg_conf: tiny.yml                   # pgsql template:  {oltp|olap|crit|tiny}, use tiny for sandbox
    patroni_mode: default               # entering patroni pause mode after bootstrap  {default|pause|remove}
    patroni_watchdog_mode: off          # disable patroni watchdog on meta node        {off|require|automatic}
    pg_lc_ctype: en_US.UTF8             # use en_US.UTF8 locale for i18n char support  (required by `pg_trgm`)

    #---------------
    # biz databases                     # Defining Business Databases (Optional)
    #---------------
    pg_databases:                       # define business databases on this cluster, array of database definition
      # define the default `meta` database
      - name: meta                      # required, `name` is the only mandatory field of a database definition
        baseline: cmdb.sql              # optional, database sql baseline path, (relative path among ansible search path, e.g files/)
        # owner: postgres               # optional, database owner, postgres by default
        # template: template1           # optional, which template to use, template1 by default
        # encoding: UTF8                # optional, database encoding, UTF8 by default. (MUST same as template database)
        # locale: C                     # optional, database locale, C by default.  (MUST same as template database)
        # lc_collate: C                 # optional, database collate, C by default. (MUST same as template database)
        # lc_ctype: C                   # optional, database ctype, C by default.   (MUST same as template database)
        # tablespace: pg_default        # optional, default tablespace, 'pg_default' by default.
        # allowconn: true               # optional, allow connection, true by default. false will disable connect at all
        # revokeconn: false             # optional, revoke public connection privilege. false by default. (leave connect with grant option to owner)
        # pgbouncer: true               # optional, add this database to pgbouncer database list? true by default
        comment: pigsty meta database   # optional, comment string for this database
        connlimit: -1                   # optional, database connection limit, default -1 disable limit
        schemas: [pigsty]               # optional, additional schemas to be created, array of schema names
        extensions:                     # optional, additional extensions to be installed: array of schema definition `{name,schema}`
          - { name: adminpack, schema: pg_catalog }    # install adminpack to pg_catalog
          - { name: postgis, schema: public }          # if schema is omitted, extension will be installed according to search_path.
          - { name: timescaledb }                      # some extensions are not relocatable, you can just omit the schema part

      # define an additional database named grafana & prometheus (optional)
      # - { name: grafana,    owner: dbuser_grafana    , revokeconn: true , comment: grafana    primary database }
      # - { name: prometheus, owner: dbuser_prometheus , revokeconn: true , comment: prometheus primary database , extensions: [{ name: timescaledb }]}

    #---------------
    # biz users                         # Defining Business Users (Optional)
    #---------------
    pg_users:                           # define business users/roles on this cluster, array of user definition
      # define admin user for meta database (This user are used for pigsty app deployment by default)
      - name: dbuser_meta               # required, `name` is the only mandatory field of a user definition
        password: md5d3d10d8cad606308bdb180148bf663e1  # md5 salted password of 'DBUser.Meta'
        # optional, plain text and md5 password are both acceptable (prefixed with `md5`)
        login: true                     # optional, can login, true by default  (new biz ROLE should be false)
        superuser: false                # optional, is superuser? false by default
        createdb: false                 # optional, can create database? false by default
        createrole: false               # optional, can create role? false by default
        inherit: true                   # optional, can this role use inherited privileges? true by default
        replication: false              # optional, can this role do replication? false by default
        bypassrls: false                # optional, can this role bypass row level security? false by default
        pgbouncer: true                 # optional, add this user to pgbouncer user-list? false by default (production user should be true explicitly)
        connlimit: -1                   # optional, user connection limit, default -1 disable limit
        expire_in: 3650                 # optional, now + n days when this role is expired (OVERWRITE expire_at)
        expire_at: '2030-12-31'         # optional, YYYY-MM-DD 'timestamp' when this role is expired  (OVERWRITTEN by expire_in)
        comment: pigsty admin user      # optional, comment string for this user/role
        roles: [dbrole_admin]           # optional, belonged roles. default roles are: dbrole_{admin,readonly,readwrite,offline}
        parameters: {}                  # optional, role level parameters with `ALTER ROLE SET`
        # search_path: public         # key value config parameters according to postgresql documentation (e.g: use pigsty as default search_path)
      - {name: dbuser_view , password: DBUser.Viewer  ,pgbouncer: true ,roles: [dbrole_readonly], comment: read-only viewer for meta database}

      # define additional business users for prometheus & grafana (optional)
      - {name: dbuser_grafana    , password: DBUser.Grafana    ,pgbouncer: true ,roles: [dbrole_admin], comment: admin user for grafana database }
      - {name: dbuser_prometheus , password: DBUser.Prometheus ,pgbouncer: true ,roles: [dbrole_admin], comment: admin user for prometheus database , createrole: true }

    #---------------
    # hba rules                                         # Defining extra HBA rules on this cluster (Optional)
    #---------------
    pg_hba_rules_extra:                                 # Extra HBA rules to be installed on this cluster
      - title: reject grafana non-local access          # required, rule title (used as hba description & comment string)
        role: common                                    # required, which roles will be applied? ('common' applies to all roles)
        rules:                                          # required, rule content: array of hba string
          - local   grafana         dbuser_grafana                          md5
          - host    grafana         dbuser_grafana      127.0.0.1/32        md5
          - host    grafana         dbuser_grafana      10.10.10.10/32      md5

    vip_mode: l2                        # setup a level-2 vip for cluster pg-meta
    vip_address: 10.10.10.2             # virtual ip address that binds to primary instance of cluster pg-meta
    vip_cidrmask: 8                     # cidr network mask length
    vip_interface: eth1                 # interface to add virtual ip
Pigsty 1.3+:定制不同类型的Redis集群
#----------------------------------#
# redis sentinel example           #
#----------------------------------#
redis-meta:
  hosts:
    10.10.10.10:
      redis_node: 1
      redis_instances:  { 6001 : {} ,6002 : {} , 6003 : {} }
  vars:
    redis_cluster: redis-meta
    redis_mode: sentinel
    redis_max_memory: 128MB

#----------------------------------#
# redis cluster example            #
#----------------------------------#
redis-test:
  hosts:
    10.10.10.11:
      redis_node: 1
      redis_instances: { 6501 : {} ,6502 : {} ,6503 : {} ,6504 : {} ,6505 : {} ,6506 : {} }
    10.10.10.12:
      redis_node: 2
      redis_instances: { 6501 : {} ,6502 : {} ,6503 : {} ,6504 : {} ,6505 : {} ,6506 : {} }
  vars:
    redis_cluster: redis-test           # name of this redis 'cluster'
    redis_mode: cluster                 # standalone,cluster,sentinel
    redis_max_memory: 64MB              # max memory used by each redis instance
    redis_mem_policy: allkeys-lru       # memory eviction policy

#----------------------------------#
# redis standalone example         #
#----------------------------------#
redis-common:
  hosts:
    10.10.10.13:
      redis_node: 1
      redis_instances:
        6501: {}
        6502: { replica_of: '10.10.10.13 6501' }
        6503: { replica_of: '10.10.10.13 6501' }
  vars:
    redis_cluster: redis-common         # name of this redis 'cluster'
    redis_mode: standalone              # standalone,cluster,sentinel
    redis_max_memory: 64MB              # max memory used by each redis instance
Pigsty 1.4+:安装并监控一套MatrixDB集群
#----------------------------------#
# cluster: mx-mdw (gp master)
#----------------------------------#
mx-mdw:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary , nodename: mx-mdw-1 }
  vars:
    gp_role: master          # this cluster is used as greenplum master
    pg_shard: mx             # pgsql sharding name & gpsql deployment name
    pg_cluster: mx-mdw       # this master cluster name is mx-mdw
    pg_databases:
      - { name: matrixmgr , extensions: [ { name: matrixdbts } ] }
      - { name: meta }
    pg_users:
      - { name: meta , password: DBUser.Meta , pgbouncer: true }
      - { name: dbuser_monitor , password: DBUser.Monitor , roles: [ dbrole_readonly ], superuser: true }

    pgbouncer_enabled: true                # enable pgbouncer for greenplum master
    pgbouncer_exporter_enabled: false      # enable pgbouncer_exporter for greenplum master
    pg_exporter_params: 'host=127.0.0.1&sslmode=disable'  # use 127.0.0.1 as local monitor host

#----------------------------------#
# cluster: mx-sdw (gp master)
#----------------------------------#
mx-sdw:
  hosts:
    10.10.10.11:
      nodename: mx-sdw-1        # greenplum segment node
      pg_instances:             # greenplum segment instances
        6000: { pg_cluster: mx-seg1, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633 }
        6001: { pg_cluster: mx-seg2, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634 }
    10.10.10.12:
      nodename: mx-sdw-2
      pg_instances:
        6000: { pg_cluster: mx-seg2, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633  }
        6001: { pg_cluster: mx-seg3, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634  }
    10.10.10.13:
      nodename: mx-sdw-3
      pg_instances:
        6000: { pg_cluster: mx-seg3, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633 }
        6001: { pg_cluster: mx-seg1, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634 }
  vars:
    gp_role: segment               # these are nodes for gp segments
    pg_shard: mx                   # pgsql sharding name & gpsql deployment name
    pg_cluster: mx-sdw             # these segment clusters name is mx-sdw
    pg_preflight_skip: true        # skip preflight check (since pg_seq & pg_role & pg_cluster not exists)
    pg_exporter_config: pg_exporter_basic.yml                             # use basic config to avoid segment server crash
    pg_exporter_params: 'options=-c%20gp_role%3Dutility&sslmode=disable'  # use gp_role = utility to connect to segments

自由部署体验齐

无论是几万核的生产环境,还是1核2G的本地虚拟机,云上云下,用哪个云,体验如一!

无论是生产环境、预发环境、还是本地开发测试环境,对Pigsty来说,只有配置文件的内容差异。无论在哪里部署,都能带来统一的使用体验。

Pigsty可以利用Vagrant与Virtualbox,在您自己的笔记本电脑上拉起安装所需的虚拟机沙箱环境,或通过Terraform,自动向云服务商申请ECS/VPC资源,一键创建,一键销毁,自动获取多云部署的能力。

沙箱环境中的虚拟机具有固定的资源名称与IP地址,非常适于软件开发测试、实验演示。 沙箱配置默认为2核4GB的单节点,IP地址 10.10.10.10,部署有一个名为pg-meta-1的单机数据库实例。 此外还有四节点版本的完整版沙箱,带有额外三个数据库节点,可用于充分展现Pigsty高可用架构与监控系统的能力。

沙箱所需机器规格

系统要求

  • Linux内核,x86_64处理器架构
  • 使用 CentOS 7 / RedHat 7 / Oracle Linux 7 或其他等效操作系统发行版
  • 强烈推荐使用 CentOS 7.8.2003 x86_64 ,这是经过长时间生产环境的测试的操作系统环境

单节点基本规格

  • 最低规格:1核,1GB (容易OOM,建议内存至少2GB)
  • 推荐规格:2核,4GB (沙箱默认配置)
  • 将部署一个单机PostgreSQL实例pg-meta-1
  • 在沙箱中,该节点的IP固定为10.10.10.10

四节点基本规格

  • 元节点要求同单节点所述
  • 部署一个额外的三节点PostgreSQL数据库集群pg-test
  • 普通数据库节点,最低规格:1核,1GB,建议使用2GB内存。
  • 三节点的IP地址固定为:10.10.10.11, 10.10.10.12, 10.10.10.13

应用广泛生态全

一键拉起生产级SaaS应用,数据分析快速上手,低代码开发可视化大屏

SaaS软件应用

Pigsty在元节点上默认安装了Docker,您可以一键拉起各类SaaS应用:开源私有代码托管平台Gitlab,开源论坛Discourse,开源社交网络Mastodon,开源ERP软件Odoo,以及用友、金蝶等软件。 您可以使用Docker拉起无状态的部分,修改其数据库连接串使用外部数据库,获取丝滑的云原生管理体验与生产级的数据持久性。详情请参考 教程:Docker应用

数据分析与可视化应用

Pigsty既是开箱即用的PostgreSQL发行版,也可以用做数据分析环境,或制作低代码的可视化应用。您可以直接从SQL数据处理到Echarts绘图一步到位,也可以使用更精细的工作流:例如使用PG作为主数据库,存储数据并用SQL实现业务逻辑;使用内置的PostgREST自动生成后端API,使用内置的JupyterLab用Python进行复杂数据分析,并使用Echarts进行数据可视化,并通过Grafana获得交互能力。

Pigsty自带有几个应用样例作为参考:

  • 分析PG CSV日志样本pglog
  • 新冠疫情数据可视化 covid
  • 全球地表气象站数据查询 isd
  • 数据库流行度排行趋势 dbeng
  • 查询大厂工作上下班安排 worktime

自主可控更省钱

Pigsty可将数据库的综合持有成本降低 50% ~ 80% ,并让数据真正掌控在用户自己的手中!

公有云数据库/RDS,是一种所谓"开箱即用"的解决方案,但它交出的答卷离让用户满意还有很长路要走:相比自建数据库成本昂贵,许多需要超级用户权限的功能被阉割,愚笨的UI与大锅饭式的功能,但在所有问题中,最重要的问题莫过于云软件的安全成本问题:

自主可控

  • 运行在你自己的电脑上的软件,即使软件供应商倒闭也可以继续运行下去。但如果提供云软件的公司/部门倒闭或决定停止支持,这些软件就没法工作了,而你用这些软件创造的数据就被锁死了。因为数据只存储在云端,而不是你自己服务器的磁盘上,而您能指望的补偿通常只有鸡肋的代金券。
  • 无法定制或扩展的问题在云数据库中进一步加剧。云数据库通常不向用户提供数据库超级用户,这将锁死一大批高级功能,以及自行加装扩展功能的能力。与此相对应,‘流复制’,‘高可用’这些本该是数据库标配的东西往往作为增值项向用户出售。
  • 云服务可能在没有警告和追索手段的情况下突然暂停你的账户。您可能在完全无辜的情况下,被自动化系统判定为违反服务条款:未备案使用80与53端口,账户被爆破并用于发送恶意软件或钓鱼邮件,触发违背服务条款。或因为一些政治原因被云厂商锤翻,例如Parler。
  • 国内不用SaaS坚持自研或开源自建的习惯,是被恶劣的生态产业环境真金白银教育出来的。在信息时代把核心资产 — 数据放在别人的硬盘上,就像把金条放在超市存包柜中一样。您无法避免,无法监督、甚至无法意识到利益冲突的云厂商,或者仅仅是怀有恶意或好奇的运维与DBA人员偷窥盗窃您的珍贵数据。

Pigsty则不然,它可以部署在任意地方,包括您自己的服务器上。它开源免费,无需License,无需互联网访问,不收集任何用户数据。您可以在自己的服务器运行它直到海枯石烂。

降本增效

云数据库的成本则是另一个问题:省钱是用户的刚需。公有云厂商的RDS相比传统商业数据库也许有优势,但在自建开源数据库前仍然是暴利天价。据统计,RDS的综合持有成本比起基于云服务器自建要高达 2~3倍,比起IDC托管自建更是高出 5~10倍

Pigsty相比使用云数据库有显著成本优势。例如,您可以使用云数据库一半的开销购买同规格的云服务器,并使用Pigsty自行部署数据库。在这种情况下,您既可以享受公有云的绝大部份管理之快捷便利(IaaS),又可以立竿见影节省一半以上的开销。

更重要的是,Pigsty能显著提高用户效能:它允许一两个高级DBA将所有琐碎杂务交由软件处理,轻松管理几百套数据库集群;也可以让一个初级研发人员,经过简单的学习培训后,即可迅速达到一个高级DBA的廉价七成正确水平。

Pigsty开源免费,在提供类似甚至超过云厂商RDS使用体验的前提下,可将数据库的综合持有成本降低 50% ~ 80% ,并让数据真正掌控在用户自己的手中!

4 - FAQ: 常见问题

从 Pigsty v1.5.1 标签恢复的历史文档。

这里列出了Pigsty用户常遇到的问题,如果您遇到了难以解决的问题,可以联系我们,或提交Issue


准备

您需要确保机器节点硬件规格与操作系统符合安装要求,详情参见:准备工作

机器节点要求

警告

最小规格 1C/2GB,节点处理器为x86_64架构,目前不支持 ARM 架构。

安装Pigsty需要至少一个机器节点:规格至少为1核2GB,1核1G也可安装但容易OOM。

如果您希望部署自我管理的高可用PostgreSQL数据库集群,建议最少使用3个规格相同的节点。

操作系统要求

警告

Pigsty强烈建议使用CentOS 7.8操作系统,可以节省大量无意义的DEBUG时间。

这是一个经过充分验证的操作系统版本,Pigsty开发、测试、打包都默认基于CentOS 7.8。CentOS 7.6也经过充分的验证。其他CentOS 7.x及其等效版本RHEL7 , Oracle Linux 7理论上没有问题,但并未进行测试与验证。

软件版本策略

警告

请使用特定版本的Release,不要直接使用Github Master分支,该开发分支有可能处于不一致的状态。

Pigsty遵循语义版本号规则: <major>.<minor>.<release>。大版本更新意味着重大的根本性架构调整,次版本号增长意味着一次显著更新,通常意味着软件包版本更新,API的微小变动,以及其它增量功能变更,通常会包含一份升级注意事项说明。Release版本号通常用于Bug修复与文档更新,Release版本号增长不会变更软件包版本(即 v1.0.1 与 v1.0.0对应的 pkg.tgz是相同的)。

Pigsty计划会每1-3个月发布一个Minor Release,每1-2年发布一个Major Release。

沙箱虚拟机置备

警告

使用Vagrant一键拉起基于本地虚拟机的本地沙箱,或使用Terraform在公有云厂商创建云端沙箱

部署Pigsty需要用到物理机/虚拟机节点,您可以直接自备物理机/虚拟机用于部署。但IaaS资源置备仍然是一件麻烦事,所以Pigsty提供了基于Vagrant与HashiCorp的IaaS层资源模板,您可以一键获取部署Pigsty4节点沙箱环境所需的虚拟机资源。

沙箱环境是一个配置规格、对象标识符、IP地址与默认数据库全部预先确定的环境,由一个元节点与三个普通节点组成,无论是本地版还是云端版都保持一致,用于开发/测试/演示/说明。使用以下命令拉起Vagrant本地沙箱:

make deps    # 安装homebrew,并通过homebrew安装vagrant与virtualbox(需重启)
make dns     # 向本机/etc/hosts写入静态域名 (需sudo输入密码)
make start   # 使用Vagrant拉起单个meta节点  (start4则为4个节点)

下载

Pigsty源码包是安装Pigsty时的必选项。离线软件包是可选的推荐项,情请参考 软件下载

如何下载Pigsty源码包

警告

curl -SL https://github.com/Vonng/pigsty/releases/download/v1.5.1/pigsty.tgz | gzip -d | tar -xC ~

执行以上命令,可自动下载最新稳定版本 pigsty.tgz ,并解压至 ~/pigsty目录。您也可以从下列位置手工下载特定版本的Pigsty源码包,如果您需要在无互联网的环境中安装,可以提前下载并通过 scp/sftp 等方式上传至生产服务器。

https://github.com/Vonng/pigsty/releases/download/v1.5.1/pigsty.tgz   # Github Release
http://download.pigsty.cc/v1.5.1/pigsty.tgz                           # 中国大陆用加速CDN
https://pan.baidu.com/s/1DZIa9X2jAxx69Zj-aRHoaw?pwd=8su9              # 百度云网盘下载

下载其他Pigsty软件包

警告

./download pigsty pkg app matrix

Pigsty源码包内提供了一个download脚本,用于下载Pigsty相关资源:Pigsty源代码包本身:pigsty.tgz / 离线软件安装包:pkg.tgz / MatrixDB/Greenplum软件包:matrix.tgz / 一些SaaS应用镜像与可视化应用案例:app.tgz。其中源码包为必选项,离线软件包 pkg.tgz为建议项,使用 ./download pkg 会自动下载并提取离线软件包。

# download to /tmp/*.tgz
./download pigsty.tgz   # download pigsty source tarball
./download pkg.tgz      # download pigsty offline pkgs
./download app.tgz      # download extra pigsty apps
./download matrix.tgz   # download matrixdb packages
# download and extract
./download pigsty       # download and extract pigsty to ~/pigsty
./download pkg          # download and extract pkg    to /www/pigsty
./download app          # download and extract app    to ~/app
./download matrix       # download and extract matrix to /www/matrix

如何下载Pigsty离线软件包

警告

./download pkg 或在配置过程中根据提示自动下载。

Pigsty的离线软件包 pkg.tgz 打包了所有所需的软件依赖。在执行Pigsty安装时如果使用离线软件包,可以跳过从互联网下载软件的步骤。

./configure 过程中,如果离线安装包/tmp/pkg.tgz不存在,向导会提示用户下载,回答“Y”即可自动从Github或CDN下载;回答“N”则会跳过下载。您也可以从下列位置手工下载离线软件包,并放置于 /tmp/pkg.tgz,则安装时会自动使用。

curl https://github.com/Vonng/pigsty/releases/download/v1.5.1/pkg.tgz -o /tmp/pkg.tgz
curl http://download.pigsty.cc/v1.5.1/pkg.tgz -o /tmp/pkg.tgz         # China CDN
https://pan.baidu.com/s/1DZIa9X2jAxx69Zj-aRHoaw?pwd=8su9              # Baidu Yun

离线软件包出现RPM冲突

警告

不用离线包直接从上游下载,或仅删除问题包并从可用源补缺

Pigsty离线软件包基于CentOS 7.8操作系统制作,如果您使用的不是此精确OS Release,或者并未使用全新安装操作系统的节点进行安装,有小概率会出现RPM包依赖问题。

如果只是个别RPM依赖问题,您可以在 /www/pigsty 中删除相关RPM包,并删除标记文件 /www/pigsty/repo_complete。而后,执行常规的安装流程时,Pigsty会从 repo_upsteram 指定的上游或其他本地可用源下载缺失的依赖RPM包。如果您没有可用的互联网访问或本地源,请使用相同OS环境的有网节点制作离线软件包 后,拷贝至生产环境使用。


配置

Pigsty的安装、配置、部署都是一键傻瓜式,唯有配置是Pigsty的核心灵魂。

配置过程做了些什么

警告

检测环境,生成配置,启用离线软件包(可选),安装基本工具Ansible。

当您下载完 Pigsty 源码包,解压并进入其中后,需要先执行 ./configure 完成环境配置过程

Pigsty会检测当前环境是否满足安装要求,并根据当前机器环境生成推荐配置文件 pigsty.yml。在files/conf/目录中,有一系列名为pigsty-*.yml的配置文件,可以作为不同场景下的配置参考模板,通过-m指定。

Configure过程会安装Ansible,一般节点的默认源都带有此软件包,如果离线安装包存在,则会从离线安装包内安装Ansible。

Pigsty的配置文件在哪

警告

源码根目录下 pigsty.yml 是默认的、唯一的配置源。

Pigsty有且仅有一个配置文件pigsty.yml ,位于源代码根目录下,它描述了整个环境的状态。

在同一目录的ansible.cfg中:inventory = pigsty.yml 指定了此文件为默认配置文件,您也可以在执行剧本时,使用-i参数,指定使用其他位置的配置文件。此外,如果您使用CMDB作为配置源,那么请在CMDB中修改配置。

配置文件中的占位IP地址

警告

Pigsty使用10.10.10.10作为当前节点IP地址占位符,将在配置过程中被替换为当前节点的首要IP地址。

当配置过程检测到当前机器上有多块网卡与多个IP地址时,配置向导会提示您输入主要使用的IP地址, 即用户从内部网络访问该节点时使用的IP地址,注意请不要使用公网IP地址。

该IP地址,将用于替换配置文件模板中的 10.10.10.10

用户需要修改什么配置吗?

警告

单机部署通常啥配置也不用改,会自动调整,绝大多数参数都有合适的默认值。

Pigsty提供了220+配置参数,您可以定制整个基础设施/平台/数据库的方方面面。通常在单机安装的情况下,不需要对配置文件进行任何调整即可直接使用。但仍然有个别参数,如果有需要,可以提前调整:

  • 访问Web服务组件时使用的域名:nginx_upstream (一些服务只能使用域名通过Nginx代理访问)
  • Pigsty假设存在一个/data目录用于盛放所有数据,如果您的数据盘挂载点与此不同,可以调整这些路径。

安装

安装时执行了什么?

警告

执行make install安装时,会调用ansible-playbook执行预置剧本 infra.yml,在元节点上完成安装。

configure过程默认会生成配置文件,并在其中将当前节点标记为 元节点。而make install则会针对元节点执行Pigsty元节点初始化剧本 infra.yml ,部署基础设施组件,并将元节点作为一个普通的节点进行初始化,并在其上部署一个单例PostgreSQL数据库作为CMDB。

下载RPM包速度太慢

警告

如果直接从上游下不动,最好还是使用离线软件包,或者配置代理服务器,和可用本地镜像源。

Pigsty已经尽可能使用国内yum镜像进行下载,然而少量软件包仍然受到GFW的影响,导致下载缓慢,例如直接从Github下载的相关软件。有以下解决方案:

  1. Pigsty提供离线软件包,预先打包了所有软件及其依赖,可以跳过从互联网下载软件的步骤。

  2. 通过 proxy_env 指定代理服务器,通过代理服务器下载。

  3. 通过 repo_upsteram 使用其他国内可用的镜像源。

远端节点无法通过标准SSH命令访问

警告

通过主机实例级 ansible连接参数,指定不一样的端口。

如果您的目标机器藏在SSH跳板机之后,或者进行了某些定制化修改无法通过ssh ip的方式直接访问,则可以考虑使用 Ansible连接参数。您可以通过 ansible_port指定其他SSH端口,或 ansible_host 指定SSH Alias。

pg-test:
  vars: { pg_cluster: pg-test }
  hosts:
    10.10.10.11: {pg_seq: 1, pg_role: primary, ansible_host: node-1 }
    10.10.10.12: {pg_seq: 2, pg_role: replica, ansible_port: 22223, ansible_user: admin }
    10.10.10.13: {pg_seq: 3, pg_role: offline, ansible_port: 22224 }

远端节点SSH与SUDO需要密码

警告

使用 -k-K参数,在提示符时输入密码,参考管理用户置备

执行部署与变更时,您所使用的管理用户必须拥有所有节点的sshsudo权限。免密码并非必需,您总是可以在执行剧本时通过-k|-K参数传入ssh与sudo的密码,甚至通过 -eansible_host=<another_user> 使用其他用户来执行剧本。但Pigsty强烈建议为管理用户配置SSH免密码登陆与免密码sudo


沙箱

Pigsty沙箱提供了标准的开发/测试/演示环境,可以在本地用Vagrant或云端用Terraform快速拉起。

Vagrant沙箱首次启动太慢

警告

第一次使用Vagrant拉起某个操作系统镜像,会下载对应BOX。

Pigsty沙箱默认使用CentOS 7虚拟机,Vagrant首次启动虚拟机时,会下载CentOS/7的ISO镜像Box,尺寸不小。

使用代理可能会提高下载速度,下载CentOS7 Box只需要在首次启动沙箱时进行,后续重建沙箱时会直接复用。

用户也可以选择自行下载CentOS 7 安装ISO镜像手工创建所需虚拟机。

阿里云CentOS 7.8 RPM报错

警告

阿里云CentOS 7.8 服务器默认安装了DNS缓存服务 nscd,移除即可。

阿里云的CentOS 7.8 服务器镜像默认安装了 nscd ,锁死了 glibc 版本,会导致安装时出现RPM依赖错误。

"Error: Package: nscd-2.17-307.el7.1.x86_64 (@base)"

在所有机器上执行 yum remove -y nscd 即可解决此问题,使用Ansible可以批量执行:

ansible all -b -a 'yum remove -y nscd'

虚拟机时间失去同步

警告

sudo ntpdate -u pool.ntp.org 或使用 make sync4

Virtualbox虚拟机关机后虚拟机内时间可能与宿主机不一致。可以尝试使用以下命令:make sync,强制执行NTP时间同步。

sudo ntpdate -u pool.ntp.org
make sync4 # 使用NTP POOL时间同步快捷方式
make ss    # 使用阿里云NTP服务器同步

即可解决长时间休眠或关机重启后监控系统没有数据的问题。此外,重启虚拟机也可以强行重置时间,且无需互联网访问:make dw4; make up4

为什么不使用容器盛放数据库

警告

使用Docker/Kubernetes盛放数据库仍然不成熟

虽然Docker对于提高环境兼容性有非常好的效果,然而数据库并不属于容器使用的最佳场景。此外Docker与Kubernetes本身也有使用门槛。为了满足“降低门槛”的主旨,Pigsty采用裸机部署。

Pigsty在设计之初就考虑到容器化云化的需求,这体现在其配置定义的声明式实现中。并不需要太多修改就可以迁移改造为云原生解决方案。当时机成熟时,会使用Kubernetes Operator的方式进行重构。


监控

监控系统的性能存储开销有多大

警告

监控查询开销微不足道,百毫秒量级,10秒一次,普通实例约产生2k ~ 5k时间序列。

一个典型的生产实例,产出5千个时间序列,一次抓取大约耗时 200ms 左右;相比抓取周期15s几乎微不足道。

存储取决于用户数据库的复杂程度(workload)。作为参考:200个生产数据库实例1天产生的监控数据量约为16GB。Pigsty默认保留两周的监控数据,可以通过参数调整。

是否可以监控已有的PG实例?

警告

Pigsty不承诺对外部实例的监控质量:Pigsty创建的PostgreSQL在绝大多数情况下表现显著优于土法手造实例

对于非Pigsty供给方案创建的外部数据库,可以使用仅监控模式部署,详情请参考文档。

如果该实例可以被Pigsty管理,您可以考虑采用与标准部署相同的方式,在目标节点上部署 node_exporter,pg_exporter, promtail 等组件。

如果您只有访问该数据库的URL(例如RDS云数据库实例),则可以使用 精简监控部署 模式,在该模式下,Pigsty会通过部署于元节点本地的 pg_exporter 实例监控远程PG实例。

监控已有PG实例需要怎么做?

警告

监控对象被移除后为什么还能看到

警告

使用 pgsql-remove.yml 剧本移除监控目标


INFRA

基础设施包括哪些组件?

警告

Pigsty提供了一套完整的PaaS环境,详情请参考系统架构:基础设施

Ansible/Pigsty CLI用于发起管理与部署;元节点上的PostgreSQL作为CMDB;Consul Server作为元数据库用于高可用;NTPD与DNS提供时间与域名解析基础服务;Docker作为无状态应用部署底座;Prometheus用于监控指标时序数据收集,Loki用于日志收集;Grafana用于监控/可视化展示,AlertManager用于汇总告警;YumRepo用于提供本地软件源;Nginx对外收拢所有WebUI类服务访问入口。

是否可以使用已有的DCS集群

警告

Pigsty默认会在元节点上提供DCS服务,但更推荐使用外部的多个节点组成的高可用DCS服务集群。

dcs_servers中填入对应的集群,即可使用外部的DCS集群。

DCS Server与元节点并没有对应关系:在默认情况下,Pigsty会在元节点上安装一个单节点的Consul Server。如果在执行节点初始化时当前节点的IP地址在 dcs_servers 中被定义,则该节点会配置DCS Server服务。DCS用于其他数据库实例的高可用选主。在生产环境中,建议使用3~5个节点的专用外部DCS集群。


NODES

Abort because consul instance already exists

警告

Pigsty提供了DCS误删保护机制,配置dcs_clean = true 可以硬干。

当目标节点的Consul服务已经存在时,nodes.yml 会根据 dcs_clean 参数采取行动,如果为真,那么在初始化过程中现有的Consul会被抹除。

Pigsty也提供了相应的保护机制 参数: dcs_safeguard

您可以在配置文件 pigsty.yml 中修改这些参数,也可以直接在执行剧本时,通过额外参数机制指定:

./nodes.yml -e dcs_clean=true

PGSQL

Abort because postgres instance already exists

警告

Pigsty提供了数据库误删保护机制,配置pg_clean = true 可以硬干。

当目标节点的PostgreSQL服务已经存在时,pgsql.yml 会根据 pg_clean 参数采取行动,如果为真,那么在初始化过程中现有的PostgreSQL实例会被抹除。

Pigsty也提供了相应的保护机制 参数: pg_safeguard

您可以在配置文件 pigsty.yml 中修改这些参数,也可以直接在执行剧本时,通过额外参数机制指定:

./pgsql.yml -e pg_clean=true

PostgreSQL数据库如何保证高可用

警告

Patroni 作为HA Agent,Consul作为DCS,Haproxy作为默认流量分发器,详见高可用集群

Pigsty使用Patroni代管Postgres,Patroni使用Consul达成领导者共识,当主库故障超过阈值后(30秒),会触发新一轮领导者选举,获胜者成为新的集群主库,所有其他从库追随新的集群主库,原有故障主库上线后会自动降级为从库并追随新主库。

客户端使用HAProxy服务接入数据库,HAproxy使用HTTP健康检查从Patroni处获取主从角色信息,并依此分发流量。Pigsty的数据库集群成员在使用上幂等,只要集群还有任意一个实例存活,读写与只读流量都可以继续工作,访问任意一个实例的5433端口,都可以确保访问集群主库读写服务。

DCS自身的可用性通过多节点共识保证,故生产环境中建议部署3个或更多元节点,或使用外部的DCS集群。

如何确保PostgreSQL集群故障不丢数据

警告

使用pg_conf: crit.yml 模板,或手工启用同步复制。

Crit模板针对数据一致性和持久性而优化,默认启用同步提交与数据校验和。可以确保在故障切换时没有任何数据损失,并能及时检测上报因存储故障、断电等其他异常情况导致的静默数据腐坏。

数据损坏导致拖从库失败

警告

找到问题机器,修改 patroni 配置文件clonefrom: false并重载生效

Pigsty默认为PGSQL集群中的所有成员都启用 cloneform: true 功能,即,制作从库时可以从该实例上拖取基础备份。如果某个实例因为数据文件损坏无法完成从库制作,那么您可以修改该实例上的Patroni配置文件,将clonefrom设置为false,以避免从损坏的实例上拉取数据。

5 - 概念导览

从 Pigsty v1.5.1 标签恢复的历史文档。

Index

Glossary

节点

Node

元节点

Meta

源码包

Source Package

离线软件包

Offline Software Package

沙箱

Sandbox

生产环境

Production Environment/Prod Env

单节点模式

Singleton Meta

集群管理模式

Cluster Manage

数据库集群

Database Cluster

沙箱

Sandbox

置备

Provisioning

管理用户

Admin Uesr

管理用户置备

Admin Provisioning

软件置备

Software Provisioning

配置过程

Configure

配置清单

Inventory

配置项

Config Entry

集群

Cluster

实例

Instance

服务

Service

水平分片集群

Sharding Cluster

剧本

Playbook

部署

Deploy/Deployment

主库

Primary

从库

Replica

同步从库

Standby

离线从库

Offline

延迟从库

Delayed

热备份

Hot Standby

冷备份

Cold Standby

恢复

Restore

告警

Alert/Alerting

指标

Metric/Metrics

面板

Dashboard

仪表盘

Panel

监控目标

Monitor Target

仅监控模式

Monly

身份

Identity

身份参数

Identity Parameter

健康检查

HealthCheck

服务发行

Service Discovery

Redis标准主从

Standalone

Redis原生集群

Native Cluster

Redis哨兵

Redis Sentinel

6 - 架构

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty在逻辑由几个独立模块组成,可以根据不同的场景自由排列组合。

模块

Pigsty目前提供四个功能模块:

  • INFRA 是Pigsty的基础设施部分,包括监控/告警/可视化/日志/DNS/NTP等公共组件。
  • NODES 是主机节点管理模块,用于配置节点,安装软件,收集监控指标与日志。
  • PGSQL 是PostgreSQL数据库部署管控模块,包括各种类型的PG集群部署与监控。
  • REDIS 是Redis数据库部署管控模块,包括Redis 主从/集群/哨兵部署与监控

用法

您可以自行选择在哪些节点上启用哪些模块,适配不同的需求场景。

默认情况下,Pigsty将执行单机安装,将当前节点初始化为一个加装了 INFRANODES,与PGSQL元节点

您可以进一步加入其他节点,并在其上加装不同的数据库模块。

单机部署

如果您想将Pigsty当作开箱即用的单机PostgreSQL发行版来使用,那么在一台机器上依次安装 INFRA, NODES, PGSQL 三个模块,就会有一个立即可用的,自我监控管理的数据库实例。

执行 infra.yml 剧本在单机上安装Pigsty,在该节点上部署基础设施 ,并拉起一个单节点PostgreSQL数据库集群。个人用户、简单场景、小微企业可以直接开箱使用此数据库。完整安装Pigsty的节点称为元节点(Meta)。

但Pigsty的能力不只于此,它还可以用于监控管理更多的节点与数据库。

主机监控

如果您想要一个生产环境的大规模主机监控系统,那么在一台机器上安装INFRA模块,在所有被监控的机器节点上安装NODES模块即可。所有的主机节点会配置有软件源,软件包,DNS,NTP,节点监控,日志收集,DCS Agent这些生产环境所需的组件。纳入Pigsty管理的主机节点会带有详细的监控信息,并可以用于进一步部署各式各样的数据库模块。

在元节点上通过 nodes.yml 剧本为更多节点加装NODES模块,纳入Pigsty管理中。

数据库集群

当您将节点纳入Pigsty后,这些节点可以用于进一步部署各种数据库集群

如果您想部署管理大量的PostgreSQL集群,在这些纳入Pigsty管理的节点上再加装 **PGSQL **模块即可。您可以一键部署各种各样的PGSQL集群:单实例,一主N从的高可用集群,同步集群,法定人数提交的同步集群,带有离线ETL角色的集群,异地容灾的备集群,延迟复制集群,Citus分布式集群,TimescaleDB集群,MatrixDB数据仓库集群。

如果你想部署并监控管理很多Redis集群,也只要在Pigsty托管的节点上加装REDIS模块即可。

使用 pgsql.yml 创建高可用的PostgreSQL数据库集群,使用 redis.yml创建主从、集群、哨兵模式的Redis集簇,使用 pgsql-matrixdb.yml 部署 Greenplum/MatrixDB 数据仓库。

Pigsty后续会按需逐步添加新类型的数据库功能模块:KAFKA, MINIO, MONGO等。

模型

一套完整的Pigsty系统,可称为一个部署(Deployment)/ 环境(Environment)

例如:生产环境,测试环境,预发环境等。

一套Pigsty部署在架构上分为两个部分:一套基础设施,与多套集群,两者均通过一份配置清单(Inventory)进行描述。

集群包含有节点实例服务三种核心资源:一个集群会包含多个实例,部署于多个 节点(Node)上,提供多种不同的 服务(Service),每个数据库实例之下又会有更细分的ER模型。

7 - 基础设施

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty提供了一套完整的,开箱即用的PaaS基础设施。

每一套 Pigsty 部署(Deployment) 中,都需要有一些基础设施,才能使整个系统正常工作。基础设施通常由专业的运维团队或云厂商负责,但Pigsty作为一个开箱即用的PaaS解决方案,将基本的基础设施集成至供给方案中。

概览

Pigsty会在元节点(默认为当前安装的节点)上部署一套完整的基础设施,包括:

组件 端口 默认域名 说明
Nginx 80 pigsty 所有Web服务的入口,文件服务器
Yum Repo 80 yum.pigsty 本地YUM软件源
Grafana 3000 g.pigsty 监控系统/可视化平台
AlertManager 9093 a.pigsty 报警聚合管理组件
Prometheus 9090 p.pigsty 监控时序数据库
Loki 3100 l.pigsty 实时日志收集基础设施
Consul 8500 c.pigsty 分布式配置管理与服务发现
Docker 2375 - 运行无状态服务的容器平台
PostgreSQL 5432 - Pigsty CMDB
Ansible - - 用于发起管理命令的组件
Consul DNS 8600 - Consul提供的DNS服务(可选)
Dnsmasq 53 - DNS域名解析服务器(可选)
NTP 123 - NTP时间服务器(可选)

基础设施部署于 元节点 上。一套环境中包含一个或多个元节点,用于基础设施部署。除了 分布式配置存储(DCS) 之外,所有基础设施组件都采用副本式部署。

说明

若配置有多个元节点,元节点上的DCS(etcd/consul)会共同作为DCS服务器集群。

Nginx

Nginx是Pigsty所有WebUI类服务的访问入口,默认使用管理节点80端口。

有许多带有WebUI的基础设施组件通过Nginx对外暴露服务,例如Grafana,Prometheus,AlertManager,Consul,以及HAProxy流量管理页等。 此外,YumRepo,文档,执行计划可视化器等静态文件资源也通过Nginx对外提供服务。

Nginx会根据 nginx_upstream 的内容,通过域名的方式,将访问请求转发至对应的上游组件处理。 Pigsty强烈建议使用域名访问Pigsty UI系统,而不是直接通过IP+端口的方式访问,基于以下几个理由:

  • 一些组件默认只监听 127.0.0.1 ,因此只能通过Nginx代理访问
  • 通过域名访问可以将访问收拢至Nginx,审计一切请求,并方便地集成认证机制。
  • 域名更容易记忆,并提供了配置灵活性。

如果您没有可用的互联网域名或本地DNS解析,您可以在 /etc/hostsC:\Windows\System32\drivers\etc\hosts中添加本地静态解析记录。

Nginx相关配置参数位于:配置:INFRA - NGINX

Yum Repo

Pigsty会在安装时首先建立一个本地Yum软件源,以加速后续软件安装。

该Yum源由Nginx提供服务,默认位于为 /www/pigsty,可以访问 http://yum.pigsty/pigsty 获取。Pigsty的离线软件包即是将已经建立好的Yum Repo目录整个打成压缩包。

当Pigsty尝试构建本地源时,如果发现本地源目录 /www/pigsty 已经存在,且带有 /www/pigsty/repo_complete 标记文件,则会认为本地源已经构建完成,从而跳过从原始上游下载软件的步骤,消除了对互联网访问的依赖。

Repo文件位于 /www/pigsty.repo,默认可以通过http://yum.pigsty/pigsty.repo 获取

curl http://yum.pigsty/pigsty.repo -o /etc/yum.repos.d/pigsty.repo

您也可以在没有Nginx的情况下直接使用文件本地源:

[pigsty-local]
name=Pigsty local $releasever - $basearch
baseurl=file:///www/pigsty/
enabled=1
gpgcheck=0

Yum Repo相关配置参数位于:配置:INFRA - REPO

Grafana

Grafana是开源的可视化/监控平台,是Pigsty WebUI的核心,默认监听3000端口,可以直接通过IP:3000或域名http://g.pigsty访问。

Pigsty的监控系统基于Dashboard构建,通过URL进行连接与跳转。您可以快速地在监控中下钻上卷,快速定位故障与问题。

此外,Grafana还可以用作通用的低代码前后端平台,制作交互式可视化数据应用。因此,Pigsty使用的Grafana带有一些额外的可视化插件,例如ECharts面板。

Grafana相关配置参数位于:配置:INFRA - GRAFANA

AlertManager

AlertManager是与Prometheus配套的告警平台,默认监听9093端口,可以直接通过IP:9093或域名http://a.pigsty访问。

Prometheus的告警事件会发送至AlertManager,但如果需要进一步处理,用户需要进一步对其进行配置,例如提供SMTP服务配置以发送告警邮件。

Prometheus

Prometheus是监控时序数据库,默认监听9090端口,可以直接通过IP:9090或域名http://p.pigsty访问。

Prometheus是监控用时序数据库。

  • Prometheus默认通过本地静态文件服务发现获取监控对象,并为其关联身份信息。
  • Prometheus可以选择使用Consul服务发现,自动获取监控对象。
  • Prometheus从Exporter拉取监控指标数据,进行预计算加工后存入自己的TSDB中。
  • Prometheus计算报警规则,将报警事件发往Alertmanager处理。

Prometheus相关配置参数位于:配置:INFRA - PROMETHEUS

Loki

Prometheus是监控时序数据库,默认监听3100端口。

Loki是用于日志收集的日志数据库,节点上的Promtail向元节点上的Loki推送日志。

LOKI相关配置参数位于:配置:INFRA - LOKI

Consul

Consul Server用于保存DCS的状态,达成共识,提供元数据查询服务,亦提供基于DCS的服务发现。

Consul相关配置参数位于:配置:INFRA - DCS

Docker

Pigsty默认在元节点上安装Docker,您可以拉起各式各样的无状态应用,并使用外部数据库获得生产级的持久性。Docker相关配置参数位于:配置:INFRA - DOCKER

PostgreSQL

PostgreSQL相关配置参数位于:配置:PGSQL,使用CMDB作为配置源,请参考CMDB教程

  • 用于支持各种高级功能的MetaDB(亦是一个标准的数据库集群,由Ansible拉起)

  • 用于执行剧本,发起控制的Ansible,使用动态Inventory时会访问CMDB

  • 定时任务控制器(支持备份,清理,统计,巡检,等特性),会访问CMDB

Ansible

Pigsty默认会在元节点上安装Ansible,Ansible是一个流行的运维工具,采用声明式的配置风格与幂等的剧本设计,可以极大降低系统维护的复杂度。命令行工具 pigsty-cli 会调用Ansible Playbook发起管控

Ansible相关配置参数位于:配置:INFRA - CONNECT

Dnsmasq

Dnsmasq提供环境内的DNS解析服务(可选)

  • DNS服务为可选,可使用已有DNS服务器
  • 部分DNS解析将转交由Consul DNS进行

DNSMASQ相关配置参数位于:配置:INFRA - Nameserver

NTP

NTP服务用于同步环境内所有节点的时间(可选)

NTP相关配置参数位于:配置:NODES - NTP

Demo

Pigsty 提供了一个公开演示的demo,地址为: http://demo.pigsty.cc

因为演示实例为1核1GB的空虚拟机空实例,故显示内容较为单薄,请以实际效果为准。

8 - 概念:节点

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty使用节点(Node)进行安装与部署,节点可以是物理机,虚拟机,甚至Pod。

在Pigsty中有两种节点:元节点 与(普通)节点

元节点用于发起管理,普通节点是纳入Pigsty管理的节点。

  • 元节点(Meta):执行 infra.yml 剧本安装Pigsty,安装 INFRANODESPGSQL 三个模块。
  • 节点(Node):通过 nodes.yml 剧本纳入管理的普通节点,默认安装 NODES 模块。

元节点

元节点即完整安装Pigsty,带有管理功能的节点,部署有完整的基础设施组件。

当您在某节点上执行 ./configure 时,当前节点会被默认作为元节点,填入配置文件 meta 分组中。

在每套环境中,Pigsty最少需要一个元节点,该节点将作为整个环境的控制中心。元节点负责各种管理工作:保存状态,管理配置,发起任务,收集指标,等等。整个环境的基础设施组件,Nginx,Grafana,Prometheus,Alertmanager,NTP,DNS Nameserver,DCS都将部署在元节点上。

复用元节点

元节点亦可复用为普通数据库节点,在元节点上默认运行有名为 pg-meta 的PostgreSQL数据库集群。提供额外的扩展功能:CMDB,巡检报告,扩展应用,日志分析,数据分析与处理等

以Pigsty附带的四节点沙箱环境为例,组件在节点上的分布如下图所示:

沙箱由一个元节点与四个普通节点组成,这里元节点也被复用为一个普通节点。沙箱内部署有一套基础设施与两套数据库集群meta 为元节点,部署有基础设施组件,同时被复用为普通数据库节点,部署有单主数据库集群pg-metanode-1node-2node-3 为普通数据库节点,部署有数据库集群pg-test

元节点上的服务

元节点上默认运行的服务如下所示:

组件 端口 说明 默认域名
Nginx 80 所有Web服务的入口,文件服务器 pigsty
Yum 80 本地YUM软件源 yum.pigsty
Grafana 3000 监控系统/可视化平台 g.pigsty
AlertManager 9093 报警聚合管理组件 a.pigsty
Prometheus 9090 监控时序数据库 p.pigsty
Loki 3100 实时日志收集基础设施 l.pigsty
Consul (Server) 8500 分布式配置管理与服务发现 c.pigsty
Docker 2375 运行无状态服务的容器平台 -
PostgreSQL 5432 Pigsty CMDB -
Ansible - 用于发起管理命令的组件 -
Consul DNS 8600 Consul提供的DNS服务(可选) -
Dnsmasq 53 DNS域名解析服务器(可选) -
NTP 123 NTP时间服务器(可选) -
Pgbouncer 6432 Pgbouncer连接池服务 -
Patroni 8008 Patroni高可用组件 -
Haproxy Primary 5433 集群读写服务(主库连接池)代理 -
Haproxy Replica 5434 集群只读服务(从库连接池)代理 -
Haproxy Default 5436 集群主库直连服务(用于管理,DDL/DML变更) -
Haproxy Offline 5438 集群离线读取服务(直连离线实例,用于ETL,交互式查询) -
Haproxy Admin 9101 Haproxy监控指标与流量管理页面 -
PG Exporter 9630 Postgres监控指标导出器 -
PGBouncer Exporter 9631 Pgbouncer监控指标导出器 -
Node Exporter 9100 机器节点监控指标导出器 -
Promtail 9080 实时收集节点与数据库日志 -
vip-manager - 将VIP绑定至集群主库上

元节点与DCS

默认情况下,元节点上将部署元数据库 (Consul 或 Etcd),用户也可以使用已有的外部DCS集群。如果将DCS部署至元节点上,建议在生产环境使用3个元节点,以充分保证DCS服务的可用性。DCS外的基础设施组件都将以对等副本的方式部署在所有元节点上。元节点的数量要求最少1个,推荐3个,建议不超过5个。

警告

DCS用于支持数据库高可用的故障检测与选主,在默认模式停止DCS服务会导致所有数据库集群拒绝写入,因此请务必确保DCS服务的可靠性(增加元节点数量,或使用外部独立维护的高可用DCS集群)。

使用多个元节点

复数个元节点是可能的,通常一个元节点足矣,两个元节点可以互为备份,三个元节点自身便足以部署生产级DCS Server集群。

本着开箱即用的原则,Pigsty默认在所有元节点上部署DCS Server。但如果单纯是为了追求DCS Server集群的高可用而使用超过3个管理节点并没有太大的意义。您可以使用一个外部维护管理的,3~5节点的DCS集群来保证DCS服务可用性。

元节点的特征是节点地址配置于配置文件的 all.children.meta.host 分组中,带有meta_node: true 标记。在 configure 过程中,执行安装的当前节点会被配置为元节点,复数个元节点则需要手工配置,可参考三管理节点样例配置文件: pigsty-dcs3.yml

如果您没有使用任何外部DCS集群服务作为仲裁者,那么有意义的高可用最少需要3个节点。如果您只有两个节点,建议主库故障时人工介入以避免脑裂出现。

节点

您可以使用Pigsty管理更多的节点,并使用这些节点部署数据库。

纳入Pigsty管理的节点会被 nodes.yml 调整至 配置:NODES 所描述的状态,加装节点监控与日志收集组件,您可以从监控系统中查阅节点状态与日志。被Pigsty管理的节点可以进一步用于部署各种数据库,或您自己的应用。

节点身份

每个节点都有身份参数,通过在<cluster>.hosts<cluster>.vars中的相关参数进行配置。

在Pigsty中,节点有两个重要的身份参数: nodenamenode_cluster,这两者将在监控系统中用作节点的 实例标识ins) 与 集群标识cls)。nodenamenode_cluster 并不是必选参数,当留白或置空时,nodename 会使用节点当前的主机名,而 node_cluster 则会使用固定的默认值:nodes

此外,Pigsty还会使用IP地址作为数据库节点的唯一标识, IP地址即配置清单中主机的inventory_hostname ,体现为<cluster>.hosts对象中的key。尽管一个节点可能有多块网卡和多个IP地址,但您必须指定一个首要IP地址作为节点唯一标识。该地址应当为内网地址,即您访问该节点上的数据库时使用那个IP地址。

该IP地址并不一定是管理节点SSH访问使用的IP地址,您可以通过 Ansible Connect 相关参数,通过SSH隧道或跳板机中转的方式间接操作管理目标节点。

名称 类型 层级 必要性 说明
inventory_hostname ip - 必选 节点IP地址
nodename string I 可选 节点名称
node_cluster string C 可选 节点集群名称

以下集群配置声明了一个三节点集群:

node-test:
  hosts:
    10.10.10.11: { nodename: node-test-1 }
    10.10.10.12: { pg_hostname: true } # 从PG借用身份 pg-test-2
    10.10.10.13: {  } # 不显式指定nodename,则使用原有hostname: node-3
  vars:
    node_cluster: node-test
host node_cluster nodename instance
10.10.10.11 node-test node-test-1 pg-test-1
10.10.10.12 node-test pg-test-2 pg-test-2
10.10.10.13 node-test node-3 pg-test-3

在监控系统中,相关的时序监控数据标签为:

node_load1{cls="pg-meta", ins="pg-meta-1", ip="10.10.10.10", job="nodes"}
node_load1{cls="pg-test", ins="pg-test-1", ip="10.10.10.11", job="nodes"}
node_load1{cls="pg-test", ins="pg-test-2", ip="10.10.10.12", job="nodes"}
node_load1{cls="pg-test", ins="pg-test-3", ip="10.10.10.13", job="nodes"}

节点默认服务

组件 端口 说明
Consul Agent 8500 分布式配置管理,服务发现组件Consul的本地Agent
Node Exporter 9100 机器节点监控指标导出器
Promtail 9080 实时收集Postgres,Pgbouncer,Patroni日志 (选装)
Consul DNS 8600 Consul Agent提供的DNS服务

PGSQL节点服务

PGSQL节点是用于部署PostgreSQL集群的节点, 在标准节点上额外加装了 PGSQL 模块。

在执行默认的PostgreSQL部署时,因为Pigsty默认采用节点独占1:1部署,因此可以通过 pg_hostname 参数,将数据库实例的身份参数(pg_clusterpg_instance)借用至节点的 nodenamenode_cluster 身份参数上。

除了 节点默认服务) 外,PGSQL节点上运行有下列服务:

组件 端口 说明
Postgres 5432 Postgres数据库服务
Pgbouncer 6432 Pgbouncer连接池服务
Patroni 8008 Patroni高可用组件
Consul 8500 分布式配置管理,服务发现组件Consul的本地Agent
Haproxy Primary 5433 集群读写服务(主库连接池)代理
Haproxy Replica 5434 集群只读服务(从库连接池)代理
Haproxy Default 5436 集群主库直连服务(用于管理,DDL/DML变更)
Haproxy Offline 5438 集群离线读取服务(直连离线实例,用于ETL,交互式查询)
Haproxy service 543x 集群提供的额外自定义服务将依次分配端口
Haproxy Admin 9101 Haproxy监控指标与流量管理页面
PG Exporter 9630 Postgres监控指标导出器
PGBouncer Exporter 9631 Pgbouncer监控指标导出器
Node Exporter 9100 机器节点监控指标导出器
Promtail 9080 实时收集Postgres,Pgbouncer,Patroni日志 (选装)
Consul DNS 8600 Consul提供的DNS服务
vip-manager - 将VIP绑定至集群主库上

节点交互

以单个 元节点 和 单个 节点 构成的环境为例,架构如下图所示:

元节点与数据库节点之间的交互主要包括:

  • 数据库集群/节点的域名依赖元节点的Nameserver进行解析 (可选)。

  • 数据库节点软件安装需要用到元节点上的Yum Repo。

  • 数据库集群/节点的监控指标会被元节点的Prometheus收集。

  • 数据库的日志会被Promtail收集并发往Loki。

  • Pigsty会从元节点上发起对数据库节点的管理:

    • 执行集群创建,扩缩容,实例/集群回收
    • 创建业务用户、业务数据库、修改服务、HBA修改;
    • 执行日志采集、垃圾清理,备份,巡检等
  • 数据库节点的Consul会向元节点的DCS同步本地注册的服务,并代理状态读写操作。

  • 数据库节点会从元节点(或其他NTP服务器)同步时间l

9 - PGSQL 概念

从 Pigsty v1.5.1 标签恢复的历史文档。

介绍 PostgreSQL 数据库集群管理所需的核心概念

PGSQL集群

生产环境的PGSQL数据库以集群为单位进行组织,集群是一个由主从复制所关联的一组数据库实例所构成的逻辑实体。每个数据库集群是一个自组织的业务服务单元,由至少一个数据库实例组成。

沙箱环境

集群是基本的业务服务单元,下图展示了沙箱环境中的复制拓扑。其中pg-meta-1单独构成一个数据库集群pg-meta,而pg-test-1pg-test-2pg-test-3共同构成另一个逻辑集群pg-test

pg-meta-1
(primary)

pg-test-1 -------------> pg-test-2
(primary)      |         (replica)
               |
               ^-------> pg-test-3
                         (replica)

高可用

主库故障RTO ≈ 30s~1min,RPO < 10MB,从库故障RTO≈0(仅故障实例连接中断)

Pigsty默认创建创建高可用PostgreSQL数据库集群。只要集群中有任意实例存活,集群就可以对外提供完整的读写服务与只读服务。Pigsty可以自动进行故障切换,业务方只读流量不受影响;读写流量的影响视具体配置与负载,通常在几秒到几十秒的范围。

默认情况下, Pigsty部署的集群采用 可用性优先 模式,主库宕机时,未及时复制至从库部分的数据可能会丢失(正常约几百KB,不超过10MB),您可以参考 同步从库 的说明,使用 一致性优先 模式,此模式下 RPO = 0 。

Pigsty的高可用使用 Patroni + HAProxy实现,前者负责故障切换,后者负责流量切换。Patroni会利用DCS服务进行心跳保活,集群主库默认会注册一个时长为15秒的租约并定期续租。当主库故障无法续租时,租约释放,触发新一轮集群选举。通常,复制延迟最小者(数据损失最小化)会被选举为新的集群领导者。集群进入新的时间线,包括旧主库在内的其他成员都会重新追随新的领导者。

Pigsty提供了多种流量接入方式,如果您使用默认的HAProxy接入,则无需担心集群故障切换对业务流量产生影响。HAProxy会自动检测集群中的实例状态,并正确分发流量。例如,5433端口上的 Primary服务,会使用HTTP GET ip:8008/primary 健康检查,从集群中所有的Patroni处获取信息,找出集群主库,并将流量分发至主库上。HAProxy本身是无状态的,均匀部署在每个节点/实例上。任意或所有HAProxy都可以作为集群的服务接入点。

组件交互

在单个数据库节点/实例上,各组件通过以下联系相互配合:

  • vip-manager通过查询Consul获取集群主库信息,将集群专用L2 VIP绑定至主库节点(默认沙箱接入方案)。
  • Haproxy是数据库流量入口,用于对外暴露服务,使用不同端口(543x)区分不同的服务。
    • Haproxy的9101端口暴露Haproxy的内部监控指标,同时提供Admin界面控制流量。
    • Haproxy 5433端口默认指向集群主库连接池6432端口
    • Haproxy 5434端口默认指向集群从库连接池6432端口
    • Haproxy 5436端口默认直接指向集群主库5432端口
    • Haproxy 5438端口默认直接指向集群离线实例5432端口
  • Pgbouncer用于池化数据库连接,缓冲故障冲击,暴露额外指标。
    • 生产服务(高频非交互,5433/5434)必须通过Pgbouncer访问。
    • 直连服务(管理与ETL,5436/5438)必须绕开Pgbouncer直连。
  • Postgres提供实际数据库服务,通过流复制构成主从数据库集群。
  • Patroni用于监管Postgres服务,负责主从选举与切换,健康检查,配置管理。
    • Patroni使用Consul达成共识,作为集群领导者选举的依据。
  • Consul Agent用于下发配置,接受服务注册,服务发现,提供DNS查询。
    • 所有使用端口的进程服务都会注册至Consul中
  • PGB Exporter,PG Exporter, Node Exporter分别用于暴露数据库,连接池,节点的监控指标
  • Promtail是日志收集组件,用于向基础设施Loki发送采集到的PG,PGB,Patroni与节点日志

实体模型

在Pigsty中,PostgreSQL有四类核心实体:

实体说明

  • 集群(Cluster) 是基本自治单元,由用户指定唯一标识,表达业务含义,作为顶层命名空间。
  • 集群在硬件层面上包含一系列的节点(Node),即物理机,虚机(或Pod),可以通过IP唯一标识。
  • 集群在软件层面上包含一系列的实例(Instance),即软件服务器,可以通过IP:Port唯一标识。
  • 集群在服务层面上包含一系列的服务(Service),即可访问的域名与端点,可以通过域名唯一标识。

实体命名规则

  • 集群的命名可以使用任意满足DNS域名规范的名称,不能带点([a-zA-Z0-9-]+)。
  • 节点命名采用集群名称作为前缀,后接-,再接一个整数序号(建议从0开始分配,与k8s保持一致)
  • PGSQL采用独占式部署,节点与实例一一对应,因此实例命名可与节点命名一致,即${cluster}-${seq}的方式。
  • 服务命名亦采用集群名称作为前缀,后接-连接服务具体内容,如primary, replica,offline,standby等。

以沙箱环境的测试数据库集群 pg-test 为例:

  • 一个集群:用于测试的数据库集群名为“pg-test
  • 两种角色:primaryreplica,分别是集群主库与从库。
  • 三个实例:集群由三个数据库实例:pg-test-1, pg-test-2, pg-test-3组成
  • 三个节点:集群部署在三个节点上:10.10.10.11, 10.10.10.12, 10.10.10.13上。
  • 四个服务:

身份参数

实体与标识符是一种概念模型,下面介绍Pigsty中的具体实现。

pg_clusterpg_rolepg_seq 属于 身份参数 ,用于生成实体标识。

除IP地址外,这三个参数是定义一套新的数据库集群的最小必须参数集

  • 集群标识:pg_cluster{{ pg_cluster }}
  • 实例标识:pg_instance{{ pg_cluster }}-{{ pg_seq }}
  • 服务标识:pg_service{{ pg_cluster }}-{{ pg_role }}
  • 节点标识:nodename
    • pg_hostname: true: 使用与 pg_instance相同的:{{ pg_cluster }}-{{ pg_seq }}
    • pg_hostname: false: 显式指定{{ nodename }}则直接使用,否则使用现有主机名。

下面是沙箱环境中 pg-test 集群的定义样例:

pg-test:
  hosts:
    10.10.10.11: {pg_seq: 1, pg_role: replica}
    10.10.10.12: {pg_seq: 2, pg_role: primary}
    10.10.10.13: {pg_seq: 3, pg_role: replica}
  vars:
    pg_cluster: pg-test
    pg_hostname: true     # 使用1:1 PG实例的身份作为节点的身份

因此,该集群三个成员的身份标识如下:

host cluster instance service nodename
10.10.10.11 pg-test pg-test-1 pg-test-primary pg-test-1
10.10.10.12 pg-test pg-test-2 pg-test-replica pg-test-2
10.10.10.13 pg-test pg-test-3 pg-test-replica pg-test-3

在监控系统中,相关的时序监控数据标签为:

pg_up{cls="pg-meta", ins="pg-meta-1", ip="10.10.10.10", job="pgsql"}
pg_up{cls="pg-test", ins="pg-test-1", ip="10.10.10.11", job="pgsql"}
pg_up{cls="pg-test", ins="pg-test-2", ip="10.10.10.12", job="pgsql"}
pg_up{cls="pg-test", ins="pg-test-3", ip="10.10.10.13", job="pgsql"}

集群(Cluster)

集群是基本的自治业务单元,这意味着集群能够作为一个整体组织对外提供服务。类似于k8s中Deployment的概念。注意这里的集群是软件层面的概念,不要与PG Cluster(数据库集簇,即包含多个PG Database的单个PG实例的数据目录)或Node Cluster(机器集群)混淆。

集群是管理的基本单位之一,是用于统合各类资源的组织单位。例如一个PG集群可能包括:

  • 三个物理机器节点
  • 一个主库实例,对外提供数据库读写服务。
  • 两个从库实例,对外提供数据库只读副本服务。
  • 两个对外暴露的服务:读写服务,只读副本服务。

集群命名规则

每个集群都有用户根据业务需求定义的唯一标识符,本例中定义了一个名为pg-test的数据库集群。

集群名称,其实类似于命名空间的作用。所有隶属本集群的资源,都会使用该命名空间。

集群标识符cls)必须在一套环境中唯一,建议采用符合DNS标准 RFC1034 命名规则的标识符。

良好的集群名称应当仅使用小写字母,数字,以及 减号连字符(hyphen)-,且只使用字母启头。这样集群中所有对象都可以该标识符作为自己标识符的前缀,严格约束的标识符可以应用于更广泛地场景。

cluster_name := [a-z][a-z0-9-]*

集群命名中不应该包括点(dot).,之所以强调不要在集群名称中用,是因为有一种流行的命名方式便是采用点号分隔的层次标识符,例如com.foo.bar。这种命名方式虽然简洁名快,但用户给出的名字中域名层次数目不可控。如果集群需要与外部系统交互,而外部系统对于命名有约束,这样的名字就会带来麻烦。最直观的例子是Kubernetes中的Pod,Pod的命名规则中不允许出现.

集群命名的内涵,建议采用-分隔的两段式,三段式名称,例如:

<集群类型>-<业务>-<业务线>

典型的集群名称包括:pg-meta, pg-test-fin, pg-infrastructure-biz


实例(Instance)

实例指带一个具体的数据库服务器,它可以是单个进程,也可能是共享命运的一组进程,也可以是一个Pod中几个紧密关联的容器。实例的关键要素在于:

  • 可以通过实例标识ins)符唯一标识
  • 具有处理请求的能力(而不管接收请求的究竟是数据库,还是连接池或负载均衡器)

例如,我们可以把一个Postgres进程,为之服务的独占Pgbouncer连接池,PgExporter监控组件,高可用组件,管理Agent看作一个提供服务的整体,视为一个数据库实例,使用同样的标识符指称。

实例命名规则

实例隶属于集群,每个实例在集群范围内都有着自己的唯一标识用于区分。实例标识符ins建议采用与Kubernetes Pod一致的命名规则:即集群名称连以从0/1开始递增分配的整数序号<cls>-<seq>

Pigsty默认使用从1开始的自增序列号依次为集群中的新数据库实例命名,例如,数据库集群pg-test有三个数据库实例,那么这三个实例就可以依次命名为:pg-test-1, pg-test-2pg-test-3

实例名ins一旦分配即不可变,该实例将在整个集群的生命周期中使用此标识符。

此外,采用独占节点部署模式时,数据库实例与机器节点可以互相使用对方的标识符。即我们也可用数据库实例标识ins来唯一指称一个机器节点。


节点(Node)

节点是对硬件资源的一种抽象,通常指代一台工作机器,无论是物理机(bare metal)还是虚拟机(vm),或者是Kubernetes 中的Pod。

说明

注意 Kubernetes 中Node是硬件资源的抽象,但在实际管理使用上,这里Node概念类似于Kubernetes中Pod的概念。

节点的关键特征是:

  • 节点是硬件资源的抽象,可以运行软件服务,部署数据库实例
  • 节点可以使用IP地址作为唯一标识符

节点命名规则

Pigsty使用 ip 地址作为节点唯一标识符,如果机器有多个IP地址,则以配置清单中指定的,实际访问使用的IP地址为准。为便于管理,节点应当拥有一个人类可读的充满意义的名称作为节点的主机名。主机名nodename,数据库实例标识ins,节点标识ip 三者在Pigsty中彼此一一对应,可交叉混用做数据库实例、机器节点、HAProxy负载均衡器的标识符。

节点的命名与数据库实例一致,在整个集群的生命周期中保持不变,便于监控与管理。


服务(Service)

服务 是对软件服务(例如Postgres,Redis)的一种命名抽象(named abstraction)。服务可以有各种各样的实现,但其的关键要素在于:

  • 可以寻址访问的服务名称,用于对外提供接入,例如:
    • 一个DNS域名(pg-test-primary
    • 一个Nginx/Haproxy Port
  • 服务流量路由解析与负载均衡机制,用于决定哪个实例负责处理请求,例如:
    • DNS L7:DNS解析记录
    • HTTP Proxy: Nginx/Ingress L7:Nginx Upstream配置
    • TCP Proxy: Haproxy L4:Haproxy Backend配置
    • Kubernetes:Ingress: Pod Selector
    • 服务也需要决定由哪个组件来处理请求:连接池,或是数据库本身。

更多关于服务的介绍,请参考服务一章。

服务命名规则

服务标识 (svc) 由两部分组成:作为命名空间的 cls, 与服务承载的角色role

在PostgreSQL数据库集群中,实例可能有不同的身份:集群领导者(主库),普通从库,同步从库,离线从库,延迟从库,不同的实例可能会提供不同的服务;同时直连数据库与通过连接池中间件访问数据库也属于性质不同的服务。通常我们会使用服务目标实例的身份角色来标识服务,例如在数据库集群pg-test中:

  • 指向 主库连接池(primary)角色实例的服务,叫做pg-test-primary
  • 指向 从库连接池(replica)角色实例的服务,叫做pg-test-replica
  • 指向 离线从库数据库(offline)的服务,叫做pg-test-offline
  • 指向 同步复制从库(standby)的服务,叫做pg-test-standby

请注意,服务并不够成对实例的划分,同一个服务可以指向集群内多个不同的实例,然而同一个实例也可以承接来自不同服务的请求。例如,角色为 standby的同步从库既可以承接来自 pg-test-standby 的同步读取请求,也可以承接来自 pg-test-replica 的普通读取请求。

10 - Redis 概念

从 Pigsty v1.5.1 标签恢复的历史文档。

介绍 Redis 数据库集群管理所需的核心概念

部署:Redis配置:Redis | 剧本:Redis

实体概念模型

Redis的实体概念模型与PostgreSQL几乎相同,同样包括 集群(Cluster)实例(Instance) 的概念。注意这里的Cluster概念指的不是 Redis原生集群方案中的集群。

核心的区别在于,Redis通常采用单机多实例部署,一个物理/虚拟机节点上通常会部署多个 Redis实例,以充分利用多核CPU。因此,定义Redis实例的方式与PGSQL稍有不同。

在Pigsty管理的Redis中,节点完全隶属于集群,即目前尚不允许在一个节点上部署两个不同集群的Redis实例,但这并不影响您在在一个节点上部署多个独立Redis实例。

Redis身份参数

身份参数是定义Redis集群时必须提供的信息,包括:

名称 属性 说明 例子
redis_cluster 必选,集群级别 集群名 redis-test
redis_node 必选,节点级别 节点编号 1,2
redis_instances 必选,节点级别 实例定义 { 6001 : {} ,6002 : {}}
  • redis_cluster 标识了Redis集群的名称,在集群层面进行配置,作为集群资源的顶层命名空间。
  • redis_node 标识了节点在集群中的序号
  • redis_instances 是一个JSON对象,Key为实例端口号,Value为一个JSON对象,包含实例特殊的配置

11 - PGSQL服务与接入

从 Pigsty v1.5.1 标签恢复的历史文档。

如何定义PostgreSQL服务,并通过负载均衡与连接池实现稳定可靠高性能的接入

单机用户无需关注服务接入的概念,这是针对在生产环境中使用高可用PostgreSQL数据库集群所提出的概念。


单机用户

完成单机部署后,该节点的5432端口对外提供PostgreSQL数据库服务,80端口对外提供UI类服务。

在当前元节点上,使用管理用户无参数执行 psql 可以直接连接到本机预定义的 meta 数据库,开箱即用。

从外部(宿主机)使用客户端工具访问PG时,可以使用以下URL:

psql postgres://dbuser_dba:[email protected]/meta         # 默认超级用户 直连
psql postgres://dbuser_meta:[email protected]/meta       # 默认业务用户 直连

您可以使用由 pg_admin_usernamepg_admin_password 指定的管理员用户,或预先在meta数据库中定义的其他业务用户(dbuser_meta)访问该数据库。

在生产环境使用Pigsty部署的高可用数据库集群,强烈不建议使用IP直连的方式接入数据库服务


服务

**服务(Service)**是数据库集群对外提供功能的形式。

在真实世界的生产环境中,我们会使用基于复制的主从数据库集群。集群中有且仅有一个实例作为领导者(主库),可以接受写入,而其他实例(从库)则会从持续从集群领导者获取变更日志,与领导者保持一致。同时从库还可以承载只读请求,对于读多写少的场景可以显著分担主库负载,因此区分集群的写入请求与只读请求是一个常规实践。

此外对于高频短连接的生产环境,我们还会通过连接池中间件(Pgbouncer)对请求进行池化,减少连接与后端进程的创建开销。但对于ETL与变更执行等场景,我们又需要绕过连接池,直接访问数据库。

此外,高可用集群在故障时会出现故障切换(Failover),故障切换会导致集群的领导者出现变更。因此高可用的数据库方案要求写入流量可以自动适配集群的领导者变化。

这些不同的访问需求(读写分离,池化与直连,故障切换自动适配)最终抽象为服务的概念。

通常来说,数据库集群必须提供一种服务

  • 读写服务(primary) :可以写入数据库

对于生产数据库集群至少应当提供两种服务

  • 读写服务(primary) :可以写入数据库
  • 只读服务(replica) :可以访问只读数据副本

此外,根据具体的业务场景,可能还会有其他的服务,例如:

  • 离线从库服务(offline):不承接线上只读流量的专用从库,用于ETL与个人查询
  • 同步从库服务(standby) :采用同步提交,没有复制延迟的只读服务
  • 延迟从库服务(delayed) : 允许业务访问固定时间间隔之前的旧数据
  • 默认直连服务(default) : 允许(管理)用户绕过连接池直接管理数据库的服务

默认服务

Pigsty默认对外提供四种服务:primary, replica, default, offline

您可以通过配置文件为全局或单个集群定义新的服务

服务 端口 用途 说明
primary 5433 生产读写 通过连接池连接至集群主库
replica 5434 生产只读 通过连接池连接至集群从库
default 5436 管理 直接连接至集群主库
offline 5438 ETL/个人用户 直接连接至集群可用的离线实例

以默认的元数据库pg-meta为例

psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5433/meta     # 生产读写
psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5434/meta     # 生产只读
psql postgres://dbuser_dba:DBUser.DBA@pg-meta:5436/meta       # 直连主库
psql postgres://dbuser_stats:DBUser.Stats@pg-meta:5438/meta   # 直连离线

下面将详细介绍这四种服务

Primary服务

Primary服务服务于线上生产读写访问,它将集群的5433端口,映射为 主库连接池(默认6432) 端口。

Primary服务选择集群中的所有实例作为其成员,但只有健康检查/primary为真者,才能实际承接流量。

在集群中有且仅有一个实例是主库,只有其健康检查为真。

# primary service will route {ip|name}:5433 to primary pgbouncer (5433->6432 rw)
- name: primary           # service name {{ pg_cluster }}-primary
  src_ip: "*"
  src_port: 5433
  dst_port: pgbouncer     # 5433 route to pgbouncer
  check_url: /primary     # primary health check, success when instance is primary
  selector: "[]"            # select all instance as primary service candidate

主库上的高可用组件Patroni针对Primary健康检查返回200,用于确保集群不会出现一个以上的主库实例。

当集群发生故障切换时,新主库的健康检查为真,老主库的健康检查为假,因此流量将迁移至新主库上。业务方会察觉到约30秒的 Primary服务 不可用时间。

Replica服务

Replica服务服务于线上生产只读访问,它将集群的5434端口,映射为 从库连接池(默认6432) 端口。

Replica服务选择集群中的所有实例作为其成员,但只有健康检查/read-only为真者,才能实际承接流量,该健康检查对所有可以承接只读流量的实例(包括主库)返回成功。所以集群中的任何成员都可以承载只读流量。

但默认情况下,只有从库承载只读请求,Replica服务定义了selector_backup,该选择器将集群的主库作为 备份实例 加入到Replica服务中。只要当Replica服务中所有其他实例,即所有从库宕机时,主库才会开始承接只读流量

另一个作为备份实例的角色是offline角色,Offline实例通常专用于OLAP/ETL/个人交互式查询,不适合与在线查询混合,因此只有当集群中所有的replica宕机后,offline才会被用于承接只读流量。

# replica service will route {ip|name}:5434 to replica pgbouncer (5434->6432 ro)
- name: replica           # service name {{ pg_cluster }}-replica
  src_ip: "*"
  src_port: 5434
  dst_port: pgbouncer
  check_url: /read-only   # read-only health check. (including primary)
  selector: "[]"          # select all instance as replica service candidate
  selector_backup: "[? pg_role == `primary` || pg_role == `offline` ]"

Default服务

Default服务服务于线上主库直连,它将集群的5436端口,映射为主库Postgres端口(默认5432)。

Default服务针对交互式的读写访问,包括:执行管理命令,执行DDL变更,连接至主库执行DML,执行CDC。交互式的操作不应当通过连接池访问,因此Default服务将流量直接转发至Postgres,绕过了Pgbouncer。

Default服务与Primary服务类似,采用相同的配置选项。出于演示目显式填入了默认参数。

# default service will route {ip|name}:5436 to primary postgres (5436->5432 primary)
- name: default           # service's actual name is {{ pg_cluster }}-default
  src_ip: "*"             # service bind ip address, * for all, vip for cluster virtual ip address
  src_port: 5436          # bind port, mandatory
  dst_port: postgres      # target port: postgres|pgbouncer|port_number , pgbouncer(6432) by default
  check_method: http      # health check method: only http is available for now
  check_port: patroni     # health check port:  patroni|pg_exporter|port_number , patroni by default
  check_url: /primary     # health check url path, / as default
  check_code: 200         # health check http code, 200 as default
  selector: "[]"          # instance selector
  haproxy:                # haproxy specific fields
    maxconn: 3000         # default front-end connection
    balance: roundrobin   # load balance algorithm (roundrobin by default)
    default_server_options: 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'

Offline服务

Offline服务用于离线访问与个人查询。它将集群的5438端口,映射为离线实例Postgres端口(默认5432)。

Offline服务针对交互式的只读访问,包括:ETL,离线大型分析查询,个人用户查询。交互式的操作不应当通过连接池访问,因此Default服务将流量直接转发至离线实例的Postgres,绕过了Pgbouncer。

离线实例指的是 pg_roleoffline 或带有 pg_offline_query 标记的实例。离线实例外的其他其他从库将作为Offline的备份实例,这样当Offline实例宕机时,Offline服务仍然可以从其他从库获取服务。

# offline service will route {ip|name}:5438 to offline postgres (5438->5432 offline)
- name: offline           # service name {{ pg_cluster }}-offline
  src_ip: "*"
  src_port: 5438
  dst_port: postgres
  check_url: /replica     # offline MUST be a replica
  selector: "[? pg_role == `offline` || pg_offline_query ]"         # instances with pg_role == 'offline' or instance marked with 'pg_offline_query == true'
  selector_backup: "[? pg_role == `replica` && !pg_offline_query]"  # replica are used as backup server in offline service

自定义服务

在以上由 pg_services 配置的默认服务之外,用户可以使用相同的服务定义,在 pg_services_extra 配置项中为PostgreSQL数据库集群定义额外的服务。

一个集群都可以定义多个服务,每个服务包含任意数量的集群成员,服务通过端口进行区分。以下代码定义了一个新的服务standby,使用5435端口对外提供同步读取功能。该服务会从集群中的同步从库(或主库)进行读取,从而确保所有读取都不存在延迟。

# standby service will route {ip|name}:5435 to sync replica's pgbouncer (5435->6432 standby)
- name: standby                   # required, service name, the actual svc name will be prefixed with `pg_cluster`, e.g: pg-meta-standby
  src_ip: "*"                     # required, service bind ip address, `*` for all ip, `vip` for cluster `vip_address`
  src_port: 5435                  # required, service exposed port (work as kubernetes service node port mode)
  dst_port: postgres              # optional, destination port, postgres|pgbouncer|<port_number>   , pgbouncer(6432) by default
  check_method: http              # optional, health check method: http is the only available method for now
  check_port: patroni             # optional, health check port: patroni|pg_exporter|<port_number> , patroni(8008) by default
  check_url: /read-only?lag=0     # optional, health check url path, / by default
  check_code: 200                 # optional, health check expected http code, 200 by default
  selector: "[]"                  # required, JMESPath to filter inventory ()
  selector_backup: "[? pg_role == `primary`]"  # primary used as backup server for standby service (will not work because /sync for )
  haproxy:                        # optional, adhoc parameters for haproxy service provider (vip_l4 is another service provider)
    maxconn: 3000                 # optional, max allowed front-end connection
    balance: roundrobin           # optional, haproxy load balance algorithm (roundrobin by default, other: leastconn)
    default_server_options: 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'

必选项目

  • 名称(service.name

    服务名称,服务的完整名称以数据库集群名为前缀,以service.name为后缀,通过-连接。例如在pg-test集群中name=primary的服务,其完整服务名称为pg-test-primary

  • 端口(service.port

    在Pigsty中,服务默认采用NodePort的形式对外暴露,因此暴露端口为必选项。但如果使用外部负载均衡服务接入方案,您也可以通过其他的方式区分服务。

  • 选择器(service.selector

    选择器指定了服务的实例成员,采用JMESPath的形式,从所有集群实例成员中筛选变量。默认的[]选择器会选取所有的集群成员。

可选项目

  • 备份选择器(service.selector

    可选的 备份选择器service.selector_backup会选择或标记用于服务备份的实例列表,即集群中所有其他成员失效时,备份实例才接管服务。例如可以将primary实例加入replica服务的备选集中,当所有从库失效后主库依然可以承载集群的只读流量。

  • 源端IP(service.src_ip

    表示服务对外使用的IP地址,默认为*,即本机所有IP地址。使用vip则会使用vip_address变量取值,或者也可以填入网卡支持的特定IP地址。

  • 宿端口(service.dst_port

    服务的流量将指向目标实例上的哪个端口?postgres 会指向数据库监听的端口,pgbouncer会指向连接池所监听的端口,也可以填入固定的端口号。

  • 健康检查方式(service.check_method:

    服务如何检查实例的健康状态?目前仅支持HTTP

  • 健康检查端口(service.check_port:

    服务检查实例的哪个端口获取实例的健康状态? patroni会从Patroni(默认8008)获取,pg_exporter会从PG Exporter(默认9630)获取,用户也可以填入自定义的端口号。

  • 健康检查路径(service.check_url:

    服务执行HTTP检查时,使用的URL PATH。默认会使用/作为健康检查,PG Exporter与Patroni提供了多样的健康检查方式,可以用于主从流量区分。例如,/primary仅会对主库返回成功,/replica仅会对从库返回成功。/read-only则会对任何支持只读的实例(包括主库)返回成功。

  • 健康检查代码(service.check_code:

    HTTP健康检查所期待的代码,默认为200

  • Haproxy特定配置(service.haproxy

    关于服务供应软件(HAProxy)的专有配置项

服务实现

目前Pigsty默认使用基于HAProxy的服务实现,也有基于DPVS 4层负载均衡(L4VIP)的私有实现。两者相互等效,各有优势。详情请参考接入一节。


接入

接入是为了解决生产环境中高并发,高可用,高性能的问题。个人用户可以选择无视接入机制,绕过域名、VIP、负载均衡器、连接池,直接通过IP地址访问数据库。

个人用户可直接用连接串 postgres://dbuser_dba:[email protected]:5432/meta 访问默认数据库 (注意替换IP地址与密码,沙箱环境可从宿主机访问)

在Pigsty的默认配置中,每一个数据库实例/节点上都一一对应部署有一个功能完整的负载均衡器(HAProxy),因此整个数据库集群中的任意实例都可以作为整个集群的服务接入点。Pigsty数据库集群的交付边界止步于接入层负载均衡器(HAProxy);您需要自行决定接入策略:如何将业务流量分发至集群中的一台、多台、或全部负载均衡实例

Pigsty提供了丰富的接入方式,用户可以根据自己的网络基础设施情况与喜好自行选择。作为样例,Pigsty沙箱中使用了一个绑定在集群主库上的L2 VIP,一个绑定在该VIP上的域名。应用程序通过域名透过L2 VIP访问集群主库上的负载均衡实例。当该节点不可用时,VIP会随集群主库漂移,流量也随之由新主库上的负载均衡器承载,如下图所示:

另一种经典的策略是直接使用DNS轮询的方式,将DNS域名解析至所有实例,本文会给出几种常见的接入模式。

用户接口

从用户的角度来看,访问数据库只需要一个连接串;而Pigsty向最终用户交付的接口,也是一个数据库连接串。

不同的接入方式在形式上的区别是连接串中主机端口部分的不同。

端口

Pigsty使用不同的端口来区分数据库服务,提供Postgres等效服务的端口如下:

端口 服务 类型 说明
5432 postgres 数据库 直接访问当前节点数据库实例
6432 pgbouncer 连接池 通过连接池访问当前节点数据库
5433 primary 服务 负载均衡并通过连接池访问集群主库
5434 replica 服务 负载均衡并通过连接池访问集群主库
5436 default 服务 通过负载均衡直达集群主库
5438 offline 服务 通过负载均衡直达集群离线访问实例

主机

类型 样例 说明
集群域名 pg-test 直接访问当前节点数据库实例
集群VIP 10.10.10.3 通过连接池访问当前节点数据库
特定实例域名 pg-test-1 负载均衡并通过连接池访问集群主库
特定实例IP 10.10.10.11 负载均衡并通过连接池访问集群主库
所有IP地址 10.10,10.11,10.12 使用Multihost特性,需要客户端支持

根据host部分填入的内容,与可用的port值,可以排列组合出多种连接串来。

可用连接串组合

以单节点沙箱环境为例,以下连接串都可以用于数据库集群pg-test上的test数据库:

可用连接串排列组合
# 通过集群域名接入
postgres://test@pg-test:5432/test               # DNS -> L2 VIP -> 主库直连
postgres://test@pg-test:6432/test               # DNS -> L2 VIP -> 主库连接池 -> 主库
postgres://test@pg-test:5433/test               # DNS -> L2 VIP -> HAProxy -> 主库连接池 -> 主库
postgres://test@pg-test:5434/test               # DNS -> L2 VIP -> HAProxy -> 从库连接池 -> 从库
postgres://dbuser_dba@pg-test:5436/test         # DNS -> L2 VIP -> HAProxy -> 主库直连(管理用)
postgres://dbuser_stats@pg-test:5438/test       # DNS -> L2 VIP -> HAProxy -> 离线库直连(ETL/个人查询用)

# 通过集群VIP直接接入
postgres://[email protected]:5432/test            # L2 VIP -> 主库直连
postgres://[email protected]:6432/test            # L2 VIP -> 主库连接池 -> 主库
postgres://[email protected]:5433/test            # L2 VIP -> HAProxy -> 主库连接池 -> 主库
postgres://[email protected]:5434/test            # L2 VIP -> HAProxy -> 从库连接池 -> 从库
postgres://[email protected]:5436/test      # L2 VIP -> HAProxy -> 主库直连(管理用)
postgres://[email protected]:5438/test   # L2 VIP -> HAProxy -> 离线库直连(ETL/个人查询用)

# 直接指定任意集群实例名
postgres://test@pg-test-1:5432/test             # DNS -> 数据库实例直连 (单实例接入)
postgres://test@pg-test-1:6432/test             # DNS -> 连接池 -> 数据库
postgres://test@pg-test-1:5433/test             # DNS -> HAProxy -> 连接池 -> 数据库读写
postgres://test@pg-test-1:5434/test             # DNS -> HAProxy -> 连接池 -> 数据库只读
postgres://dbuser_dba@pg-test-1:5436/test       # DNS -> HAProxy -> 数据库直连
postgres://dbuser_stats@pg-test-1:5438/test     # DNS -> HAProxy -> 数据库离线读写

# 直接指定任意集群实例IP接入
postgres://[email protected]:5432/test           # 数据库实例直连 (直接指定实例,无自动流量分发)
postgres://[email protected]:6432/test           # 连接池 -> 数据库
postgres://[email protected]:5433/test           # HAProxy -> 连接池 -> 数据库读写
postgres://[email protected]:5434/test           # HAProxy -> 连接池 -> 数据库只读
postgres://[email protected]:5436/test     # HAProxy -> 数据库直连
postgres://[email protected]:5438/test   # HAProxy -> 数据库离线读写

# 直接指定任意集群实例IP接入
postgres://[email protected]:5432/test           # 数据库实例直连 (直接指定实例,无自动流量分发)
postgres://[email protected]:6432/test           # 连接池 -> 数据库
postgres://[email protected]:5433/test           # HAProxy -> 连接池 -> 数据库读写
postgres://[email protected]:5434/test           # HAProxy -> 连接池 -> 数据库只读
postgres://[email protected]:5436/test     # HAProxy -> 数据库直连
postgres://[email protected]:5438/test   # HAProxy -> 数据库离线读写

# 智能客户端自动读写分离(连接池)
postgres://[email protected]:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=primary
postgres://[email protected]:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=prefer-standby

# 智能客户端自动读写分离(数据库)
postgres://[email protected]:5432,10.10.10.12:5432,10.10.10.13:5432/test?target_session_attrs=primary
postgres://[email protected]:5432,10.10.10.12:5432,10.10.10.13:5432/test?target_session_attrs=prefer-standby

在集群层次,用户可以通过集群域名+服务端口的方式访问集群提供的 四种默认服务,Pigsty强烈建议使用这种方式。当然用户也可以绕开域名,直接使用集群的VIP(L2 or L4)访问数据库集群。

在实例层次,用户可以通过节点IP/域名 + 5432端口直连Postgres数据库,也可以用6432端口经由Pgbouncer访问数据库。还可以通过Haproxy经由5433~543x访问实例所属集群提供的服务。

典型接入方案

Pigsty推荐使用基于Haproxy的接入方案(1/2),在生产环境中如果有基础设施支持,也可以使用基于L4VIP(或与之等效的负载均衡服务)的接入方案(3)。

序号 方案 说明
1 L2VIP + Haproxy Pigsty沙箱使用的标准接入架构,使用L2 VIP确保Haproxy高可用
2 DNS + Haproxy 标准高可用接入方案,系统无单点。
3 L4VIP + Haproxy 方案2的变体,使用L4 VIP确保Haprxoy高可用。
4 L4 VIP 大规模高性能生产环境建议使用DPVS L4 VIP直接接入
5 Consul DNS 使用Consul DNS进行服务发现,绕开VIP与Haproxy
6 Static DNS 传统静态DNS接入方式
7 IP 采用智能客户端接入

L2 VIP + Haproxy

方案简介

Pigsty沙箱使用的标准接入方案,采用单个域名绑定至单个L2 VIP,VIP指向集群中的HAProxy。

集群中的Haproxy采用Node Port的方式统一对外暴露 服务。每个Haproxy都是幂等的实例,提供完整的负载均衡与服务分发功能。Haproxy部署于每一个数据库节点上,因此整个集群的每一个成员在使用效果上都是幂等的。(例如访问任何一个成员的5433端口都会连接至主库连接池,访问任意成员的5434端口都会连接至某个从库的连接池)

Haproxy本身的可用性通过幂等副本实现,每一个Haproxy都可以作为访问入口,用户可以使用一个、两个、多个,所有Haproxy实例,每一个Haproxy提供的功能都是完全相同的。

每个集群都分配有一个L2 VIP,固定绑定至集群主库。当主库发生切换时,该L2 VIP也会随之漂移至新的主库上。这是通过vip-manager实现的:vip-manager会查询Consul获取集群当前主库信息,然后在主库上监听VIP地址。

集群的L2 VIP有与之对应的域名。域名固定解析至该L2 VIP,在生命周期中不发生变化。

方案优越性

  • 无单点,高可用
  • VIP固定绑定至主库,可以灵活访问

方案局限性

  • 多一跳
  • Client IP地址丢失,部分HBA策略无法正常生效
  • 所有候选主库必须位于同一二层网络
    • 作为备选,用户也可以通过使用L4 VIP绕开此限制,但相比L2 VIP会额外多一跳。
    • 作为备选,用户也可以选择不用L2 VIP,而用DNS直接指向HAProxy,但可能会受到客户端DNS缓存的影响。

方案示意

DNS + Haproxy

方案简介

标准高可用接入方案,系统无单点。灵活性,适用性,性能达到一个较好的平衡。

集群中的Haproxy采用Node Port的方式统一对外暴露 服务。每个Haproxy都是幂等的实例,提供完整的负载均衡与服务分发功能。Haproxy部署于每一个数据库节点上,因此整个集群的每一个成员在使用效果上都是幂等的。(例如访问任何一个成员的5433端口都会连接至主库连接池,访问任意成员的5434端口都会连接至某个从库的连接池)

Haproxy本身的可用性通过幂等副本实现,每一个Haproxy都可以作为访问入口,用户可以使用一个、两个、多个,所有Haproxy实例,每一个Haproxy提供的功能都是完全相同的。

用户需要自行确保应用能够访问到任意一个健康的Haproxy实例。作为最朴素的一种实现,用户可以将数据库集群的DNS域名解析至若干Haproxy实例,并启用DNS轮询响应。而客户端可以选择完全不缓存DNS,或者使用长连接并实现建立连接失败后重试的机制。又或者参考方案2,在架构侧通过额外的L2/L4 VIP确保Haproxy本身的高可用。

方案优越性

  • 无单点,高可用
  • VIP固定绑定至主库,可以灵活访问

方案局限性

  • 多一跳

  • Client IP地址丢失,部分HBA策略无法正常生效

  • Haproxy本身的高可用通过幂等副本,DNS轮询与客户端重连实现

    DNS应有轮询机制,客户端应当使用长连接,并有建连失败重试机制。以便单Haproxy故障时可以自动漂移至集群中的其他Haproxy实例。如果无法做到这一点,可以考虑使用接入方案2,使用L2/L4 VIP确保Haproxy高可用。

方案示意

L4 VIP + Haproxy

四层负载均衡 + HAProxy接入

方案简介

接入方案1/2的另一种变体,通过L4 VIP确保Haproxy的高可用

方案优越性

  • 无单点,高可用
  • 可以同时使用所有的Haproxy实例,均匀承载流量。
  • 所有候选主库不需要位于同一二层网络。
  • 可以操作单一VIP完成流量切换(如果同时使用了多个Haproxy,不需要逐个调整)

方案局限性

  • 多两跳,较为浪费,如果有条件可以直接使用方案4: L4 VIP直接接入。
  • Client IP地址丢失,部分HBA策略无法正常生效

L4 VIP

四层负载均衡接入

方案简介

大规模高性能生产环境建议使用 L4 VIP接入(FullNAT,DPVS)

方案优越性

  • 性能好,吞吐量大
  • 可以通过toa模块获取正确的客户端IP地址,HBA可以完整生效。

方案局限性

  • 仍然多一条。
  • 需要依赖外部基础设施,部署复杂。
  • 未启用toa内核模块时,仍然会丢失客户端IP地址。
  • 没有Haproxy屏蔽主从差异,集群中的每个节点不再“幂等”。

Consul DNS

Consul DNS接入

方案简介

L2 VIP并非总是可用,特别是所有候选主库必须位于同一二层网络的要求可能不一定能满足。

在这种情况下,可以使用DNS解析代替L2 VIP

方案优越性

  • 少一跳

方案局限性

  • 依赖Consul DNS
  • 用户需要合理配置DNS缓存策略

Static DNS

静态DNS接入

方案简介

传统静态DNS接入方式

方案优越性

  • 少一跳
  • 实施简单

方案局限性

  • 没有灵活性
  • 主从切换时容易导致流量损失

IP

IP直连接入

方案简介

采用智能客户端直连数据库IP接入

方案优越性

  • 直连数据库/连接池,少一条
  • 不依赖额外组件进行主从区分,降低系统复杂性。

方案局限性

  • 灵活性太差,集群扩缩容繁琐。

12 - PGSQL业务用户与数据库

从 Pigsty v1.5.1 标签恢复的历史文档。

如何定义并创建PostgreSQL业务用户数据库


用户

在PostgreSQL中,用户(User) 指的是数据库集簇中的一个对象,由SQL语句CREATE USER/ROLE所创建。

在PostgreSQL中,用户直接隶属于数据库集簇而非某个具体的数据库。因此在创建业务数据库和业务用户时,应当遵循"先用户,后数据库"的原则。

定义用户

Pigsty通过两个配置参数定义数据库集群中的角色与用户:

前者定义了整套环境中共有的角色,后者定义单个集群中特有的业务角色与用户。二者形式相同,均为用户定义对象数组。 下面是一个用户定义的例子:

- name: dbuser_meta               # required, `name` is the only mandatory field of a user definition
  password: md5d3d10d8cad606308bdb180148bf663e1  # md5 salted password of 'DBUser.Meta'
  # optional, plain text and md5 password are both acceptable (prefixed with `md5`)
  login: true                     # optional, can login, true by default  (new biz ROLE should be false)
  superuser: false                # optional, is superuser? false by default
  createdb: false                 # optional, can create database? false by default
  createrole: false               # optional, can create role? false by default
  inherit: true                   # optional, can this role use inherited privileges? true by default
  replication: false              # optional, can this role do replication? false by default
  bypassrls: false                # optional, can this role bypass row level security? false by default
  pgbouncer: true                 # optional, add this user to pgbouncer user-list? false by default (production user should be true explicitly)
  connlimit: -1                   # optional, user connection limit, default -1 disable limit
  expire_in: 3650                 # optional, now + n days when this role is expired (OVERWRITE expire_at)
  expire_at: '2030-12-31'         # optional, YYYY-MM-DD 'timestamp' when this role is expired  (OVERWRITTEN by expire_in)
  comment: pigsty admin user      # optional, comment string for this user/role
  roles: [dbrole_admin]           # optional, belonged roles. default roles are: dbrole_{admin,readonly,readwrite,offline}
  parameters: {}                  # optional, role level parameters with `ALTER ROLE SET`
  # search_path: public         # key value config parameters according to postgresql documentation (e.g: use pigsty as default search_path)
  • name : 每一个用户或角色必须指定 name,唯一的必选参数。
  • password : 是可选项,如果留空则不设置密码,可以使用MD5密文密码。
  • login, superuser, createdb, createrole, inherit, replication, bypassrls : 都是布尔类型标记,用于设置用户属性。如果不设置,则采用系统默认值。 其中pg_default_roles的用户默认不带有login属性,而pg_users默认带有login属性,可通过显式配置覆盖。
  • expire_atexpire_in用于控制用户过期时间,expire_at使用形如YYYY-mm-DD的日期时间戳。expire_in使用从现在开始的过期天数,如果expire_in存在则会覆盖expire_at选项。
  • pgbouncer: true 用于控制是否将新用户加入Pgbouncer用户列表中,该参数必须显式定义为true,相应用户才会被加入到Pgbouncer用户列表。
  • roles 为该角色/用户所属的分组,可以指定多个分组,例如为用户添加默认角色

创建用户

在创建数据库集群(或主库实例)时,pg_default_rolespg_users 定义的角色和用户会自动依序创建。

在运行中的已有数据库集群上,使用预制剧本 pgsql-createuser.yml 来创建新的业务数据库。

首先,您需要在相应数据库集群配置的 pg_users 配置项中添加该用户的定义。然后,使用以下命令即可在对应集群上创建该用户或角色。

bin/createuser <pg_cluster> <username>    # <pg_cluster> 为集群名称,<user.name> 是新用户名。必须先定义,再执行脚本进行创建
bin/createuser pg-meta dbuser_meta        # 例:在pg-meta集群中创建dbuser_meta用户
./pgsql-createuser.yml -l <pg_cluster> -e pg_user=<user.name>  # 该脚本实际上调用了以下Ansible剧本完成对应任务

当目标用户已经存在时,Pigsty会修改目标用户的属性使其符合配置。

如果被创建的用户带有pgbouncer: true标记,该剧本会同时修改并重载数据库集群内所有Pgbouncer的配置/etc/pgbouncer/userlist.txt

警告

务必通过预置剧本或脚本添加新业务用户与业务数据库,否则难以保证连接池配置信息与数据库同步

Pgbouncer中的用户

Pgbouncer的操作系统用户将与数据库超级用户保持一致,都使用{{ pg_dbsu }},默认为postgres。 Pigsty默认使用Postgres管理用户作为Pgbouncer的管理用户,使用Postgres的监控用户同时作为Pgbouncer的监控用户。

Pgbouncer的用户列表通过/etc/pgbouncer/userlist.txt文件进行控制, Pgbouncer的用户权限通过/etc/pgbouncer/pgb_hba.conf进行控制。

只有显式添加pgbouncer: true配置条目的用户才会被加入到Pgbouncer用户列表中,并通过Pgbouncer访问数据库。 通常生产应用使用的账号应当通过Pgbouncer连接池访问数据库,而个人用户,管理,ETL等则应当直接访问数据库。

正常情况下请使用 pgsql-createuser.yml 剧本管理数据库用户。紧急情况下亦可在数据库实例上以postgres用户执行以下命令来手工添加用户,需要在集群中所有Pgbouncer上执行该命令并重新加载配置。

# 紧急情况下可以使用该命令手工添加用户,用法:pgbouncer-create-user <username> [password]
/pg/bin/pgbouncer-create-user

pgbouncer-create-user dbp_vonng Test.Password # 明文密码
pgbouncer-create-user dbp_vonng md596bceae83ba2937778af09adf00ae738 # md5密码
pgbouncer-create-user dbp_vonng auto          # 从数据库查询获取密码
pgbouncer-create-user dbp_vonng null          # 使用空密码

数据库

这里的 数据库(Database) 所指代的既非数据库软件,也不是数据库服务器进程,而是指数据库集簇中的一个逻辑对象,由SQL语句CREATE DATABASE所创建。

Pigsty会对默认模板数据库template1进行修改与定制,创建默认模式,安装默认扩展,配置默认权限,新创建的数据库默认会从template1继承这些设置。

PostgreSQL提供了 模式(Schema) 作为命名空间,因此并不推荐在单个数据库集簇中创建过多数据库。

pg_exporter 默认会通过 自动发现 机制查找所有业务数据库并监控。

定义数据库

Pigsty通过 pg_databases 配置参数定义数据库集群中的数据库,这是一个数据库定义构成的对象数组, 数组内的数据库按照定义顺序依次创建,因此后面定义的数据库可以使用先前定义的数据库作为模板

下面是一个数据库定义的例子:

- name: meta                      # required, `name` is the only mandatory field of a database definition
  baseline: cmdb.sql              # optional, database sql baseline path, (relative path among ansible search path, e.g files/)
  owner: postgres                 # optional, database owner, postgres by default
  template: template1             # optional, which template to use, template1 by default
  encoding: UTF8                  # optional, database encoding, UTF8 by default. (MUST same as template database)
  locale: C                       # optional, database locale, C by default.  (MUST same as template database)
  lc_collate: C                   # optional, database collate, C by default. (MUST same as template database)
  lc_ctype: C                     # optional, database ctype, C by default.   (MUST same as template database)
  tablespace: pg_default          # optional, default tablespace, 'pg_default' by default.
  allowconn: true                 # optional, allow connection, true by default. false will disable connect at all
  revokeconn: false               # optional, revoke public connection privilege. false by default. (leave connect with grant option to owner)
  pgbouncer: true                 # optional, add this database to pgbouncer database list? true by default
  comment: pigsty meta database   # optional, comment string for this database
  connlimit: -1                   # optional, database connection limit, default -1 disable limit
  schemas: [pigsty]               # optional, additional schemas to be created, array of schema names
  extensions:                     # optional, additional extensions to be installed: array of schema definition `{name,schema}`
    - {name: adminpack, schema: pg_catalog}    # install adminpack to pg_catalog and install postgis to public
    - {name: postgis, schema: public}          # if schema is omitted, extension will be installed according to search_path.
  • name:数据库名称,必选项
  • baseline:SQL文件路径(Ansible搜索路径,通常位于files),用于初始化数据库内容。
  • owner:数据库属主,默认为postgres
  • template:数据库创建时使用的模板,默认为template1
  • encoding:数据库默认字符编码,默认为UTF8,默认与实例保持一致。建议不要配置与修改。
  • locale:数据库默认的本地化规则,默认为C,建议不要配置,与实例保持一致。
  • lc_collate:数据库默认的本地化字符串排序规则,默认与实例设置相同,建议不要修改,必须与模板数据库一致。强烈建议不要配置,或配置为C
  • lc_ctype:数据库默认的LOCALE,默认与实例设置相同,建议不要修改或设置,必须与模板数据库一致。建议配置为C或en_US.UTF8
  • allowconn:是否允许连接至数据库,默认为true,不建议修改。
  • revokeconn:是否回收连接至数据库的权限?默认为false。如果为true,则数据库上的PUBLIC CONNECT权限会被回收。只有默认用户(dbsu|monitor|admin|replicator|owner)可以连接。此外,admin|owner 会拥有GRANT OPTION,可以赋予其他用户连接权限。
  • tablespace:数据库关联的表空间,默认为pg_default
  • connlimit:数据库连接数限制,默认为-1,即没有限制。
  • extensions:对象数组 ,每一个对象定义了一个数据库中的扩展,以及其安装的模式
  • parameters:KV对象,每一个KV定义了一个需要针对数据库通过ALTER DATABASE修改的参数。
  • pgbouncer:布尔选项,是否将该数据库加入到Pgbouncer中。所有数据库都会加入至Pgbouncer列表,除非显式指定pgbouncer: false
  • comment:数据库备注信息。

创建数据库

在创建数据库集群(或主库实例)时,pg_databases 定义的数据库会依序自动创建。

在运行中的已有数据库集群上,使用预制剧本 pgsql-createdb.yml 来创建新的业务数据库。

首先在相应数据库集群配置的 pg_databases 配置项中添加该数据库的定义。然后,使用以下命令即可在对应集群上创建该数据库:

bin/createdb <pg_cluster>  <database.name> # <pg_cluster> 为集群名称,<database.name> 是新数据库的name。
bin/createdb pg-meta meta                  # 例:在pg-meta集群中创建meta数据库
./pgsql-createdb.yml -l <pg_cluster> -e pg_database=<dbname>  # 该脚本实际上调用了以下Ansible剧本完成对应任务

当目标数据库已经存在时,Pigsty会修改目标数据库的属性使其符合配置。

如果您为数据库配置了owner参数,则必须确保数据库创建时该用户已经存在。所以通常建议先完成业务用户的创建,再创建数据库。

该剧本默认会修改并重载数据库集群内所有Pgbouncer的配置/etc/pgbouncer/database.txt。但如果被创建的数据库带有pgbouncer: false标记,该剧本会跳过Pgbouncer配置阶段

警告

如果数据库会通过连接池对外服务,请务必通过预置剧本或脚本创建

Pgbouncer中的数据库

Pgbouncer的操作系统用户将与数据库超级用户保持一致,都使用{{ pg_dbsu }},默认为postgres。 Pgbouncer的管理数据库名为pgbouncer,可以使用postgresdbuser_dba用户进行管理,在操作系统用户postgres下执行快捷方式pgb即可以管理员身份连接至pgbouncer

Pgbouncer中的数据库列表通过/etc/pgbouncer/database.txt文件进行控制,默认内容类似以下格式

# 数据库名 = 实际目标连接信息
meta = host=/var/run/postgresql
grafana = host=/var/run/postgresql
prometheus = host=/var/run/postgresql

在Pigsty中,Pgbouncer与Postgres实例采用1:1同机部署,使用 /var/run/postgresql Unix Socket通信。

通常情况下,所有新数据库都会被加入到Pgbouncer的数据库列表中。如果您希望某数据库无法通过Pgbouncer访问,可以在数据库定义中显式指定pgbouncer: false

正常情况下请使用 pgsql-createdb.yml 剧本创建新的数据库。亦可在数据库实例上以postgres用户执行以下命令来手工添加数据库,需要在集群中所有Pgbouncer上执行该命令并重新加载配置。

# 特殊情况下可以使用该命令手工添加数据库
# pgbouncer-create-user <dbname> [connstr] [dblist=/etc/pgbouncer/database.txt]
/pg/bin/pgbouncer-create-db
pgbouncer-create-db meta                     # 创建meta数据库,指向本机同名数据库
pgbouncer-create-db test host=10.10.10.13    # 创建test数据库并将其指向10.10.10.13上的同名数据库
说明

手工修改Pgbouncer配置后,请通过systemctl reload pgbouncer重载生效。(切勿使用pgbouncer -R

13 - PGSQL 权限认证与访问控制

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty提供了一套开箱即用的访问控制模型,简单实用,可满足基本安全需求。

PostgreSQL提供了标准的访问控制机制:认证(Authentication)与权限(Privileges),认证与权限都基于角色(Role)体系进行。


角色

Pigsty的默认角色体系包含四个默认角色,以及四个默认用户

以下是Pigsty自带的8个默认用户/角色的定义

name attr roles desc
dbrole_readonly Cannot login role for global readonly access
dbrole_readwrite Cannot login dbrole_readonly role for global read-write access
dbrole_offline Cannot login role for restricted read-only access (offline instance)
dbrole_admin Cannot login
Bypass RLS
pg_monitor
pg_signal_backend
dbrole_readwrite
role for object creation
postgres Superuser
Create role
Create DB
Replication
Bypass RLS
system superuser
replicator Replication
Bypass RLS
pg_monitor
dbrole_readonly
system replicator
dbuser_monitor 16 connections pg_monitor
dbrole_readonly
system monitor user
dbuser_dba Bypass RLS
Superuser
dbrole_admin system admin user

默认角色

Pigsty带有四个默认角色:

  • 只读角色(dbrole_readonly):对所有数据表具有只读权限。
  • 读写角色(dbrole_readwrite):对所有数据表具有写入权限,继承dbrole_readonly
  • 管理角色(dbrole_admin):可以执行DDL变更,继承dbrole_readwrite
  • 离线角色(dbrole_offline):特殊只读角色,用于执行慢查询/ETL/交互查询,仅允许在特定实例上访问。

其定义如下所示

- { name: dbrole_readonly  , login: false , comment: role for global read-only access  }                            # production read-only role
- { name: dbrole_offline ,   login: false , comment: role for restricted read-only access (offline instance) }      # restricted-read-only role
- { name: dbrole_readwrite , login: false , roles: [dbrole_readonly], comment: role for global read-write access }  # production read-write role
- { name: dbrole_admin , login: false , roles: [pg_monitor, dbrole_readwrite] , comment: role for object creation } # production DDL change role
警告

不建议普通用户修改默认角色的名称

默认用户

Pigsty带有四个默认用户:

  • 超级用户(postgres),数据库的拥有者与创建者,与操作系统用户一致
  • 复制用户(replicator),用于主从复制的系统用户
  • 监控用户(dbuser_monitor),用于监控数据库与连接池指标的用户
  • 管理员(dbuser_dba),执行日常管理操作与数据库变更的管理员用户

其定义如下所示:

- { name: postgres , superuser: true , comment: system superuser }                             # system dbsu, name is designated by `pg_dbsu`
- { name: dbuser_dba , superuser: true , roles: [dbrole_admin] , comment: system admin user }  # admin dbsu, name is designated by `pg_admin_username`
- { name: replicator , replication: true , bypassrls: true , roles: [pg_monitor, dbrole_readonly] , comment: system replicator }                   # replicator
- { name: dbuser_monitor , roles: [pg_monitor, dbrole_readonly] , comment: system monitor user , parameters: {log_min_duration_statement: 1000 } } # monitor user

在Pigsty中,4个默认的重要用户的用户名和密码是由独立参数控制与管理的:

pg_dbsu: postgres                             # os user for database

# - system roles - #
pg_replication_username: replicator           # system replication user
pg_replication_password: DBUser.Replicator    # system replication password
pg_monitor_username: dbuser_monitor           # system monitor user
pg_monitor_password: DBUser.Monitor           # system monitor password
pg_admin_username: dbuser_dba                 # system admin user
pg_admin_password: DBUser.DBA                 # system admin password

出于安全考虑,不建议为默认超级用户postgres设置密码或允许远程访问,所以没有专门的dbsu_password选项。 如果有此类需求,可在pg_default_roles中为超级用户设置密码。

警告

在生产环境使用时,请务必修改所有默认用户的密码

此外,用户可以在 pg_users 定义集群特定的业务用户,定义方式与 pg_default_roles 一致。

警告

如果有较高数据安全需求,建议移除 dbuser_monitordborle_readony 角色,部分监控系统功能会不可用。


认证

认证是数据库验证来访连接身份的过程。Pigsty默认使用md5密码认证,并基于PostgreSQL HBA机制提供访问控制。

HBA是Host Based Authentication的缩写,可以将其视作IP黑白名单。

HBA配置方式

在Pigsty中,所有实例的HBA都由配置文件生成而来,最终生成的HBA规则因实例的角色(pg_role)而不同。 Pigsty的HBA由下列变量控制:

每个变量都是由下列样式的规则组成的数组:

- title: allow intranet admin password access
  role: common
  rules:
    - host    all     +dbrole_admin               10.0.0.0/8          md5
    - host    all     +dbrole_admin               172.16.0.0/12       md5
    - host    all     +dbrole_admin               192.168.0.0/16      md5

基于角色的HBA

role = common的HBA规则组会安装到所有的实例上,而其他的取值,例如(role : primary)则只会安装至pg_role = primary的实例上。因此用户可以通过角色体系定义灵活的HBA规则。

作为特例role: offline 的HBA规则,除了会安装至pg_role == 'offline'的实例,也会安装至pg_offline_query == true的实例上。

HBA的渲染优先级规则为:

  • hard_coded_rules 全局硬编码规则
  • pg_hba_rules_extra.common 集群通用规则
  • pg_hba_rules_extra.pg_role 集群角色规则
  • pg_hba_rules.pg_role 全局角色规则
  • pg_hba_rules.offline 集群离线规则
  • pg_hba_rules_extra.offline 全局离线规则
  • pg_hba_rules.common 全局通用规则

默认HBA规则

在默认配置下,主库与从库会使用以下的HBA规则:

  • 超级用户通过本地操作系统认证访问
  • 其他用户可以从本地用密码访问
  • 复制用户可以从局域网段通过密码访问
  • 监控用户可以通过本地访问
  • 所有人都可以在元节点上使用密码访问
  • 管理员可以从局域网通过密码访问
  • 所有人都可以从内网通过密码访问
  • 读写用户(生产业务账号)可以通过本地(连接池)访问 (部分访问控制转交连接池处理)
  • 在从库上:只读用户(个人)可以从本地(连接池)访问。 (意味主库上拒绝只读用户连接)
  • pg_role == 'offline' 或带有pg_offline_query == true的实例上,会添加允许dbrole_offline分组用户访问的HBA规则。
默认HBA规则详情
#==============================================================#
# Default HBA
#==============================================================#
# allow local su with ident"
local   all             postgres                               ident
local   replication     postgres                               ident

# allow local user password access
local   all             all                                    md5

# allow local/intranet replication with password
local   replication     replicator                              md5
host    replication     replicator         127.0.0.1/32         md5
host    all             replicator         10.0.0.0/8           md5
host    all             replicator         172.16.0.0/12        md5
host    all             replicator         192.168.0.0/16       md5
host    replication     replicator         10.0.0.0/8           md5
host    replication     replicator         172.16.0.0/12        md5
host    replication     replicator         192.168.0.0/16       md5

# allow local role monitor with password
local   all             dbuser_monitor                          md5
host    all             dbuser_monitor      127.0.0.1/32        md5

#==============================================================#
# Extra HBA
#==============================================================#
# add extra hba rules here

#==============================================================#
# primary HBA
#==============================================================#

#==============================================================#
# special HBA for instance marked with 'pg_offline_query = true'
#==============================================================#

#==============================================================#
# Common HBA
#==============================================================#
#  allow meta node password access
host    all     all                         10.10.10.10/32      md5

#  allow intranet admin password access
host    all     +dbrole_admin               10.0.0.0/8          md5
host    all     +dbrole_admin               172.16.0.0/12       md5
host    all     +dbrole_admin               192.168.0.0/16      md5

#  allow intranet password access
host    all             all                 10.0.0.0/8          md5
host    all             all                 172.16.0.0/12       md5
host    all             all                 192.168.0.0/16      md5

#  allow local read/write (local production user via pgbouncer)
local   all     +dbrole_readonly                                md5
host    all     +dbrole_readonly           127.0.0.1/32         md5

#==============================================================#
# Ad Hoc HBA
#===========================================================

修改HBA规则

HBA规则会在集群/实例初始化时自动生成。

用户可以在数据库集群/实例创建并运行后通过剧本修改并应用新的HBA规则:

./pgsql.yml -t pg_hba    # 通过-l指定目标集群
bin/reloadhba <cluster>  # 重载目标集群的HBA规则

当数据库集簇目录被销毁重建后,新副本会拥有和集群主库相同的HBA规则(因为从库的数据集簇目录是主库的二进制副本,而HBA规则也在数据集簇目录中)。 这通常不是用户期待的行为。您可以使用上面的命令针对特定实例进行HBA修复。

Pgbouncer的HBA

在Pigsty中,Pgbouncer亦使用HBA进行访问控制,用法与Postgres HBA基本一致

默认的Pgbouncer HBA规则允许从本地和内网通过密码访问

pgbouncer_hba_rules:                          # pgbouncer host-based authentication rules
  - title: local password access
    role: common
    rules:
      - local  all          all                                     md5
      - host   all          all                     127.0.0.1/32    md5

  - title: intranet password access
    role: common
    rules:
      - host   all          all                     10.0.0.0/8      md5
      - host   all          all                     172.16.0.0/12   md5
      - host   all          all                     192.168.0.0/16  md5

权限

Pigsty的默认权限模型与默认角色紧密关联。使用Pigsty访问控制模型时,新创建的业务用户都应当属于四种默认角色之一,默认角色拥有的权限如下所示:

  • 所有用户都可以访问所有模式
  • 只读用户可以读取所有表
  • 读写用户可以对所有表进行DML操作(INSERT, UPDATE, DELETE)
  • 管理员可以执行DDL变更操作(CREATE, USAGE, TRUNCATE, REFERENCES, TRIGGER)
  • 离线用户与只读用户类似,但只允许访问pg_role == 'offline'pg_offline_query = true 的实例
GRANT USAGE                         ON SCHEMAS   TO dbrole_readonly;
GRANT SELECT                        ON TABLES    TO dbrole_readonly;
GRANT SELECT                        ON SEQUENCES TO dbrole_readonly;
GRANT EXECUTE                       ON FUNCTIONS TO dbrole_readonly;
GRANT USAGE                         ON SCHEMAS   TO dbrole_offline;
GRANT SELECT                        ON TABLES    TO dbrole_offline;
GRANT SELECT                        ON SEQUENCES TO dbrole_offline;
GRANT EXECUTE                       ON FUNCTIONS TO dbrole_readonly;
GRANT INSERT, UPDATE, DELETE        ON TABLES    TO dbrole_readwrite;
GRANT USAGE,  UPDATE                ON SEQUENCES TO dbrole_readwrite;
GRANT TRUNCATE, REFERENCES, TRIGGER ON TABLES    TO dbrole_admin;
GRANT CREATE                        ON SCHEMAS   TO dbrole_admin;
GRANT USAGE                         ON TYPES     TO dbrole_admin;
Owner Schema Type Access privileges
username schema postgres=UC/postgres
dbrole_readonly=U/postgres
dbrole_offline=U/postgres
dbrole_admin=C/postgres
username sequence postgres=rwU/postgres
dbrole_readonly=r/postgres
dbrole_readwrite=wU/postgres
dbrole_offline=r/postgres
username table postgres=arwdDxt/postgres
dbrole_readonly=r/postgres
dbrole_readwrite=awd/postgres
dbrole_offline=r/postgres
dbrole_admin=Dxt/postgres
username function =X/postgres
postgres=X/postgres
dbrole_readonly=X/postgres
dbrole_offline=X/postgres

对象权限的维护

数据库对象的默认访问权限通过PostgreSQL的ALTER DEFAULT PRIVILEGES确保。

所有由 {{ dbsu }}, {{ pg_admin_username }}, {{ dbrole_admin }} 创建的对象,都会拥有以上默认权限。 反过来说,如果是由其他角色创建的对象,则并不会配置有正确的默认访问权限。

Pigsty非常不建议使用业务用户执行DDL变更,因为PostgreSQL的ALTER DEFAULT PRIVILEGE仅针对“由特定用户创建的对象”生效,默认情况下超级用户postgresdbuser_dba创建的对象拥有默认的权限配置,如果希望授予业务用户执行DDL的权限,那么除了为业务用户赋予 dbrole_admin 角色外,使用者还需牢记在执行DDL变更时首先要执行:

SET ROLE dbrole_admin; -- dbrole_admin 创建的对象具有正确的默认权限

这样创建的对象才会具有默认的访问权限。

数据库的权限

数据库有三种权限:CONNECT, CREATE, TEMP,以及特殊的属主OWNERSHIP。数据库的定义由参数pg_database控制。一个完整的数据库定义如下所示:

pg_databases:                       # define business databases on this cluster, array of database definition
  # define the default `meta` database
  - name: meta                      # required, `name` is the only mandatory field of a database definition
    baseline: cmdb.sql              # optional, database sql baseline path, (relative path among ansible search path, e.g files/)
    owner: postgres                 # optional, database owner, postgres by default
    template: template1             # optional, which template to use, template1 by default
    encoding: UTF8                  # optional, database encoding, UTF8 by default. (MUST same as template database)
    locale: C                       # optional, database locale, C by default.  (MUST same as template database)
    lc_collate: C                   # optional, database collate, C by default. (MUST same as template database)
    lc_ctype: C                     # optional, database ctype, C by default.   (MUST same as template database)
    tablespace: pg_default          # optional, default tablespace, 'pg_default' by default.
    allowconn: true                 # optional, allow connection, true by default. false will disable connect at all
    revokeconn: false               # optional, revoke public connection privilege. false by default. (leave connect with grant option to owner)
    pgbouncer: true                 # optional, add this database to pgbouncer database list? true by default
    comment: pigsty meta database   # optional, comment string for this database
    connlimit: -1                   # optional, database connection limit, default -1 disable limit
    schemas: [pigsty]               # optional, additional schemas to be created, array of schema names
    extensions:                     # optional, additional extensions to be installed: array of schema definition `{name,schema}`
      - {name: adminpack, schema: pg_catalog}    # install adminpack to pg_catalog and install postgis to public
      - {name: postgis, schema: public}          # if schema is omitted, extension will be installed according to search_path.

默认情况下,如果数据库没有配置属主,那么数据库超级用户dbsu将会作为数据库的默认OWNER,否则将为指定用户。

默认情况下,所有用户都具有对新创建数据库的CONNECT 权限,如果希望回收该权限,设置 revokeconn == true,则该权限会被回收。只有默认用户(dbsu|admin|monitor|replicator)与数据库的属主才会被显式赋予CONNECT权限。同时,admin|owner将会具有CONNECT权限的GRANT OPTION,可以将CONNECT权限转授他人。

如果希望实现不同数据库之间的访问隔离,可以为每一个数据库创建一个相应的业务用户作为owner,并全部设置revokeconn选项,这种配置对于多租户实例尤为实用。

一个进行权限隔离的数据库样例
#--------------------------------------------------------------#
# pg-infra (example database for cluster loading)
#--------------------------------------------------------------#
pg-infra:
  hosts:
    10.10.10.40: { pg_seq: 1, pg_role: primary }
    10.10.10.41: { pg_seq: 2, pg_role: replica , pg_offline_query: true }
  vars:
    pg_cluster: pg-infrastructure
    pg_version: 14
    vip_address: 10.10.10.4
    pgbouncer_poolmode: session
    pg_hba_rules_extra:
      - title: allow confluence jira gitlab eazybi direct access
        role: common
        rules:
          - host    confluence dbuser_confluence   10.0.0.0/8        md5
          - host    jira       dbuser_jira         10.0.0.0/8        md5
          - host    gitlab     dbuser_gitlab       10.0.0.0/8        md5

    pg_users:
      # infra prod user
      - { name: dbuser_hybridcloud, password: ssag-2xd, pgbouncer: true, roles: [ dbrole_readwrite ] }
      - { name: dbuser_confluence, password: mc2iohos , pgbouncer: true, roles: [ dbrole_admin ] }
      - { name: dbuser_gitlab, password: sdf23g22sfdd , pgbouncer: true, roles: [ dbrole_readwrite ] }
      - { name: dbuser_jira, password: sdpijfsfdsfdfs , pgbouncer: true, roles: [ dbrole_admin ] }
    pg_databases:
      # infra database
      - { name: hybridcloud , revokeconn: true, owner: dbuser_hybridcloud , parameters: { search_path: yay,public } , connlimit: 100 }
      - { name: confluence , revokeconn: true, owner: dbuser_confluence , connlimit: 100 }
      - { name: gitlab , revokeconn: true, owner: dbuser_gitlab, connlimit: 100 }
      - { name: jira , revokeconn: true, owner: dbuser_jira , connlimit: 100 }

创建对象的权限

默认情况下,出于安全考虑,Pigsty会撤销PUBLIC用户在数据库下CREATE新模式的权限, 同时也会撤销PUBLIC用户在public模式下创建新关系的权限。 数据库超级用户与管理员不受此限制,他们总是可以在任何地方执行DDL变更。

在数据库中创建对象的权限与用户是否为数据库属主无关,这只取决于创建该用户时是否为该用户赋予管理员权限

pg_users:
  - {name: test1, password: xxx , groups: [dbrole_readwrite]}  # 不能创建Schema与对象
  - {name: test2, password: xxx , groups: [dbrole_admin]}      # 可以创建Schema与对象

14 - Pigsty部署

从 Pigsty v1.5.1 标签恢复的历史文档。

部署Pigsty分为三步:部署准备修改配置执行剧本

Pigsty的资源准备、下载安装、部署扩容缩容均为一键傻瓜式,真正的灵魂在于 配置


准备工作

安装Pigsty前,您需要准备符合要求的资源:物理机/虚拟机节点,管理用户,下载Pigsty软件。


修改配置

完成准备工作后,您需要通过配置向Pigsty表明自己的需求。我需要什么样的基础设施与数据库服务。


执行剧本

修改配置后,您已经向Pigsty表明了自己的需求。接下来便可以通过执行剧本,将需求落地。


部署方式

  • 标准部署:您自己准备全新节点,完成标准Pigsty部署流程。
  • 沙箱部署 : 通过预制的vagrant模板一键拉起本地虚拟机沙箱环境。
  • 多云部署:使用terraform模板在云服务供应商处拉起所需虚拟机资源,并执行部署。
  • 仅监控部署 : 使用单节点Pigsty监控现有数据库集群。

15 - 准备工作

从 Pigsty v1.5.1 标签恢复的历史文档。

如何准备Pigsty部署所需的资源:


节点置备

在部署Pigsty前,用户需要准备机器节点资源,包括至少一个元节点,与任意数量的普通节点

节点可以使用任意类型:物理机、本地虚拟机、云虚拟机,容器等,只需要满足以下条件:

  • 处理器架构:x86_64
  • 硬件规格至少为1核/1GB
  • 操作系统:CentOS 7.8.2003 (或其他RHEL 7等效发行版)
  • 管理用户可以从 元节点 ssh 登陆其他节点并执行sudo

如果您计划将Pigsty用作开箱即用的PostgreSQL数据库实例,则一台节点足矣。如果您还计划将Pigsty用作更多主机/数据库的管控,则可以准备更多的节点备用。


元节点置备

Pigsty需要元节点作为整个环境的控制中心,并提供基础设施 服务。

元节点的数量最少为1个,沙箱环境默认使用1个元节点。Pigsty的基础设施以副本的形式部署在多个元节点上,DCS(Consul/Etcd)例外,DCS以Quorum的形式存在。

Pigsty的数据库集群需要使用DCS以实现高可用功能,您可以使用自动部署于元节点上的DCS集群,或使用外部的DCS集群。在大规模生产环境中,如果您没有专用的外部DCS集群,建议使用3个元节点以充分保证DCS服务的可用性。

用户应当确保自己可以登录元节点,并能使用管理用户从元节点上通过ssh登陆其他数据库节点,并带有sudoroot权限。用户应当确保自己可以直接或间接访问元节点的80端口,以访问Pigsty提供的用户界面。

  • 元节点数量:奇数个,至少一个
  • 能够使用管理员用户登陆元节点
  • 能够(直接或间接)通过浏览器访问元节点80端口
  • 管理用户可以从元节点远程ssh登陆数据库节点并执行sudo (包括自身)

管理用户置备

Pigsty需要一个管理用户,该用户能够从元节点上SSH登陆其他节点,并执行sudo命令。

  • 可以在元节点上使用该用户
  • 可以使用该用户SSH登陆所有被元节点(包括自身)
  • 可以在登陆所有被元节点后执行sudo命令(包括自身)
  • 管理用户不是postgres{{ dbsu }} (使用DBSU作为管理员有安全隐患)
  • ssh 登陆免密码,sudo 命令免密码(或您知晓如何通过-k,-K手工输入)

执行部署与变更时,您所使用的管理用户必须拥有所有节点的sshsudo权限。免密码并非必需,您总是可以在执行剧本时通过-k|-K参数传入ssh与sudo的密码,甚至通过 -eansible_host=<another_user> 使用其他用户来执行剧本。但Pigsty强烈建议为管理用户配置SSH免密码登陆与免密码sudo

Pigsty推荐将管理用户的创建,权限配置与密钥分发放在虚拟机的Provisioning阶段完成,作为机器资源交付内容的一部分。对于生产环境来说,机器交付时应当已经配置有这样一个具有免密远程SSH登陆并执行免密sudo的用户。通常绝大多数云平台和运维体系都可以做到这一点。

Pigsty剧本nodes 可以在节点上创建管理用户,但这涉及到一个先有鸡还是先有蛋但的问题:为了在远程节点执行Ansible剧本,需要有一个管理用户。为了创建一个专用管理用户,需要在远程节点上执行Ansible剧本。 作为Bootstrap阶段的妥协,只要您有SSH登陆与SUDO权限,即使没有密码,也可以用于执行Ansible剧本,详情请参考 Nodes:创建管理用户

手工配置SSH与SUDO

手工配置SSH免密码登陆,可以通过ssh-keygenssh-copy-id的方式实现,请自行参考相关文档。

手工配置用户的免密码sudo,可以在/etc/sudoers.d/<username>文件添加以下记录实现,注意将<username>换成您使用的管理员名称即可。

%<username> ALL=(ALL) NOPASSWD: ALL

软件下载

为了运行Pigsty,您需要置备以下软件:

如需在您自己的笔记本上运行Pigsty沙箱,您还需要在宿主机上下载并安装:

  • Vagrant:虚拟机托管编排软件(跨平台,免费)
  • Virtualbox:虚拟机软件(跨平台,开源免费)

如果您希望在云厂商服务器上运行Pigsty沙箱,您需要在本地下载并安装 Terraform


Pigsty源代码

用户应当在元节点上获取Pigsty项目源码,通常解压至管理用户HOME目录下。

# 推荐使用此命令下载 pigsty.tgz 源码包,该脚本将区分墙内墙外,在大陆使用CDN加速下载
curl -SL https://github.com/Vonng/pigsty/releases/download/v1.5.1/pigsty.tgz | gzip -d | tar -xC ~  # get latest pigsty source

您也可以通过其他途径下载源码压缩包:

# https://github.com/Vonng/pigsty/releases/download/v1.5.1/pigsty.tgz   # Github Release
# http://download.pigsty.cc/v1.5.1/pigsty.tgz                           # China CDN
# https://pan.baidu.com/s/1DZIa9X2jAxx69Zj-aRHoaw?pwd=8su9              # 百度云网盘下载
# git clone --branch v1.5.1 --depth 1 https://github.com/pgsty/pigsty.git                             # 克隆冻结的 v1.5.1 标签

此外 pigsty 项目根目录下的 download 脚本也可以用于下载源代码。

./download pigsty.tgz    # 从Github/CDN下载当前版本pigsty.tgz至/tmp/pigsty.tgz
./download pigsty        # 从Github/CDN下载当前版本pigsty.tgz并解压至~/pigsty(如已存在则跳过)

Pigsty离线软件包

离线软件包打包了所有软件依赖,大小约1GB,为可选项。在元节点上完整安装Pigsty时,如果/tmp/pkg.tgz已经存在,Pigsty会直接使用该软件包构建本地源,否则Pigsty会从网络下载所有依赖的软件包。

官方离线软件包基于CentOS 7.8.2003操作系统环境制作,如果您使用的操作系统并非此版本并出现依赖错漏问题,请参考FAQ直接从原始上游安装。或在带有互联网(Github)访问的装有同样操作系统机器上制作离线安装包后拷贝至网络隔离的环境中使用。

您可以使用以下命令,在待安装Pigsty的元节点上提前下载离线软件包(只需要在单个元节点上下载即可,下载至/tmp/pkg.tgz

curl https://github.com/Vonng/pigsty/releases/download/v1.5.1/pkg.tgz -o /tmp/pkg.tgz   # Github Release,最权威
curl http://download.pigsty.cc/v1.5.1/pkg.tgz -o /tmp/pkg.tgz                           # 或在中国大陆用CDN下载

此外 pigsty 项目根目录下的 download 脚本也可以用于下载离线软件包。

./download pkg.tgz    # 从Github/CDN下载当前版本 pkg.tgz至 /tmp/pkg.tgz
./download pkg        # 从Github/CDN下载当前版本 pkg.tgz 并解压至 /www/pigsty

最后,百度网盘也提供了离线软件包资源下载:https://pan.baidu.com/s/1DZIa9X2jAxx69Zj-aRHoaw?pwd=8su9

16 - 沙箱环境

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty支持使用 本地沙箱云端沙箱 两种方式,可用于快速在本机或云端准备标准的1/4节点演示环境。

尽管安装Pigsty已经非常简单了,但是搭建满足要求虚拟机仍然是比较费事的,您可能需要用到各类虚拟机软件。

因此Pigsty提供了沙箱环境,进一步免除用户准备环境的烦恼。完整地创建并跑通沙箱安装部署流程,对于在生产环境中部署有Pigsty 很大的帮助。

沙箱环境简介

沙箱环境是一个配置规格、对象标识符、与默认数据库预先确定的环境,无论是本地版还是云端版都保持一致。

沙箱环境使用固定的IP地址,以便于演示说明,沙箱的元节点IP地址固定为:10.10.10.1010.10.10.10 也是所有配置文件模板中元节点IP地址的占位符,执行 配置 时,该IP地址会被作为元节点的实际IP地址

您可以使用单节点沙箱,这种部署下,只有一个元节点meta,节点上部署有完整的基础设施,和一个单例Postgres数据库pg-meta

  • meta 10.10.10.10 pg-meta.pg-meta-1

单节点沙箱则适合用于个人开发、实验、学习;作为数据分析与可视化的环境;以及设计、演示、分发交互式数据应用,四节点沙箱可以完整演示Pigsty的功能,充分探索高可用架构与监控系统的能力,请您自行按需选择。

在四节点沙箱环境中,有三个额外的节点,与一个额外一套三节点PostgreSQL集群 pg-test

  • node-1 10.10.10.11 pg-test.pg-test-1
  • node-2 10.10.10.12 pg-test.pg-test-2
  • node-3 10.10.10.13 pg-test.pg-test-3

同时,沙箱环境还会使用以下两个IP地址与两条静态DNS记录,用于接入数据库集群。

  • 10.10.10.2 pg-meta
  • 10.10.10.2 pg-test

Pigsty提供了基于Vagrant的本地沙箱(使用Virtualbox拉起本地虚拟机),以及基于Terraform的云端沙箱(使用云厂商API创建虚拟机)。

  • 本地沙箱可以在普通Mac/PC上运行,不需要任何费用,但若想在本机运行完整的4节点沙箱环境,您的Mac/PC应当至少有 4C/8G的硬件规格。

  • 云端沙箱可以方便地向他人展示与共享,使用前需要您创建一个云账号,虚拟机资源按需创建使用,用后可以一键销毁,会有一些费用(通常非常便宜,一天几块钱)

本地沙箱

Pigsty本地沙箱底层依托于 Vagrant 托管本地的 Virtualbox 虚拟机。

使用Pigsty沙箱前,您需要在操作系统中安装 Vagrant 与 Virtualbox,两者都是免费的跨平台开源软件。您也可以选择自己使用喜爱的虚拟机软件(Parallel Desktop,VMWare)自行创建虚拟机进行标准安装部署

快速开始

确保 VagrantVirtualbox 安装并可用,按照官方向导安装即可。在MacOS上,您可以直接使用 homebrew 一键完成两者的安装(需要重启)。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # 安装Homebrew
brew install vagrant virtualbox # 在MacOS宿主机上安装Vagrant与Virtualbox

在 MacOS 操作系统中,可以通过以下四条快捷方式来安装软件依赖,配置本地静态DNS,拉起虚拟机。在Windows与Linux下则需要少量额外手工步骤。

make deps    # 安装homebrew,并通过homebrew安装vagrant与virtualbox(需重启)
make dns     # 向本机/etc/hosts写入静态域名 (需sudo输入密码)
make start   # 使用Vagrant拉起单个meta节点  (start4则为4个节点)

接下来,您可以 ssh meta 登陆默认元节点,元节点访问所有节点的SSH sudo已经配置完毕,您可以直接执行Pigsty安装。

Vagrant

通常为了测试“数据库集群”这样的系统,用户需要事先准备若干台虚拟机。尽管云服务已经非常方便,但本地虚拟机访问通常比云虚拟机访问方便,响应迅速,成本低廉。本地虚拟机配置相对繁琐,Vagrant 可解决这一问题。

Pigsty用户无需了解vagrant的原理,只需要知道vagrant可以简单、快捷地按照用户的需求,在笔记本、PC或Mac上拉起若干台虚拟机。用户需要完成的工作,就是将自己的虚拟机需求,以Vagrant配置文件的形式表达出来。

Vagrantfile 提供了一个Vagrantfile样例。这是Pigsty沙箱所使用的Vagrantfile,定义了四台虚拟机,包括一台2核/4GB的中控机/元节点 meta和3台1核/1GB 的数据库节点 node-1, node-2, node3

通过make up , make new, make start等快捷方式使用沙箱时,默认只会使用单个元节点meta。而make up4make new4make start4则会使用全部的虚拟机。这里N值定义了额外的数据库节点数量(3台)。如果您的机器配置不足,则可以考虑使用更小的N值,减少数据库节点的数量。用户还可以修改每台机器的CPU核数和内存资源等,如配置文件中的注释所述。更详情的定制请参考Vagrant与Virtualbox文档。

Vagrantfile样例
IMAGE_NAME = "centos/7"
N=3  # 数据库机器节点数量,可修改为0

Vagrant.configure("2") do |config|
    config.vm.box = IMAGE_NAME
    config.vm.box_check_update = false
    config.ssh.insert_key = false

    # 元节点
    config.vm.define "meta", primary: true do |meta|  # 元节点默认的ssh别名为`meta`
        meta.vm.hostname = "meta"
        meta.vm.network "private_network", ip: "10.10.10.10"
        meta.vm.provider "virtualbox" do |v|
            v.linked_clone = true
            v.customize [
                    "modifyvm", :id,
                    "--memory", 4096, "--cpus", "2",   # 元节点的内存与CPU核数:默认为2核/4GB
                    "--nictype1", "virtio", "--nictype2", "virtio",
                    "--hwv·irtex", "on", "--ioapic", "on", "--rtcuseutc", "on", "--vtxvpid", "on", "--largepages", "on"
                ]
        end
        meta.vm.provision "shell", path: "provision.sh"
    end

    # 初始化N个数据库节点
    (1..N).each do |i|
        config.vm.define "node-#{i}" do |node|  # 数据库节点默认的ssh别名分别为`node-{1,2,3}`
            node.vm.box = IMAGE_NAME
            node.vm.network "private_network", ip: "10.10.10.#{i + 10}"
            node.vm.hostname = "node-#{i}"
            node.vm.provider "virtualbox" do |v|
                v.linked_clone = true
                v.customize [
                        "modifyvm", :id,
                        "--memory", 2048, "--cpus", "1", # 数据库节点的内存与CPU核数:默认为1核/2GB
                        "--nictype1", "virtio", "--nictype2", "virtio",
                        "--hwvirtex", "on", "--ioapic", "on", "--rtcuseutc", "on", "--vtxvpid", "on", "--largepages", "on"
                    ]
            end
            node.vm.provision "shell", path: "provision.sh"
        end
    end
end

vagrant 二进制程序会根据 Vagrantfile 中的定义,默认调用 Virtualbox 完成本地虚拟机的创建工作。进入Pigsty根目录下的vagrant目录,执行vagrant up,即可拉起所有的四台虚拟机。Makefile提供了大量对vagrant原始命令的封装。

沙箱环境默认使用的虚拟机镜像为IMAGE_NAME = "centos/7"。首次执行时会从互联网下载centos 7.8.2003的virtualbox镜像,后续重新创建新虚拟机时时将直接克隆此BOX。

Virtualbox

Virtualbox是一个开源免费的跨平台虚拟机软件。在MacOS上安装Virtualbox非常简单:brew install virtualbox,其他操作系统上与之类似。

安装Virtualbox后,可能需要重新启动计算机以加载虚拟机内核模块。请注意Pigsty需要x86_64运行环境,安装有M1芯片的Macbook可能无法正常运行Virtualbox。

DNS配置

Pigsty默认通过域名访问所有Web系统,如果您没有DNS服务器或公共域名,可以使用本地静态DNS记录,沙箱环境使用的静态DNS记录如下所示:

# pigsty dns records
10.10.10.10 meta pigsty c.pigsty g.pigsty l.pigsty p.pigsty a.pigsty cli.pigsty lab.pigsty api.pigsty mx.pigsty
10.10.10.11 node-1   # sandbox node node-1
10.10.10.12 node-2   # sandbox node node-2
10.10.10.13 node-3   # sandbox node node-3
10.10.10.2  pg-meta  # sandbox vip for pg-meta
10.10.10.3  pg-test  # sandbox vip for pg-test

在MacOS与Linux中,执行sudo make dns会将上述记录写入 /etc/hosts (需要sudo权限),在Windows中,则需要您手工添加上述记录至:C:\Windows\System32\drivers\etc\hosts中。


多云部署

如果您手头没有x86_64架构的PC、笔记本、Mac,使用即用即毁的云虚拟机可能是另一个不错的选择。

Terraform

Terraform 是开源免费的 基础设施即代码 工具。您只需要声明好所需的云虚拟机、网络与安全组配置等,一键即可拉起对应的资源。

在MacOS下安装Terraform,只需要执行brew install terraform即可。然后您需要有云厂商账号,并获取AccessKey与AccessSecret凭证,充点钱,就可以开始云端沙箱部署之旅啦。

配置文件

项目根目录 terraform/ 中提供了若干云厂商的 Terraform 资源定义文件,您可以使用这些模板快速在云上申请虚拟机资源用于部署Pigsty。这里以阿里云为例:

cd terraform        # 进入terraform目录中
vi alicloud.tf      # 编辑配置文件,填入您的阿里云AccessKey与SecretKey
阿里云样例Terraform文件
provider "alicloud" {
  access_key = "xxxxxx"
  secret_key = "xxxxxx"
  region = "cn-beijing"
}

# use 10.10.10.0/24 cidr block as demo network
resource "alicloud_vpc" "vpc" {
  vpc_name   = "pigsty-demo-network"
  cidr_block = "10.10.10.0/24"
}

# add virtual switch for pigsty demo network
resource "alicloud_vswitch" "vsw" {
  vpc_id     = "${alicloud_vpc.vpc.id}"
  cidr_block = "10.10.10.0/24"
  zone_id    = "cn-beijing-k"
}

# add default security group and allow all tcp traffic
resource "alicloud_security_group" "default" {
  name   = "default"
  vpc_id = "${alicloud_vpc.vpc.id}"
}
resource "alicloud_security_group_rule" "allow_all_tcp" {
  ip_protocol       = "tcp"
  type              = "ingress"
  nic_type          = "intranet"
  policy            = "accept"
  port_range        = "1/65535"
  priority          = 1
  security_group_id = "${alicloud_security_group.default.id}"
  cidr_ip           = "0.0.0.0/0"
}

# https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/instance
resource "alicloud_instance" "pg-meta-1" {
  instance_name              = "pg-meta-1"
  host_name                  = "pg-meta-1"
  instance_type              = "ecs.s6-c1m2.small"
  vswitch_id                 = "${alicloud_vswitch.vsw.id}"
  security_groups            = ["${alicloud_security_group.default.id}"]
  image_id                   = "centos_7_8_x64_20G_alibase_20200914.vhd"
  password                   = "PigstyDemo4"
  private_ip                 = "10.10.10.10"
  internet_max_bandwidth_out = 40 # 40Mbps , alloc a public IP
}

resource "alicloud_instance" "pg-test-1" {
  instance_name   = "pg-test-1"
  host_name       = "pg-test-1"
  instance_type   = "ecs.s6-c1m1.small"
  vswitch_id      = "${alicloud_vswitch.vsw.id}"
  security_groups = ["${alicloud_security_group.default.id}"]
  image_id        = "centos_7_8_x64_20G_alibase_20200914.vhd"
  password        = "PigstyDemo4"
  private_ip      = "10.10.10.11"
}

resource "alicloud_instance" "pg-test-2" {
  instance_name   = "pg-test-2"
  host_name       = "pg-test-2"
  instance_type   = "ecs.s6-c1m1.small"
  vswitch_id      = "${alicloud_vswitch.vsw.id}"
  security_groups = ["${alicloud_security_group.default.id}"]
  image_id        = "centos_7_8_x64_20G_alibase_20200914.vhd"
  password        = "PigstyDemo4"
  private_ip      = "10.10.10.12"
}

resource "alicloud_instance" "pg-test-3" {
  instance_name   = "pg-test-3"
  host_name       = "pg-test-3"
  instance_type   = "ecs.s6-c1m1.small"
  vswitch_id      = "${alicloud_vswitch.vsw.id}"
  security_groups = ["${alicloud_security_group.default.id}"]
  image_id        = "centos_7_8_x64_20G_alibase_20200914.vhd"
  password        = "PigstyDemo4"
  private_ip      = "10.10.10.13"
}


output "meta_ip" {
  value = "${alicloud_instance.pg-meta-1.public_ip}"
}

执行计划

首先,使用terraform命令,创建上面定义的云资源(共享1C1G临时用用很便宜,按需付费)

terraform init      # 安装 terraform provider: aliyun (仅第一次需要)
terraform apply     # 生成执行计划:创建虚拟机,虚拟网段/交换机/安全组

执行 apply 并输入 yes后,terraform会调用阿里云API创建对应的虚拟机资源。

Terraform Apply执行结果
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # alicloud_instance.pg-meta-1 will be created
  + resource "alicloud_instance" "pg-meta-1" {
      + availability_zone                  = (known after apply)
      + credit_specification               = (known after apply)
      + deletion_protection                = false
      + dry_run                            = false
      + host_name                          = "pg-meta-1"
      + id                                 = (known after apply)
      + image_id                           = "centos_7_8_x64_20G_alibase_20200914.vhd"
      + instance_charge_type               = "PostPaid"
      + instance_name                      = "pg-meta-1"
      + instance_type                      = "ecs.s6-c1m2.small"
      + internet_charge_type               = "PayByTraffic"
      + internet_max_bandwidth_in          = (known after apply)
      + internet_max_bandwidth_out         = 40
      + key_name                           = (known after apply)
      + password                           = (sensitive value)
      + private_ip                         = "10.10.10.10"
      + public_ip                          = (known after apply)
      + role_name                          = (known after apply)
      + secondary_private_ip_address_count = (known after apply)
      + secondary_private_ips              = (known after apply)
      + security_groups                    = (known after apply)
      + spot_strategy                      = "NoSpot"
      + status                             = "Running"
      + subnet_id                          = (known after apply)
      + system_disk_category               = "cloud_efficiency"
      + system_disk_performance_level      = (known after apply)
      + system_disk_size                   = 40
      + volume_tags                        = (known after apply)
      + vswitch_id                         = (known after apply)
    }

  # alicloud_instance.pg-test-1 will be created
  + resource "alicloud_instance" "pg-test-1" {
      + availability_zone                  = (known after apply)
      + credit_specification               = (known after apply)
      + deletion_protection                = false
      + dry_run                            = false
      + host_name                          = "pg-test-1"
      + id                                 = (known after apply)
      + image_id                           = "centos_7_8_x64_20G_alibase_20200914.vhd"
      + instance_charge_type               = "PostPaid"
      + instance_name                      = "pg-test-1"
      + instance_type                      = "ecs.s6-c1m1.small"
      + internet_max_bandwidth_in          = (known after apply)
      + internet_max_bandwidth_out         = 0
      + key_name                           = (known after apply)
      + password                           = (sensitive value)
      + private_ip                         = "10.10.10.11"
      + public_ip                          = (known after apply)
      + role_name                          = (known after apply)
      + secondary_private_ip_address_count = (known after apply)
      + secondary_private_ips              = (known after apply)
      + security_groups                    = (known after apply)
      + spot_strategy                      = "NoSpot"
      + status                             = "Running"
      + subnet_id                          = (known after apply)
      + system_disk_category               = "cloud_efficiency"
      + system_disk_performance_level      = (known after apply)
      + system_disk_size                   = 40
      + volume_tags                        = (known after apply)
      + vswitch_id                         = (known after apply)
    }

  # alicloud_instance.pg-test-2 will be created
  + resource "alicloud_instance" "pg-test-2" {
      + availability_zone                  = (known after apply)
      + credit_specification               = (known after apply)
      + deletion_protection                = false
      + dry_run                            = false
      + host_name                          = "pg-test-2"
      + id                                 = (known after apply)
      + image_id                           = "centos_7_8_x64_20G_alibase_20200914.vhd"
      + instance_charge_type               = "PostPaid"
      + instance_name                      = "pg-test-2"
      + instance_type                      = "ecs.s6-c1m1.small"
      + internet_max_bandwidth_in          = (known after apply)
      + internet_max_bandwidth_out         = 0
      + key_name                           = (known after apply)
      + password                           = (sensitive value)
      + private_ip                         = "10.10.10.12"
      + public_ip                          = (known after apply)
      + role_name                          = (known after apply)
      + secondary_private_ip_address_count = (known after apply)
      + secondary_private_ips              = (known after apply)
      + security_groups                    = (known after apply)
      + spot_strategy                      = "NoSpot"
      + status                             = "Running"
      + subnet_id                          = (known after apply)
      + system_disk_category               = "cloud_efficiency"
      + system_disk_performance_level      = (known after apply)
      + system_disk_size                   = 40
      + volume_tags                        = (known after apply)
      + vswitch_id                         = (known after apply)
    }

  # alicloud_instance.pg-test-3 will be created
  + resource "alicloud_instance" "pg-test-3" {
      + availability_zone                  = (known after apply)
      + credit_specification               = (known after apply)
      + deletion_protection                = false
      + dry_run                            = false
      + host_name                          = "pg-test-3"
      + id                                 = (known after apply)
      + image_id                           = "centos_7_8_x64_20G_alibase_20200914.vhd"
      + instance_charge_type               = "PostPaid"
      + instance_name                      = "pg-test-3"
      + instance_type                      = "ecs.s6-c1m1.small"
      + internet_max_bandwidth_in          = (known after apply)
      + internet_max_bandwidth_out         = 0
      + key_name                           = (known after apply)
      + password                           = (sensitive value)
      + private_ip                         = "10.10.10.13"
      + public_ip                          = (known after apply)
      + role_name                          = (known after apply)
      + secondary_private_ip_address_count = (known after apply)
      + secondary_private_ips              = (known after apply)
      + security_groups                    = (known after apply)
      + spot_strategy                      = "NoSpot"
      + status                             = "Running"
      + subnet_id                          = (known after apply)
      + system_disk_category               = "cloud_efficiency"
      + system_disk_performance_level      = (known after apply)
      + system_disk_size                   = 40
      + volume_tags                        = (known after apply)
      + vswitch_id                         = (known after apply)
    }

  # alicloud_security_group.default will be created
  + resource "alicloud_security_group" "default" {
      + id                  = (known after apply)
      + inner_access        = (known after apply)
      + inner_access_policy = (known after apply)
      + name                = "default"
      + security_group_type = "normal"
      + vpc_id              = (known after apply)
    }

  # alicloud_security_group_rule.allow_all_tcp will be created
  + resource "alicloud_security_group_rule" "allow_all_tcp" {
      + cidr_ip           = "0.0.0.0/0"
      + id                = (known after apply)
      + ip_protocol       = "tcp"
      + nic_type          = "intranet"
      + policy            = "accept"
      + port_range        = "1/65535"
      + priority          = 1
      + security_group_id = (known after apply)
      + type              = "ingress"
    }

  # alicloud_vpc.vpc will be created
  + resource "alicloud_vpc" "vpc" {
      + cidr_block        = "10.10.10.0/24"
      + id                = (known after apply)
      + ipv6_cidr_block   = (known after apply)
      + name              = (known after apply)
      + resource_group_id = (known after apply)
      + route_table_id    = (known after apply)
      + router_id         = (known after apply)
      + router_table_id   = (known after apply)
      + status            = (known after apply)
      + vpc_name          = "pigsty-demo-network"
    }

  # alicloud_vswitch.vsw will be created
  + resource "alicloud_vswitch" "vsw" {
      + availability_zone = (known after apply)
      + cidr_block        = "10.10.10.0/24"
      + id                = (known after apply)
      + name              = (known after apply)
      + status            = (known after apply)
      + vpc_id            = (known after apply)
      + vswitch_name      = (known after apply)
      + zone_id           = "cn-beijing-k"
    }

Plan: 8 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + meta_ip = (known after apply)

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

alicloud_vpc.vpc: Creating...
alicloud_vpc.vpc: Creation complete after 6s [id=vpc-2zed78z7n5z06o1dmydhj]
alicloud_security_group.default: Creating...
alicloud_vswitch.vsw: Creating...
alicloud_security_group.default: Creation complete after 1s [id=sg-2ze7x7zu8tcdsefroofa]
alicloud_security_group_rule.allow_all_tcp: Creating...
alicloud_security_group_rule.allow_all_tcp: Creation complete after 0s [id=sg-2ze7x7zu8tcdsefroofa:ingress:tcp:1/65535:intranet:0.0.0.0/0:accept:1]
alicloud_vswitch.vsw: Creation complete after 6s [id=vsw-2zejctjdr16ryz194jxz4]
alicloud_instance.pg-test-3: Creating...
alicloud_instance.pg-test-2: Creating...
alicloud_instance.pg-test-1: Creating...
alicloud_instance.pg-meta-1: Creating...
alicloud_instance.pg-test-3: Still creating... [10s elapsed]
alicloud_instance.pg-test-2: Still creating... [10s elapsed]
alicloud_instance.pg-test-1: Still creating... [10s elapsed]
alicloud_instance.pg-meta-1: Still creating... [10s elapsed]
alicloud_instance.pg-meta-1: Creation complete after 16s [id=i-2zef4frw6kezb47339wr]
alicloud_instance.pg-test-1: Still creating... [20s elapsed]
alicloud_instance.pg-test-2: Still creating... [20s elapsed]
alicloud_instance.pg-test-3: Still creating... [20s elapsed]
alicloud_instance.pg-test-2: Creation complete after 23s [id=i-2zefzvz0fyl7mloc4v30]
alicloud_instance.pg-test-1: Still creating... [30s elapsed]
alicloud_instance.pg-test-3: Still creating... [30s elapsed]
alicloud_instance.pg-test-3: Creation complete after 33s [id=i-2zeeyodo2pc8b1k2d167]
alicloud_instance.pg-test-1: Creation complete after 33s [id=i-2zef4frw6kezb47339ws]

SSH配置与微调

其中,管理机将分配一个按量付费的公网IP,您也可以使用命令terraform output将其打印出来。

# 打印公网IP与root密码
ssh_pass='PigstyDemo4'
public_ip=$(terraform output | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
echo "meta node: root:${ssh_pass}@${public_ip}"

接下来,我们先来配置本地登录云端管理机器的SSH配置(默认用户root,密码PigstyDemo4

# 创建 ~/.ssh/pigsty_terraform 文件,包含云端管理机器的SSH定义(可选,好用一点)
cat > ~/.ssh/pigsty_terraform <<-EOF
Host demo
  User root
  HostName ${public_ip}
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication yes
EOF
chmod 0600 ~/.ssh/pigsty_terraform

# 启用该配置
if ! grep --quiet "Include ~/.ssh/pigsty_terraform" ~/.ssh/config ; then
    (echo 'Include ~/.ssh/pigsty_terraform' && cat ~/.ssh/config) >  ~/.ssh/config.tmp;
    mv ~/.ssh/config.tmp ~/.ssh/config && chmod 0600 ~/.ssh/config;
fi

然后,您可以通过SSH别名demo访问该云端管理机了。

# 添加本地到元节点的免密访问
sshpass -p ${ssh_pass} ssh-copy-id demo

然后,您就可以免密从本地访问该节点了,如果只需要进行单节点安装,这样就行了。接下来,在该元节点上完成标准安装

DNS配置

Pigsty默认通过域名访问所有Web系统,尽管您可以使用 IP:Port的方式访问主要系统的Web界面,但这并不是推荐的行为。

云端沙箱环境使用的静态DNS记录如下所示,您需要填入元节点的公网IP地址

<public_ip> meta pigsty c.pigsty g.pigsty l.pigsty p.pigsty a.pigsty cli.pigsty lab.pigsty api.pigsty mx.pigsty

在MacOS与Linux中,需要将上述记录写入 /etc/hosts (需要sudo权限),在Windows中,则需要您手工添加至:C:\Windows\System32\drivers\etc\hosts中。

特殊注意事项

阿里云虚拟机CentOS 7.8镜像中运行有 nscd ,锁死了 glibc 版本,会导致安装时出现RPM依赖错误。

在所有机器上执行 yum remove -y nscd 即可解决此问题。

完成上述准备工作后,所有机器准备工作已经就绪,可以开始常规的 Pigsty下载配置安装三部曲啦。

17 - 监控系统部署

从 Pigsty v1.5.1 标签恢复的历史文档。

如何使用Pigsty监控已有PostgreSQL实例?

对于由Pigsty所创建的实例,所有监控组件均已自动配置妥当。但对于非Pigsty所创建的现存Pigsty实例,若希望使用Pigsty监控系统的部分对其监控,则需一些额外的配置。

太长;不看

  1. 在目标实例创建监控对象:监控对象配置

  2. 在配置清单中声明该集群:

    pg-test:
      hosts:                                # 为每个实例分配唯一本地端口
        10.10.10.11: { pg_seq: 1, pg_role: primary , pg_exporter_port: 20001}
        10.10.10.12: { pg_seq: 2, pg_role: replica , pg_exporter_port: 20002}
        10.10.10.13: { pg_seq: 3, pg_role: offline , pg_exporter_port: 20003}
      vars:
        pg_cluster: pg-test                 # 填入集群名称
        pg_version: 14                      # 填入数据库大版本
        pg_databases: [{ name: test }]      # 填入数据库列表(每个数据库对象作为一个数组元素)
    
    # 在全局/集群/实例配置中提供监控用户密码 pg_monitor_username/pg_monitor_password
  3. 针对该集群执行剧本:./pgsql-monly.yml -l pg-test

  4. 该剧本会在Grafana中注册目标PostgreSQL数据源,因此PGCAT功能完整可用。该剧本会在元节点本地部署PG Exporter监控远程PG实例,故PGSQL中纯数据库相关指标可用。但主机节点、连接池、负载均衡、高可用Patroni相关指标则不可用。

监控部署概述

如果用户只希望使用Pigsty的监控系统部分,比如希望使用Pigsty监控系统监控已有的PostgreSQL实例,那么可以使用 仅监控部署(monitor only) 模式。仅监控模式下,您可以使用Pigsty管理监控其他PostgreSQL实例(目前默认支持10+以上的版本,更老的版本可以通过手工修改 pg_exporter 配置文件支持)

首先,您需要在1台元节点上完成标准的Pigsty的标准安装流程,然后便可以将更多的数据库实例接入监控。按照目标数据库节点的访问权限,又可以分为两种情况:

如果目标节点可被管理

如果目标DB节点可以被Pigsty所管理(ssh可达,sudo可用),那么您可以使用 pgsql.yml 剧本中的pg-exporter任务,使用相同的的方式,在目标节点上部署监控组件:PG Exporter, 您也可以使用该剧本的其他任务,在已有实例节点上部署额外的组件及其监控:连接池Pgbouncer与负载均衡器HAProxy。此外,您也可以使用 nodes.yml 中的 node-exporterpromtail 任务,部署主机节点监控与日志收集组件。从而获得与原生Pigsty数据库实例完全一致的使用体验。

因为目标数据库集群已存在,您需要参考本节的内容手工在目标数据库集群上创建监控用户、模式与扩展。其余流程与完整部署并无区别。

# 修改pigsty配置参数,在节点上添加yum repo,然后通过yum安装软件包
exporter_install: yum # none|yum|binary, none by default
exporter_repo_url: http://<your primary ip address>/pigsty.repo

./nodes.yml -l <yourcluster> -t node-exporter  # 部署节点指标监控
./nodes.yml -l <yourcluster> -t promtail       # 部署节点日志收集
./pgsql.yml -l <yourcluster> -t pg-exporter    # 部署PG指标监控收集

如果只有数据库连接串

如果您只能通过PGURL(数据库连接串)的方式访问目标数据库,则可以考虑使用仅监控模式/精简模式(Monitor Only:Monly)监控目标数据库。在此模式下,所有监控组件均部署在安装Pigsty的元节点上。监控系统不会有 节点,连接池,负载均衡器,高可用组件的相关指标,但数据库本身,以及数据目录(Catalog)中的实时状态信息仍然可用。

为了执行精简监控部署,您同样需要参考本节的内容手工在目标数据库集群上创建监控用户、模式与扩展,并确保可以从元节点上使用监控用户访问目标数据库。此后,针对目标集群执行 pgsql-monly.yml剧本即可完成部署。

本文着重介绍此种监控部署模式

图:仅监控模式架构示意图,部署于管理机本地的多个PG Exporter用于监控多个远程数据库实例。

精简部署与标准部署的区别

Pigsty监控系统由三个核心模块组成:

事项\等级 L1 L2 L3
名称 基础部署 托管部署 完整部署
英文 basic managed full
场景 只有连接串 DB已存在,节点可管理 实例由Pigsty创建
PGCAT功能 ✅ 完整可用 ✅ 完整可用 ✅ 完整可用
PGSQL功能 ✅ 限PG指标 ✅ 限PG与节点指标 ✅ 完整功能
连接池指标 ❌ 不可用 ⚠️ 选装 ✅ 预装项
负载均衡器指标 ❌ 不可用 ⚠️ 选装 ✅ 预装项
PGLOG功能 ❌ 不可用 ⚠️ 选装 ✅ 预装项
PG Exporter ⚠️ 部署于元节点 ✅ 部署于DB节点 ✅ 部署于DB节点
Node Exporter ❌ 不部署 ✅ 部署于DB节点 ✅ 部署于DB节点
侵入DB节点 ✅ 无侵入 ⚠️ 安装Exporter ⚠️ 完全由Pigsty管理
监控现有实例 ✅ 可支持 ✅ 可支持 ❌ 仅用于Pigsty托管实例
监控用户与视图 人工创建 人工创建 Pigsty自动创建
部署使用剧本 pgsql-monly.yml pgsql.yml -t pg-exporter,promtail
nodes.yml -t node-exporter
pgsql.yml -t pg-exporter
nodes.yml -t node-exporter
所需权限 元节点可达的PGURL DB节点ssh与sudo权限 DB节点ssh与sudo权限
功能概述 基础功能:PGCAT+PGSQL 大部分功能 完整功能

监控已有实例:精简模式

为数据库实例部署监控系统分为三步:准备监控对象修改配置清单执行部署剧本

准备监控对象

为了将外部现存PostgreSQL实例纳入监控,您需要有一个可用于访问该实例/集群的连接串。任何可达连接串(业务用户,超级用户)均可使用,但我们建议使用一个专用监控用户以避免权限泄漏。

  • 监控用户:默认使用的用户名为 dbuser_monitor, 该用户需要属于 pg_monitor 角色组,或确保具有相关视图访问权限。
  • 监控认证:默认使用密码访问,您需要确保HBA策略允许监控用户从管理机或DB节点本地访问数据库。
  • 监控模式:固定使用名称 monitor,用于安装额外的监控视图与扩展插件,非必选,但强烈建议创建。
  • 监控扩展:强烈建议启用PG自带的监控扩展 pg_stat_statements

关于监控对象的准备细节,请参考文后:监控对象配置 一节。

修改配置清单

如同部署一个全新的Pigsty实例一样,您需要在配置清单(配置文件或CMDB)中声明该目标集群。例如,为集群与实例指定身份标识。不同之处在于,您还需要在实例层次为每一个实例手工分配一个唯一的本地端口号( pg_exporter_port)。

下面是一个数据库集群声明样例:

pg-test:
  hosts:                                # 为每个实例分配唯一本地端口
    10.10.10.11: { pg_seq: 1, pg_role: primary , pg_exporter_port: 20001}
    10.10.10.12: { pg_seq: 2, pg_role: replica , pg_exporter_port: 20002}
    10.10.10.13: { pg_seq: 3, pg_role: offline , pg_exporter_port: 20003}
  vars:
    pg_cluster: pg-test                 # 填入集群名称
    pg_version: 14                      # 填入数据库大版本
    pg_databases: [{ name: test }]      # 填入数据库列表(每个数据库对象作为一个数组元素)

# 在全局/集群/实例配置中提供监控用户密码 pg_monitor_username/pg_monitor_password

注,即使您通过域名访问数据库,依然需要通过填入实际IP地址的方式来声明数据库集群。

若要启用PGCAT功能,您需要显式在 pg_databases 中列出目标集群的数据库名称列表,在此列表中的数据库将被注册为Grafana的数据源,您可以直接通过Grafana访问该实例的Catalog数据。若您不希望使用PGCAT相关功能,不设置该变量,或置为空数组即可。

连接信息

说明:Pigsty将默认使用以下规则生成监控连接串。但参数 pg_exporter_url 存在时,将直接覆盖拼接连接串。

postgres://{{ pg_monitor_username }}:{{ pg_monitor_password }}@{{ inventory_hostname }}:{{ pg_port }}/postgres?sslmode=disable

您可以在全局使用统一的监控用户/密码设置,或者在集群层面实例层次根据实际情况按需配置以下连接参数

pg_monitor_username: dbuser_monitor  # 监控用户名,若使用全局统一配置则无需在此配置
pg_monitor_password: DBUser.Monitor  # 监控用户密码,若使用全局统一配置则无需在此配置
pg_port: 5432                        # 若使用非标准的数据库端口,在此修改
示例:在实例层面指定连接信息 ```yaml pg-test: hosts: # Specify the access URL for the instance 10.10.10.11: pg_seq: 1 pg_role: primary pg_exporter_port: 20001 pg_monitor_username: monitor_user1 pg_monitor_password: monitor_pass1 10.10.10.12: pg_seq: 2 pg_role: replica pg_exporter_port: 20002 # Specify pg_exporter_url directly pg_exporter_url: 'postgres://someuser:[email protected]:5432/postgres?sslmode=disable'' 10.10.10.13: pg_seq: 3 pg_role: offline pg_exporter_port: 20003 pg_monitor_username: monitor_user3 pg_monitor_password: monitor_pass3 vars: pg_cluster: pg-test # Fill in cluster name pg_version: 14 # Fill in the major version of the database pg_databases: [{ name: test }] # Fill in the database list (each database object as an array element) ```

执行部署剧本

集群声明完成后,将其纳入监控非常简单,在元节点上针对目标集群使用剧本 pgsql-monly.yml 即可:

./pgsql-monly.yml -l <cluster>     # 在指定集群上完成监控部署

监控已有实例:托管部署

在托管部署模式下,目标DB节点可以被Pigsty所管理(ssh可达,sudo可用),用户将在已有的节点上加装以下监控组件:promtail, node_exporter, pg_exporter。

您可以使用 nodes.yml中的node-exporter任务,以及 pgsql.yml 剧本中的pg-exporter任务,在目标节点上部署监控组件:node_exporterpg_exporter

因为目标数据库集群已存在,您需要在目标数据库集群上创建监控用户、模式与扩展

# 修改pigsty配置参数,在节点上添加yum repo,然后通过yum安装软件包
exporter_install: yum # none|yum|binary, none by default
exporter_repo_url: http://<your primary ip address>/pigsty.repo

./nodes.yml -l <yourcluster> -t promtail       # 部署节点日志收集(可选,注意日志位置)
./nodes.yml -l <yourcluster> -t node-exporter  # 部署节点指标监控
./pgsql.yml -l <yourcluster> -t pg-exporter    # 部署PG指标监控收集

exporter_install的值为yum时,Pigsty会从 exporter_repo_url 指定的URL下载Repo文件至节点本地的/etc/yum.repos.d中。通常您应当填入管理节点上的Pigsty本地源地址,例如:http://10.10.10.10/pigsty.repo


监控对象配置

如何在已有实例上配置监控所需的用户,模式,扩展、视图与函数。

监控用户

以Pigsty默认使用的监控用户dbuser_monitor为例,在目标数据库集群创建以下用户。

CREATE USER dbuser_monitor;
GRANT pg_monitor TO dbuser_monitor;
COMMENT ON ROLE dbuser_monitor IS 'system monitor user';
ALTER USER dbuser_monitor SET log_min_duration_statement = 1000;
ALTER USER dbuser_monitor PASSWORD 'DBUser.Monitor'; -- 按需修改监控用户密码(建议修改!!)

请注意,这里创建的监控用户与密码需要与 pg_monitor_usernamepg_monitor_password 保持一致。

配置数据库 pg_hba.conf 文件,添加以下规则以允许监控用户从本地,以及管理机使用密码访问数据库。

# allow local role monitor with password
local   all  dbuser_monitor                    md5
host    all  dbuser_monitor  127.0.0.1/32      md5
host    all  dbuser_monitor  <管理机器IP地址>/32 md5

监控模式

监控模式与扩展是可选项,即使没有,Pigsty监控系统的主体也可以正常工作,但我们强烈建议创建监控模式,并至少启用PG官方自带的 pg_stat_statements,该扩展提供了关于查询性能的重要数据。注意:该扩展必须列入数据库参数shared_preload_libraries 中方可生效,修改该参数需要重启数据库。

创建扩展模式:

CREATE SCHEMA IF NOT EXISTS monitor;               -- 创建监控专用模式
GRANT USAGE ON SCHEMA monitor TO dbuser_monitor;   -- 允许监控用户使用

监控扩展

创建扩展插件:

-- 强烈建议启用 pg_stat_statements 扩展
CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "monitor";

-- 可选的其他扩展
CREATE EXTENSION IF NOT EXISTS "pgstattuple" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_qualstats" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_buffercache" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pageinspect" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_prewarm" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_visibility" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_freespacemap" WITH SCHEMA "monitor";

监控视图

监控视图提供了若干常用的预处理结果,并对某些需要高权限的监控指标进行权限封装(例如共享内存分配),便于查询与使用。强烈建议在所有需要监控的数据库中创建

监控模式与监控视图定义
--==================================================================--
--                            Monitor Schema                        --
--==================================================================--

----------------------------------------------------------------------
-- cleanse
----------------------------------------------------------------------
CREATE SCHEMA IF NOT EXISTS monitor;
GRANT USAGE ON SCHEMA monitor TO dbuser_monitor;
GRANT USAGE ON SCHEMA monitor TO "{{ pg_admin_username }}";
GRANT USAGE ON SCHEMA monitor TO "{{ pg_replication_username }}";

--==================================================================--
--                            Monitor Views                         --
--==================================================================--

----------------------------------------------------------------------
-- Table bloat estimate : monitor.pg_table_bloat
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_table_bloat CASCADE;
CREATE OR REPLACE VIEW monitor.pg_table_bloat AS
SELECT CURRENT_CATALOG AS datname, nspname, relname , tblid , bs * tblpages AS size,
       CASE WHEN tblpages - est_tblpages_ff > 0 THEN (tblpages - est_tblpages_ff)/tblpages::FLOAT ELSE 0 END AS ratio
FROM (
         SELECT ceil( reltuples / ( (bs-page_hdr)*fillfactor/(tpl_size*100) ) ) + ceil( toasttuples / 4 ) AS est_tblpages_ff,
                tblpages, fillfactor, bs, tblid, nspname, relname, is_na
         FROM (
                  SELECT
                      ( 4 + tpl_hdr_size + tpl_data_size + (2 * ma)
                          - CASE WHEN tpl_hdr_size % ma = 0 THEN ma ELSE tpl_hdr_size % ma END
                          - CASE WHEN ceil(tpl_data_size)::INT % ma = 0 THEN ma ELSE ceil(tpl_data_size)::INT % ma END
                          ) AS tpl_size, (heappages + toastpages) AS tblpages, heappages,
                      toastpages, reltuples, toasttuples, bs, page_hdr, tblid, nspname, relname, fillfactor, is_na
                  FROM (
                           SELECT
                               tbl.oid AS tblid, ns.nspname , tbl.relname, tbl.reltuples,
                               tbl.relpages AS heappages, coalesce(toast.relpages, 0) AS toastpages,
                               coalesce(toast.reltuples, 0) AS toasttuples,
                               coalesce(substring(array_to_string(tbl.reloptions, ' ') FROM 'fillfactor=([0-9]+)')::smallint, 100) AS fillfactor,
                               current_setting('block_size')::numeric AS bs,
                               CASE WHEN version()~'mingw32' OR version()~'64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END AS ma,
                               24 AS page_hdr,
                               23 + CASE WHEN MAX(coalesce(s.null_frac,0)) > 0 THEN ( 7 + count(s.attname) ) / 8 ELSE 0::int END
                                   + CASE WHEN bool_or(att.attname = 'oid' and att.attnum < 0) THEN 4 ELSE 0 END AS tpl_hdr_size,
                               sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 0) ) AS tpl_data_size,
                               bool_or(att.atttypid = 'pg_catalog.name'::regtype)
                                   OR sum(CASE WHEN att.attnum > 0 THEN 1 ELSE 0 END) <> count(s.attname) AS is_na
                           FROM pg_attribute AS att
                                    JOIN pg_class AS tbl ON att.attrelid = tbl.oid
                                    JOIN pg_namespace AS ns ON ns.oid = tbl.relnamespace
                                    LEFT JOIN pg_stats AS s ON s.schemaname=ns.nspname AND s.tablename = tbl.relname AND s.inherited=false AND s.attname=att.attname
                                    LEFT JOIN pg_class AS toast ON tbl.reltoastrelid = toast.oid
                           WHERE NOT att.attisdropped AND tbl.relkind = 'r' AND nspname NOT IN ('pg_catalog','information_schema')
                           GROUP BY 1,2,3,4,5,6,7,8,9,10
                       ) AS s
              ) AS s2
     ) AS s3
WHERE NOT is_na;
COMMENT ON VIEW monitor.pg_table_bloat IS 'postgres table bloat estimate';

----------------------------------------------------------------------
-- Index bloat estimate : monitor.pg_index_bloat
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_index_bloat CASCADE;
CREATE OR REPLACE VIEW monitor.pg_index_bloat AS
SELECT CURRENT_CATALOG AS datname, nspname, idxname AS relname, tblid, idxid, relpages::BIGINT * bs AS size,
       COALESCE((relpages - ( reltuples * (6 + ma - (CASE WHEN index_tuple_hdr % ma = 0 THEN ma ELSE index_tuple_hdr % ma END)
                                               + nulldatawidth + ma - (CASE WHEN nulldatawidth % ma = 0 THEN ma ELSE nulldatawidth % ma END))
                                  / (bs - pagehdr)::FLOAT  + 1 )), 0) / relpages::FLOAT AS ratio
FROM (
         SELECT nspname,idxname,indrelid AS tblid,indexrelid AS idxid,
                reltuples,relpages,
                current_setting('block_size')::INTEGER                                                               AS bs,
                (CASE WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END)  AS ma,
                24                                                                                                   AS pagehdr,
                (CASE WHEN max(COALESCE(pg_stats.null_frac, 0)) = 0 THEN 2 ELSE 6 END)                               AS index_tuple_hdr,
                sum((1.0 - COALESCE(pg_stats.null_frac, 0.0)) *
                    COALESCE(pg_stats.avg_width, 1024))::INTEGER                                                     AS nulldatawidth
         FROM pg_attribute
                  JOIN (
             SELECT pg_namespace.nspname,
                    ic.relname                                                   AS idxname,
                    ic.reltuples,
                    ic.relpages,
                    pg_index.indrelid,
                    pg_index.indexrelid,
                    tc.relname                                                   AS tablename,
                    regexp_split_to_table(pg_index.indkey::TEXT, ' ') :: INTEGER AS attnum,
                    pg_index.indexrelid                                          AS index_oid
             FROM pg_index
                      JOIN pg_class ic ON pg_index.indexrelid = ic.oid
                      JOIN pg_class tc ON pg_index.indrelid = tc.oid
                      JOIN pg_namespace ON pg_namespace.oid = ic.relnamespace
                      JOIN pg_am ON ic.relam = pg_am.oid
             WHERE pg_am.amname = 'btree' AND ic.relpages > 0 AND nspname NOT IN ('pg_catalog', 'information_schema')
         ) ind_atts ON pg_attribute.attrelid = ind_atts.indexrelid AND pg_attribute.attnum = ind_atts.attnum
                  JOIN pg_stats ON pg_stats.schemaname = ind_atts.nspname
             AND ((pg_stats.tablename = ind_atts.tablename AND pg_stats.attname = pg_get_indexdef(pg_attribute.attrelid, pg_attribute.attnum, TRUE))
                 OR (pg_stats.tablename = ind_atts.idxname AND pg_stats.attname = pg_attribute.attname))
         WHERE pg_attribute.attnum > 0
         GROUP BY 1, 2, 3, 4, 5, 6
     ) est;
COMMENT ON VIEW monitor.pg_index_bloat IS 'postgres index bloat estimate (btree-only)';


----------------------------------------------------------------------
-- Relation Bloat : monitor.pg_bloat
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_bloat CASCADE;
CREATE OR REPLACE VIEW monitor.pg_bloat AS
SELECT coalesce(ib.datname, tb.datname)                                                   AS datname,
       coalesce(ib.nspname, tb.nspname)                                                   AS nspname,
       coalesce(ib.tblid, tb.tblid)                                                       AS tblid,
       coalesce(tb.nspname || '.' || tb.relname, ib.nspname || '.' || ib.tblid::RegClass) AS tblname,
       tb.size                                                                            AS tbl_size,
       CASE WHEN tb.ratio < 0 THEN 0 ELSE round(tb.ratio::NUMERIC, 6) END                 AS tbl_ratio,
       (tb.size * (CASE WHEN tb.ratio < 0 THEN 0 ELSE tb.ratio::NUMERIC END)) ::BIGINT    AS tbl_wasted,
       ib.idxid,
       ib.nspname || '.' || ib.relname                                                    AS idxname,
       ib.size                                                                            AS idx_size,
       CASE WHEN ib.ratio < 0 THEN 0 ELSE round(ib.ratio::NUMERIC, 5) END                 AS idx_ratio,
       (ib.size * (CASE WHEN ib.ratio < 0 THEN 0 ELSE ib.ratio::NUMERIC END)) ::BIGINT    AS idx_wasted
FROM monitor.pg_index_bloat ib
         FULL OUTER JOIN monitor.pg_table_bloat tb ON ib.tblid = tb.tblid;

COMMENT ON VIEW monitor.pg_bloat IS 'postgres relation bloat detail';


----------------------------------------------------------------------
-- monitor.pg_index_bloat_human
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_index_bloat_human CASCADE;
CREATE OR REPLACE VIEW monitor.pg_index_bloat_human AS
SELECT idxname                            AS name,
       tblname,
       idx_wasted                         AS wasted,
       pg_size_pretty(idx_size)           AS idx_size,
       round(100 * idx_ratio::NUMERIC, 2) AS idx_ratio,
       pg_size_pretty(idx_wasted)         AS idx_wasted,
       pg_size_pretty(tbl_size)           AS tbl_size,
       round(100 * tbl_ratio::NUMERIC, 2) AS tbl_ratio,
       pg_size_pretty(tbl_wasted)         AS tbl_wasted
FROM monitor.pg_bloat
WHERE idxname IS NOT NULL;
COMMENT ON VIEW monitor.pg_index_bloat_human IS 'postgres index bloat info in human-readable format';

----------------------------------------------------------------------
-- monitor.pg_table_bloat_human
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_table_bloat_human CASCADE;
CREATE OR REPLACE VIEW monitor.pg_table_bloat_human AS
SELECT tblname                                          AS name,
       idx_wasted + tbl_wasted                          AS wasted,
       pg_size_pretty(idx_wasted + tbl_wasted)          AS all_wasted,
       pg_size_pretty(tbl_wasted)                       AS tbl_wasted,
       pg_size_pretty(tbl_size)                         AS tbl_size,
       tbl_ratio,
       pg_size_pretty(idx_wasted)                       AS idx_wasted,
       pg_size_pretty(idx_size)                         AS idx_size,
       round(idx_wasted::NUMERIC * 100.0 / idx_size, 2) AS idx_ratio
FROM (SELECT datname,
             nspname,
             tblname,
             coalesce(max(tbl_wasted), 0)                         AS tbl_wasted,
             coalesce(max(tbl_size), 1)                           AS tbl_size,
             round(100 * coalesce(max(tbl_ratio), 0)::NUMERIC, 2) AS tbl_ratio,
             coalesce(sum(idx_wasted), 0)                         AS idx_wasted,
             coalesce(sum(idx_size), 1)                           AS idx_size
      FROM monitor.pg_bloat
      WHERE tblname IS NOT NULL
      GROUP BY 1, 2, 3
     ) d;
COMMENT ON VIEW monitor.pg_table_bloat_human IS 'postgres table bloat info in human-readable format';



----------------------------------------------------------------------
-- Activity Overview: monitor.pg_session
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_session CASCADE;
CREATE OR REPLACE VIEW monitor.pg_session AS
SELECT coalesce(datname, 'all') AS datname, numbackends, active, idle, ixact, max_duration, max_tx_duration, max_conn_duration
FROM (
         SELECT datname,
                count(*)                                         AS numbackends,
                count(*) FILTER ( WHERE state = 'active' )       AS active,
                count(*) FILTER ( WHERE state = 'idle' )         AS idle,
                count(*) FILTER ( WHERE state = 'idle in transaction'
                    OR state = 'idle in transaction (aborted)' ) AS ixact,
                max(extract(epoch from now() - state_change))
                FILTER ( WHERE state = 'active' )                AS max_duration,
                max(extract(epoch from now() - xact_start))      AS max_tx_duration,
                max(extract(epoch from now() - backend_start))   AS max_conn_duration
         FROM pg_stat_activity
         WHERE backend_type = 'client backend'
           AND pid <> pg_backend_pid()
         GROUP BY ROLLUP (1)
         ORDER BY 1 NULLS FIRST
     ) t;
COMMENT ON VIEW monitor.pg_session IS 'postgres activity group by session';


----------------------------------------------------------------------
-- Sequential Scan: monitor.pg_seq_scan
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_seq_scan CASCADE;
CREATE OR REPLACE VIEW monitor.pg_seq_scan AS
    SELECT schemaname                                                        AS nspname,
           relname,
           seq_scan,
           seq_tup_read,
           seq_tup_read / seq_scan                                           AS seq_tup_avg,
           idx_scan,
           n_live_tup + n_dead_tup                                           AS tuples,
           round(n_live_tup * 100.0::NUMERIC / (n_live_tup + n_dead_tup), 2) AS live_ratio
    FROM pg_stat_user_tables
    WHERE seq_scan > 0
      and (n_live_tup + n_dead_tup) > 0
    ORDER BY seq_scan DESC;
COMMENT ON VIEW monitor.pg_seq_scan IS 'table that have seq scan';
查看共享内存分配的函数(PG13以上可用)
DROP FUNCTION IF EXISTS monitor.pg_shmem() CASCADE;
CREATE OR REPLACE FUNCTION monitor.pg_shmem() RETURNS SETOF
   pg_shmem_allocations AS $$ SELECT * FROM pg_shmem_allocations;$$ LANGUAGE SQL SECURITY DEFINER;
COMMENT ON FUNCTION monitor.pg_shmem() IS 'security wrapper for pg_shmem';

18 - PostgreSQL集群部署

从 Pigsty v1.5.1 标签恢复的历史文档。

本文介绍使用Pigsty部署PostgreSQL集群的几种不同方式:PGSQL相关剧本配置请参考相关文档。

  • 身份参数:介绍定义标准PostgreSQL高可用集群所需的身份参数。
  • 单机部署:定义一个单实例的PostgreSQL集群
  • 主从集群:定义一个一主一从的标准可用性集群。
  • 同步从库:定义一个同步复制,RPO = 0 的高一致性集群。
  • 法定人数同步提交:定义数据一致性更高的集群:多数从库成功方返回提交。
  • 离线从库:用于单独承载OLAP分析,ETL,交互式个人查询的专用实例
  • 备份集群:制作现有集群的实时在线克隆,用于异地灾备或延迟从库。
  • 延迟从库:用于应对误删表删库等软件/人为故障,比PITR更快。
  • 级联复制:用于搭建一个集群内的级联复制,针对大量从库场景(20+),降低主库复制压力。
  • Citus集群部署:部署Citus分布式数据库集群
  • MatrixDB集群部署:部署Greenplum7/PostgreSQL12兼容的时序数据仓库。

身份参数

核心身份参数是定义 PostgreSQL 数据库集群时必须提供的信息,包括:

名称 属性 说明 例子
pg_cluster 必选,集群级别 集群名 pg-test
pg_role 必选,实例级别 实例角色 primary, replica
pg_seq 必选,实例级别 实例序号 1, 2, 3,...

身份参数的内容遵循 实体命名规则 。其中 pg_clusterpg_rolepg_seq 属于核心身份参数,是定义数据库集群所需的最小必须参数集,核心身份参数必须显式指定,不可忽略。

  • pg_cluster 标识了集群的名称,在集群层面进行配置,作为集群资源的顶层命名空间。

  • pg_role标识了实例在集群中扮演的角色,在实例层面进行配置,可选值包括:

    • primary:集群中的唯一主库,集群领导者,提供写入服务。
    • replica:集群中的普通从库,承接常规生产只读流量。
    • offline:集群中的离线从库,承接ETL/SAGA/个人用户/交互式/分析型查询。
    • standby:集群中的同步从库,采用同步复制,没有复制延迟(保留)。
    • delayed:集群中的延迟从库,显式指定复制延迟,用于执行回溯查询与数据抢救(保留)。
  • pg_seq 用于在集群内标识实例,通常采用从0或1开始递增的整数,一旦分配不再更改。

其他身份参数

  • pg_shard 用于标识集群所属的上层 分片集簇,只有当集群是水平分片集簇的一员时需要设置。

  • pg_sindex 用于标识集群的分片集簇编号,只有当集群是水平分片集簇的一员时需要设置。

  • pg_instance衍生身份参数,用于唯一标识一个数据库实例,其构成规则为

    {{ pg_cluster }}-{{ pg_seq }}。 因为pg_seq是集群内唯一的,因此该标识符全局唯一。

水平分片集簇

pg_shardpg_sindex 用于定义特殊的分片数据库集簇,是可选的身份参数,目前为Citus与Greenplum保留。

假设用户有一个水平分片的 分片数据库集簇(Shard) ,名称为test。这个集簇由四个独立的集群组成:pg-test1, pg-test2pg-test3pg-test-4。则用户可以将 pg_shard: test 的身份绑定至每一个数据库集群,将pg_sindex: 1|2|3|4 分别绑定至每一个数据库集群上。如下所示:

pg-test1:
  vars: {pg_cluster: pg-test1, pg_shard: test, pg_sindex: 1}
  hosts: {10.10.10.10: {pg_seq: 1, pg_role: primary}}
pg-test2:
  vars: {pg_cluster: pg-test1, pg_shard: test, pg_sindex: 2}
  hosts: {10.10.10.11: {pg_seq: 1, pg_role: primary}}
pg-test3:
  vars: {pg_cluster: pg-test1, pg_shard: test, pg_sindex: 3}
  hosts: {10.10.10.12: {pg_seq: 1, pg_role: primary}}
pg-test4:
  vars: {pg_cluster: pg-test1, pg_shard: test, pg_sindex: 4}
  hosts: {10.10.10.13: {pg_seq: 1, pg_role: primary}}

通过这样的定义,您可以方便地从 PGSQL Shard 监控面板中,观察到这四个水平分片集群的横向指标对比。同样的功能对于 Citus 与 MatrixDB集群同样有效。

单机部署

让我们从最简单的案例开始,在单个节点上部署单实例PostgreSQL。

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-test

使用以下命令,在 10.10.10.11 节点上创建一个单主的数据库实例。

bin/createpg pg-test

单实例数据库无法应对硬件故障,建议在生产使用时,最少使用一主一从的配置。

主从集群

复制可以极大高数据库系统可靠性,是应对硬件故障的最佳手段,在生产环境中强烈建议至少使用一主一从的配置。

Pigsty原生支持设置主从复制,例如,声明一个典型的一主一从高可用数据库集群,可以使用:

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
  vars:
    pg_cluster: pg-test

使用 bin/createpg pg-test,即可创建出该集群来。如果您已经在第一步 单机部署中完成了10.10.10.11的部署,那么也可以使用 bin/createpg 10.10.10.12,进行集群扩容,为集群添加一台从库。

如果主库出现故障,或者我们希望将从库提升为新主库,可以使用 pg 命令:

pg switchover pg-test     # 手工执行Switchover(原主库可用)
pg switchover pg-test     # 手工执行Failover (原主库不可用)

请注意,自动故障切换需要第三方进行仲裁,在Pigsty中,部署于管理节点上的DCS提供了此仲裁服务。

三节点标准HA

如果您的整套环境只有两个节点,且没有使用外部DCS进行仲裁,则无法进行安全可靠的自动故障切换,当故障发生时,您需要手工介入,人工仲裁。任何真正有意义的高可用方案,在没有特殊硬件(如心跳线等Fencing硬件)支持下,至少需要整个环境中有三个节点。因为高可用所依赖的仲裁者(DCS)本身的高可用至少需要三个节点。

如果您的整套环境中有三个节点,则可以使用 pigsty-dcs3.yml 中的样例,构建一个3元节点 x 3实例PG集群的基础高可用单元。在此部署下, 三个管理节点上部署有Consul Server,任意一个节点故障,整个集群都可以继续正常工作。

在生产环境中,您可以使用此三节点集群作为整个集群的管控核心,管理更多的数据库集群。在已有3节点DCS的仲裁者的情况下,您可以部署大量1主1从的基本高可用PGSQL集群,这些集群可以自动进行故障切换。

children:
  meta:   # meta nodes are defined in this special group "meta"
    vars:
      pg_cluster: pg-meta        # define a cluster pg-meta on 3 meta nodes
      meta_node: true            # mark this group as meta nodes
      ansible_group_priority: 99 # overwrite with the highest priority
    hosts:
      10.10.10.10: { pg_seq: 1, pg_role: primary }
      10.10.10.11: { pg_seq: 2, pg_role: replica , nginx_enabled: false }
      10.10.10.12: { pg_seq: 3, pg_role: replica , nginx_enabled: false, pg_offline_query: true }
vars:
  dcs_servers:            # dcs server dict in name:ip format
    meta-1: 10.10.10.10   # you could use existing dcs cluster
    meta-2: 10.10.10.11   # host which have their IP listed here will be init as server
    meta-3: 10.10.10.12   # 3 or 5 dcs nodes are recommended for production environment

同步从库

CAP定理指出:可用性与一致性两者相互抵触,用户必须根据自己的需求进行权衡。 高可用是一方面,而另一面则是高一致,Pigsty允许您创建高一致性的集群,确保出现故障切换时数据不丢,乃至于整个集群保持实时同步一致。

正常情况下,PostgreSQL的复制延迟在几十KB/10ms的量级,对于常规业务而言可以近似忽略不计。重要的是,当主库出现故障时,尚未完成复制的数据会丢失!当您在处理非常关键与精密的业务查询时(例如和钱打交道),复制延迟可能会成为一个问题。此外,或者在主库写入后,立刻向从库查询刚才的写入(read-your-write),也会对复制延迟非常敏感。

为了解决此类问题,需要用到同步从库。 一种简单的配置同步从库的方式是使用 pg_conf = crit 模板,该模板会自动启用同步复制与校验和,适用于和钱有关的,追求一致性的场景。

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 3, pg_role: replica }
  vars:
    pg_cluster: pg-test
    pg_conf: crit.yml

或者,您可以在集群创建完毕后,通过在元节点上执行 pg edit-config <cluster.name> ,编辑集群配置文件,修改参数synchronous_mode的值为true并应用即可。

$ pg edit-config pg-test
---
+++
-synchronous_mode: false
+synchronous_mode: true
 synchronous_mode_strict: false

Apply these changes? [y/N]: y

对于启用同步提交的集群,您可以在参考配置文件,在集群中额外配置 standby 服务,提供与主库完全一致的无延迟读取服务。

- name: standby
  src_ip: "*"
  src_port: 5435
  dst_port: pgbouncer
  check_method: http
  check_port: patroni
  check_url: /sync
  check_code: 200
  selector: "[]"
  selector_backup: "[? pg_role == `primary`]"
警告

使用同步提交时,强烈建议集群至少有3个实例,否则唯一的从库故障将立即导致主库不可用。

在PG中启用同步提交,默认会有一个从库实例被选为同步从库,而其他的实例会仍然会使用异步提交模式,以降低事务延迟,提高性能。如果您需要在整个集群范围内获得更强的一致性,可以使用法定人数同步提交

法定人数同步提交

在默认情况下,同步复制会从所有候选从库 挑选一个实例,作为同步从库,任何主库事务只有当复制到从库并Flush至磁盘上时,方视作成功提交并返回。 如果我们期望更高的数据持久化保证,例如,在一个一主三从的四实例集群中,至少有两个从库成功刷盘后才确认提交,则可以使用法定人数提交。

使用法定人数提交时,需要修改 PostgreSQL 中 synchronous_standby_names 参数的值,并配套修改Patroni中 synchronous_node_count 的值。假设三个从库分别为 pg-test-2, pg-test-3, pg-test-4 ,那么应当配置:

  • synchronous_standby_names = ANY 2 (pg-test-2, pg-test-3, pg-test-4)
  • synchronous_node_count : 2
pg-test:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary } # pg-test-1
    10.10.10.11: { pg_seq: 2, pg_role: replica } # pg-test-2
    10.10.10.12: { pg_seq: 3, pg_role: replica } # pg-test-3
    10.10.10.13: { pg_seq: 4, pg_role: replica } # pg-test-4
  vars:
    pg_cluster: pg-test

执行pg edit-config pg-test,并修改配置如下:

$ pg edit-config pg-test
---
+++
@@ -82,10 +82,12 @@
     work_mem: 4MB
+    synchronous_standby_names: 'ANY 2 (pg-test-2, pg-test-3, pg-test-4)'

-synchronous_mode: false
+synchronous_mode: true
+synchronous_node_count: 2
 synchronous_mode_strict: false

Apply these changes? [y/N]: y

应用后,即可看到配置生效,出现两个Sync Standby,当集群出现Failover或扩缩容时,请相应调整这些参数以免服务不可用。

+ Cluster: pg-test (7080814403632534854) +---------+----+-----------+-----------------+
| Member    | Host        | Role         | State   | TL | Lag in MB | Tags            |
+-----------+-------------+--------------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.10 | Leader       | running |  1 |           | clonefrom: true |
| pg-test-2 | 10.10.10.11 | Sync Standby | running |  1 |         0 | clonefrom: true |
| pg-test-3 | 10.10.10.12 | Sync Standby | running |  1 |         0 | clonefrom: true |
| pg-test-4 | 10.10.10.13 | Replica      | running |  1 |         0 | clonefrom: true |
+-----------+-------------+--------------+---------+----+-----------+-----------------+

离线从库

当您的在线业务请求负载水位很大时,将数据分析/ETL/个人交互式查询放置在专用的离线只读从库上是一个更为合适的选择。

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 2, pg_role: offline } # 定义一个新的Offline实例
  vars:
    pg_cluster: pg-test

使用 bin/createpg pg-test,即可创建出该集群来。如果您已经完成了第一步 单机部署与第二步 主从集群,那么可以使用 bin/createpg 10.10.10.13,进行集群扩容,向集群中添加一台离线从库实例。

离线从库默认不承载 replica 服务,只有当所有 replica 服务中的实例均不可用时,离线实例才会用于紧急承载只读流量。如果您只有一主一从,或者干脆只有一个主库,没有专用的离线实例,可以通过为该实例设置 pg_offline_query 标记,该实例仍然扮演原来的角色,但同时也承载 offline 服务,用作 准离线实例

备份集群

您可以使用 Standby Cluster 的方式,制作现有集群的克隆,使用这种方式,您可以从现有数据库平滑迁移至Pigsty集群中。

创建 Standby Cluster 的方式无比简单,您只需要确保备份集群的主库上配置有合适的 pg_upstream 参数,即可自动从原始上游拉取备份。

# pg-test是原始数据库
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-test
    pg_version: 14


# pg-test2将作为pg-test1的Standby Cluster
pg-test2:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary , pg_upstream: 10.10.10.11 } # 实际角色为 Standby Leader
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars:
    pg_cluster: pg-test2
    pg_version: 14          # 制作Standby Cluster时,数据库大版本必须保持一致!
bin/createpg pg-test     # 创建原始集群
bin/createpg pg-test2    # 创建备份集群

提升备份集群

当您想要将整个备份集群提升为一个独立运作的集群时,编辑新集群的Patroni配置文件,移除所有standby_cluster配置,备份集群中的Standby Leader会被提升为独立的主库。

pg edit-config pg-test2  # 移除 standby_cluster 配置定义并应用

移除下列配置:整个standby_cluster定义部分。

-standby_cluster:
-  create_replica_methods:
-  - basebackup
-  host: 10.10.10.11
-  port: 5432

修改备份集群上游复制源

当源集群发生Failover主库发生变化时,您需要调整备份集群的复制源。执行pg edit-config <cluster>,并修改standby_cluster中的源地址为新主库,应用即可生效。这里需要注意,从源集群的从库进行复制是可行的,源集群发生Failover并不会影响备份集群的复制。但新集群在只读从库上无法创建复制槽,可能出现相关报错,并存在潜在的复制中断风险,建议及时调整备份集群的上游复制源。

 standby_cluster:
   create_replica_methods:
   - basebackup
-  host: 10.10.10.13
+  host: 10.10.10.12
   port: 5432

修改 standby_cluster.host 中复制上游的IP地址,应用即可生效(无需重启,Reload即可)。

延迟从库

高可用与主从复制可以解决机器硬件故障带来的问题,但无法解决软件Bug与人为操作导致的故障,例如:误删库删表。误删数据通常需要用到冷备份,但另一种更优雅高效快速的方式是事先准备一个延迟从库。

您可以使用 备份集群 的功能创建延时从库,例如,现在您希望为pg-test 集群指定一个延时从库:pg-testdelay,该集群是pg-test1小时前的状态。因此如果出现了误删数据,您可以立即从延时从库中获取并回灌入原始集群中。

# pg-test是原始数据库
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: primary }
  vars:
    pg_cluster: pg-test
    pg_users: [ { name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] , comment: test user } ]
    pg_databases: [ { name: test , extensions: [ { name: postgis, schema: public } ] } ]

# pg-testdelay 将作为 pg-test 库的延时从库
pg-testdelay:
  hosts:
    10.10.10.13: { pg_seq: 1, pg_role: primary , pg_upstream: 10.10.10.11 } # 实际角色为 Standby Leader
  vars:
    pg_cluster: pg-testdelay

创建完毕后,在元节点使用 pg edit-config pg-testdelay编辑延时集群的Patroni配置文件,修改 standby_cluster.recovery_min_apply_delay 为你期待的值,例如1h,应用即可。

 standby_cluster:
   create_replica_methods:
   - basebackup
   host: 10.10.10.11
   port: 5432
+  recovery_min_apply_delay: 1h

级连复制

在创建集群时,如果为集群中的某个从库指定 pg_upstream 参数(指定为集群中另一个从库),那么该实例将尝试从该指定从库构建逻辑复制。

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica } # 尝试从2号从库而非主库复制
    10.10.10.13: { pg_seq: 2, pg_role: replica, pg_upstream: 10.10.10.12 }
  vars:
    pg_cluster: pg-test

Citus集群部署

Citus是一个PostgreSQL生态的分布式扩展插件,默认情况下Pigsty安装Citus,但不启用。 pigsty-citus.yml 提供了一个部署Citus集群的配置文件案例。为了启用Citus,您需要修改以下参数:

  • max_prepared_transaction: 修改为一个大于max_connections的值,例如800。
  • pg_libs:必须包含citus,并放置在最前的位置。
  • 您需要在业务数据库中包含 citus 扩展插件(但您也可以事后手工通过CREATE EXTENSION自行安装)
Citus集群样例配置
#----------------------------------#
# cluster: citus coordinator
#----------------------------------#
pg-meta:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary , pg_offline_query: true }
  vars:
    pg_cluster: pg-meta
    vip_address: 10.10.10.2
    pg_users: [ { name: citus , password: citus , pgbouncer: true , roles: [ dbrole_admin ] } ]
    pg_databases: [ { name: meta , owner: citus , extensions: [ { name: citus } ] } ]

#----------------------------------#
# cluster: citus data nodes
#----------------------------------#
pg-node1:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-node1
    vip_address: 10.10.10.3
    pg_users: [ { name: citus , password: citus , pgbouncer: true , roles: [ dbrole_admin ] } ]
    pg_databases: [ { name: meta , owner: citus , extensions: [ { name: citus } ] } ]

pg-node2:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary  , pg_offline_query: true }
  vars:
    pg_cluster: pg-node2
    vip_address: 10.10.10.4
    pg_users: [ { name: citus , password: citus , pgbouncer: true , roles: [ dbrole_admin ] } ]
    pg_databases: [ { name: meta , owner: citus , extensions: [ { name: citus } ] } ]

pg-node3:
  hosts:
    10.10.10.13: { pg_seq: 1, pg_role: primary  , pg_offline_query: true }
  vars:
    pg_cluster: pg-node3
    vip_address: 10.10.10.5
    pg_users: [ { name: citus , password: citus , pgbouncer: true , roles: [ dbrole_admin ] } ]
    pg_databases: [ { name: meta , owner: citus , extensions: [ { name: citus } ] } ]

接下来,您需要参照Citus多节点部署指南,在 Coordinator 节点上,执行以下命令以添加数据节点:

sudo su - postgres; psql meta
SELECT * from citus_add_node('10.10.10.11', 5432);
SELECT * from citus_add_node('10.10.10.12', 5432);
SELECT * from citus_add_node('10.10.10.13', 5432);
SELECT * FROM citus_get_active_worker_nodes();
  node_name  | node_port
-------------+-----------
 10.10.10.11 |      5432
 10.10.10.13 |      5432
 10.10.10.12 |      5432
(3 rows)

成功添加数据节点后,您可以使用以下命令,在协调者上创建样例数据表,并将其分布到每个数据节点上。

-- 声明一个分布式表
CREATE TABLE github_events
(
    event_id     bigint,
    event_type   text,
    event_public boolean,
    repo_id      bigint,
    payload      jsonb,
    repo         jsonb,
    actor        jsonb,
    org          jsonb,
    created_at   timestamp
) PARTITION BY RANGE (created_at);
-- 创建分布式表
SELECT create_distributed_table('github_events', 'repo_id');

更多Citus相关功能介绍,请参考Citus官方文档

MatrixDB集群部署

Greenplum是基于PostgreSQL生态构建的分布式数据仓库,广受广大用户喜爱。MatrixDB是Greenplum的一个分支,基于Greenplum 7 ,使用PostgreSQL 12内核。因为Greenplum 7尚未正式发布,因此Pigsty目前使用MatrixDB作为Greenplum的替代实现。

因为MatrixDB基于PostgreSQL生态,因此大多数PostgreSQL剧本与任务可以复用在 MatrixDB 上。MatrixDB 专用的额外参数只有两个:

  • gp_role:定义Greenplum集群的身份,mastersegment
  • pg_instances:定义Segment实例,用于部署Segment实例监控。

详情请参考 MatrixDB部署

MatrixDB集群样例配置 4节点
#----------------------------------#
# cluster: mx-mdw (gp master)
#----------------------------------#
mx-mdw:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary , nodename: mx-mdw-1 }
  vars:
    gp_role: master          # this cluster is used as greenplum master
    pg_shard: mx             # pgsql sharding name & gpsql deployment name
    pg_cluster: mx-mdw       # this master cluster name is mx-mdw
    pg_databases:
      - { name: matrixmgr , extensions: [ { name: matrixdbts } ] }
      - { name: meta }
    pg_users:
      - { name: meta , password: DBUser.Meta , pgbouncer: true }
      - { name: dbuser_monitor , password: DBUser.Monitor , roles: [ dbrole_readonly ], superuser: true }

    pgbouncer_enabled: true                # enable pgbouncer for greenplum master
    pgbouncer_exporter_enabled: false      # enable pgbouncer_exporter for greenplum master
    pg_exporter_params: 'host=127.0.0.1&sslmode=disable'  # use 127.0.0.1 as local monitor host

#----------------------------------#
# cluster: mx-sdw (gp master)
#----------------------------------#
mx-sdw:
  hosts:
    10.10.10.11:
      nodename: mx-sdw-1        # greenplum segment node
      pg_instances:             # greenplum segment instances
        6000: { pg_cluster: mx-seg1, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633 }
        6001: { pg_cluster: mx-seg2, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634 }
    10.10.10.12:
      nodename: mx-sdw-2
      pg_instances:
        6000: { pg_cluster: mx-seg2, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633  }
        6001: { pg_cluster: mx-seg3, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634  }
    10.10.10.13:
      nodename: mx-sdw-3
      pg_instances:
        6000: { pg_cluster: mx-seg3, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633 }
        6001: { pg_cluster: mx-seg1, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634 }
  vars:
    gp_role: segment               # these are nodes for gp segments
    pg_shard: mx                   # pgsql sharding name & gpsql deployment name
    pg_cluster: mx-sdw             # these segment clusters name is mx-sdw
    pg_preflight_skip: true        # skip preflight check (since pg_seq & pg_role & pg_cluster not exists)
    pg_exporter_config: pg_exporter_basic.yml   # use basic config to avoid segment server crash
    pg_exporter_params: 'options=-c%20gp_role%3Dutility&sslmode=disable'  # use gp_role = utility to connect to segments

19 - 部署与监控Redis

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty是一个PostgreSQL发行版,也是一个通用应用运行时。您可以用它管理、部署、监控其他应用与数据库,例如Redis。

与PostgreSQL类似,部署Redis同样需要两个步骤:

  1. 声明/定义Redis集群
  2. 执行Playbook创建Redis集群

Redis集群定义

下面给出了三个Redis集群的精简定义,包括:

  • 一个1节点,3实例的Redis Sentinel集群 redis-sentinel
  • 一个2节点,12实例的的Redis Cluster集群 redis-cluster
  • 一个1节点,一主两从的Redis Standalone集群 redis-standalone

您需要在节点上为Redis实例分配唯一的端口号。

Redis Sentinel集群定义

#----------------------------------#
# redis sentinel example           #
#----------------------------------#
redis-meta:
  hosts:
    10.10.10.10:
      redis_node: 1
      redis_instances:  { 6001 : {} ,6002 : {} , 6003 : {} }
  vars:
    redis_cluster: redis-meta
    redis_mode: sentinel
    redis_max_memory: 128MB

Redis原生集群定义

#----------------------------------#
# redis cluster example            #
#----------------------------------#
redis-test:
  hosts:
    10.10.10.11:
      redis_node: 1
      redis_instances: { 6501 : {} ,6502 : {} ,6503 : {} ,6504 : {} ,6505 : {} ,6506 : {} }
    10.10.10.12:
      redis_node: 2
      redis_instances: { 6501 : {} ,6502 : {} ,6503 : {} ,6504 : {} ,6505 : {} ,6506 : {} }
  vars:
    redis_cluster: redis-test           # name of this redis 'cluster'
    redis_mode: cluster                 # standalone,cluster,sentinel
    redis_max_memory: 64MB              # max memory used by each redis instance
    redis_mem_policy: allkeys-lru       # memory eviction policy

Redis普通主从实例定义

#----------------------------------#
# redis standalone example         #
#----------------------------------#
redis-common:
  hosts:
    10.10.10.13:
      redis_node: 1
      redis_instances:
        6501: {}
        6502: { replica_of: '10.10.10.13 6501' }
        6503: { replica_of: '10.10.10.13 6501' }
  vars:
    redis_cluster: redis-common         # name of this redis 'cluster'
    redis_mode: standalone              # standalone,cluster,sentinel
    redis_max_memory: 64MB              # max memory used by each redis instance

创建Redis集群

部署剧本

使用剧本redis.yml创建Redis实例/集群

./redis.yml -l redis-sentinel
./redis.yml -l redis-cluster
./redis.yml -l redis-standalone

其他注意事项

尽管这样做并不是推荐的行为,您可以将PostgreSQL与Redis进行混合部署,以充分利用机器资源。

redis.yml 剧本会在机器上同时部署Redis监控Exporter,包括redis_exporternode_exporter(可选)

在此过程中,如果机器的node_exporter存在,将会被重新部署。

Prometheus默认会使用"多目标抓取"模式,使用节点上9121端口的Redis Exporter抓取该节点上所有的Redis实例。

查阅Redis监控

目前Pigsty提供了3个Redis监控面板,作为一个独立监控应用 REDIS的组成部分,分别为:

  • Redis Overview:提供整个环境中Redis的全局概览
  • Redis Cluster: 关注单个Redis业务集群的监控信息
  • Redis Instance:关注单个Redis实例的详细监控信息

您可以使用自带的 redis-benchmark 测试

其他功能

Pigsty v1.5.1 支持 Redis 集群整体部署与监控;标签中的 redis.yml / redis-remove.yml 也可通过 -e redis_port=<port> 操作单个实例。

20 - MatrixDB部署与监控

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty可用于部署与监控MatrixDB(等于Greenplum 7+时序数据库)

因为目前MatrixDB使用的是PostgreSQL 12的内核,而原生Greenplum仍然使用9.6内核,因此优先使用MatrixDB替代Greenplum实现,后续将添加原生的Greenplum支持。

实体概念模型

MatrixDB在逻辑上由两部分组成,Master与Segments,两者均由PostgreSQL实例组成,实例分为四类:Master/Standby/Primary/Mirror

  • Master为用户直接接触的访问端点,用于承接查询,一套MatrixDB部署仅有一个,通常使用独立节点部署。
  • Standby是Master实例的物理从库,用于当Master故障时顶替,是可选的组件,通常也使用独立节点部署。
  • 一套MatrixDB部署通常有多个Segment,每个Segment通常由一个必选的 primary 实例与一个 可选的 mirror 实例组成。
  • Segment的primary负责实际存储与计算,mirror通常不承担读写流量,当primary宕机时顶替primary,通常与primary分布在不同节点上。
  • Segment的primary与mirror分布由MatrixDB安装向导决定,在集群的Segments节点上通常可能存在有多个不同的Segment实例

部署惯例

  • Master集群 (master/standby) (gp_role = master) 构成一个PostgreSQL集群,通常命名包含mdw,如mx-mdw
  • 每个Segment (primary/mirror) (gp_role = segment) 构成一个PostgreSQL集群,通常集群命名包含seg,如 mx-seg1, mx-seg2
  • 用户应当显式为集群节点命名,例如 mx-sdw-1, mx-sdw-2, …

下载软件

MatrixDB & Greenplum 的RPM包并不是标准Pigsty部署的一部分,因此不会放入默认的pkg.tgz中。 MatrixDB & Greenplum 的RPM包及其完整依赖将打包为一个单独的离线软件包 matrix.tgz。 您可以向Pigsty元节点上添加新的matrix源。

# 下载地址(Github):https://github.com/Vonng/pigsty/releases/download/v1.5.1/matrix.tgz
# 下载地址(China CDN):http://download.pigsty.cc/v1.5.1/matrix.tgz
# 下载脚本,在元节点上,pigsty目录下,直接使用 download matrix 下载并解压
./download matrix

该命令会创建一个 /www/matrix.repo 文件,默认情况下,您可以访问http://pigsty/matrix.repo获取该Repo,该Repo文件指向 http://pigsty/matrix目录。

配置

MatrixDB / Greenplum 的安装将复用 PGSQL 任务与配置,专属配置参数为 gp_rolepg_instances

配置文件pigsty-mxdb.yml 给出了一个在四节点沙箱环境部署MatrixDB的样例。

使用 `configure -m mxdb`,将自动使用该配置文件作为配置模板。
./configure -m mxdb

此配置文件中 node_repo_local_urls添加了新Yum源地址,http://pigsty/matrix.repo 确保所有节点都可以访问Matrix Repo。

开始部署

在四节点沙箱环境中部署MatrixDB,注意,默认将使用DBSU mxadmin:mxadmin 作为监控用户名与密码

# 如果您准备在meta节点上部署 MatrixDB Master,添加no_cmdb选项,否则正常安装即可。
./infra.yml -e no_cmdb=true

# 配置所有用于安装MatrixDB的节点
./nodes.yml

# 在上述节点上安装MatrixDB
./pgsql-matrixdb.yml

安装完成后,您需要通过MatrixDB 提供的WEB UI完成接下来的安装。打开 http://mx.pigsty 或访问 http://10.10.10.10:8240 ,填入 pgsql-matrixdb.yml 最后输出的初始用户密码进入安装向导。

按照提示依次添加MatrixDB的节点:10.10.10.11, 10.10.10.12, 10.10.10.13,点击确认安装并等待完成后,进行下一步。

因为监控默认使用 mxadmin:mxadmin 作为监控用户名密码,请填入mxadmin 或您自己的密码。

如果您在安装向导中指定了不同的密码, 请一并更改 pg_monitor_usernamepg_monitor_password 变量(如果您使用不同于dbsu的用户,通常还需要在所有实例上配置额外的HBA)。

请注意,目前MatrixDB / Greenplum 在节点上分配 Segment的逻辑并不确定。当初始化完成后,您可以修改 pg_instances 中Segment实例的定义,并重新部署监控以反映真实拓扑。

收尾工作

最后,在Greenplum/MatrixDB Master节点上手工执行以下命令,允许监控组件访问从库,并重启生效。

sudo su - mxadmin
psql postgres -c "ALTER SYSTEM SET hot_standby = on;"  # 配置 hot_standby=on 以允许从库查询
gpconfig -c hot_standby -v on -m on                    # 配置 hot_standby=on 以允许从库查询
gpstop -a -r -M immediate                              # 立即重启MatrixDB以生效

然后,您便可以从监控系统中,观察到所有MatrixDB集群。MatrixDB Dashboard 提供了关于数据仓库的整体监控概览。

可选项目

您可以将 MatrixDB 的 Master集群视作一个普通 PostgreSQL 集群,使用 pgsql-createdbpgsql-createuser 创建业务数据库与用户。

bin/createuser mx-mdw  dbuser_monitor   # 在Master主库上创建监控用户
bin/createdb   mx-mdw  matrixmgr        # 在Master主库上创建监控专用数据库
bin/createdb   mx-mdw  meta             # 在Master主库上创建新数据库

21 - Pigsty剧本

从 Pigsty v1.5.1 标签恢复的历史文档。

了解Pigsty提供的预置剧本,功能、使用方式与注意事项。

Pigsty在底层通过 Ansible Playbook 实现核心管控功能,Pigsty提供的预置剧本分为四大类:

  • infra : 使用 infra 系列剧本在元节点上单机安装Pigsty,并加装可选功能。
  • nodes : 使用 nodes 系列剧本将更多节点纳入Pigsty监控管理,并供后续使用。
  • pgsql : 使用 pgsql 系列剧本在已有节点上部署与管理PostgreSQL数据库集群。
  • redis : 使用 redis 系列剧本在已有节点上部署与管理各种模式的Redis集群。

剧本概览

剧本 功能 链接
infra 在元节点上完整安装Pigsty src
infra-demo 一次性完整初始化四节点演示沙箱环境的特殊剧本 src
infra-jupyter 在元节点上加装可选数据分析服务组件Jupyter Lab src
nodes 节点置备,将节点纳入Pigsty管理,可用于后续数据库部署 src
nodes-remove 节点移除,卸载节点DCS与监控,不再纳入Pigsty管理 src
pgsql 部署PostgreSQL集群,或集群扩容 src
pgsql-remove 下线PostgreSQL集群,或集群缩容 src
pgsql-createuser 创建PostgreSQL业务用户 src
pgsql-createdb 创建PostgreSQL业务数据库 src
pgsql-monly 仅监控模式,接入现存PostgreSQL实例或RDS src
pgsql-migration 生成PostgreSQL半自动数据库迁移方案(Beta) src
pgsql-matrixdb 复用PG角色部署一套MatrixDB数据仓库集群(Beta) src
redis 部署集群/主从/Sentinel模式的Redis数据库 src
redis-remove Redis集群/节点下线 src

典型使用流程如下:

  1. 使用 infra 系列剧本在元节点/本机安装 Pigsty ,部署基础设施。

    所有剧本都在元节点上发起执行,infra 系列剧本只作用于元节点本身。

  2. 使用 nodes 系列剧本将其他节点纳入或移除Pigsty管理

    节点被托管后,可从元节点Grafana访问节点监控与日志,节点加入Consul集群。

  3. 使用 pgsql 系列剧本在纳入管理的节点上部署PostgreSQL集群

    在托管节点上执行部署后,可以从元节点访问PostgreSQL监控与日志。

  4. 使用 redis 系列剧本在纳入管理的节点上部署Redis集群

    在托管节点上执行部署后,可以从元节点访问Redis监控与日志。

                                           meta     node
[infra.yml]  ./infra.yml [-l meta]        +pigsty
[nodes.yml]  ./nodes.yml -l pg-test                 +consul +monitor
[pgsql.yml]  ./pgsql.yml -l pg-test                 +pgsql
[redis.yml]  ./redis.yml -l pg-test                 +redis

绝大多数剧本都是幂等设计,这意味着一些部署剧本在没有开启保护选项的情况下,可能会抹除现有数据库并创建新数据库。 当您处理现有数据库集群,或在生产环境进行操作时,请充分阅读并理解文档,再三校对命令,谨慎操作。对于误操作导致的数据库损失,作者不负任何责任。


Ansible快速上手

Pigsty剧本使用Ansible编写,您并不需要完全理解Ansible的原理,只需要很少的知识即足以充分利用 Ansible 剧本。

  • Ansible安装:如何安装Ansible?(Pigsty用户通常无需操心)
  • 主机子集:如何针对特定主机执行剧本?
  • 任务子集:如何执行剧本中的某些特定任务?
  • 额外参数:如何传入额外的命令行参数以控制剧本行为?

Ansible安装

Ansible剧本需要使用ansible-playbook可执行命令,在EL7兼容系统中可通过以下命令安装 Ansible。

yum install ansible

当使用离线软件包时,Pigsty会在Configure阶段尝试从离线软件包中安装ansible。

执行Ansible剧本时,直接将剧本作为可执行程序执行即可。执行剧本时有三个核心的参数需要关注:-l|-t|-e,分别用于限制执行的主机,与执行的任务,以及传入额外的参数。

主机子集

可以通过 -l|--limit <selector> 参数选择执行的目标,不指定此参数时,大多数剧本默认会以配置文件中定义的所有主机作为执行对象,这是非常危险的。 强烈建议在执行剧本时,指定执行的对象。

常用的对象有两种,集群与主机,例如:

./pgsql.yml                 # 在配置清单的所有主机上执行pgsql剧本(危险!)
./pgsql.yml -l pg-test      # 针对 pg-test 集群中的主机执行pgsql剧本
./pgsql.yml -l 10.10.10.10  # 针对 10.10.10.10 的主机执行pgsql剧本
./pgsql.yml -l pg-*         # 针对符合 pg-* 模式 (glob) 的集群执行剧本

任务子集

可以通过-t|--tags <tags>来选择执行的任务子集,不指定此参数时,会执行完整的剧本,指定此参数时,则将执行所选的任务子集,这是非常实用的。

./pgsql.yml -t pg_hba                            # 重新生成并应用集群HBA规则

用户可以通过,分隔,一次执行多个任务,例如当集群角色成员发生变化时,可以使用以下命令调整集群负载均衡配置。

./pgsql.yml -t haproxy_config,haproxy_reload     # 重新生成集群负载均衡器配置并应用

额外参数

可以通过-e|--extra-vars KEY=VALUE 传入额外的命令行参数,覆盖已有参数,或控制一些特殊的行为。

例如,以下剧本的部分行为可以通过命令行参数进行控制。

./nodes.yml -e ansible_user=admin -k -K      # 在配置节点时,使用另一个管理员用户 admin,并输入ssh与sudo密码
./pgsql.yml -e pg_clean=true        # 在安装PG时,强制抹除已有运行中数据库实例(危险)
./infra-remove.yml -e rm_metadata=true       # 在卸载Pigsty时,一并移除数据
./infra-remove.yml -e rm_metapkgs=true      # 在卸载Pigsty时,一并卸载软件
./nodes-remove.yml -e dcs_safeguard=false     # 在移除节点时,即使上面有DCS Server也强制移除
./pgsql-remove.yml -e rm_pgdata=true         # 在移除PG时,一并移除数据
./pgsql-remove.yml -e rm_pgpkgs=true         # 在移除PG时,一并卸载软件

22 - 剧本:INFRA

从 Pigsty v1.5.1 标签恢复的历史文档。

使用 infra 系列剧本在当前元节点上安装Pigsty,并加装可选功能。

剧本 功能 链接
infra 在元节点上完整安装Pigsty src
infra-demo 一次性完整初始化四节点演示沙箱环境的特殊剧本 src
infra-remove 在元节点上卸载Pigsty src
infra-jupyter 在元节点上加装可选数据分析服务组件组件Jupyter Lab src

infra

infra.yml 剧本会在元节点 (默认为当前节点)上完成Pigsty的安装与部署。

当您将Pigsty用作开箱即用的数据库时,只要在本节点上直接执行 infra.yml ,即可完成安装。

What

执行该剧本将完成以下任务

  • 配置元节点的目录与环境变量
  • 下载并建立一个本地yum软件源,加速后续安装。(若使用离线软件包,则跳过下载阶段)
  • 将当前元节点作为一个普通节点纳入 Pigsty 管理
  • 部署基础设施组件,包括 Prometheus, Grafana, Loki, Alertmanager, Consul Server等
  • 在当前节点上部署一个普通的PostgreSQL单实例集群,纳入监控。

Where

该剧本默认针对元节点执行

  • Pigsty默认将使用当前执行此剧本的节点作为Pigsty的元节点。
  • Pigsty在配置过程中默认会将当前节点标记为元节点,并使用当前节点首要IP地址替换配置模板中的占位IP地址10.10.10.10
  • 元节点除了可以发起管理,部署有基础设施外。与一个部署了PG的普通托管节点并无区别。
  • Pigsty默认使用元节点部署DCS Server,用于数据库高可用,但您完全可以选用外部DCS集群。
  • 使用多个元节点是可能的,参考 DCS3 配置模板:部署3节点的DCS Server,允许其中一台宕机。

How

执行该剧本的一些注意事项

  • 本剧本为幂等剧本,重复执行会抹除元节点上的Consul Server与CMDB(关闭保护选项情况下)
  • 使用离线软件包时,完整执行该剧本耗时约5-8分钟,视机器配置而异。
  • 不使用离线软件包而直接从互联网原始上游下载软件时,可能耗时10-20分钟,根据您的网络条件而异。
  • 本剧本会将元节点作为一个普通节点纳入管理,并部署PG数据库,覆盖了nodes.ymlpgsql.yml的所有内容,因此infra.yml如果可以在元节点上成功执行完毕,那么则在相同状态的普通节点上一定可以成功完成数据库部署。
  • 元节点上默认的pg-meta将用作Pigsty元数据库,用于承载高级特性。

Tasks

该剧本

./infra.yml --tags=environ                       # 重新在元节点上配置环境
./infra.yml --tags=repo -e repo_rebuild=true     # 强制重新创建本地源
./infra.yml --tags=repo_upstream                 # 加入上游YumRepo
./infra.yml --tags=prometheus                    # 重新创建Prometheus
./infra.yml --tags=nginx_config,nginx_restart    # 重新生成Nginx配置文件并重启
……

配置清单中,隶属于 meta分组下的节点将被设置 meta_node 标记,用作 Pigsty 的元节点。


infra-demo

infra-demo.yml 是用于演示环境的特殊剧本,通过交织元节点与普通节点初始化的方式,可以一次性完成4节点沙箱环境的初始化。 在四节点沙箱中,本剧本可等效为

./infra.yml              # 在元节点安装 Pigsty
./nodes.yml -l pg-test   # 将 pg-test 所属三节点纳入管理
./pgsql.yml -l pg-test   # 在 pg-test 三节点上部署数据库集群

此外,当您尝试部署复数个元节点时,如果选择默认将DCS Server部署在所有元节点上时,也可以使用此剧本一次性拉起所有元节点以及其上的DCS与数据库集群。

警告

请注意,配置不当的情况下,此剧本有一次性抹平整个环境的奇效,在生产环境可以移除以避免 “Fat Finger” 的风险。


infra-remove

infra-remove.yml 剧本是 infra 剧本的反向操作。

会将Pigsty从元节点卸载,剧本会依次卸载下列组件。

  • grafana-server
  • prometheus
  • alertmanager
  • node_exporter
  • consul
  • loki

infra-jupyter

infra-jupyter.yml 剧本用于在元节点上加装 Jupyter Lab服务

详细教程请参考 教程:启用Jupyter Lab服务

23 - 剧本:NODES

从 Pigsty v1.5.1 标签恢复的历史文档。

使用 NODES 系列剧本将更多节点纳入Pigsty管理,将节点调整至配置描述的状态。

当您使用 infra.yml 在元节点上完成Pigsty的完整安装后,您可以进一步使用 nodes.yml 将更多节点添加至Pigsty中,或者使用 nodes-remove.yml 将节点从环境中移除。

剧本 功能 链接
nodes 节点置备,将节点纳入Pigsty管理,可用于后续数据库部署 src
nodes-remove 节点移除,卸载节点DCS与监控,不再纳入Pigsty管理 src

nodes

nodes.yml 剧本将更多节点添加至Pigsty中。该剧本需要在 元节点 上发起,针对目标节点执行。

此剧本可以将目标机器节点调整至配置清单所描述的状态,安装Consul服务,并将其纳入Pigsty监控系统,并允许您在这些置备好的节点上进一步部署不同类型的数据库集群。

nodes.yml 剧本的行为由 节点配置 决定。在使用本地源的情况下,完整执行此剧本可能耗时1~3分钟,视机器配置而异。

./nodes.yml                      # 初始化所有清单中的节点(危险!)
./nodes.yml -l pg-test           # 初始化在 pg-test 分组下的机器(推荐!)
./nodes.yml -l pg-meta,pg-test   # 同时初始化pg-meta与pg-test两个集群中的节点
./nodes.yml -l 10.10.10.11       # 初始化10.10.10.11这台机器节点

此剧本包含的功能与任务如下:

  • 生成节点身份参数
  • 初始化节点
    • 配置节点名称
    • 配置节点静态DNS解析
    • 配置节点动态DNS解析服务器
    • 配置节点的Yum源
    • 安装指定的RPM软件包
    • 配置 numa/swap/firewall等特性
    • 配置节点tuned调优模板
    • 配置节点的快捷命令与环境变量
    • 创建节点管理员并配置SSH
    • 配置节点时区
    • 配置节点NTP服务
  • 在节点上初始化DCS服务:Consul 与 ETCD
    • 抹除现有Consul
    • 初始化当前节点的 Consul Agent或Server 服务
  • 初始化节点监控组件并纳入Pigsty
    • 在节点上安装 Node Exporter
    • 将 Node Exporter 注册至元节点上的 Prometheus 中。
警告

对于已有数据库运行的节点执行该剧本需要谨慎,使用不当存在误触发短暂数据库不可用的风险,因为初始化节点会抹除DCS Agent

节点置备会配置节点的DCS服务(Consul Agent),因此在对运行有PostgreSQL数据库的节点运行此剧本时,请小心! dcs_clean 参数提供了避免误删的选项作为保险,允许以在初始化过程中,当检测到已有运行中DCS时自动中止或跳过高危操作,避免最坏情况发生。

警告

尽管如此,在使用完整的nodes.yml剧本或其中关于dcs|consul的部分时,请再三检查--tags|-t--limit|-l 参数是否正确。确保自己在正确的目标上执行正确的任务。

保护机制

Pigsty提供保护机制,避免误删运行中的Consul实例,包括了两个相关参数:

  • dcs_safeguard:默认关闭,只要打开,在任意情况下运行中的 DCS 实例都不会被清理。
  • dcs_clean:Consul 角色兜底值与 v1.5.1 随附沙箱清单均为 true;受保护环境应设为 false 并启用保护参数。

当遇到现存实例时,nodes.yml 剧本会有以下行为表现:

dcs_safeguard / dcs_clean dcs_clean=true dcs_clean=false
dcs_safeguard=true 中止执行 中止执行
dcs_safeguard=false 抹除实例 中止执行

当遇到现存实例时, nodes-remove.yml剧本会有以下行为表现:

dcs_safeguard / dcs_clean dcs_clean=true dcs_clean=false
dcs_safeguard=true 中止执行 中止执行
dcs_safeguard=false 抹除实例 抹除实例

选择性执行

用户可以通过ansible的标签机制,选择性执行本剧本的一个子集。例如,如果只想执行节点监控部署的任务,则可以通过以下命令:

./nodes.yml --tags=node-monitor

一些常用的任务子集包括:

# play
./nodes.yml --tags=node-id         # 打印节点身份参数:名称与集群
./nodes.yml --tags=node-init       # 初始化节点,完成配置
./nodes.yml --tags=node-dcs        # 在节点上初始化DCS服务:Consul
./nodes.yml --tags=node-monitor    # 初始化节点监控组件并纳入Pigsty

# tasks
./nodes.yml --tags=node_name       # 配置节点名称
./nodes.yml --tags=node_dns        # 配置节点静态DNS解析
./nodes.yml --tags=node_resolv     # 配置节点动态DNS解析服务器
./nodes.yml --tags=node_repo       # 配置节点的Yum源
./nodes.yml --tags=node_pkgs       # 安装指定的RPM软件包
./nodes.yml --tags=node_feature    # 配置 numa/swap/firewall等特性
./nodes.yml --tags=node_tuned      # 配置节点tuned调优模板
./nodes.yml --tags=node_profile    # 配置节点的快捷命令与环境变量
./nodes.yml --tags=node_admin      # 创建节点管理员并配置SSH
./nodes.yml --tags=node_timezone   # 配置节点时区
./nodes.yml --tags=node_ntp        # 配置节点NTP服务

./nodes.yml --tags=consul          # 在节点上配置consul agent/server
./nodes.yml --tags=consul -e dcs_clean=true   # 在节点上强制抹除重新配置consul

./nodes.yml --tags=node_exporter   # 在节点上配置 node_exporter 并注册
./nodes-remove.yml --tags=register # 将节点监控从元节点上取消注册
./nodes.yml --tags=node_register   # 将节点监控注册到元节点上

创建管理用户

管理用户是一个先有鸡还是先有蛋的问题。为了执行Ansible剧本,需要有一个管理用户。为了创建一个专用的管理用户,需要执行此Ansible剧本。

Pigsty推荐将管理用户的创建,权限配置与密钥分发放在虚拟机的Provisioning阶段完成,作为机器资源交付内容的一部分。对于生产环境来说,机器交付时应当已经配置有这样一个具有免密远程SSH登陆并执行免密sudo的用户。通常绝大多数云平台和运维体系都可以做到这一点。

如果您只能使用ssh密码和sudo密码,那么必须在所有剧本执行时添加额外的参数 --ask-pass|-k--ask-become-pass|-K,并在提示出现时输入ssh密码与sudo密码。您可以使用 nodes.yml 中创建管理员用户的功能,使用当前用户创建一个专用管理员用户,以下参数用于创建默认的管理员用户:

./nodes.yml -t node_admin -l <目标机器> --ask-pass --ask-become-pass

默认创建的管理员用户为 dba(uid=88),请不要使用 postgres{{ dbsu }} 作为管理用户,请尽量避免直接使用 root 作为管理用户。

在沙箱环境中的默认用户 vagrant 默认已经配置有免密登陆和免密sudo,您可以从宿主机或沙箱元节点使用vagrant登陆所有的数据库节点。

例如:

./nodes.yml --limit <target_hosts>  --tags node_admin  -e ansible_user=<another_admin> --ask-pass --ask-become-pass

详情请参考:准备:管理用户置备


nodes-remove

nodes-remove.yml 剧本是 nodes剧本的反向操作,用于将节点从Pigsty中移除。

该剧本需要在 元节点 上发起,针对目标节点执行。

./nodes-remove.yml               # 移除所有节点(危险!)
./nodes-remove.yml -l nodes-test # 移除 nodes-test 分组下的机器
./nodes-remove.yml -l 10.10.10.11 # 移除 10.10.10.11 这台机器节点
./nodes-remove.yml -l 10.10.10.10 -e dcs_safeguard=false # 若节点为 DCS Server,显式关闭保护后移除。

任务子集

# play
./nodes-remove.yml --tags=register      # 移除节点注册信息
./nodes-remove.yml --tags=node-exporter # 移除节点指标收集器
./nodes-remove.yml --tags=promtail      # 移除Promtail日志收集组件
./nodes-remove.yml --tags=consul        # 移除Consul Agent服务
./nodes-remove.yml --tags=consul -e dcs_safeguard=false # 移除Consul服务(包括Server!)

24 - 剧本:PGSQL

从 Pigsty v1.5.1 标签恢复的历史文档。

使用PGSQL系列剧本,拉起定义好的高可用PostgreSQL数据库集群

剧本概览

剧本 功能 链接
pgsql 部署PostgreSQL集群,或集群扩容 src
pgsql-remove 下线PostgreSQL集群,或集群缩容 src
pgsql-createuser 创建PostgreSQL业务用户 src
pgsql-createdb 创建PostgreSQL业务数据库 src
pgsql-monly 仅监控模式,接入现存PostgreSQL实例或RDS src
pgsql-migration 生成PostgreSQL半自动数据库迁移方案(Beta) src
pgsql-matrixdb 复用PG角色部署一套MatrixDB数据仓库集群(Beta) src

pgsql

完成了基础设施初始化后,用户可以 pgsql.yml 完成数据库集群的初始化

首先在 Pigsty配置文件 中完成数据库集群的定义,然后通过执行pgsql.yml将变更应用至实际环境中。

./pgsql.yml                      # 在所有清单中的机器上执行数据库集群初始化操作(危险!)
./pgsql.yml -l pg-test           # 在 pg-test 分组下的机器执行数据库集群初始化(推荐!)
./pgsql.yml -l pg-meta,pg-test   # 同时初始化pg-meta与pg-test两个集群
./pgsql.yml -l 10.10.10.11       # 初始化10.10.10.11这台机器上的数据库实例

本剧本主要完成以下工作:

  • 安装、部署、初始化PostgreSQL, Pgbouncer, Patroni(postgres
  • 安装PostgreSQL监控系统(monitor
  • 安装部署Haproxy与VIP,对外暴露服务(service
  • 将数据库实例注册至基础设施,接受监管(register

该剧本使用不当存在误删数据库的风险,因为初始化数据库会抹除原有数据库的痕迹保险参数提供了避免误删的选项作为保险,以在初始化过程中,当检测到已有运行中实例时,允许自动中止或跳过高危操作,避免最坏情况发生。尽管如此,在使用pgsql.yml时,请再三检查--tags|-t--limit|-l 参数是否正确。确保自己在正确的目标上执行正确的任务。使用不带参数的pgsql.yml在生产环境中是一个高危操作,务必三思而后行。

注意事项

  • 强烈建议在执行时添加-l参数,限制命令执行的对象范围。

  • 单独针对某一集群从库执行初始化时,用户必须自行确保主库已经完成初始化

  • 集群扩容时,如果Patroni拉起从库的时间过长,Ansible剧本可能会因为超时而中止。(但制作从库的进程会继续,例如制作从库需超过1天的场景)。

  • 您可以在从库自动制作完毕后,通过Ansible的--start-at-taskWait for patroni replica online任务继续执行后续步骤。详情请参考SOP

保护机制

pgsql.yml提供保护机制,避免误删运行中的PostgreSQL数据库,包括了两个相关参数:

  • pg_safeguard:默认关闭,只要打开,在任意情况下该数据库实例不会被清理。
  • pg_clean:角色兜底值为 false,但 v1.5.1 随附的沙箱清单设置为 true;受保护环境应关闭并启用保护参数。

当遇到现存实例时,pgsql.yml 剧本会有以下行为表现:

pg_safeguard / pg_clean pg_clean=true pg_clean=false
pg_safeguard=true 中止执行 中止执行
pg_safeguard=false 抹除实例 中止执行

当遇到现存实例时, pgsql-remove.yml 剧本会有以下行为表现:

pg_safeguard / pg_clean pg_clean=true pg_clean=false
pg_safeguard=true 中止执行 中止执行
pg_safeguard=false 抹除实例 抹除实例

选择性执行

用户可以通过ansible的标签机制,可以选择执行剧本的一个子集。

举个例子,如果只想执行服务初始化的部分,则可以通过以下命令进行

./pgsql.yml --tags=service      # 刷新集群的服务定义

常用的命令子集如下:

# 基础设施初始化
./pgsql.yml --tags=infra        # 完成基础设施的初始化,包括机器节点初始化与DCS部署


# 数据库初始化
./pgsql.yml --tags=pgsql        # 完成数据库部署:数据库、监控、服务

./pgsql.yml --tags=postgres     # 完成数据库部署
./pgsql.yml --tags=monitor      # 完成监控的部署
./pgsql.yml --tags=service      # 完成负载均衡的部署,(Haproxy & VIP)
./pgsql.yml --tags=register     # 将服务注册至基础设施

日常管理任务

日常管理也可以使用./pgsql.yml来修改数据库集群的状态,常用的命令子集如下:

./pgsql.yml --tags=node_admin           # 在目标节点上创建管理员用户

# 如果当前管理员没有ssh至目标节点的权限,可以使用其他具有ssh的用户创建管理员(输入密码)
./pgsql.yml --tags=node_admin -e ansible_user=other_admin -k

./pgsql.yml --tags=pg_scripts           # 更新/pg/bin/目录脚本
./pgsql.yml --tags=pg_hba               # 重新生成并应用集群HBA规则
./pgsql.yml --tags=pgbouncer            # 重置Pgbouncer
./pgsql.yml --tags=pg_user              # 全量刷新业务用户
./pgsql.yml --tags=pg_db                # 全量刷新业务数据库

./pgsql.yml --tags=register_consul      # 在目标实例本地注册Consul服务(本地执行)
./pgsql.yml --tags=register_prometheus  # 在Prometheus中注册监控对象(代理至所有Meta节点执行)
./pgsql.yml --tags=register_grafana     # 在Grafana中注册监控对象(只注册一次)
./pgsql.yml --tags=register_nginx       # 在Nginx注册负载均衡器(代理至所有Meta节点执行)

# 使用二进制安装的方式重新部署监控
./pgsql.yml --tags=monitor -e exporter_install=binary

# 刷新集群的服务定义(当集群成员或服务定义发生变化时执行)
./pgsql.yml --tags=haproxy_config,haproxy_reload

pgsql-remove

数据库下线:可以移除现有的数据库集群或实例,回收节点:pgsql-remove.yml

pgsql-remove.ymlpgsql.yml的反向操作,会依次完成

  • 将数据库实例从基础设施取消注册(register
  • 停止负载均衡器,服务组件(service
  • 移除监控系统组件(monitor
  • 移除Pgbouncer,Patroni,Postgres(postgres
  • 移除数据库目录(rm_pgdata: true
  • 移除软件包(rm_pgpkgs: true

该剧本有两个命令行选项,可用于移除数据库目录与软件包(默认下线不会移除数据与安装包)

rm_pgdata: false        # remove postgres data? false by default
rm_pgpkgs: false        # uninstall pg_packages? false by default

日常管理

./pgsql-remove.yml -l pg-test          # 下线 pg-test 集群
./pgsql-remove.yml -l 10.10.10.13      # 下线实例 10.10.10.13 (实际上是pg-test.pg-test-3)
./pgsql-remove.yml -l 10.10.10.13 -e rm_pgdata=true # 下线,一并移除数据目录(可能较慢)
./pgsql-remove.yml -l 10.10.10.13 -e rm_pgpkgs=true   # 下线,一并移除安装的PG相关软件包

pgsql-createdb

创建业务数据库:可以在现有集群中创建新的数据库或修改现有数据库pgsql-createdb.yml

强烈建议通过剧本或包装脚本与工具在已有集群中创建新数据库,这样可以确保:

  • 配置文件清单与实际情况保持一致
  • Pgbouncer连接池与数据库保持一致
  • Grafana中所注册的数据源与实际情况保持一致。

日常管理

数据库的创建请参考 数据库 一节。

# 在 pg-test 集群创建名为 test 的数据库
./pgsql-createdb.yml -l pg-test -e pg_database=test

可以使用包装脚本简化命令:

bin/createdb <pg_cluster> <dbname>

pgsql-createuser

创建业务用户:可以在现有集群中创建新的用户或修改现有用户pgsql-createuser.yml

日常管理

业务用户的创建请参考 用户 一节

# 在 pg-test 集群创建名为 test 的用户
./pgsql-createuser.yml -l pg-test -e pg_user=test

可以使用包装脚本简化命令:

bin/createuser <pg_cluster> <username>

请注意,pg_user 指定的用户,必须已经存在于集群pg_users的定义中,否则会报错。这意味着用户必须先定义,再创建。


pgsql-monly

用于执行仅监控部署的专用剧本,详情请参考:仅监控部署


pgsql-matrixdb

用于部署MatrixDB的专用剧本,详情请参考:部署MatrixDB集群


pgsql-migration

用于数据库自动化迁移的剧本,目前仍处于Beta状态,详情请参考:数据库集群迁移

25 - 剧本:REDIS

从 Pigsty v1.5.1 标签恢复的历史文档。

使用REDIS系列剧本,定义并拉起 传统主从、集群、Sentinel模式的Redis数据库。

剧本 功能 链接
redis 部署集群/主从/Sentinel模式的Redis数据库 src
redis-remove Redis集群/节点下线 src

redis

用于在节点上部署Redis集群,节点,实例。

Deploy redis instances on nodes.

# init all redis instances on group <cluster>
 ./redis.yml -l <cluster>       # 初始化 <cluster> 分组中的所有redis实例

# init all redis instances specific node
 ./redis.yml -l 10.10.10.10     # 初始化 10.10.10.10 节点上所有的redis实例

# 初始化一个特定的Redis实例,如 10.10.10.11:6501 (跳过设置Redis节点的部分)
 ./redis.yml -l 10.10.10.11 -e redis_port=6501 -t redis

Alias script bin/createredis wrap above playbook with:

bin/createredis redis-common            # 初始化redis集群 redis-common
bin/createredis 10.10.10.10             # 初始化redis节点 10.10.10.10
bin/createredis 10.10.10.13 6501 6502   # 初始化单个redis实例 10.10.10:13:6501 10.10.10:13:6502

redis-remove

用于从节点上移除所有Redis实例

# Remove cluster `redis-test`
redis-remove.yml -l redis-test

# Remove all instance on redis node 10.10.10.13
redis-remove.yml -l 10.10.10.13

# Remove one specific instance 10.10.10.13:6501
redis-remove.yml -l 10.10.10.13 -e redis_port=6501

26 - 配置Pigsty

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty采用声明式配置:用户配置描述状态,而Pigsty负责将真实组件调整至所期待的状态。

Pigsty通过配置清单(Inventory)来定义基础设施与数据库集群,每一套Pigsty部署都有一份对应的配置:无论是几百集群的生产环境,还是1核1GB的本地沙箱,在Pigsty中除了配置内容外没有任何区别。Pigsty的配置采用"Infra as Data"的哲学:用户通过声明式的配置描述自己的需求,而Pigsty负责将真实组件调整至所期待的状态。

在形式上,配置清单的具体实现可以是默认的本地配置文件,也可以是来自CMDB中的动态配置数据,本文介绍时均以默认YAML配置文件pigsty.yml 为例。在 配置过程 中,Pigsty会检测当前节点环境,并自动生成推荐的配置文件。

配置清单的内容主要是配置项,下列 v1.5.1 源码可核对的摘要包含 211 个配置参数,可以在多个层次进行配置,大多数参数可以直接使用默认值。配置项按照类目可以分为四大类:INFRA/基础设施NODES/主机节点PGSQL/PG数据库REDIS/Redis数据库,并可进一步细分为32个小类。


配置过程

进入 Pigsty 项目目录执行 configure,Pigsty会检测根据当前机器环境生成推荐配置文件,这一过程称作 配置 / Configure

./configure [-n|--non-interactive] [-d|--download] [-i|--ip <ipaddr>] [-m|--mode {auto|demo}]

configure会检查下列事项,小问题会自动尝试修复,否则提示报错退出。

check_kernel     # kernel        = Linux
check_machine    # machine       = x86_64
check_release    # release       = CentOS 7.x
check_sudo       # current_user  = NOPASSWD sudo
check_ssh        # current_user  = NOPASSWD ssh
check_ipaddr     # primary_ip (arg|probe|input)              (INTERACTIVE: ask for ip)
check_admin      # check current_user@primary_ip nopass ssh sudo
check_mode       # check machine spec to determine node mode (tiny|oltp|olap|crit)
check_config     # generate config according to primary_ip and mode
check_pkg        # check offline installation package exists (INTERACTIVE: ask for download)
check_repo       # create repo from pkg.tgz if exists
check_repo_file  # create local file repo file if repo exists
check_utils      # check ansible sshpass and other utils installed

直接运行 ./configure 将启动交互式命令行向导,提示用户回答以下三个问题:

IP地址

当检测到当前机器上有多块网卡与多个IP地址时,配置向导会提示您输入主要使用的IP地址, 即您用于从内部网络访问该节点时使用的IP地址。注意请不要使用公网IP地址。

下载软件包

当节点的/tmp/pkg.tgz路径下未找到离线软件包时,配置向导会询问是否从Github下载。 选择Y即会开始下载,选择N则会跳过。如果您的节点有良好的互联网访问与合适的代理配置,或者需要自行制作离线软件包,可以选择N

配置模板

使用什么样的配置文件模板。 配置向导会根据当前机器环境自动选择配置模板,因此不会询问用户这个问题,用户通常也无需关心。 但用户总是可以通过命令行参数-m <mode>手工指定想要使用的配置模板,例如:

  • demo 项目默认配置文件,4节点沙箱使用的配置文件,启用全部功能。
  • auto 在生产环境中部署时推荐的配置文件模板,配置更加稳定保守。
  • 此外Pigsty预置了几种配置模板,可以直接通过-m参数指定并使用,详见files/conf目录

configure过程中,配置向导会根据当前机器环境自动选择配置模板,但用户可以通过-m <mode>手工指定使用配置模板。配置模板最重要的部分是将模板中占位IP地址10.10.10.10替换为当前机器的真实IP地址(内网主IP),并根据当前机器的配置选择合适的数据库规格模板。您可以直接使用默认生成的配置文件,或基于自动生成的配置文件进行进一步的定制与修改。

配置过程的标准输出
$ ./configure
configure pigsty v1.5.1 begin
[ OK ] kernel = Linux
[ OK ] machine = x86_64
[ OK ] release = 7.8.2003 , perfect
[ OK ] sudo = root ok
[ OK ] ssh = [email protected] ok
[ OK ] primary_ip = 10.10.10.10  (from probe)
[ OK ] admin = [email protected] ok
[ OK ] spec = mini (cpu = 2)
[ OK ] config = auto @ 10.10.10.10
[ OK ] cache = /tmp/pkg.tgz exists
[ OK ] repo = /www/pigsty ok
[ OK ] repo file = /etc/yum.repos.d/pigsty-local.repo
[ OK ] utils = install from local file repo
[ OK ] ansible = ansible 2.9.27
configure pigsty done. Use 'make install' to proceed

配置文件

Pigsty项目根目录下有一个具体的配置文件样例:pigsty.yml

配置文件顶层是一个keyall的单个对象,包含两个子项目:varschildren

all:                      # 顶层对象 all
  vars: <123 keys>        # 全局配置 all.vars

  children:               # 分组定义:all.children 每一个项目定义了一个数据库集群
    meta: <2 keys>...     # 特殊分组 meta ,定义了环境元节点

    pg-meta: <2 keys>...  # 数据库集群 pg-meta 的详细定义
    pg-test: <2 keys>...  # 数据库集群 pg-test 的详细定义
    ...

vars的内容为KV键值对,定义了全局配置参数,K为配置项名称,V为配置项内容。

children 的内容也是KV结构,K为集群名称,V为具体的集群定义,一个样例集群的定义如下所示:

  • 集群定义同样包括两个子项目:vars定义了集群层面的配置。hosts定义了集群的实例成员。
  • 集群配置中的参数会覆盖全局配置中的对应参数,而集群的配置参数又会被实例级别的同名配置参数所覆盖。集群配置参数中,唯pg_cluster为必选项,这是集群的名称,须与上层集群名保持一致。
  • hosts中采用KV的方式定义集群实例成员,K为IP地址(须ssh可达),V为具体的实例配置参数
  • 实例配置参数中有两个必须参数:pg_seq,与 pg_role,分别为实例的唯一序号和实例的角色。
pg-test:                 # 数据库集群名称默认作为群组名称
  vars:                  # 数据库集群级别变量
    pg_cluster: pg-test  # 一个定义在集群级别的必选配置项,在整个pg-test中保持一致。
  hosts:                 # 数据库集群成员
    10.10.10.11: {pg_seq: 1, pg_role: primary} # 数据库实例成员
    10.10.10.12: {pg_seq: 2, pg_role: replica} # 必须定义身份参数 pg_role 与 pg_seq
    10.10.10.13: {pg_seq: 3, pg_role: offline} # 可以在此指定实例级别的变量

Pigsty配置文件遵循Ansible规则,采用YAML格式,默认使用单一配置文件。Pigsty的默认配置文件路径为Pigsty源代码根目录下的 pigsty.yml 。默认配置文件是在同目录下的ansible.cfg通过inventory = pigsty.yml指定的。您可以在执行任何剧本时,通过-i <config_path>参数指定其他的配置文件。

配置文件需要与Ansible 配合使用。Ansible是一个流行的DevOps工具,但普通用户无需了解Ansible的具体细节。如果您精通Ansible,则可以根据Ansible的清单组织规则自行调整配置文件的组织与结构:例如,使用分立式的配置文件,为每个集群设置单独的群组定义与变量定义文件。

您并不需要精通Ansible,用几分钟时间浏览Ansible快速上手,便足以开始使用Ansible执行剧本。

配置项

配置项的形式为键值对:键是配置项的名称,值是配置项的内容。值的形式各异,可能是简单的单个字符串,也可能是复杂的对象数组。

Pigsty的参数可以在不同的层次进行配置,并依据规则继承与覆盖,高优先级的配置项会覆盖低优先级的同名配置项。因此用户可以有的放矢,可以在不同层次,不同粒度上针对具体集群与具体实例进行精细配置。

配置项的层次

在Pigsty的配置文件中,配置项 可以出现在三种位置,全局集群实例集群vars中定义的配置项会以同名键覆盖的方式覆盖全局配置项实例中定义的配置项又会覆盖集群配置项与全局配置项。

粒度 范围 优先级 说明 位置
Global 全局 在同一套部署环境内一致 all.vars.xxx
Cluster 集群 在同一套集群内保持一致 all.children.<cls>.vars.xxx
Instance 实例 最细粒度的配置层次 all.children.<cls>.hosts.<ins>.xxx

并非所有配置项都适合在所有层次使用。例如,基础设施的参数通常只会在全局配置中定义,数据库实例的标号,角色,负载均衡权重等参数只能在实例层次配置,而一些操作选项则只能使用命令行参数提供(例如要创建的数据库名称),关于配置项的详情与适用范围,请参考配置项清单

兜底与覆盖

除了配置文件中的三种配置粒度,Pigsty配置项目中还有两种额外的优先级层次:默认值兜底与命令行参数强制覆盖:

  • 默认:当一个配置项在全局/集群/实例级别都没有出现时,将使用默认配置项。默认值的优先级最低,所有配置项都有默认值。默认参数定义于roles/<role>/defaults/main.yml中。
  • 参数:当用户通过命令行传入参数时,参数指定的配置项具有最高优先级,将覆盖一切层次的配置。一些配置项只能通过命令行参数的方式指定与使用。
层级 来源 优先级 说明 位置
Default 默认 最低 代码逻辑定义的默认值 roles/<role>/defaults/main.yml
Global 全局 在同一套部署环境内一致 all.vars.xxx
Cluster 集群 在同一套集群内保持一致 all.children.<cls>.vars.xxx
Instance 实例 最细粒度的配置层次 all.children.<cls>.hosts.<ins>.xxx
Argument 参数 最高 通过命令行参数传入 -e

配置类目

v1.5.1 源码可核对的摘要包含 211 个固定配置项,分为四个部分:INFRA, NODES, PGSQL, REDIS,共计32类。

通常只有节点/数据库身份参数是必选参数,其他配置参数可直接使用默认值,按需修改。

Category Section Description Count
INFRA CONNECT 连接参数 1
INFRA REPO 本地源基础设施 10
INFRA CA 公私钥基础设施 5
INFRA NGINX NginxWeb服务器 5
INFRA NAMESERVER DNS服务器 1
INFRA PROMETHEUS 监控时序数据库 7
INFRA EXPORTER 通用Exporter配置 3
INFRA GRAFANA Grafana可视化平台 9
INFRA LOKI Loki日志收集平台 5
INFRA DCS 分布式配置存储元数据库 8
NODES NODE_IDENTITY 节点身份参数 5
NODES NODE_DNS 节点域名解析 5
NODES NODE_REPO 节点软件源 3
NODES NODE_PACKAGES 节点软件包 4
NODES NODE_FEATURES 节点功能特性 6
NODES NODE_MODULES 节点内核模块 1
NODES NODE_TUNE 节点参数调优 2
NODES NODE_ADMIN 节点管理员 6
NODES NODE_TIME 节点时区与时间同步 4
NODES NODE_EXPORTER 节点指标暴露器 3
NODES PROMTAIL 日志收集组件 5
PGSQL PG_IDENTITY PGSQL数据库身份参数 13
PGSQL PG_BUSINESS PGSQL业务对象定义 11
PGSQL PG_INSTALL PGSQL安装 11
PGSQL PG_BOOTSTRAP PGSQL集群初始化 24
PGSQL PG_PROVISION PGSQL集群模板置备 9
PGSQL PG_EXPORTER PGSQL指标暴露器 13
PGSQL PG_SERVICE PGSQL服务接入 16
REDIS REDIS_IDENTITY REDIS身份参数 3
REDIS REDIS_PROVISION REDIS集群置备 14
REDIS REDIS_NODE REDIS指标暴露器 3
配置项清单
ID Name Section Level Description
100 proxy_env CONNECT G 代理服务器配置
110 nginx_enabled REPO G 是否启用本地源
111 repo_name REPO G 本地源名称
112 repo_address REPO G 本地源外部访问地址
113 nginx_port REPO G 本地源端口
114 nginx_home REPO G 本地源文件根目录
115 repo_rebuild REPO A 是否重建Yum源
116 repo_remove REPO A 是否移除已有REPO文件
117 repo_upstreams REPO G Yum源的上游来源
118 repo_packages REPO G Yum源需下载软件列表
119 repo_url_packages REPO G 通过URL直接下载的软件
120 ca_method CA G CA的创建方式
121 ca_subject CA G 自签名CA主题
122 ca_homedir CA G CA证书根目录
123 ca_cert CA G CA证书
124 ca_key CA G CA私钥名称
130 nginx_upstream NGINX G Nginx上游服务器
131 nginx_indexes NGINX G 首页导航栏显示的应用列表
140 dns_records NAMESERVER G 动态DNS解析记录
150 prometheus_data_dir PROMETHEUS G Prometheus数据库目录
151 prometheus_options PROMETHEUS G Prometheus命令行参数
152 prometheus_reload PROMETHEUS A Reload而非Recreate
153 prometheus_sd_method PROMETHEUS G 服务发现机制:static
154 prometheus_scrape_interval PROMETHEUS G Prom抓取周期
155 prometheus_scrape_timeout PROMETHEUS G Prom抓取超时
156 prometheus_sd_interval PROMETHEUS G Prom服务发现刷新周期
160 exporter_install EXPORTER G 安装监控组件的方式
161 exporter_repo_url EXPORTER G 监控组件的YumRepo
162 exporter_metrics_path EXPORTER G 监控暴露的URL Path
170 grafana_endpoint GRAFANA G Grafana地址
171 grafana_admin_username GRAFANA G Grafana管理员用户名
172 grafana_admin_password GRAFANA G Grafana管理员密码
173 grafana_database GRAFANA G Grafana后端数据库类型
174 grafana_pgurl GRAFANA G Grafana的PG数据库连接串
175 grafana_plugin_method GRAFANA G 如何安装Grafana插件
176 grafana_plugin_cache GRAFANA G Grafana插件缓存地址
177 grafana_plugin_list GRAFANA G 安装的Grafana插件列表
178 grafana_plugin_git GRAFANA G 从Git安装的Grafana插件
180 loki_endpoint LOKI G 用于接收日志的loki服务endpoint
181 loki_clean LOKI A 是否在安装Loki时清理数据库目录
182 loki_options LOKI G Loki的命令行参数
183 loki_data_dir LOKI G Loki的数据目录
184 loki_retention LOKI G Loki日志默认保留天数
200 dcs_servers DCS G DCS服务器名称:IP列表
201 dcs_registry DCS G 服务注册的位置
202 pg_dcs_type DCS G 使用的DCS类型
203 dcs_name DCS G DCS集群名称
204 dcs_clean DCS C/A 若DCS实例存在如何处理
205 dcs_safeguard DCS C/A 完全禁止清理DCS实例
206 consul_data_dir DCS G Consul数据目录
207 etcd_data_dir DCS G Etcd数据目录
300 meta_node NODE_IDENTITY C 表示此节点为元节点
301 nodename NODE_IDENTITY I 指定节点实例标识
302 node_cluster NODE_IDENTITY C 节点集群名,默认名为nodes
303 nodename_overwrite NODE_IDENTITY C 用Nodename覆盖机器HOSTNAME
304 nodename_exchange NODE_IDENTITY C 是否在剧本节点间交换主机名
310 node_etc_hosts_default NODE_DNS C 写入机器的静态DNS解析
311 node_etc_hosts NODE_DNS C/I 同上,用于集群实例层级
312 node_dns_method NODE_DNS C 如何配置DNS服务器?
313 node_dns_servers NODE_DNS C 配置动态DNS服务器列表
314 node_dns_options NODE_DNS C 配置/etc/resolv.conf
320 node_repo_method NODE_REPO C 节点使用Yum源的方式
321 node_repo_remove NODE_REPO C 是否移除节点已有Yum源
322 node_repo_local_urls NODE_REPO C 本地源的URL地址
330 node_packages_default NODE_PACKAGES C 节点安装软件列表
331 node_packages NODE_PACKAGES C 节点额外安装的软件列表
332 node_packages_meta NODE_PACKAGES G 元节点所需的软件列表
333 node_packages_meta_pip NODE_PACKAGES G 元节点上通过pip3安装的软件包
340 node_disable_numa NODE_FEATURES C 关闭节点NUMA
341 node_disable_swap NODE_FEATURES C 关闭节点SWAP
342 node_disable_firewall NODE_FEATURES C 关闭节点防火墙
343 node_disable_selinux NODE_FEATURES C 关闭节点SELINUX
344 node_static_network NODE_FEATURES C 是否使用静态DNS服务器
345 node_disk_prefetch NODE_FEATURES C 是否启用磁盘预读
346 node_kernel_modules NODE_MODULES C 启用的内核模块
350 node_tune NODE_TUNE C 节点调优模式
351 node_sysctl_params NODE_TUNE C 操作系统内核参数
360 node_admin_enabled NODE_ADMIN G 是否创建管理员用户
361 node_admin_uid NODE_ADMIN G 管理员用户UID
362 node_admin_username NODE_ADMIN G 管理员用户名
363 node_admin_ssh_exchange NODE_ADMIN C 在实例间交换管理员SSH密钥
364 node_admin_pk_current NODE_ADMIN A 是否将当前用户的公钥加入管理员账户
365 node_admin_pk_list NODE_ADMIN C 可登陆管理员的公钥列表
370 node_timezone NODE_TIME C NTP时区设置
371 node_ntp_enabled NODE_TIME C 是否配置NTP服务?
372 node_ntp_service NODE_TIME C NTP服务类型:ntp或chrony
373 node_ntp_servers NODE_TIME C NTP服务器列表
380 node_exporter_enabled NODE_EXPORTER C 启用节点指标收集器
381 node_exporter_port NODE_EXPORTER C 节点指标暴露端口
382 node_exporter_options NODE_EXPORTER C/I 节点指标采集选项
390 promtail_enabled PROMTAIL C 是否启用Promtail日志收集服务
391 promtail_clean PROMTAIL C/A 是否在安装promtail时移除已有状态信息
392 promtail_port PROMTAIL G promtail使用的默认端口
393 promtail_options PROMTAIL C/I promtail命令行参数
394 promtail_positions PROMTAIL C promtail状态文件位置
500 pg_cluster PG_IDENTITY C PG数据库集群名称
501 pg_shard PG_IDENTITY C PG集群所属的Shard (保留)
502 pg_sindex PG_IDENTITY C PG集群的分片号 (保留)
503 gp_role PG_IDENTITY C 当前PG集群在GP中的角色
504 pg_role PG_IDENTITY I PG数据库实例角色
505 pg_seq PG_IDENTITY I PG数据库实例序号
506 pg_instances PG_IDENTITY I 当前节点上的所有PG实例
507 pg_upstream PG_IDENTITY I 实例的复制上游节点
508 pg_offline_query PG_IDENTITY I 是否允许离线查询
509 pg_backup PG_IDENTITY I 是否在实例上存储备份
510 pg_weight PG_IDENTITY I 实例在负载均衡中的相对权重
511 pg_hostname PG_IDENTITY C/I 将PG实例名称设为HOSTNAME
512 pg_preflight_skip PG_IDENTITY C/A 跳过PG身份参数校验
520 pg_users PG_BUSINESS C 业务用户定义
521 pg_databases PG_BUSINESS C 业务数据库定义
522 pg_services_extra PG_BUSINESS C 集群专有服务定义
523 pg_hba_rules_extra PG_BUSINESS C 集群/实例特定的HBA规则
524 pgbouncer_hba_rules_extra PG_BUSINESS C Pgbounce特定HBA规则
525 pg_admin_username PG_BUSINESS G PG管理用户
526 pg_admin_password PG_BUSINESS G PG管理用户密码
527 pg_replication_username PG_BUSINESS G PG复制用户
528 pg_replication_password PG_BUSINESS G PG复制用户的密码
529 pg_monitor_username PG_BUSINESS G PG监控用户
530 pg_monitor_password PG_BUSINESS G PG监控用户密码
540 pg_dbsu PG_INSTALL C PG操作系统超级用户
541 pg_dbsu_uid PG_INSTALL C 超级用户UID
542 pg_dbsu_sudo PG_INSTALL C 超级用户的Sudo权限
543 pg_dbsu_home PG_INSTALL C 超级用户的家目录
544 pg_dbsu_ssh_exchange PG_INSTALL C 是否交换超级用户密钥
545 pg_version PG_INSTALL C 安装的数据库大版本
546 pgdg_repo PG_INSTALL C 是否添加PG官方源?
547 pg_add_repo PG_INSTALL C 是否添加PG相关上游源?
548 pg_bin_dir PG_INSTALL C PG二进制目录
549 pg_packages PG_INSTALL C 安装的PG软件包列表
550 pg_extensions PG_INSTALL C 安装的PG插件列表
560 pg_clean PG_BOOTSTRAP C/A PG存在时如何处理
561 pg_safeguard PG_BOOTSTRAP C/A 禁止清除存在的PG实例
562 pg_data PG_BOOTSTRAP C PG数据目录
563 pg_fs_main PG_BOOTSTRAP C PG主数据盘挂载点
564 pg_fs_bkup PG_BOOTSTRAP C PG备份盘挂载点
565 pg_dummy_filesize PG_BOOTSTRAP C 占位文件/pg/dummy的大小
566 pg_listen PG_BOOTSTRAP C PG监听的IP地址
567 pg_port PG_BOOTSTRAP C PG监听的端口
568 pg_localhost PG_BOOTSTRAP C PG使用的UnixSocket地址
580 patroni_enabled PG_BOOTSTRAP C Patroni是否启用
581 patroni_mode PG_BOOTSTRAP C Patroni配置模式
582 pg_namespace PG_BOOTSTRAP C Patroni使用的DCS命名空间
583 patroni_port PG_BOOTSTRAP C Patroni服务端口
584 patroni_watchdog_mode PG_BOOTSTRAP C Patroni Watchdog模式
585 pg_conf PG_BOOTSTRAP C Patroni使用的配置模板
586 pg_libs PG_BOOTSTRAP C PG默认加载的共享库
587 pg_encoding PG_BOOTSTRAP C PG字符集编码
588 pg_locale PG_BOOTSTRAP C PG使用的本地化规则
589 pg_lc_collate PG_BOOTSTRAP C PG使用的本地化排序规则
590 pg_lc_ctype PG_BOOTSTRAP C PG使用的本地化字符集定义
591 pgbouncer_enabled PG_BOOTSTRAP C 是否启用Pgbouncer
592 pgbouncer_port PG_BOOTSTRAP C Pgbouncer端口
593 pgbouncer_poolmode PG_BOOTSTRAP C Pgbouncer池化模式
594 pgbouncer_max_db_conn PG_BOOTSTRAP C Pgbouncer最大单DB连接数
600 pg_provision PG_PROVISION C 是否在PG集群中应用模板
601 pg_init PG_PROVISION C 自定义PG初始化脚本
602 pg_default_roles PG_PROVISION G/C 默认创建的角色与用户
603 pg_default_privileges PG_PROVISION G/C 数据库默认权限配置
604 pg_default_schemas PG_PROVISION G/C 默认创建的模式
605 pg_default_extensions PG_PROVISION G/C 默认安装的扩展
606 pg_reload PG_PROVISION A 是否重载数据库配置(HBA)
607 pg_hba_rules PG_PROVISION G/C 全局HBA规则
608 pgbouncer_hba_rules PG_PROVISION G/C Pgbouncer全局HBA规则
620 pg_exporter_config PG_EXPORTER C PG指标定义文件
621 pg_exporter_enabled PG_EXPORTER C 启用PG指标收集器
622 pg_exporter_port PG_EXPORTER C PG指标暴露端口
623 pg_exporter_params PG_EXPORTER C/I PG Exporter额外的URL参数
624 pg_exporter_url PG_EXPORTER C/I 采集对象数据库的连接串(覆盖)
625 pg_exporter_auto_discovery PG_EXPORTER C/I 是否自动发现实例中的数据库
626 pg_exporter_exclude_database PG_EXPORTER C/I 数据库自动发现排除列表
627 pg_exporter_include_database PG_EXPORTER C/I 数据库自动发现囊括列表
628 pg_exporter_options PG_EXPORTER C/I PG Exporter命令行参数
629 pgbouncer_exporter_enabled PG_EXPORTER C 启用PGB指标收集器
630 pgbouncer_exporter_port PG_EXPORTER C PGB指标暴露端口
631 pgbouncer_exporter_url PG_EXPORTER C/I 采集对象连接池的连接串
632 pgbouncer_exporter_options PG_EXPORTER C/I PGB Exporter命令行参数
640 pg_services PG_SERVICE G/C 全局通用服务定义
641 haproxy_enabled PG_SERVICE C/I 是否启用Haproxy
642 haproxy_reload PG_SERVICE A 是否重载Haproxy配置
643 haproxy_auth_enabled PG_SERVICE G/C 是否对Haproxy管理界面启用认证
644 haproxy_admin_username PG_SERVICE G HAproxy管理员名称
645 haproxy_admin_password PG_SERVICE G HAproxy管理员密码
646 haproxy_exporter_port PG_SERVICE C HAproxy指标暴露器端口
647 haproxy_client_timeout PG_SERVICE C HAproxy客户端超时
648 haproxy_server_timeout PG_SERVICE C HAproxy服务端超时
649 vip_mode PG_SERVICE C VIP模式:none
650 vip_reload PG_SERVICE A 是否重载VIP配置
651 vip_address PG_SERVICE C 集群使用的VIP地址
652 vip_cidrmask PG_SERVICE C VIP地址的网络CIDR掩码长度
653 vip_interface PG_SERVICE C VIP使用的网卡
654 dns_mode PG_SERVICE C DNS配置模式
655 dns_selector PG_SERVICE C DNS解析对象选择器
700 redis_cluster REDIS_IDENTITY C Redis数据库集群名称
701 redis_node REDIS_IDENTITY I Redis节点序列号
702 redis_instances REDIS_IDENTITY I Redis实例定义
721 redis_mode REDIS_PROVISION C Redis集群模式
722 redis_conf REDIS_PROVISION C Redis配置文件模板
723 redis_fs_main REDIS_PROVISION C PG数据库实例角色
724 redis_bind_address REDIS_PROVISION C Redis监听的端口地址
725 redis_clean REDIS_PROVISION C Redis存在时执行何种操作
726 redis_safeguard REDIS_PROVISION C 禁止抹除现存的Redis
727 redis_max_memory REDIS_PROVISION C/I Redis可用的最大内存
728 redis_mem_policy REDIS_PROVISION C 内存逐出策略
729 redis_password REDIS_PROVISION C Redis密码
730 redis_rdb_save REDIS_PROVISION C RDB保存指令
731 redis_aof_enabled REDIS_PROVISION C 是否启用AOF
732 redis_rename_commands REDIS_PROVISION C 重命名危险命令列表
740 redis_cluster_replicas REDIS_PROVISION C 集群每个主库带几个从库
741 redis_exporter_enabled REDIS_NODE C 是否启用Redis监控
742 redis_exporter_port REDIS_NODE C Redis Exporter监听端口
743 redis_exporter_options REDIS_NODE C/I Redis Exporter命令参数

27 - 配置:Infra

从 Pigsty v1.5.1 标签恢复的历史文档。

使用 INFRA剧本部署PGSQL集群,将集群状态调整至 PGSQL配置所描述的状态。

配置Pigsty基础设施,由INFRA系列剧本使用。

基础设施配置主要处理此类问题:本地Yum源,机器节点基础服务:DNS,NTP,内核模块,参数调优,管理用户,安装软件包,DCS Server的架设,监控基础设施的安装与初始化(Grafana,Prometheus,Alertmanager),全局流量入口Nginx的配置等等。

通常来说,基础设施部分需要修改的内容很少,通常涉及到的主要修改只是对元节点的IP地址进行文本替换,这一步会在./configure过程中自动完成,另一处偶尔需要改动的地方是 nginx_upstream中定义的访问域名。其他参数很少需要调整,按需即可。

  • CONNECT : 连接参数
  • CA : 公私钥基础设施
  • NGINX : Nginx Web服务器
  • REPO : 本地源基础设施
  • NAMESERVER : DNS服务器
  • PROMETHEUS : 监控时序数据库
  • EXPORTER : 通用Exporter配置
  • GRAFANA : Grafana可视化平台
  • LOKI : Loki日志收集平台
  • DCS : 分布式配置存储元数据库(Consul Server/ETCD)
  • CONSUL : DCS实现:Consul
  • ETCD : DCS实现:ETCD

参数概览

部署于元节点上的 基础设施 由下列配置项所描述。

ID Name Section Type Level Comment
100 proxy_env CONNECT dict G 代理服务器配置
110 ca_method CA enum G CA的创建方式
111 ca_subject CA string G 自签名CA主题
112 ca_homedir CA path G CA证书根目录
113 ca_cert CA string G CA证书
114 ca_key CA string G CA私钥名称
120 nginx_enabled NGINX bool C/I 是否启用本地源
121 nginx_port NGINX int G Nginx端口
122 nginx_home NGINX path G Nginx文件根目录
123 nginx_upstream NGINX upstream[] G Nginx上游服务器
124 nginx_indexes NGINX app[] G 首页导航栏显示的应用列表
130 repo_name REPO string G 本地源名称
131 repo_address REPO string G 本地源外部访问地址
132 repo_rebuild REPO bool A 是否重建Yum源
133 repo_remove REPO bool A 是否移除已有REPO文件
134 repo_upstreams REPO repo[] G Yum源的上游来源
135 repo_packages REPO string[] G Yum源需下载软件列表
136 repo_url_packages REPO url[] G 通过URL直接下载的软件
140 nameserver_enabled NAMESERVER bool C/I 是否在元节点上启用DNSMASQ
141 dns_records NAMESERVER string[] G 动态DNS解析记录
150 prometheus_enabled PROMETHEUS bool C/I 是否在元节点上启用Prometheus
151 prometheus_data_dir PROMETHEUS path G Prometheus数据库目录
152 prometheus_options PROMETHEUS string G Prometheus命令行参数
153 prometheus_reload PROMETHEUS bool A Reload而非Recreate
154 prometheus_sd_method PROMETHEUS enum G 服务发现机制:static
155 prometheus_scrape_interval PROMETHEUS interval G Prom抓取周期
156 prometheus_scrape_timeout PROMETHEUS interval G Prom抓取超时
157 prometheus_sd_interval PROMETHEUS interval G Prom服务发现刷新周期
160 exporter_install EXPORTER enum G 安装监控组件的方式
161 exporter_repo_url EXPORTER string G 监控组件的YumRepo
162 exporter_metrics_path EXPORTER string G 监控暴露的URL Path
170 grafana_enabled GRAFANA bool C/I 是否在元节点上启用Grafana
171 grafana_endpoint GRAFANA url G Grafana地址
172 grafana_admin_username GRAFANA string G Grafana管理员用户名
173 grafana_admin_password GRAFANA string G Grafana管理员密码
174 grafana_database GRAFANA enum G Grafana后端数据库类型
175 grafana_pgurl GRAFANA url G Grafana的PG数据库连接串
176 grafana_plugin_method GRAFANA enum G 如何安装Grafana插件
177 grafana_plugin_cache GRAFANA path G Grafana插件缓存地址
178 grafana_plugin_list GRAFANA string[] G 安装的Grafana插件列表
179 grafana_plugin_git GRAFANA url[] G 从Git安装的Grafana插件
180 loki_enabled LOKI bool C/I 是否在元节点上启用Loki
181 loki_endpoint LOKI url G 用于接收日志的loki服务端点
182 loki_clean LOKI bool A 在初始化Loki时清理数据
183 loki_options LOKI string G Loki的命令行参数
184 loki_data_dir LOKI string G Loki的数据目录
185 loki_retention LOKI interval G Loki日志默认保留天数
190 dcs_name DCS string G DCS服务名称
191 dcs_servers DCS dict G DCS服务器地址字典
192 dcs_registry DCS enum G 服务注册的位置
193 dcs_safeguard DCS bool C/A 完全禁止清理DCS实例
194 dcs_clean DCS bool C/A 初始化时清除现存DCS实例
195 consul_enabled CONSUL bool G 是否全局启用Consul
196 consul_data_dir CONSUL string G Consul数据目录
197 etcd_enabled ETCD bool G 是否全局启用ETCD
198 etcd_data_dir ETCD string G ETCD数据目录

CONNECT

proxy_env

在某些受到“互联网封锁”的地区,有些软件的下载会受到影响。例如从中国大陆访问PostgreSQL的官方源,下载速度可能只有几KB每秒。

但如果使用了合适的HTTP代理,则可以达到几MB每秒。因此如果用户有代理服务器,请通过proxy_env进行配置,样例如下:

proxy_env: # global proxy env when downloading packages
  http_proxy: 'http://username:[email protected]'
  https_proxy: 'http://username:[email protected]'
  all_proxy: 'http://username:[email protected]'
  no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.aliyuncs.com,mirrors.tuna.tsinghua.edu.cn,mirrors.zju.edu.cn"

ansible_host

如果您的目标机器藏在SSH跳板机之后,或者进行了某些定制化修改无法通过ssh ip的方式直接访问,则可以考虑使用 Ansible连接参数

例如下面的例子中,ansible_host 通过SSH别名的方式告知Pigsty通过ssh node-1 的方式而不是ssh 10.10.10.11的方式访问目标数据库节点。通过这种方式,用户可以自由指定数据库节点的连接方式,并将连接配置保存在管理用户的~/.ssh/config中独立管理。

  pg-test:
    vars: { pg_cluster: pg-test }
    hosts:
      10.10.10.11: {pg_seq: 1, pg_role: primary, ansible_host: node-1}
      10.10.10.12: {pg_seq: 2, pg_role: replica, ansible_host: node-2}
      10.10.10.13: {pg_seq: 3, pg_role: offline, ansible_host: node-3}

ansible_host是ansible连接参数中最典型的一个。通常只要用户可以通过 ssh <name>的方式访问目标机器,为实例配置ansible_host变量,值为<name>即可,其他常用的Ansible SSH连接参数如下所示:

  • ansible_host : 在此指定目标机器的IP、主机名或SSH别名

  • ansible_port : 指定一个不同于22的SSH端口

  • ansible_user : 指定SSH使用的用户名

  • ansible_ssh_pass : SSH密码(请不要存储明文,可通过-k参数指定从键盘输入)

  • ansible_ssh_private_key_file : SSH私钥路径

  • ansible_ssh_common_args : SSH通用参数


CA

用于搭建本地公私钥基础设施,当您需要SSL证书等高级安全特性时,可以使用此任务。

ca_method

CA的创建方式, 类型:enum,层级:G,默认值为:"create"

  • create:创建新的公私钥用于CA
  • copy:拷贝现有的CA公私钥用于构建CA

ca_subject

自签名CA主题, 类型:string,层级:G,默认值为:"/CN=root-ca"

ca_homedir

CA证书根目录, 类型:path,层级:G,默认值为:"/ca"

ca_cert

CA证书名称, 类型:string,层级:G,默认值为:"ca.crt"

ca_key

CA私钥名称, 类型:string,层级:G,默认值为:"ca.key"


NGINX

Pigsty通过元节点上的Nginx对外暴露所有Web类服务,如首页,Grafana,Prometheus,AlertManager,Consul,以及可选的PGWeb与Jupyter Lab。此外,本地软件源,本地文档,与其他本地WEB工具如Pev2,Pgbadger也由Nginx对外提供服务。

您可以绕过Nginx直接通过端口访问元节点上的部分服务,但部分服务出于安全性原因不宜对外暴露,只能通过Nginx代理访问。Nginx通过域名区分不同的服务,因此,如果您为各个服务配置的域名在当前环境中无法解析,则需要您自行在/etc/hosts中配置后使用。

nginx_enabled

是否启用本地源, 类型:bool,层级:C/I,默认值为:true

是否在元节点上启用Nginx Server?

设置为false则会在当前节点跳过设置Nginx与构建本地源的过程。当您有多个元节点时,可以在备用元节点上设置此参数为false

nginx_port

本地源端口, 类型:int,层级:G,默认值为:80

Pigsty通过元节点上的该端口访问所有Web服务,请确保您可以访问元节点上的该端口。

nginx_home

本地源文件根目录, 类型:path,层级:G,默认值为:"/www"

该目录将作为HTTP服务器的根对外暴露,包含本地源,以及其他静态文件内容。

nginx_upstream

Nginx上游服务器, 类型:upstream[],层级:G,默认值为:

nginx_upstream:                   # domain names and upstream servers
- { name: home,         domain: pigsty,     endpoint: "10.10.10.10:80" }
- { name: grafana,      domain: g.pigsty,   endpoint: "10.10.10.10:3000" }
- { name: loki,         domain: l.pigsty,   endpoint: "10.10.10.10:3100" }
- { name: prometheus,   domain: p.pigsty,   endpoint: "10.10.10.10:9090" }
- { name: alertmanager, domain: a.pigsty,   endpoint: "10.10.10.10:9093" }
- { name: consul,       domain: c.pigsty,   endpoint: "127.0.0.1:8500" }

每一条记录包含三个子段:name, domain, endpoint,分别代表组件名称,外部访问域名,以及内部的TCP端点。

默认记录的name 定义是固定的,通过硬编码引用,请勿修改。您可以任意新增其他名称的上游服务器记录。

domain是外部访问此上游服务器时应当使用的域名,当您访问Pigsty Web服务时,应当使用域名通过Nginx代理访问。

endpoint是内部可达的TCP端点,占位IP地址10.10.10.10会在Configure过程中被替换为元节点IP。

如果您使用了多个元节点,并通过 grafana_enabledprometheus_enabledloki_enabled 等参数在实例层次为不同元节点分配了角色,则需要在这里将对应服务的IP地址替换为实际承载该服务的IP地址。

nginx_indexes

首页导航栏显示的应用列表, 类型:app[],层级:G,默认值为:

nginx_indexes:                            # application nav links on home page
  - { name: Pev2    , url : '/pev2'        , comment: 'postgres explain visualizer 2' }
  - { name: Logs    , url : '/logs'        , comment: 'realtime pgbadger log sample' }
  - { name: Report  , url : '/report'      , comment: 'daily log summary report ' }
  - { name: Pkgs    , url : '/pigsty'      , comment: 'local yum repo packages' }
  - { name: Repo    , url : '/pigsty.repo' , comment: 'local yum repo file' }
  - { name: ISD     , url : '${grafana}/d/isd-overview'   , comment: 'noaa isd data visualization' }
  - { name: Covid   , url : '${grafana}/d/covid-overview' , comment: 'covid data visualization' }

每一条记录都会渲染为Pigsty首页App下拉菜单的导航连接,应用均为可选项目,默认挂载于Pigsty默认服务器下http://pigsty/ 其中,url 参数指定了应用的URL PATH,特例是如果URL中存在${grafana}字符串,会被自动替换为nginx_upstream 中定义的Grafana域名。


REPO

当在元节点上安装Pigsty时,Pigsty会在本地拉起一个YUM软件源,供当前环境安装RPM软件包使用。

Pigsty在初始化过程中,会从互联网上游源(由 repo_upstreams指定), 下载所有软件包及其依赖(由 repo_packages指定)至 {{ nginx_home }} / {{ repo_name }} (默认为/www/pigsty)。所有依赖的软件总大小约1GB左右,下载速度取决于您的网络情况。

建立本地Yum源时,如果该目录已经存在,而且目录中存在名为repo_complete的标记文件,Pigsty会认为本地Yum源已经初始化完毕,跳过软件下载阶段。

尽管Pigsty已经尽量使用镜像源以加速下载,但少量包的下载仍可能受到防火墙的阻挠。如果某些软件包的下载速度过慢,您可以通过proxy_env配置项设置下载代理以完成首次下载,或直接下载预先打包好的离线安装包

离线安装包即是把{{ nginx_home }}/{{ repo_name }}目录整个打成压缩包pkg.tgz。在configure过程中,如果Pigsty发现离线软件包/tmp/pkg.tgz存在,则会将其解压至{{ nginx_home }}/{{ repo_name }}目录,进而在安装时跳过软件下载的步骤。

默认的离线安装包基于CentOS 7.8.2003 x86_64操作系统制作,如果您使用的操作系统与此不同,或并非使用全新安装的操作系统环境,则有概率出现RPM软件包冲突与依赖错误的问题,请参照FAQ解决。

repo_name

本地源名称, 类型:string,层级:G,默认值为:"pigsty",不建议修改此参数。

repo_address

本地源外部访问地址, 类型:string,层级:G,默认值为:"pigsty"

本地yum源对外提供服务的地址,可以是域名也可以是IP地址,默认为yum.pigsty

如果使用域名,您必须确保在当前环境中,该域名会正确解析到本地源所在的服务器,也就是元节点。

如果您的本地yum源没有使用标准的80端口,您需要在地址中加入端口,并与 nginx_port 变量保持一致。

您可以通过节点参数中的静态DNS配置 node_etc_hosts_default) 来为当前环境中的所有节点默认写入pigsty本地源域名。

repo_rebuild

是否重建Yum源, 类型:bool,层级:A,默认值为:false

如果为true,那么在任何情况下都会执行Repo重建的工作,即无视离线软件包存在与否。

repo_remove

是否移除已有REPO文件, 类型:bool,层级:A,默认值为:true

如果为真,在执行本地源初始化的过程中,元节点上/etc/yum.repos.d中所有已有的repo会被全部移除,备份至/etc/yum.repos.d/backup 目录中。

因为操作系统已有的源内容不可控,建议强制移除已有源并通过 repo_upstreams 进行显式配置。

当您的节点有其他自行配置的源,或需要从特定源下载一些特殊版本的RPM包时,可以设置为false,保留已有源。

repo_upstreams

Yum源的上游来源, 类型:repo[],层级:

默认使用阿里云的CentOS7镜像源,清华大学Grafana镜像源,PackageCloud的Prometheus源,PostgreSQL官方源,以及SCLo,Harbottle,Nginx等软件源。

repo_packages

Yum源需下载软件列表, 类型:string[],层级:G,默认值为:

epel-release nginx wget yum-utils yum createrepo sshpass zip unzip                                              # ----  boot   ---- #
ntp chrony uuid lz4 bzip2 nc pv jq vim-enhanced make patch bash lsof wget git tuned perf ftp lrzsz rsync        # ----  node   ---- #
numactl grubby sysstat dstat iotop bind-utils net-tools tcpdump socat ipvsadm telnet ca-certificates keepalived # ----- utils ----- #
readline zlib openssl openssh-clients libyaml libxml2 libxslt libevent perl perl-devel perl-ExtUtils*           # ---  deps:pg  --- #
readline-devel zlib-devel uuid-devel libuuid-devel libxml2-devel libxslt-devel openssl-devel libicu-devel       # --- deps:devel -- #
grafana prometheus2 pushgateway alertmanager mtail consul consul_exporter consul-template etcd dnsmasq          # -----  meta ----- #
node_exporter nginx_exporter blackbox_exporter redis_exporter                                                   # ---- exporter --- #
ansible python python-pip python-psycopg2                                                                       # - ansible & py3 - #
python3 python3-psycopg2 python36-requests python3-etcd python3-consul python36-urllib3 python36-idna python36-pyOpenSSL python36-cryptography
patroni patroni-consul patroni-etcd pgbouncer pg_cli pgbadger pg_activity tail_n_mail                           # -- pgsql common - #
pgcenter boxinfo check_postgres emaj pgbconsole pg_bloat_check pgquarrel barman barman-cli pgloader pgFormatter pitrery pspg pgxnclient PyGreSQL
postgresql14* postgis32_14* citus_14* pglogical_14* timescaledb-2-postgresql-14 pg_repack_14 wal2json_14        # -- pg14 packages -#
pg_qualstats_14 pg_stat_kcache_14 pg_stat_monitor_14 pg_top_14 pg_track_settings_14 pg_wait_sampling_14 pg_probackup-std-14
pg_statement_rollback_14 system_stats_14 plproxy_14 plsh_14 pldebugger_14 plpgsql_check_14 pgmemcache_14 # plr_14
mysql_fdw_14 ogr_fdw_14 tds_fdw_14 sqlite_fdw_14 firebird_fdw_14 hdfs_fdw_14 mongo_fdw_14 osm_fdw_14 pgbouncer_fdw_14
hypopg_14 geoip_14 rum_14 hll_14 ip4r_14 prefix_14 pguri_14 tdigest_14 topn_14 periods_14
bgw_replstatus_14 count_distinct_14 credcheck_14 ddlx_14 extra_window_functions_14 logerrors_14 mysqlcompat_14 orafce_14
repmgr_14 pg_auth_mon_14 pg_auto_failover_14 pg_background_14 pg_bulkload_14 pg_catcheck_14 pg_comparator_14
pg_cron_14 pg_fkpart_14 pg_jobmon_14 pg_partman_14 pg_permissions_14 pg_prioritize_14 pgagent_14
pgaudit16_14 pgauditlogtofile_14 pgcryptokey_14 pgexportdoc_14 pgfincore_14 pgimportdoc_14 powa_14 pgmp_14 pgq_14
pgquarrel-0.7.0-1 pgsql_tweaks_14 pgtap_14 pgtt_14 postgresql-unit_14 postgresql_anonymizer_14 postgresql_faker_14
safeupdate_14 semver_14 set_user_14 sslutils_14 table_version_14 # pgrouting_14 osm2pgrouting_14
clang coreutils diffutils rpm-build rpm-devel rpmlint rpmdevtools bison flex # gcc gcc-c++                      # - build utils - #
docker-ce docker-compose kubelet kubectl kubeadm kubernetes-cni helm                                            # - cloud native- #

每一行都是一组由空格分割的软件包名称,在这里指定的软件会通过repotrack进行下载。

repo_url_packages

通过URL直接下载的软件, 类型:url[],层级:G

通过URL,而非YUM下载一些软件:

  • pg_exporter必须项,监控系统核心组件
  • vip-manager必选项,启用L2 VIP时所必须的软件包,用于管理VIP
  • loki, promtail必选项,日志收集服务端与客户端二进制。
  • haproxy:通常为必选项,用于提供负载均衡服务,不启用/不使用时可以跳过。
  • polysh:可选,并行在多台节点上执行ssh命令
  • pev2:可选,PostgreSQL执行计划可视化
  • redis可选,当安装Redis时为必选
https://github.com/Vonng/loki-rpm/releases/download/v2.5.0/loki-2.5.0.x86_64.rpm
https://github.com/Vonng/loki-rpm/releases/download/v2.5.0/promtail-2.5.0.x86_64.rpm
https://github.com/Vonng/pg_exporter/releases/download/v0.5.0/pg_exporter-0.5.0.x86_64.rpm
https://github.com/cybertec-postgresql/vip-manager/releases/download/v1.0.2/vip-manager-1.0.2-1.x86_64.rpm
https://github.com/Vonng/haproxy-rpm/releases/download/v2.6.0/haproxy-2.6.0-1.el7.x86_64.rpm
https://github.com/Vonng/pigsty-pkg/releases/download/misc/redis-6.2.7-1.el7.remi.x86_64.rpm
https://github.com/dalibo/pev2/releases/download/v0.24.0/pev2.tar.gz
https://github.com/Vonng/pigsty-pkg/releases/download/misc/polysh-0.4-1.noarch.rpm

NAMESERVER

Pigsty默认可以使用DNSMASQ在元节点上搭建一个开箱即用的域名服务器,限于中国的互联网管理政策(53端口需备案),默认不启用。

nameserver_enabled

是否启用 DNSMASQ,部署于元节点上提供 DNS 服务,类型:bool,层级:C/I;v1.5.1 随附的 pigsty.yml 默认值为:false(角色兜底值为 true

dns_records

动态DNS解析记录, 类型:string[],层级:G,默认值为[]空列表,在沙箱环境中默认有以下解析记录。

dns_records:                    # dynamic dns record resolved by dnsmasq
  - 10.10.10.2  pg-meta         # sandbox vip for pg-meta
  - 10.10.10.3  pg-test         # sandbox vip for pg-test
  - 10.10.10.10 meta-1          # sandbox node meta-1
  - 10.10.10.11 node-1          # sandbox node node-1
  - 10.10.10.12 node-2          # sandbox node node-2
  - 10.10.10.13 node-3          # sandbox node node-3
  - 10.10.10.10 pg-meta-1       # sandbox instance pg-meta-1
  - 10.10.10.11 pg-test-1       # sandbox instance node-1
  - 10.10.10.12 pg-test-2       # sandbox instance node-2
  - 10.10.10.13 pg-test-3       # sandbox instance node-3

PROMETHEUS

Prometheus是Pigsty监控系统核心组件,用于拉取时序数据,进行指标预计算,评估告警规则。

prometheus_enabled

是否在元节点上启用Prometheus?类型:bool,层级:C/I,默认值为:true

如果您有多个元节点,默认情况下,Pigsty会在所有元节点上部署Prometheus。如果您想一台用于Prometheus监控指标收集,一台用于Loki日志收集,则可以在其他元节点的实例层次上将此参数设置为false

prometheus_data_dir

Prometheus数据库目录, 类型:path,层级:G,默认值为:"/data/prometheus/data"

prometheus_options

Prometheus命令行参数, 类型:string,层级:G,默认值为:"--storage.tsdb.retention=15d"

默认参数会保留 15 天监控数据。如果您的磁盘有余裕,可以增大监控数据的保留时长。

prometheus_reload

在执行Prometheus任务时,是否仅仅只是重载配置,而不是整个重建。类型:bool,层级:A,默认值为:false

默认情况下,执行执行prometheus任务时会清除已有监控数据,如果设置为true,执行Prometheus任务时不会清除已有数据目录。

prometheus_sd_method

服务发现机制:static|consul, 类型:enum,层级:G,默认值为:"static"

Prometheus使用的服务发现机制,默认为static,另外的选项 consul 将使用Consul进行服务发现(将逐步弃用)。 Pigsty建议使用static服务发现,该方式提供了更高的可靠性与灵活性,Consul服务发现将逐步停止支持。

static服务发现依赖/etc/prometheus/targets/{infra,nodes,pgsql,redis}/*.yml中的配置进行服务发现。 采用这种方式的优势是,监控系统不依赖Consul,当节点宕机时,监控目标会报错提示,而不是直接消失。此外,当Pigsty监控系统与外部管控方案集成时,这种模式对原系统的侵入性较小。

可以使用以下命令,从配置文件生成Prometheus所需的监控对象配置文件。

./nodes.yml -t register_prometheus  # 生成主机监控目标列表
./pgsql.yml -t register_prometheus  # 生成PostgreSQL/Pgbouncer/Patroni/Haproxy监控目标列表
./redis.yml -t register_prometheus  # 生成Redis监控目标列表

prometheus_scrape_interval

Prometheus抓取周期, 类型:interval,层级:G,默认值为:"10s"

在生产环境,10秒 - 30秒是一个较为合适的抓取周期。如果您需要更精细的的监控数据粒度,则可以调整此参数。

prometheus_scrape_timeout

Prometheus抓取超时, 类型:interval,层级:G,默认值为:"8s"

设置抓取超时可以有效避免监控系统查询导致的雪崩,原则是本参数必须小于并接近 prometheus_scrape_interval ,确保每次抓取时长不超过抓取周期。

prometheus_sd_interval

Prometheus服务发现刷新周期, 类型:interval,层级:G,默认值为:"5s"

每隔本参数指定的时长,Prometheus就会重新检查本地文件目录,刷新监控目标对象。


EXPORTER

定义通用的指标暴露器选项,例如Exporter的安装方式,监听的URL路径等。

exporter_install

安装监控组件的方式, 类型:enum,层级:G,默认值为:"none"

指明安装Exporter的方式:

  • none:不安装,(默认行为,Exporter已经在先前由 node.pkgs 任务完成安装)
  • yum:使用yum安装(如果启用yum安装,在部署Exporter前执行yum安装 node_exporterpg_exporter
  • binary:使用拷贝二进制的方式安装(从元节点中直接拷贝node_exporterpg_exporter 二进制,不推荐)

使用yum安装时,如果指定了exporter_repo_url(不为空),在执行安装时会首先将该URL下的REPO文件安装至/etc/yum.repos.d中。这一功能可以在不执行节点基础设施初始化的环境下直接进行Exporter的安装。 不推荐普通用户使用binary安装,这种模式通常用于紧急故障抢修与临时问题修复。

<meta>:<pigsty>/files/node_exporter ->  <target>:/usr/bin/node_exporter
<meta>:<pigsty>/files/pg_exporter   ->  <target>:/usr/bin/pg_exporter

exporter_repo_url

监控组件的Yum Repo URL, 类型:string,层级:G,默认值为:""

默认为空,当 exporter_installyum 时,该参数指定的Repo会被添加至节点源列表中。

exporter_metrics_path

监控暴露的URL Path, 类型:string,层级:G,默认值为:"/metrics"

所有Exporter对外暴露指标的URL PATH,默认为/metrics,该变量被外部角色prometheus引用,Prometheus会根据这里的配置,对监控对象应用此配置。

受此参数影响的指标暴露器包括:


GRAFANA

Grafana是Pigsty监控系统的可视化平台。

grafana_enabled

是否在元节点上启用Grafana?类型:bool,层级:C/I,默认值为:true

如果您有多个元节点,默认情况下,Pigsty会在所有元节点上部署Grafana。您可以在不想启用Grafana的元节点的实例层次上将此参数设置为false

grafana_endpoint

Grafana地址, 类型:url,层级:G,默认值为:"http://10.10.10.10:3000"

Grafana对外提供服务的端点,Grafana初始化与安装监控面板会使用该端点调用Grafana API

在Configure过程中,占位IP10.10.10.10会在configure过程中被实际IP替换。

grafana_admin_username

Grafana管理员用户名, 类型:string,层级:G,默认值为:"admin"

grafana_admin_password

Grafana管理员密码, 类型:string,层级:G,默认值为:"pigsty"

grafana_database

Grafana后端数据库类型, 类型:enum,层级:G,默认值为:"sqlite3"

备选为postgres,使用postgres时,必须确保目标数据库已经存在并可以访问。即首次初始化基础设施前,无法使用元节点上的Postgres,因为Grafana先于该数据库而创建。

为了避免产生循环依赖(Grafana依赖Postgres,PostgreSQL依赖包括Grafana在内的基础设施),您需要在首次完成安装后,修改此参数并重新执行 grafana相关任务。 详情请参考【教程:使用Postgres作为Grafana后端数据库

grafana_pgurl

Grafana的PostgreSQL数据库连接串, 类型:url,层级:G,默认值为:"postgres://dbuser_grafana:DBUser.Grafana@meta:5436/grafana"

仅当参数 grafana_databasepostgres 时有效。

grafana_plugin_method

如何安装Grafana插件, 类型:enum,层级:G,默认值为:"install"

Grafana插件的供给方式

  • none:不安装插件
  • install: 安装Grafana插件(默认),若已存在则跳过。
  • always: 无论如何都重新下载安装Grafana插件

Grafana需要访问互联网以下载若干扩展插件,如果您的元节点没有互联网访问,则应当确保使用了离线安装包。 离线安装包中默认已经包含了所有下载好的Grafana插件,位于 grafana_plugin_cache 指定的路径下。当从互联网下载插件时,Pigsty会在下载完成后打包下载好的插件,并放置于该路径下。

grafana_plugin_cache

Grafana插件缓存地址, 类型:path,层级:G,默认值为:"/www/pigsty/plugins.tgz"

grafana_plugin_list

安装的Grafana插件列表, 类型:string[],层级:G,默认值为:

grafana_plugin_list:
  - marcusolsson-csv-datasource
  - marcusolsson-json-datasource
  - marcusolsson-treemap-panel

每个数组元素是一个字符串,表示插件的名称。插件会通过grafana-cli plugins install的方式进行安装。

grafana_plugin_git

从Git安装的Grafana插件, 类型:url[],层级:G,默认值为:

grafana_plugin_git:                          # plugins that will be downloaded via git
  - https://github.com/Vonng/vonng-echarts-panel

一些插件无法通过官方命令行下载,但可以通过Git Clone的方式下载。插件会通过cd /var/lib/grafana/plugins && git clone 的方式进行安装。

默认会下载一个可视化插件:vonng-echarts-panel,提供为Grafana提供Echarts绘图支持。


LOKI

LOKI是Pigsty使用的默认日志收集服务器。

loki_enabled

是否在元节点上启用Loki?类型:bool,层级:C/I,默认值为:true

如果您有多个元节点,默认情况下,Pigsty会在所有元节点上部署Loki。如果您想一台用于Prometheus监控指标收集,一台用于Loki日志收集,则可以在其他元节点的实例层次上将此参数设置为false

loki_clean

是否在安装Loki时清理数据库目录, 类型:bool,层级:A,默认值为:false

loki_endpoint

用于接收日志的loki服务端点, 类型:url,层级:G,默认值为:"http://10.10.10.10:3100/loki/api/v1/push"

loki_options

Loki的命令行参数, 类型:string,层级:G,默认值为:"-config.file=/etc/loki.yml -config.expand-env=true"

默认的配置参数用于指定Loki配置文件位置,并启用在配置文件中展开环境变量的功能,不建议移除这两个选项。

loki_data_dir

Loki的数据目录, 类型:string,层级:G,默认值为:"/data/loki"

loki_retention

Loki日志默认保留天数, 类型:interval,层级:G,默认值为:"15d"


DCS

Distributed Configuration Store (DCS) 是一种分布式,高可用的元数据库。Pigsty使用DCS来实现数据库高可用,服务发现等功能也通过DCS实现。

Pigsty目前支持使用Consul与ETCD作为DCS。通过 pg_dcs_type 指明高可用PG使用的DCS种类,通过 dcs_registry 指明服务注册的位置。

Consul服务的可用性对于数据库高可用至关重要,因此在生产环境摆弄DCS服务时,需要特别小心。DCS本身的可用性,通过多副本实现。例如,3节点的Consul集群最多允许1个节点故障,5节点的Consul集群则可以允许两个节点故障,在大规模生产环境中,建议使用至少3个DCS Server。 Pigsty使用的DCS服务器通过参数 dcs_servers 指定,您可以使用外部的现有DCS服务器集群。也可以使用Pigsty本身管理的节点部署DCS Servers。

在默认情况下,Pigsty会在节点纳入管理时(nodes.yml)部署设置DCS服务,如果当前节点定义于 dcs_servers 中,则该节点会被初始化为 DCS Server。

Pigsty会在元节点本身部署一个单节点的DCS Server,使用多个元节点时,您也可以将其复用为DCS Server。尽管如此,元节点与DCS Server并不绑定。您可以使用任意节点作为DCS Servers。

但大的原则是,在部署任意高可用数据库集群前,您应当确保所有DCS Servers已经完成初始化。

dcs_servers

DCS服务器, 类型:dict,层级:G,默认值为:

dcs_servers:
  meta-1: 10.10.10.10      # 默认在元节点上部署单个DCS Server
  # meta-2: 10.10.10.11
  # meta-3: 10.10.10.12

字典格式,Key为DCS服务器实例名称,Value为服务器IP地址。 默认情况下,Pigsty将在节点初始化剧本中为节点配置DCS服务,默认为Consul。

您可以使用外部的DCS服务器,依次填入所有外部DCS Servers的地址即可,否则Pigsty默认将在元节点(10.10.10.10占位)上部署一个单实例DCS Server。 如果当前节点定义于 dcs_servers 中,即IP地址与任意Value匹配,则该节点会被初始化为 DCS Server,其Key将被用作Consul Server

dcs_registry

服务注册的位置, 类型:enum,层级:G,默认值为:"consul"

  • none:不执行服务注册(当执行仅监控部署时,必须指定none模式)
  • consul:将服务注册至Consul中
  • etcd:将服务注册至Etcd中(尚未支持)

pg_dcs_type

使用的DCS类型, 类型:enum,层级:G,默认值为:"consul"

可选 consuletcd。v1.5.1 的 Patroni 模板、环境模板与 PostgreSQL 角色均已实现 ETCD DCS;服务注册参数 dcs_registry=etcd 仍未实现。

CONSUL

Consul用于服务网格,健康监测,传递共识,代理DCS Server访问。

consul_enabled

是否启用 Consul Server / Agent,类型:bool,层级:G,默认值为:true。默认会在节点上配置 Consul,并在 dcs_servers 指定的节点上配置 Consul Server。

dcs_safeguard

安全保险,禁止清除存在的Consul实例,类型:bool,层级:C/A,默认值为:false

如果为true,任何情况下,Pigsty剧本都不会移除运行中的Consul实例,包括 nodes-remove.yml

详情请参考 保护机制

dcs_clean

是否在初始化时抹除现存 Consul 实例?类型:bool,层级:C/A。v1.5.1 的 Consul 角色兜底值与随附 pigsty.yml 均为 true;受保护环境应改为 false 并/或启用 dcs_safeguard

针对 nodes.yml 剧本的抹除豁免,如果指定该参数为真,那么在 nodes.yml 剧本执行时,会自动抹除已有的Consul实例。

只有当该参数启用时,nodes.yml 才是一个真正幂等的剧本。

这是危险操作;执行节点初始化前必须明确复核该值。

警告

安全保险参数 dcs_safeguard 打开时,本参数无效。

dcs_name

DCS集群名称, 类型:string,层级:G,默认值为:"pigsty"

在 Consul 中代表数据中心名称,在 ETCD 中用作初始集群令牌。

consul_data_dir

Consul数据目录, 类型:string,层级:G,默认值为:"/data/consul"


ETCD

ETCD 可作为 PostgreSQL 高可用选主的 DCS,并由 v1.5.1 的 nodes.ymlinfra.ymlinfra-demo.yml 中的 etcd 角色部署。

etcd_enabled

是否启用 ETCD,类型:bool,层级:G,默认值为:true。在 dcs_servers 中列出的节点部署 ETCD Server,并向客户端节点写入访问环境与证书。

etcd_data_dir

ETCD 数据目录,类型:string,层级:G,默认值为:"/data/etcd"

28 - 配置:Nodes

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty提供了完整的主机置备与监控功能,执行 nodes.yml 剧本即可将对应节点配置为对应状态,并纳入Pigsty监控系统。

ID Name Section Type Level Comment
300 meta_node NODE_IDENTITY bool C 表示此节点为元节点
301 nodename NODE_IDENTITY string I 指定节点实例标识
302 node_cluster NODE_IDENTITY string C 节点集群名,默认名为nodes
303 nodename_overwrite NODE_IDENTITY bool C 用Nodename覆盖机器HOSTNAME
304 nodename_exchange NODE_IDENTITY bool C 是否在剧本节点间交换主机名
310 node_etc_hosts NODE_DNS string[] C/I 同上,用于集群实例层级
311 node_etc_hosts_default NODE_DNS string[] C 写入机器的静态DNS解析
312 node_dns_method NODE_DNS enum C 如何配置DNS服务器?
313 node_dns_servers NODE_DNS string[] C 配置动态DNS服务器列表
314 node_dns_options NODE_DNS string[] C 配置/etc/resolv.conf
320 node_repo_method NODE_PACKAGE enum C 节点使用Yum源的方式
321 node_repo_remove NODE_PACKAGE bool C 是否移除节点已有Yum源
322 node_repo_local_urls NODE_PACKAGE url[] C 本地源的URL地址
331 node_packages NODE_PACKAGE string[] C 节点额外安装的软件列表
330 node_packages_default NODE_PACKAGE string[] C 节点安装软件列表
332 node_packages_meta NODE_PACKAGE string[] G 元节点所需的软件列表
333 node_packages_meta_pip NODE_PACKAGE string G 元节点上通过pip3安装的软件包
340 node_disable_firewall NODE_TUNE bool C 关闭节点防火墙
341 node_disable_selinux NODE_TUNE bool C 关闭节点SELINUX
342 node_disable_numa NODE_TUNE bool C 关闭节点NUMA
343 node_disable_swap NODE_TUNE bool C 关闭节点SWAP
344 node_static_network NODE_TUNE bool C 是否使用静态DNS服务器
345 node_disk_prefetch NODE_TUNE bool C 是否启用磁盘预读
346 node_kernel_modules NODE_TUNE string[] C 启用的内核模块
347 node_tune NODE_TUNE enum C 节点调优模式
348 node_sysctl_params NODE_TUNE dict C 操作系统内核参数
350 node_data_dir NODE_ADMIN path G 节点的数据盘挂载路径
351 node_admin_enabled NODE_ADMIN bool G 是否创建管理员用户
352 node_admin_uid NODE_ADMIN int G 管理员用户UID
353 node_admin_username NODE_ADMIN string G 管理员用户名
354 node_admin_ssh_exchange NODE_ADMIN bool C 在实例间交换管理员SSH密钥
355 node_admin_pk_current NODE_ADMIN bool A 是否将当前用户的公钥加入管理员账户
356 node_admin_pk_list NODE_ADMIN key[] C 可登陆管理员的公钥列表
360 node_timezone NODE_TIME string C NTP时区设置
361 node_ntp_enabled NODE_TIME bool C 是否配置NTP服务?
362 node_ntp_service NODE_TIME enum C NTP服务类型:ntp或chrony
363 node_ntp_servers NODE_TIME string[] C NTP服务器列表
364 node_crontab_overwrite NODE_TIME bool C/I 是否覆盖/etc/crontab
365 node_crontab NODE_TIME string[] C/I 主机定时任务列表
370 docker_enabled DOCKER bool C dockerd是否启用?
371 docker_cgroups_driver DOCKER string C docker cgroup驱动
372 docker_registry_mirrors DOCKER string[] C docker镜像仓库地址
373 docker_image_cache DOCKER path C docker镜像缓存包地址
380 node_exporter_enabled NODE_EXPORTER bool C 启用节点指标收集器
381 node_exporter_port NODE_EXPORTER int C 节点指标暴露端口
382 node_exporter_options NODE_EXPORTER string C/I 节点指标采集选项
390 promtail_enabled PROMTAIL bool C 是否启用Promtail日志收集服务
391 promtail_clean PROMTAIL bool C/A 是否在安装promtail时移除已有状态信息
392 promtail_port PROMTAIL int G promtail使用的默认端口
393 promtail_options PROMTAIL string C/I promtail命令行参数
394 promtail_positions PROMTAIL string C promtail状态文件位置

NODE_IDENTITY

每个节点都有身份参数,通过在<cluster>.hosts<cluster>.vars中的相关参数进行配置。

Pigsty使用IP地址作为数据库节点的唯一标识,该IP地址必须是数据库实例监听并对外提供服务的IP地址,但不宜使用公网IP地址。尽管如此,用户并不一定非要通过该IP地址连接至该数据库。例如,通过SSH隧道或跳板机中转的方式间接操作管理目标节点也是可行的。但在标识数据库节点时,首要IPv4地址依然是节点的核心标识符,这一点非常重要,用户应当在配置时保证这一点。 IP地址即配置清单中主机的inventory_hostname ,体现为<cluster>.hosts对象中的key

除此之外,在Pigsty监控系统中,节点还有两个重要的身份参数:nodenamenode_cluster,这两者将在监控系统中用作节点的 实例标识ins) 与 集群标识cls)。在执行默认的PostgreSQL部署时,因为Pigsty默认采用节点独占1:1部署,因此可以通过 pg_hostname 参数,将数据库实例的身份参数(pg_clusterpg_instance)借用至节点的inscls标签上。

nodenamenode_cluster并不是必选的,当留白或置空时,nodename 会使用节点当前的主机名,而 node_cluster 则会使用固定的默认值:nodes

名称 类型 层级 必要性 说明
inventory_hostname ip - 必选 节点IP地址
nodename string I 可选 节点名称
node_cluster string C 可选 节点集群名称

以下集群配置声明了一个三节点节点集群:

node-test:
  hosts:
    10.10.10.11: { nodename: node-test-1 }
    10.10.10.12: { nodename: node-test-2 }
    10.10.10.13: { nodename: node-test-3 }
  vars:
    node_cluster: node-test

meta_node

表示此节点为元节点, 类型:bool,层级:C,默认值为:false

在配置清单中,meta分组下的节点默认带有此标记。带有此标记的节点会在节点软件包安装时进行额外的配置: 安装node_packages_meta指定的RPM软件包,并安装node_packages_meta_pip指定的Python软件包。

nodename

指定节点名, 类型:string,层级:I,默认值为空。

该选项可为节点显式指定名称,只在节点实例层次定义才有意义。使用默认空值或空字符串意味着不为节点指定名称,直接使用现有的 Hostname 作为节点名。

节点名nodename将在Pigsty监控系统中,用作节点实例的名称(ins标签)。此外,如果 nodename_overwrite 为真,节点名还会用作HOSTNAME。

备注:若启用pg_hostname 选项,则Pigsty会在初始化节点时,借用当前节点上一一对应PG实例的身份参数,如pg-test-1,作为节点名。

node_cluster

节点集群名,类型:string,层级:C,默认值为:"nodes"

该选项可为节点显式指定一个集群名称,通常在节点集群层次定义才有意义。使用默认空值将直接使用固定值nodes作为节点集群标识。

节点集群名node_cluster将在Pigsty监控系统中,用作节点集群的标签(cls)。

备注:若启用pg_hostname 选项,则Pigsty会在初始化节点时,借用当前节点上一一对应PG集群的身份参数,如pg-test,作为节点集群名。

nodename_overwrite

是否用节点名覆盖机器HOSTNAME, 类型:bool,层级:C,默认值为:true

布尔类型,默认为真,为真时,非空的节点名 nodename 将覆盖节点的当前主机名称。

如果 nodename 参数未定义,为空或为空字符串,则不会对主机名进行修改。

nodename_exchange

是否在剧本节点间交换主机名, 类型:bool,层级:C,默认值为:false

启用此参数时,同一组执行 nodes.yml 剧本的节点之间,会相互交换节点名称,写入/etc/hosts中。


NODE_DNS

Pigsty会为节点配置静态DNS解析记录与动态DNS服务器。

如果您的节点供应商已经为您配置了DNS服务器,您可以将 node_dns_method 设置为 none 跳过DNS设置。

node_etc_hosts

写入节点的静态DNS解析, 类型:string[],层级:C/I,默认值为空数组 []

node_etc_hosts 是一个数组,每一个元素都是形如ip domain_name的字符串,代表一条DNS解析记录,每一条记录都会在机器节点初始化时写入/etc/hosts中。

如果用户希望在全局配置基础设施地址,则可以使用 node_etc_hosts_default 参数,使用本参数添加集群/实例特定的静态DNS记录。

node_etc_hosts_default

默认写入所有节点的静态DNS记录, 类型:string[],层级:G,,默认值为Pigsty管理节点的域名解析记录:

node_etc_hosts_default:                 # static dns records in /etc/hosts
  - 10.10.10.10 meta pigsty c.pigsty g.pigsty l.pigsty p.pigsty a.pigsty cli.pigsty lab.pigsty api.pigsty

您应当确保向/etc/hosts中写入10.10.10.10 pigsty yum.pigsty这样的DNS记录,确保在DNS Nameserver启动之前便可以采用域名的方式访问本地yum源。

如果用户希望为单个集群与实例配置特定的静态DNS解析,则可以使用 node_etc_hosts 参数。

node_dns_method

如何配置DNS服务器?, 类型:enum,层级:C,默认值为:"add"

机器节点默认的动态DNS服务器的配置方式,有三种模式:

  • add:将 node_dns_servers 中的记录追加至/etc/resolv.conf,并保留已有DNS服务器。(默认)
  • overwrite:使用将 node_dns_servers 中的记录覆盖/etc/resolv.conf
  • none:跳过DNS服务器配置,如果您的环境中已经配置有DNS服务器,则可以跳过。

node_dns_servers

配置动态DNS服务器列表, 类型:string[],层级:C,默认值为 10.10.10.10

Pigsty默认会添加元节点作为DNS Server,元节点上的DNSMASQ会响应环境中的DNS请求。

node_dns_servers: # dynamic nameserver in /etc/resolv.conf
  - 10.10.10.10

node_dns_options

如果 node_dns_method 配置为addoverwrite,则本配置项中的记录会被追加或覆盖至/etc/resolv.conf中。具体格式请参考Linux文档关于/etc/resolv.conf的说明

Pigsty默认添加的解析选项为:

- options single-request-reopen timeout:1 rotate
- domain service.consul

NODE_PACKAGE

Pigsty会为纳入管理的节点配置Yum源,并安装软件包。

node_repo_method

节点使用Yum源的方式, 类型:enum,层级:C,默认值为:"local"

机器节点Yum软件源的配置方式,有三种模式:

  • local:使用元节点上的本地Yum源,默认行为,推荐使用此方式。
  • public:直接使用互联网源安装,将repo_upstream中的公共repo写入/etc/yum.repos.d/
  • none:不对本地源进行配置与修改。

node_repo_remove

是否移除节点已有Yum源, 类型:bool,层级:C,默认值为:true

如何处理节点上原有YUM源?如果启用,则Pigsty会移除 节点上/etc/yum.repos.d中原有的配置文件,并备份至/etc/yum.repos.d/backup

node_repo_local_urls

本地源的URL地址, 类型:url[],层级:C,默认值为:

如果 node_repo_method 配置为local,则这里列出的Repo文件URL会被下载至/etc/yum.repos.d

这里是一个Repo File URL 构成的数组,Pigsty默认会将元节点上的本地Yum源加入机器的源配置中。

node_repo_local_urls:
  - http://yum.pigsty/pigsty.repo

node_packages

节点安装的软件列表, 类型:string[],层级:C,默认值为空列表:[]

通过yum安装的额外软件包列表,每个数组元素为软件包名称,您可以在每一个元素中都指定一个逗号分隔的软件列表,软件包会依次安装。

默认在全局所有节点上安装的软件包通过参数 node_packages_default 进行配置,本参数可用于配置集群/节点特定的软件包。

node_packages_defaultnode_packages 类似,前者通常是全局统一配置,而 node_packages 则是针对具体节点进行例外处理。 例如,您可以为运行PG的节点安装额外的工具包。该变量通常在集群级别进行覆盖定义。

node_packages_default

节点安装软件列表, 类型:string[],层级:C,默认值为:

node_packages_meta:                           # packages for meta nodes only
  - grafana,prometheus2,alertmanager,loki,nginx_exporter,blackbox_exporter,pushgateway,redis,postgresql14
  - nginx,ansible,pgbadger,python-psycopg2,dnsmasq,polysh,coreutils,diffutils

软件包列表为数组,但每个元素可以包含由逗号分隔的多个软件包,Pigsty默认安装的软件包列表如下:

node_packages_meta

元节点所需的软件列表, 类型:string[],层级:G,默认值为:

node_packages_meta:                           # packages for meta nodes only
  - grafana,prometheus2,alertmanager,loki,nginx_exporter,blackbox_exporter,pushgateway,redis,postgresql14
  - nginx,ansible,pgbadger,python-psycopg2,dnsmasq,polysh,coreutils,diffutils

node_packages_default类似,但node_packages_meta中列出的软件包只会在元节点上安装,通常在元节点上使用的基础设施软件需要在此指定

node_packages_meta_pip

元节点上通过pip3安装的软件包, 类型:string,层级:G,默认值为:"jupyterlab"

软件包会下载至{{ nginx_home }}/{{ repo_name }}/python目录后统一安装。

目前默认会安装jupyterlab,提供完整的Python运行时环境。


NODE_TUNE

主机节点特性、内核模块与调优模板

node_disable_firewall

关闭节点防火墙, 类型:bool,层级:C,默认值为:true,请保持关闭。

node_disable_selinux

关闭节点SELINUX, 类型:bool,层级:C,默认值为:true,请保持关闭。

node_disable_numa

关闭节点NUMA, 类型:bool,层级:C,默认值为:false

布尔标记,是否关闭NUMA,默认不关闭。注意,关闭NUMA需要重启机器后方可生效!

如果您不清楚如何绑核,在生产环境使用数据库时建议关闭NUMA。

node_disable_swap

关闭节点SWAP, 类型:bool,层级:C,默认值为:false

通常情况下不建议关闭SWAP,如果您有足够的内存,且数据库采用独占式部署,则可以关闭SWAP提高性能。

当您的节点用于部署Kubernetes时,应当禁用SWAP。

node_static_network

是否使用静态DNS服务器, 类型:bool,层级:C,默认值为:true,默认启用。

启用静态网络,意味着您的DNS Resolv配置不会因为机器重启与网卡变动被覆盖。建议启用。

node_disk_prefetch

是否启用磁盘预读, 类型:bool,层级:C,默认值为:false,默认不启用。

针对HDD部署的实例可以优化吞吐量,使用HDD时建议启用。

node_kernel_modules

启用的内核模块, 类型:string[],层级:C,默认值为:

由内核模块名称组成的数组,声明了需要在节点上安装的内核模块,Pigsty默认会启用以下内核模块:

node_kernel_modules: [ softdog, ip_vs, ip_vs_rr, ip_vs_rr, ip_vs_wrr, ip_vs_sh ]

node_tune

节点调优模式, 类型:enum,层级:C,默认值为:"tiny"

针对机器进行调优的预制方案,基于tuned服务。有四种预制模式:

  • tiny:微型虚拟机
  • oltp:常规OLTP模板,优化延迟
  • olap:常规OLAP模板,优化吞吐量
  • crit:核心金融业务模板,优化脏页数量

通常,数据库的调优模板 pg_conf应当与机器调优模板配套,详情请参考定制PGSQL模版

node_sysctl_params

操作系统内核参数, 类型:dict,层级:C,默认值为空字典。字典KV结构,Key为内核sysctl参数名,Value为参数值。


NODE_ADMIN

主机节点管理用户

node_data_dir

节点的数据盘挂载路径, 类型:path,层级:C,默认值为:/data

如果指定,则该路径将作为节点的主数据库盘,如果该目录不存在,则该目录会被创建并抛出提示信息。

默认情况下,该目录属主为root,模式为0777

node_admin_enabled

是否创建管理员用户, 类型:bool,层级:G,默认值为:true

是否在每个节点上创建管理员用户(免密sudo与ssh),默认会创建名为dba (uid=88)的管理用户,可以从元节点上通过SSH免密访问环境中的其他节点并执行免密sudo。

node_admin_uid

管理员用户UID, 类型:int,层级:G,默认值为:88,手工分配时请注意UID命名空间冲突。

node_admin_username

管理员用户名, 类型:string,层级:G,默认值为:"dba"

node_admin_ssh_exchange

在实例间交换节点管理员SSH密钥, 类型:bool,层级:C,默认值为:true

启用时,Pigsty会在执行剧本时,在成员间交换SSH公钥,允许管理员 node_admin_username 从不同节点上相互访问。

node_admin_pk_current

是否将当前节点&用户的公钥加入管理员账户, 类型:bool,层级:A,默认值为:true

启用时,将当前节点上,当前用户的SSH公钥(~/.ssh/id_rsa.pub)会被拷贝至目标节点管理员用户的authorized_keys中。

生产环境部署时,请务必注意此参数,此参数会将当前执行命令用户的默认公钥安装至所有机器的管理用户上。

node_admin_pk_list

可登陆管理员的公钥列表, 类型:key[],层级:C,默认值为空数组,Demo中有vagrant用户默认的公钥。

数组,每一个元素为字符串,内容为写入到管理员用户~/.ssh/authorized_keys中的密钥,持有对应私钥的用户可以以管理员身份登录。

生产环境部署时,请务必注意此参数,仅将信任的密钥加入此列表中。


NODE_TIME

节点时区与时间同步。

如果您的节点已经配置有NTP服务器,则可以配置 node_ntp_enabledfalse,跳过NTP服务的设置。

node_timezone

节点时区设置,类型:string,层级:C,默认值为:"Asia/Hong_Kong"

在Demo中,默认使用的时区为"Asia/Hong_Kong",请根据您的实际情况调整。(请不要使用Asia/Shanghai时区,该时区缩写 CST 会导致一系列日志时区解析问题)

如果选择 false,或者留空,则Pigsty不会修改该节点的时区配置。

node_ntp_enabled

是否配置NTP服务?, 类型:bool,层级:C,默认值为:true

为真时,Pigsty会覆盖节点的/etc/ntp.conf/etc/chrony.conf,填入 node_ntp_servers 指定的NTP服务器。

如果您的服务器节点已经配置好有NTP服务器,则建议关闭,使用原有NTP服务器。

node_ntp_service

NTP服务类型:ntpchrony, 类型:enum,层级:C,默认值为:"ntp"

指明系统使用的NTP服务类型,默认使用 ntp 作为时间服务:

  • ntp:传统NTP服务
  • chrony:CentOS 7/8默认使用的时间服务

只有当 node_ntp_enabled 为真时生效。

node_ntp_servers

NTP服务器列表, 类型:string[],层级:C,默认值为:

- pool cn.pool.ntp.org iburst
- pool pool.ntp.org iburst
- pool time.pool.aliyun.com iburst
- server 10.10.10.10 iburst

只有当 node_ntp_enabled 为真时生效。

node_crontab_overwrite

是否覆盖节点的Crontab, 类型:bool,层级:C/I,默认值为true

如果启用,node_crontab 中的记录会整体覆盖 /etc/crontab 而不是追加写入。

node_crontab

节点定时任务列表, 类型:string[],层级:C/I,默认值为空数组[]

在此列表的每的一个元素都是一条记录,写入 /etc/crontab中,例如:

00 01 * * * postgres /pg/bin/pg-backup 2>>/pg/log/backup.log

DOCKER

Pigsty默认在所有元节点上启用Docker,而普通节点不启用。

docker_enabled

是否在当前节点启用Docker?类型:bool,层级:C,默认值为false,但元节点默认为true

docker_cgroups_driver

Docker使用的CGroup驱动,类型:string,层级:C,默认为systemd

docker_registry_mirrors

Docker使用的镜像仓库地址,类型:string[],层级:C,默认为空,即直接使用 DockerHub。

docker_image_cache

本地的Docker镜像离线缓存包,类型:path,层级:C,默认为:/tmp/docker.tgz

如果存在时,配置Docker时会自动加载至本地Docker中。


NODE_EXPORTER

NodeExporter用于从主机上收集监控指标数据。

node_exporter_enabled

启用节点指标收集器, 类型:bool,层级:C,默认值为:true

node_exporter_port

节点指标暴露端口, 类型:int,层级:C,默认值为:9100

node_exporter_options

节点指标采集选项, 类型:string,层级:C/I,默认值为:"--no-collector.softnet --no-collector.nvme --collector.ntp --collector.tcpstat --collector.processes"

Pigsty默认会启用ntp, tcpstat, processes 三个额外的指标收集器,禁用 softnet, nvme 两个默认的指标收集器。


PROMTAIL

主机日志收集组件,与Loki基础设施配置配套使用。

promtail_enabled

是否启用Promtail日志收集服务, 类型:bool,层级:C,默认值为:true

布尔类型,是否在当前节点启用Promtail日志收集服务?默认启用。

启用 promtail 后,Pigsty会根据配置清单中的定义,生成Promtail的配置文件,抓取下列日志并发送至由loki_endpoint指定的Loki实例。

  • INFRA:基础设施日志,只在元节点上收集

    • nginx-access: /var/log/nginx/access.log
    • nginx-error: /var/log/nginx/error.log
    • grafana: /var/log/grafana/grafana.log
  • NODES: 主机节点日志,在所有节点上收集。

    • syslog: /var/log/messages
    • dmesg: /var/log/dmesg
    • cron: /var/log/cron
  • PGSQL: PostgreSQL日志,当节点定义有pg_cluster时收集。

    • postgres: /pg/data/log/*.csv
    • patroni: /pg/log/patroni.log
    • pgbouncer: /var/log/pgbouncer/pgbouncer.log
  • REDIS: Redis日志,当节点定义有redis_cluster时收集。

    • redis: /var/log/redis/*.log

promtail_clean

是否在安装promtail时移除已有状态信息, 类型:bool,层级:C/A,默认值为:false

默认不会清理,当您选择清理时,Pigsty会在部署Promtail时移除现有状态文件 promtail_positions,这意味着Promtail会重新收集当前节点上的所有日志并发送至Loki。

promtail_port

promtail使用的默认端口, 类型:int,层级:G,默认值为:9080

promtail_options

promtail命令行参数, 类型:string,层级:C/I,默认值为:"-config.file=/etc/promtail.yml -config.expand-env=true"

运行promtail二进制程序时传入的额外命令行参数,默认值为'-config.file=/etc/promtail.yml -config.expand-env=true'

已有参数用于指定配置文件路径,并在配置文件中展开环境变量,不建议修改。

promtail_positions

promtail状态文件路径, 类型:string,层级:C,默认值为:"/var/log/positions.yaml"

Promtail记录了所有日志的消费偏移量,定期写入promtail_positions 指定的文件中。

29 - 配置:PGSQL

从 Pigsty v1.5.1 标签恢复的历史文档。

使用 PGSQL剧本部署PGSQL集群,将集群状态调整至 PGSQL配置所描述的状态。

您需要通过配置,向Pigsty表达自己对数据库的需求。Pigsty提供了100+参数来对PostgreSQL集群进行完备的描述。但用户通常只需要关心 身份参数业务对象 中的个别参数即可:前者表达数据库集群“是谁?在哪?”,后者表达这个数据库“啥样?有啥?”。

Pigsty中,关于PostgreSQL数据库的参数分为7个主要章节:

  • PG_IDENTITY : 定义PostgreSQL数据库集群的身份
  • PG_BUSINESS : 定制集群模板:用户,数据库,服务,权限规则
  • PG_INSTALL : 安装PostgreSQL软件包,扩展插件,准备目录结构与工具脚本
  • PG_BOOTSTRAP : 生成配置模板,拉起PostgreSQL集群,搭建主从复制,启用连接池
  • PG_PROVISION : PGSQL集群模板置备,创建用户与数据库,配置权限角色HBA,模式与扩展。
  • PG_EXPORTER : PGSQL指标暴露器,数据库与连接池配置监控组件
  • PG_SERVICE : 对外暴露PostgreSQL服务,安装负载均衡器 HAProxy,启用VIP,配置DNS。
ID Name Section Type Level Comment
500 pg_cluster PG_IDENTITY string C PG数据库集群名称
501 pg_shard PG_IDENTITY string C PG集群所属的Shard (保留)
502 pg_sindex PG_IDENTITY int C PG集群的分片号 (保留)
503 gp_role PG_IDENTITY enum C 当前PG集群在GP中的角色
504 pg_role PG_IDENTITY enum I PG数据库实例角色
505 pg_seq PG_IDENTITY int I PG数据库实例序号
506 pg_instances PG_IDENTITY {port:ins} I 当前节点上的所有PG实例
507 pg_upstream PG_IDENTITY string I 实例的复制上游节点
508 pg_offline_query PG_IDENTITY bool I 是否允许离线查询
509 pg_backup PG_IDENTITY bool I 是否在实例上存储备份
510 pg_weight PG_IDENTITY int I 实例在负载均衡中的相对权重
511 pg_hostname PG_IDENTITY bool C/I 将PG实例名称设为HOSTNAME
512 pg_preflight_skip PG_IDENTITY bool C/A 跳过PG身份参数校验
520 pg_users PG_BUSINESS user[] C 业务用户定义
521 pg_databases PG_BUSINESS database[] C 业务数据库定义
522 pg_services_extra PG_BUSINESS service[] C 集群专有服务定义
523 pg_hba_rules_extra PG_BUSINESS rule[] C 集群/实例特定的HBA规则
524 pgbouncer_hba_rules_extra PG_BUSINESS rule[] C Pgbounce特定HBA规则
525 pg_admin_username PG_BUSINESS string G PG管理用户
526 pg_admin_password PG_BUSINESS string G PG管理用户密码
527 pg_replication_username PG_BUSINESS string G PG复制用户
528 pg_replication_password PG_BUSINESS string G PG复制用户的密码
529 pg_monitor_username PG_BUSINESS string G PG监控用户
530 pg_monitor_password PG_BUSINESS string G PG监控用户密码
540 pg_dbsu PG_INSTALL string C PG操作系统超级用户
541 pg_dbsu_uid PG_INSTALL int C 超级用户UID
542 pg_dbsu_sudo PG_INSTALL enum C 超级用户的Sudo权限
543 pg_dbsu_home PG_INSTALL path C 超级用户的家目录
544 pg_dbsu_ssh_exchange PG_INSTALL bool C 是否交换超级用户密钥
545 pg_version PG_INSTALL int C 安装的数据库大版本
546 pgdg_repo PG_INSTALL bool C 是否添加PG官方源?
547 pg_add_repo PG_INSTALL bool C 是否添加PG相关上游源?
548 pg_bin_dir PG_INSTALL path C PG二进制目录
549 pg_packages PG_INSTALL string[] C 安装的PG软件包列表
550 pg_extensions PG_INSTALL string[] C 安装的PG插件列表
560 pg_safeguard PG_BOOTSTRAP bool C/A 彻底禁止清除存在的PG实例
561 pg_clean PG_BOOTSTRAP bool C/A 允许初始化时清除现存PG
562 pg_data PG_BOOTSTRAP path C PG数据目录
563 pg_fs_main PG_BOOTSTRAP path C PG主数据盘挂载点
564 pg_fs_bkup PG_BOOTSTRAP path C PG备份盘挂载点
565 pg_dummy_filesize PG_BOOTSTRAP size C 占位文件/pg/dummy的大小
566 pg_listen PG_BOOTSTRAP ip C PG监听的IP地址
567 pg_port PG_BOOTSTRAP int C PG监听的端口
568 pg_localhost PG_BOOTSTRAP ip path C
580 patroni_enabled PG_BOOTSTRAP bool C Patroni是否启用
581 patroni_mode PG_BOOTSTRAP enum C Patroni配置模式
582 pg_dcs_type PG_BOOTSTRAP enum G PG使用的DCS类型
583 pg_namespace PG_BOOTSTRAP path C Patroni使用的DCS命名空间
584 patroni_port PG_BOOTSTRAP int C Patroni服务端口
585 patroni_watchdog_mode PG_BOOTSTRAP enum C Patroni Watchdog模式
586 pg_conf PG_BOOTSTRAP string C Patroni使用的配置模板
587 pg_libs PG_BOOTSTRAP string C PG默认加载的共享库
588 pg_delay PG_BOOTSTRAP interval I 应用复制延迟至备份集群主库
589 pg_checksum PG_BOOTSTRAP bool C 启用数据校验和
590 pg_encoding PG_BOOTSTRAP enum C PG字符集编码
591 pg_locale PG_BOOTSTRAP enum C PG使用的本地化规则
592 pg_lc_collate PG_BOOTSTRAP enum C PG使用的本地化排序规则
593 pg_lc_ctype PG_BOOTSTRAP enum C PG使用的本地化字符集定义
594 pgbouncer_enabled PG_BOOTSTRAP bool C 是否启用Pgbouncer
595 pgbouncer_port PG_BOOTSTRAP int C Pgbouncer端口
596 pgbouncer_poolmode PG_BOOTSTRAP enum C Pgbouncer池化模式
597 pgbouncer_max_db_conn PG_BOOTSTRAP int C Pgbouncer最大单DB连接数
600 pg_provision PG_PROVISION bool C 是否在PG集群中应用模板
601 pg_init PG_PROVISION string C 自定义PG初始化脚本
602 pg_default_roles PG_PROVISION role[] G/C 默认创建的角色与用户
603 pg_default_privileges PG_PROVISION string[] G/C 数据库默认权限配置
604 pg_default_schemas PG_PROVISION string[] G/C 默认创建的模式
605 pg_default_extensions PG_PROVISION extension[] G/C 默认安装的扩展
606 pg_reload PG_PROVISION bool A 是否重载数据库配置(HBA)
607 pg_hba_rules PG_PROVISION rule[] G/C 全局HBA规则
608 pgbouncer_hba_rules PG_PROVISION rule[] G/C Pgbouncer全局HBA规则
620 pg_exporter_config PG_EXPORTER string C PG指标定义文件
621 pg_exporter_enabled PG_EXPORTER bool C 启用PG指标收集器
622 pg_exporter_port PG_EXPORTER int C PG指标暴露端口
623 pg_exporter_params PG_EXPORTER string C/I PG Exporter额外的URL参数
624 pg_exporter_url PG_EXPORTER string C/I 采集对象数据库的连接串(覆盖)
625 pg_exporter_auto_discovery PG_EXPORTER bool C/I 是否自动发现实例中的数据库
626 pg_exporter_exclude_database PG_EXPORTER string C/I 数据库自动发现排除列表
627 pg_exporter_include_database PG_EXPORTER string C/I 数据库自动发现囊括列表
628 pg_exporter_options PG_EXPORTER string C/I PG Exporter命令行参数
629 pgbouncer_exporter_enabled PG_EXPORTER bool C 启用PGB指标收集器
630 pgbouncer_exporter_port PG_EXPORTER int C PGB指标暴露端口
631 pgbouncer_exporter_url PG_EXPORTER string C/I 采集对象连接池的连接串
632 pgbouncer_exporter_options PG_EXPORTER string C/I PGB Exporter命令行参数
640 pg_services PG_SERVICE service[] G/C 全局通用服务定义
641 haproxy_enabled PG_SERVICE bool C/I 是否启用Haproxy
642 haproxy_reload PG_SERVICE bool A 是否重载Haproxy配置
643 haproxy_auth_enabled PG_SERVICE bool G/C 是否对Haproxy管理界面启用认证
644 haproxy_admin_username PG_SERVICE string G HAproxy管理员名称
645 haproxy_admin_password PG_SERVICE string G HAproxy管理员密码
646 haproxy_exporter_port PG_SERVICE int C HAproxy指标暴露器端口
647 haproxy_client_timeout PG_SERVICE interval C HAproxy客户端超时
648 haproxy_server_timeout PG_SERVICE interval C HAproxy服务端超时
649 vip_mode PG_SERVICE enum C VIP模式:none
650 vip_reload PG_SERVICE bool A 是否重载VIP配置
651 vip_address PG_SERVICE string C 集群使用的VIP地址
652 vip_cidrmask PG_SERVICE int C VIP地址的网络CIDR掩码长度
653 vip_interface PG_SERVICE string C VIP使用的网卡
654 dns_mode PG_SERVICE enum C DNS配置模式
655 dns_selector PG_SERVICE string C DNS解析对象选择器

PG_IDENTITY

pg_clusterpg_rolepg_seq 属于 身份参数

除IP地址外,这三个参数是定义一套新的数据库集群的最小必须参数集,一个典型案例如下所示。

pg-test:
  hosts:
    10.10.10.11: {pg_seq: 1, pg_role: replica}
    10.10.10.12: {pg_seq: 2, pg_role: primary}
    10.10.10.13: {pg_seq: 3, pg_role: replica}
  vars:
    pg_cluster: pg-test

其他参数都可以继承自全局配置或默认配置,但身份参数必须显式指定手工分配,目前PGSQL身份参数如下:

名称 类型 层级 说明
pg_cluster string C PG数据库集群名称
pg_seq number I PG数据库实例序号
pg_role enum I PG数据库实例角色
pg_shard string C PG数据库分片集簇名 (占位)
pg_sindex number C PG数据库分片集簇号 (占位)
  • pg_cluster 标识了集群的名称,在集群层面进行配置。
  • pg_role 在实例层面进行配置,标识了实例的角色,只有primary角色会进行特殊处理,如果不填,默认为replica角色,此外,还有特殊的delayedoffline角色。
  • pg_seq 用于在集群内标识实例,通常采用从0或1开始递增的整数,一旦分配不再更改。
  • {{ pg_cluster }}-{{ pg_seq }} 被用于唯一标识实例,即pg_instance
  • {{ pg_cluster }}-{{ pg_role }} 用于标识集群内的服务,即pg_service
  • pg_shardpg_sindex 用于水平分片集群,为Citus与Greenplum多集群管理预留。

pg_cluster

PG数据库集群名称,类型:string,层级:集群,没有默认值。必选参数,必须由用户提供

集群名将用作集群内资源的命名空间,命名需要遵循特定命名规则:[a-z][a-z0-9-]*,以兼容不同约束对身份标识的要求。

pg_shard

PG集群所属的Shard (保留), 类型:string,层级:集群,没有默认值,可选参数。

只有分片集群需要设置此参数。当多个数据库集群以水平分片的方式共同服务于同一个 业务时,Pigsty将这一组集群称为 分片集簇(Sharding Cluster)pg_shard是数据库集群所属分片集簇的名称,一个分片集簇可以指定任意名称,但Pigsty建议采用具有意义的命名规则。

例如参与分片集簇的集群,可以使用 分片集簇名 pg_shard + shard + 集群所属分片编号pg_sindex构成集群名称:

shard:  test
pg-testshard1
pg-testshard2
pg-testshard3
pg-testshard4

pg_sindex

PG集群的分片号 (保留), 类型:int,层级:C,无默认值。

集群在分片集簇中的编号,与 pg_shard 配合使用通常从0或1开始依次分配。只有分片集群需要设置此参数。

gp_role

当前PG集群在GP中的角色, 类型:enum,层级:C,默认值为:

Greenplum/MatrixDB 专用,用于指定GP部署中,此PG集群扮演的角色,可选值为:

  • master : 协调者节点
  • segment : 数据节点

身份参数集群级参数,当部署GPSQL时为必选参数

pg_role

PG数据库实例角色, 类型:enum,层级:I,无默认值,必选参数,必须由用户提供

数据库实例的角色,默认角色包括:primary, replica, offline

  • primary: 集群主库,集群中必须有一个且只能有一个成员为primary
  • replica: 集群从库,用于承担在线只读流量。
  • offline: 集群离线从库,用于承担离线只读流量,例如统计分析/ETL/个人查询等。

身份参数,必填参数,实例级参数

pg_seq

PG数据库实例序号, 类型:int,层级:I,无默认值,必选参数,必须由用户提供

数据库实例的序号,在集群内部唯一,用于区别与标识集群内的不同实例,从0或1开始分配。

pg_instances

当前节点上的所有PG实例, 类型:{port:ins},层级:I,默认值为:

当节点上部署由超过一个PG实例时,例如Greenplum的Segments,或使用仅监控模式监管已有实例,可使用此参数描述。 pg_instances 是一个对象数组,键为实例端口,值为一个字典,内容可以是任意PGSQL板块的参数,详情请参考 MatrixDB部署

pg_upstream

实例的复制上游节点, 类型:string,层级:I,默认值为空。

实例级配置项,内容为IP地址或主机名,用于指明流复制上游节点。

  • 当为集群的从库配置该参数时,填入的IP地址必须为集群内的其他节点。实例会从该节点进行流复制,此选项可用于构建级连复制

  • 当为集群的主库配置该参数时,意味着整个集群将以 备集群(Standby Cluster) 的形式运行,从上游节点接受变更。集群中的primary将扮演standby leader 的角色。

灵活使用此参数的能力,可以搭建异地灾备的集群,完成分片集群的分裂,实现延时从库。

pg_offline_query

是否允许离线查询, 类型:bool,层级:I,默认值为:false

设置为true时,无论当前实例的角色为何,用户组dbrole_offline都可以连接至该实例并执行离线查询。

对于实例数量较少(例如一主一从)的情况较为实用,用户可以将唯一的从库标记为pg_offline_query = true,从而接受ETL,慢查询与交互式访问。

pg_backup

是否在实例上存储冷备份, 类型:bool,层级:I,默认值为:false

未实现,保留标记位,带有该标记的实例节点会用于存储基础冷备份。

pg_weight

实例在负载均衡中的相对权重, 类型:int,层级:I,默认值为:100

当您希望调整实例在服务中的相对权重时,可在实例层次修改此参数,并按 SOP:集群流量调整 中介绍的方法应用生效。

pg_hostname

将PG实例名称设为HOSTNAME, 类型:bool,层级:C/I,默认值为:true

是否在初始化节点时,将PostgreSQL的实例名与集群名一并用作节点的名称与集群名,v1.5.1 随附配置中默认启用。

当采用 节点:PG 1:1 独占部署模式时,您可以将PG实例的身份赋予节点,保持节点与PG的监控身份一致。

pg_preflight_skip

跳过PG身份参数校验, 类型:bool,层级:C/A,默认值为:false

如果您不希望初始化新的数据库集群(例如与已有实例打交道时),则可以通过此参数完整跳过Patroni与Postgres初始化的任务。


PG_BUSINESS

用户需重点关注此部分参数,因为这里是业务声明自己所需数据库对象的地方。

定制集群模板:用户,数据库,服务,权限规则。

特殊的数据库用户,强烈建议在生产环境中修改这些用户的密码。

pg_users

业务用户定义, 类型:user[],层级:C,默认值为空数组。

用于在数据库集群层面定义业务用户,数组中的每一个对象定义了一个用户或角色,一个完整的用户定义如下:

pg_users:                           # define business users/roles on this cluster, array of user definition
  # define admin user for meta database (This user are used for pigsty app deployment by default)
  - name: dbuser_meta               # required, `name` is the only mandatory field of a user definition
    password: md5d3d10d8cad606308bdb180148bf663e1  # md5 salted password of 'DBUser.Meta'
    # optional, plain text and md5 password are both acceptable (prefixed with `md5`)
    login: true                     # optional, can login, true by default  (new biz ROLE should be false)
    superuser: false                # optional, is superuser? false by default
    createdb: false                 # optional, can create database? false by default
    createrole: false               # optional, can create role? false by default
    inherit: true                   # optional, can this role use inherited privileges? true by default
    replication: false              # optional, can this role do replication? false by default
    bypassrls: false                # optional, can this role bypass row level security? false by default
    pgbouncer: true                 # optional, add this user to pgbouncer user-list? false by default (production user should be true explicitly)
    connlimit: -1                   # optional, user connection limit, default -1 disable limit
    expire_in: 3650                 # optional, now + n days when this role is expired (OVERWRITE expire_at)
    expire_at: '2030-12-31'         # optional, YYYY-MM-DD 'timestamp' when this role is expired  (OVERWRITTEN by expire_in)
    comment: pigsty admin user      # optional, comment string for this user/role
    roles: [dbrole_admin]           # optional, belonged roles. default roles are: dbrole_{admin,readonly,readwrite,offline}
    parameters:                     # optional, role level parameters with `ALTER ROLE SET`
      log_min_duration_statements: 1000
    search_path: public         # key value config parameters according to postgresql documentation (e.g: use pigsty as default search_path)
  - {name: dbuser_view , password: DBUser.Viewer  ,pgbouncer: true ,roles: [dbrole_readonly], comment: read-only viewer for meta database}

  # define additional business users for prometheus & grafana (optional)
  - {name: dbuser_grafana    , password: DBUser.Grafana    ,pgbouncer: true ,roles: [dbrole_admin], comment: admin user for grafana database }
  - {name: dbuser_prometheus , password: DBUser.Prometheus ,pgbouncer: true ,roles: [dbrole_admin], comment: admin user for prometheus database }
  • 每一个用户或角色必须指定 name ,其余字段均为可选项name必须在此列表中唯一。
  • password是可选项,如果留空则不设置密码,可以使用MD5密文密码。
  • login, superuser, createdb, createrole, inherit, replication, bypassrls 都是布尔类型,用于设置用户属性。如果不设置,则采用系统默认值。
  • 用户通过CREATE USER创建,所以默认具有login属性,如果创建的是角色,需要指定login: false
  • expire_atexpire_in用于控制用户过期时间,expire_at使用形如YYYY-mm-DD的日期时间戳。expire_in使用从现在开始的过期天数,如果expire_in存在则会覆盖expire_at选项。
  • 新用户默认不会添加至Pgbouncer用户列表中,必须显式定义pgbouncer: true,该用户才会被加入到Pgbouncer用户列表。
  • 用户/角色会按顺序创建,后面定义的用户可以属于前面定义的角色。
  • 用户可以通过roles字段为业务用户添加默认权限组:
    • dbrole_readonly:默认生产只读用户,具有全局只读权限。(只读生产访问)
    • dbrole_offline:默认离线只读用户,在特定实例上具有只读权限。(离线查询,个人账号,ETL)
    • dbrole_readwrite:默认生产读写用户,具有全局CRUD权限。(常规生产使用)
    • dbrole_admin:默认生产管理用户,具有执行DDL变更的权限。(管理员)

应当为生产账号配置 pgbouncer: true,允许其通过连接池访问,普通用户不应当通过连接池访问数据库。

pg_databases

业务数据库定义, 类型:database[],层级:C,默认值为空数组。

用于在数据库集群层面定义业务用户,数组中的每一个对象定义了一个业务数据库,一个完整的数据库定义如下:

pg_databases:                       # define business databases on this cluster, array of database definition
  # define the default `meta` database
  - name: meta                      # required, `name` is the only mandatory field of a database definition
    baseline: cmdb.sql              # optional, database sql baseline path, (relative path among ansible search path, e.g files/)
    owner: postgres                 # optional, database owner, postgres by default
    template: template1             # optional, which template to use, template1 by default
    encoding: UTF8                  # optional, database encoding, UTF8 by default. (MUST same as template database)
    locale: C                       # optional, database locale, C by default.  (MUST same as template database)
    lc_collate: C                   # optional, database collate, C by default. (MUST same as template database)
    lc_ctype: C                     # optional, database ctype, C by default.   (MUST same as template database)
    tablespace: pg_default          # optional, default tablespace, 'pg_default' by default.
    allowconn: true                 # optional, allow connection, true by default. false will disable connect at all
    revokeconn: false               # optional, revoke public connection privilege. false by default. (leave connect with grant option to owner)
    pgbouncer: true                 # optional, add this database to pgbouncer database list? true by default
    comment: pigsty meta database   # optional, comment string for this database
    connlimit: -1                   # optional, database connection limit, default -1 disable limit
    schemas: [pigsty]               # optional, additional schemas to be created, array of schema names
    extensions:                     # optional, additional extensions to be installed: array of schema definition `{name,schema}`
      - {name: adminpack, schema: pg_catalog}    # install adminpack to pg_catalog and install postgis to public
      - {name: postgis, schema: public}          # if schema is omitted, extension will be installed according to search_path.

每个数据库定义中,数据库名称 name 为必选项,其余均为可选项。

  • name:数据库名称,必选项
  • owner:数据库属主,默认为postgres
  • template:数据库创建时使用的模板,默认为template1
  • encoding:数据库默认字符编码,默认为UTF8,默认与实例保持一致。建议不要配置与修改。
  • locale:数据库默认的本地化规则,默认为C,建议不要配置,与实例保持一致。
  • lc_collate:数据库默认的本地化字符串排序规则,默认与实例设置相同,建议不要修改,必须与模板数据库一致。强烈建议不要配置,或配置为C
  • lc_ctype:数据库默认的LOCALE,默认与实例设置相同,建议不要修改或设置,必须与模板数据库一致。建议配置为C或en_US.UTF8
  • allowconn:是否允许连接至数据库,默认为true,不建议修改。
  • revokeconn:是否回收连接至数据库的权限?默认为false。如果为true,则数据库上的PUBLIC CONNECT权限会被回收。只有默认用户(dbsu|monitor|admin|replicator|owner)可以连接。此外,admin|owner 会拥有GRANT OPTION,可以赋予其他用户连接权限。
  • tablespace:数据库关联的表空间,默认为pg_default
  • connlimit:数据库连接数限制,默认为-1,即没有限制。
  • extensions:对象数组 ,每一个对象定义了一个数据库中的扩展,以及其安装的模式
  • parameters:KV对象,每一个KV定义了一个需要针对数据库通过ALTER DATABASE修改的参数。
  • pgbouncer:布尔选项,是否将该数据库加入到Pgbouncer中。所有数据库都会加入至Pgbouncer,除非显式指定pgbouncer: false
  • comment:数据库备注信息。

pg_services_extra

集群专有服务定义, 类型:service[],层级:C,默认值为:

用于在数据库集群层面定义额外的服务,数组中的每一个对象定义了一个服务,一个完整的服务定义如下:

- name: default           # service's actual name is {{ pg_cluster }}-{{ service.name }}
  src_ip: "*"             # service bind ip address, * for all, vip for cluster virtual ip address
  src_port: 5436          # bind port, mandatory
  dst_port: postgres      # target port: postgres|pgbouncer|port_number , pgbouncer(6432) by default
  check_method: http      # health check method: only http is available for now
  check_port: patroni     # health check port:  patroni|pg_exporter|port_number , patroni by default
  check_url: /primary     # health check url path, / as default
  check_code: 200         # health check http code, 200 as default
  selector: "[]"          # instance selector
  haproxy:                # haproxy specific fields
    maxconn: 3000         # default front-end connection
    balance: roundrobin   # load balance algorithm (roundrobin by default)
    default_server_options: 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'

每一个集群都可以定义多个服务,每个服务包含任意数量的集群成员,服务通过端口进行区分,namesrc_port为必选项,且必须在数组内唯一。

必选项目

  • 名称(service.name

    服务名称,服务的完整名称以数据库集群名为前缀,以service.name为后缀,通过-连接。例如在pg-test集群中name=primary的服务,其完整服务名称为pg-test-primary

  • 端口(service.port

    在Pigsty中,服务默认采用NodePort的形式对外暴露,因此暴露端口为必选项。但如果使用外部负载均衡服务接入方案,您也可以通过其他的方式区分服务。

  • 选择器(service.selector

    选择器指定了服务的实例成员,采用JMESPath的形式,从所有集群实例成员中筛选变量。默认的[]选择器会选取所有的集群成员。

可选项目

  • 备份选择器(service.selector

    可选的 备份选择器service.selector_backup会选择或标记用于服务备份的实例列表,即集群中所有其他成员失效时,备份实例才接管服务。例如可以将primary实例加入replica服务的备选集中,当所有从库失效后主库依然可以承载集群的只读流量。

  • 源端IP(service.src_ip

    表示服务对外使用的IP地址,默认为*,即本机所有IP地址。使用vip则会使用vip_address变量取值,或者也可以填入网卡支持的特定IP地址。

  • 宿端口(service.dst_port

    服务的流量将指向目标实例上的哪个端口?postgres 会指向数据库监听的端口,pgbouncer会指向连接池所监听的端口,也可以填入固定的端口号。

  • 健康检查方式(service.check_method:

    服务如何检查实例的健康状态?目前仅支持HTTP

  • 健康检查端口(service.check_port:

    服务检查实例的哪个端口获取实例的健康状态? patroni会从Patroni(默认8008)获取,pg_exporter会从PG Exporter(默认9630)获取,用户也可以填入自定义的端口号。

  • 健康检查路径(service.check_url:

    服务执行HTTP检查时,使用的URL PATH。默认会使用/作为健康检查,PG Exporter与Patroni提供了多样的健康检查方式,可以用于主从流量区分。例如,/primary仅会对主库返回成功,/replica仅会对从库返回成功。/read-only则会对任何支持只读的实例(包括主库)返回成功。

  • 健康检查代码(service.check_code:

    HTTP健康检查所期待的代码,默认为200

  • Haproxy特定配置(service.haproxy

    关于服务供应软件(HAproxy)的专有配置项

    • <service>.haproxy

    这些参数现在服务中定义,使用service.haproxy来覆盖实例的参数配置。

    • maxconn

    HAProxy最大前后端连接数,默认为3000

    • balance

    haproxy负载均衡所使用的算法,可选策略为roundrobinleastconn,默认为roundrobin

    • default_server_options

    Haproxy 后端服务器实例的默认选项

    默认为: 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'

pg_hba_rules_extra

集群/实例特定的HBA规则, 类型:rule[],层级:C,默认值为:

设置数据库的客户端IP黑白名单规则。对象数组,每一个对象都代表一条规则,每一条规则由三部分组成:

  • title,规则标题,会转换为HBA文件中的注释
  • role,应用角色,common代表应用至所有实例,其他取值(如replica, offline)则仅会安装至匹配的角色上。例如role='replica'代表这条规则只会应用到pg_role == 'replica' 的实例上。
  • rules,字符串数组,每一条记录代表一条最终写入pg_hba.conf的规则。

作为一个特例,role == 'offline' 的HBA规则,还会额外安装至 pg_offline_query == true 的实例上。

pg_hba_rules 与之类似,但通常用于全局统一的HBA规则设置,pg_hba_rules_extra 会以同样的方式 追加pg_hba.conf中。

如果用户需要彻底覆写集群的HBA规则,即不想继承全局HBA配置,则应当在集群层面配置 pg_hba_rules 并覆盖全局配置。

pgbouncer_hba_rules_extra

Pgbounce特定HBA规则, 类型:rule[],层级:C,默认值为空数组。

pg_hba_rules_extra类似,用于在集群层次对Pgbouncer的HBA规则进行额外配置。

pg_admin_username

PG管理用户, 类型:string,层级:G,默认值为:"dbuser_dba"

用于执行PostgreSQL数据库管理任务(DDL变更)的数据库用户名,默认带有超级用户权限。

pg_admin_password

PG管理用户密码, 类型:string,层级:G,默认值为:"DBUser.DBA"

用于执行PostgreSQL数据库管理任务(DDL变更)的数据库用户密码,必须使用明文,默认为DBUser.DBA,强烈建议修改!

在生产环境部署时,强烈建议修改此参数!

pg_replication_username

PG复制用户, 类型:string,层级:G,默认值为:"replicator"

用于执行PostgreSQL流复制,建议在全局保持一致。

pg_replication_password

PG复制用户的密码, 类型:string,层级:G,默认值为:"DBUser.Replicator"

用于执行PostgreSQL流复制的数据库用户密码,必须使用明文。默认为DBUser.Replicator

在生产环境部署时,强烈建议修改此参数!

pg_monitor_username

PG监控用户, 类型:string,层级:G,默认值为:"dbuser_monitor"

用于执行PostgreSQL与Pgbouncer监控任务的数据库用户名

pg_monitor_password

PG监控用户密码, 类型:string,层级:G,默认值为:"DBUser.Monitor"

用于执行PostgreSQL与Pgbouncer监控任务的数据库用户密码,必须使用明文。

在生产环境部署时,强烈建议修改此参数。


PG_INSTALL

PG Install 部分负责在一台装有基本软件的机器上完成所有PostgreSQL依赖项的安装。用户可以配置数据库超级用户的名称、ID、权限、访问,配置安装所用的源,配置安装地址,安装的版本,所需的软件包与扩展插件。

这里的大多数参数只需要在整体升级数据库大版本时修改,用户可以通过 pg_version指定需要安装的软件版本,并在集群层面进行覆盖,为不同的集群安装不同的数据库版本。

pg_dbsu

PG操作系统超级用户, 类型:string,层级:C,默认值为:"postgres"

数据库默认使用的操作系统用户(超级用户)的用户名称,默认为postgres,通常不建议修改。 当安装 Greenplum / MatrixDB 时,建议修改本参数为对应推荐值:gpadmin|mxadmin

pg_dbsu_uid

超级用户UID, 类型:int,层级:C,默认值为:26

数据库默认使用的操作系统用户(超级用户)的UID。默认值为26,与CentOS下PostgreSQL官方RPM包配置一致,不建议修改。

pg_dbsu_sudo

超级用户的Sudo权限, 类型:enum,层级:C,默认值为:"limit"

  • none:没有sudo权限
  • limit:有限的sudo权限,可以执行数据库相关组件的systemctl命令,默认
  • all:带有完整sudo权限,但需要密码。
  • nopass:不需要密码的完整sudo权限(不建议)

数据库超级用户 pg_dbsu 的默认权限为受限的sudo权限:limit

pg_dbsu_home

超级用户的家目录, 类型:path,层级:C,默认值为:"/var/lib/pgsql"

数据库超级用户pg_dbsu的家目录,默认为/var/lib/pgsql

pg_dbsu_ssh_exchange

是否交换超级用户密钥, 类型:bool,层级:C,默认值为:true

是否在执行的机器之间交换 pg_dbsu 的SSH公私钥。

pg_version

安装的数据库大版本, 类型:int,层级:C,默认值为:14

当前实例安装的PostgreSQL大版本号,默认为14,最低支持至10。

请注意,PostgreSQL的物理流复制无法跨越大版本,请在全局/集群层面配置此变量,确保整个集群内所有实例都有着相同的大版本号。

pgdg_repo

是否添加PG官方源?, 类型:bool,层级:C,默认值为:false

标记,是否使用PostgreSQL官方源?默认不使用。使用该选项,可以在没有本地源的情况下,直接从互联网官方源下载安装PostgreSQL相关软件包。

pg_add_repo

是否添加PG相关上游源?, 类型:bool,层级:C,默认值为:false

如果使用,则会在安装PostgreSQL前添加PGDG的官方源。

pg_bin_dir

PG二进制目录, 类型:path,层级:C,默认值为:"/usr/pgsql/bin"

默认为/usr/pgsql/bin/,这是一个安装过程中手动创建的软连接,指向安装的具体Postgres版本目录。

例如/usr/pgsql -> /usr/pgsql-14。详情请参考 FHS

pg_packages

安装的PG软件包列表, 类型:string[],层级:C,默认值为:

- postgresql${pg_version}*
- postgis32_${pg_version}*
- citus_${pg_version}*
- timescaledb-2-postgresql-${pg_version}
- pgbouncer pg_exporter pgbadger pg_activity node_exporter consul haproxy vip-manager
- patroni patroni-consul patroni-etcd python3 python3-psycopg2 python36-requests python3-etcd
- python3-consul python36-urllib3 python36-idna python36-pyOpenSSL python36-cryptography

软件包中的${pg_version}会被替换为实际安装的PostgreSQL版本 pg_version

当您为某一个特定集群指定特殊的 pg_version 时,可以相应在集群层面调整此参数(例如安装PG14 beta时某些扩展还不存在)

pg_extensions

安装的PG插件列表, 类型:string[],层级:C,默认值为:

pg_repack_${pg_version}
pg_qualstats_${pg_version}
pg_stat_kcache_${pg_version}
pg_stat_monitor_${pg_version}
wal2json_${pg_version}"

软件包中的${pg_version}会被替换为实际安装的PostgreSQL大版本号 pg_version


PG_BOOTSTRAP

在一台安装完Postgres的机器上,创建并拉起一套数据库。

  • 集群身份定义,清理现有实例,创建目录结构,拷贝工具与脚本,配置环境变量
  • 渲染Patroni模板配置文件,使用Patroni拉起主库,使用Patroni拉起从库
  • 配置Pgbouncer,初始化业务用户与数据库,将数据库与数据源服务注册至DCS。

通过 pg_conf 可以使用默认的数据库集群模板(普通事务型 OLTP/普通分析型 OLAP/核心金融型 CRIT/微型虚机 TINY)。如果希望创建自定义的模板,可以在roles/postgres/templates中克隆默认配置并自行修改后采用,详情请参考:定制PGSQL集群

pg_safeguard

安全保险,禁止清除存在的PostgreSQL实例, 类型:bool,层级:C/A,默认值为:false

如果为true,任何情况下,Pigsty剧本都不会移除运行中的PostgreSQL实例,包括 pgsql-remove.yml

详情请参考 保护机制

pg_clean

是否抹除运行中的 PostgreSQL 实例?类型:bool,层级:C/A。角色兜底值为 false,但 v1.5.1 随附的沙箱 pigsty.yml 设置为 true;受保护环境应设为 false 并启用 pg_safeguard

针对 pgsql.yml 剧本的抹除豁免,如果指定该参数为真,那么在 pgsql.yml 剧本执行时,会自动抹除已有的PostgreSQL实例

这是一个危险的操作,因此必须显式指定。

当安全保险参数 pg_safeguard 打开时,本参数无效。

pg_data

PostgreSQL数据目录, 类型:path,层级:C,默认值为:"/pg/data",不建议更改。

pg_fs_main

PostgreSQL主数据盘挂载点, 类型:path,层级:C,默认值为:"/data"

主数据盘目录,默认为/data,Pigsty的默认目录结构假设系统中存在一个主数据盘挂载点,用于盛放数据库目录与其他状态。

pg_fs_bkup

PostgreSQL备份盘挂载点, 类型:path,层级:C,默认值为:"/data/backups"

Pigsty的默认目录结构假设系统中存在一个备份数据盘挂载点,用于盛放备份与归档数据。备份盘并不是必选项,如果系统中不存在备份盘,用户也可以指定一个主数据盘上的子目录作为备份盘根目录挂载点。

pg_dummy_filesize

占位文件/pg/dummy的大小, 类型:size,层级:C,默认值为:"64MiB"

占位文件是一个预分配的空文件,占据一定量的磁盘空间。当出现磁盘满故障时,移除该占位文件可以紧急释放一些磁盘空间应急使用,生产环境建议使用4GiB8GiB

pg_listen

PG监听的IP地址, 类型:ip,层级:C,默认值为:"0.0.0.0"

数据库监听的IP地址,默认为所有IPv4地址0.0.0.0,如果要包括所有IPv6地址,可以使用*

pg_port

PG监听的端口, 类型:int,层级:C,默认值为:5432,不建议修改。

pg_localhost

PG使用的UnixSocket地址, 类型:ip|path,层级:C,默认值为:"/var/run/postgresql"

Unix Socket目录用于盛放PostgreSQL与Pgbouncer的Unix socket文件,当客户端未指定IP地址访问数据库时,会通过本地Unix Socket访问,默认为/var/run/postgresql

patroni_enabled

Patroni是否启用, 类型:bool,层级:C,默认值为:true

布尔类型,标记位,默认为真,是否启用 Patroni (与Postgres)?如果为假,那么Pigsty将直接跳过Patroni与Postgres拉起的流程。该选项通常在接入已有实例时使用。

patroni_mode

Patroni配置模式, 类型:enum,层级:C,默认值为:"default"

  • default: 正常启用Patroni,并进入高可用自动切换模式。
  • pause: 启用Patroni,但在完成初始化后自动进入维护模式(不自动执行主从切换)
  • remove: 依然使用Patroni初始化集群,但初始化完成后移除Patroni

pg_dcs_type

PG高可用使用的DCS类型, 类型: enum, 层级: G, 默认值为: "consul".

有两种可用的DCS类型:consuletcd,默认为Consul,对应的DCS类型consul_enabledetcd_enabled 需要在Pigsty全局配置启用。

pg_namespace

Patroni使用的DCS命名空间, 类型:path,层级:C,默认值为:"/pg"

patroni_port

Patroni服务端口, 类型:int,层级:C,默认值为:8008

Patroni API服务器默认监听并对外暴露服务与健康检查的端口。

patroni_watchdog_mode

Patroni Watchdog模式, 类型:enum,层级:C,默认值为:"automatic"

当发生主从切换时,Patroni会尝试在提升从库前关闭主库。如果指定超时时间内主库仍未成功关闭,Patroni会根据配置使用Linux内核模块softdog进行fencing关机。

  • off:不使用watchdog
  • automatic:如果内核启用了softdog,则启用watchdog,不强制,默认行为。
  • required:强制使用watchdog,如果系统未启用softdog则拒绝启动。

启用Watchdog意味着系统会优先确保数据一致性,而放弃可用性,如果您的系统更重视可用性,则可以关闭Watchdog,建议关闭元节点上的Watchdog。

pg_conf

Patroni使用的配置模板, 类型:string,层级:C,默认值为:"tiny.yml"

拉起Postgres集群所用的Patroni模板。Pigsty预制了4种模板

  • oltp.yml 常规OLTP模板,默认配置
  • olap.yml OLAP模板,提高并行度,针对吞吐量优化,针对长时间运行的查询进行优化。
  • crit.yml) 核心业务模板,基于OLTP模板针对安全性,数据完整性进行优化,采用同步复制,强制启用数据校验和。
  • tiny.yml 微型数据库模板,针对低资源场景进行优化,例如运行于虚拟机中的演示数据库集群。

pg_libs

PG默认加载的共享库, 类型:string,层级:C,默认值为:"timescaledb, pg_stat_statements, auto_explain"

填入Patroni模板中shared_preload_libraries参数的字符串,控制PG启动预加载的动态库。在当前版本中,默认会加载以下库:timescaledb, pg_stat_statements, auto_explain

如果您希望默认启用Citus支持,则需要修改该参数,将 citus 添加至首位:citus, timescaledb, pg_stat_statements, auto_explain

pg_delay

搭建延时从库集群时的延迟时长,类型:interval,层级:I,默认值为:0

延迟从库指定一个具体的延迟时长,只可在Standby Cluster初始化时指定。

pg_checksum

是否启用数据校验和, 类型:bool,层级:C,默认值为:"false"

当使用核心库模板 crit 时,数据校验和无法配置,强制打开,其他情况请按需启用。

pg_encoding

PG字符集编码, 类型:enum,层级:C,默认值为:"UTF8"。如无特殊需求,不建议修改此参数。

pg_locale

PG使用的本地化规则, 类型:enum,层级:C,默认值为:"C"

如无特殊需求,不建议修改此参数,不当的排序规则可能对数据库性能产生显著影响。

pg_lc_collate

PG使用的本地化排序规则, 类型:enum,层级:C,默认值为:"C"

默认为C,如无特殊需求,,强烈不建议修改此参数。用户总是可以通过COLLATE表达式实现本地化排序相关功能,错误的本地化排序规则可能导致某些操作产生成倍的性能损失,请在真的有本地化需求的情况下修改此参数。

pg_lc_ctype

PG使用的本地化字符集定义, 类型:enum,层级:C,默认值为:"en_US.UTF8"

默认为en_US.UTF8,因为一些PG扩展(pg_trgm)需要额外的字符分类定义才可以针对国际化字符正常工作,因此Pigsty默认会使用en_US.UTF8字符集定义,不建议修改此参数。

pgbouncer_enabled

是否启用Pgbouncer, 类型:bool,层级:C,默认值为:true

pgbouncer_port

Pgbouncer端口, 类型:int,层级:C,默认值为:6432

pgbouncer_poolmode

Pgbouncer池化模式, 类型:enum,层级:C,默认值为:"transaction"

  • transaction,事务级连接池,默认,性能好,但影响 PreparedStatements 与其他一些会话级功能的使用。
  • session,会话级连接池,兼容性最强。
  • statements,语句级连接池,若您的查询均为点查,可以考虑使用此模式。

pgbouncer_max_db_conn

Pgbouncer最大单DB连接数, 类型:int,层级:C,默认值为:100

允许连接池与单个数据库之间建立的最大连接数,默认值为100

使用Transaction Pooling模式时,活跃服务端连接数通常处于个位数。如果采用Session Pooling模式,可以适当增大此参数。


PG_PROVISION

PG_BOOTSTRAP负责拉起一套全新的Postgres集群,而PG_PROVISION负责在这套全新的数据库集群中创建默认的对象,包括

  • 基本角色:只读角色,读写角色、管理角色
  • 基本用户:复制用户、超级用户、监控用户、管理用户
  • 模板数据库中的默认权限
  • 默认 模式
  • 默认 扩展
  • HBA黑白名单规则

Pigsty提供了丰富的定制选项,如果您希望进一步客制化PG集群,可以参考 定制:PGSQL集群

pg_provision

是否置备PG集群?(应用模板), 类型:bool,层级:C,默认值为:true

是否对拉起的PostgreSQL集群执行置备任务?设置为假会跳过 PG_TEMPLATE定义的任务。 但注意,数据库超级用户、复制用户、管理用户、监控用户四个默认用户的创建不受此影响。

pg_init

自定义PG初始化脚本, 类型:string,层级:C,默认值为:"pg-init"

用于初始化数据库模板的Shell脚本位置,默认为pg-init,该脚本会被拷贝至/pg/bin/pg-init后执行。

默认的pg-init 只是预渲染SQL命令的包装:

# system default roles
psql postgres -qAXwtf /pg/tmp/pg-init-roles.sql

# system default template
psql template1 -qAXwtf /pg/tmp/pg-init-template.sql

# make postgres same as templated database (optional)
psql postgres  -qAXwtf /pg/tmp/pg-init-template.sql

用户可以在自定义的pg-init脚本中添加自己的集群初始化逻辑。

pg_default_roles

默认创建的角色与用户, 类型:role[],层级:G/C,默认值为:

# - default roles - #
pg_default_roles:
  # default roles
  - { name: dbrole_readonly  , login: false , comment: role for global read-only access  }                            # production read-only role
  - { name: dbrole_readwrite , login: false , roles: [dbrole_readonly], comment: role for global read-write access }  # production read-write role
  - { name: dbrole_offline , login: false , comment: role for restricted read-only access (offline instance) }        # restricted-read-only role
  - { name: dbrole_admin , login: false , roles: [pg_monitor, dbrole_readwrite] , comment: role for object creation }  # production DDL change role

  # default users
  - { name: postgres , superuser: true , comment: system superuser }                             # system dbsu, name is designated by `pg_dbsu`
  - { name: dbuser_dba , superuser: true , roles: [dbrole_admin] , comment: system admin user }  # admin dbsu, name is designated by `pg_admin_username`
  - { name: replicator , replication: true , bypassrls: true , roles: [pg_monitor, dbrole_readonly] , comment: system replicator }                   # replicator
  - { name: dbuser_monitor , roles: [pg_monitor, dbrole_readonly] , comment: system monitor user , parameters: {log_min_duration_statement: 1000 } } # monitor user
  - { name: dbuser_stats , password: DBUser.Stats , roles: [dbrole_offline] , comment: business offline user for offline queries and ETL }           # ETL user

本参数定义了PostgreSQL中的默认角色默认用户,形式为对象数组,对象定义形式与 pg_users 中保持一致。

pg_default_privileges

定义数据库模板中的默认权限, 类型:string[],层级:G/C,默认值为:

pg_default_privileges:
  - GRANT USAGE                         ON SCHEMAS   TO dbrole_readonly
  - GRANT SELECT                        ON TABLES    TO dbrole_readonly
  - GRANT SELECT                        ON SEQUENCES TO dbrole_readonly
  - GRANT EXECUTE                       ON FUNCTIONS TO dbrole_readonly
  - GRANT USAGE                         ON SCHEMAS   TO dbrole_offline
  - GRANT SELECT                        ON TABLES    TO dbrole_offline
  - GRANT SELECT                        ON SEQUENCES TO dbrole_offline
  - GRANT EXECUTE                       ON FUNCTIONS TO dbrole_offline
  - GRANT INSERT, UPDATE, DELETE        ON TABLES    TO dbrole_readwrite
  - GRANT USAGE,  UPDATE                ON SEQUENCES TO dbrole_readwrite
  - GRANT TRUNCATE, REFERENCES, TRIGGER ON TABLES    TO dbrole_admin
  - GRANT CREATE                        ON SCHEMAS   TO dbrole_admin

详细信息请参考 默认权限

pg_default_schemas

默认创建的模式, 类型:string[],层级:G/C,默认值为:[monitor]

Pigsty默认会创建名为monitor的模式用于安装监控扩展。

pg_default_extensions

默认安装于模板数据库的扩展,对象数组,类型为extension[],层级:G/C,默认值为:

pg_default_extensions:
  - { name: 'pg_stat_statements',  schema: 'monitor' }
  - { name: 'pgstattuple',         schema: 'monitor' }
  - { name: 'pg_qualstats',        schema: 'monitor' }
  - { name: 'pg_buffercache',      schema: 'monitor' }
  - { name: 'pageinspect',         schema: 'monitor' }
  - { name: 'pg_prewarm',          schema: 'monitor' }
  - { name: 'pg_visibility',       schema: 'monitor' }
  - { name: 'pg_freespacemap',     schema: 'monitor' }
  - { name: 'pg_repack',           schema: 'monitor' }
  - name: postgres_fdw
  - name: file_fdw
  - name: btree_gist
  - name: btree_gin
  - name: pg_trgm
  - name: intagg
  - name: intarray

如果扩展没有指定schema字段,扩展会根据当前的search_path安装至对应模式中,例如public

pg_reload

是否重载数据库配置(HBA), 类型:bool,层级:A,默认值为:true

设置为true时,Pigsty会在生成HBA规则后立刻执行pg_ctl reload应用。

当您希望生成pg_hba.conf文件,并手工比较后再应用生效时,可以指定-e pg_reload=false来禁用它。

pg_hba_rules

PostgreSQL全局HBA规则, 类型:rule[],层级:G/C,默认值为:

pg_hba_rules:
  - title: allow meta node password access
    role: common
    rules:
      - host    all     all                         10.10.10.10/32      md5

  - title: allow intranet admin password access
    role: common
    rules:
      - host    all     +dbrole_admin               10.0.0.0/8          md5
      - host    all     +dbrole_admin               172.16.0.0/12       md5
      - host    all     +dbrole_admin               192.168.0.0/16      md5

  - title: allow intranet password access
    role: common
    rules:
      - host    all             all                 10.0.0.0/8          md5
      - host    all             all                 172.16.0.0/12       md5
      - host    all             all                 192.168.0.0/16      md5

  - title: allow local read-write access (local production user via pgbouncer)
    role: common
    rules:
      - local   all     +dbrole_readwrite                               md5
      - host    all     +dbrole_readwrite           127.0.0.1/32        md5

  - title: allow read-only user (stats, personal) password directly access
    role: replica
    rules:
      - local   all     +dbrole_readonly                               md5
      - host    all     +dbrole_readonly           127.0.0.1/32        md5

本参数在形式上与 pg_hba_rules_extra 完全一致,建议在全局配置统一的 pg_hba_rules,针对特定集群使用 pg_hba_rules_extra 进行额外定制。两个参数中的规则都会依次应用,后者优先级更高。

pgbouncer_hba_rules

PgbouncerL全局HBA规则, 类型:rule[],层级:G/C,默认值为:

pgbouncer_hba_rules:
  - title: local password access
    role: common
    rules:
      - local  all          all                                     md5
      - host   all          all                     127.0.0.1/32    md5

  - title: intranet password access
    role: common
    rules:
      - host   all          all                     10.0.0.0/8      md5
      - host   all          all                     172.16.0.0/12   md5
      - host   all          all                     192.168.0.0/16  md5

默认的Pgbouncer HBA规则很简单:

  1. 允许从本地使用密码登陆
  2. 允许从内网网断使用密码登陆

用户可以按照自己的需求进行定制。


PG_EXPORTER

PG Exporter 用于监控Postgres数据库与Pgbouncer连接池

pg_exporter_config

PG指标定义配置文件, 类型:string,层级:C,默认值为:"pg_exporter.yml"

pg_exporter使用的默认配置文件,定义了Pigsty中的数据库与连接池监控指标。默认为 pg_exporter.yml

Pigsty使用的PG Exporter配置文件默认从PostgreSQL 10.0 开始提供支持,目前支持至最新的PG 14版本。此外还有一些可选的配置模板:

pg_exporter_enabled

启用PG指标收集器, 类型:bool,层级:C,默认值为:true

是否安装并配置pg_exporter,为false时,将跳过当前节点上 pg_exporter 的配置,并在注册监控目标时跳过此Exporter。

pg_exporter_port

PG指标暴露端口, 类型:int,层级:C,默认值为:9630

pg_exporter_params

PG Exporter额外的URL参数, 类型:string,层级:C/I,默认值为:"sslmode=disable"

pg_exporter_url

采集对象数据库的连接串(覆盖), 类型:string,层级:C/I,默认值为:""

PG Exporter用于连接至数据库的PGURL,应当为访问postgres管理数据库的URL,该选项以环境变量的方式配置于 /etc/default/pg_exporter 中。

可选参数,默认为空字符串,如果配置了 pg_exporter_url 选项,则会直接使用该URL作为监控连接串。否则Pigsty将使用以下规则生成监控的目标URL:

以上参数将按下列方式进行拼接

postgres://{{ pg_monitor_username }}:{{ pg_monitor_password }}@:{{ pg_port }}/postgres{% if pg_exporter_params != '' %}?{{ pg_exporter_params }}{% if pg_localhost != '' %}&host={{ pg_localhost }}{% endif %}{% endif %}

如果指定了pg_exporter_url 参数,则Exporter会直接使用该连接串。

注意:当您只需要监控某一个特定业务数据库时,您可以直接使用该数据库的PGURL。如果您希望监控某一个数据库实例上所有的业务数据库,则建议使用管理数据库postgres的PGURL。

pg_exporter_auto_discovery

是否自动发现实例中的数据库, 类型:bool,层级:C/I,默认值为:true

是否启用自动数据库发现,默认开启。开启后,PG Exporter会自动检测目标实例中数据库列表的变化,并为每一个数据库创建一条抓取连接

关闭时,库内对象监控不可用。(如果您不希望在监控系统中暴露业务相关数据,可以关闭此特性)

警告

注意如果您有很多数据库(100+),或数据库内对象非常多(几k,十几k),请审慎评估对象监控产生的开销。

pg_exporter_exclude_database

数据库自动发现排除列表, 类型:string,层级:C/I,默认值为:"template0,template1,postgres"

逗号分隔的数据库名称列表,启用自动数据库发现时,此列表中的数据库不会被监控(被排除在监控对象之外)。

pg_exporter_include_database

数据库自动发现囊括列表, 类型:string,层级:C/I,默认值为:""

逗号分隔的数据库名称列表,启用自动数据库发现时,不在此列表中的数据库不会被监控(显式指定需要监控的数据库)。

pg_exporter_options

PG Exporter命令行参数, 类型:string,层级:C/I,默认值为:"--log.level=info --log.format=\"logger:syslog?appname=pg_exporter&local=7\""

pgbouncer_exporter_enabled

启用PGB指标收集器, 类型:bool,层级:C,默认值为:true

pgbouncer_exporter_port

PGB指标暴露端口, 类型:int,层级:C,默认值为:9631

pgbouncer_exporter_url

采集对象连接池的连接串, 类型:string,层级:C/I,默认值为:""

PGBouncer Exporter用于连接至数据库的URL,应当为访问pgbouncer管理数据库的URL。可选参数,默认为空字符串。

Pigsty默认使用以下规则生成监控的目标URL,如果配置了pgbouncer_exporter_url选项,则会直接使用该URL作为连接串。

PG_EXPORTER_URL='postgres://{{ pg_monitor_username }}:{{ pg_monitor_password }}@:{{ pgbouncer_port }}/pgbouncer?host={{ pg_localhost }}&sslmode=disable'

该选项以环境变量的方式配置于 /etc/default/pgbouncer_exporter 中。

pgbouncer_exporter_options

PGB Exporter命令行参数, 类型:string,层级:C/I,默认值为:"--log.level=info --log.format=\"logger:syslog?appname=pgbouncer_exporter&local=7\""

即将INFO级日志打入syslog中。


PG_SERVICE

对外暴露PostgreSQL服务,安装负载均衡器 HAProxy,启用VIP,配置DNS。

pg_services

全局通用PG服务定义, 类型:service[],层级:G,默认值为:

pg_services:                     # how to expose postgres service in cluster?
  - name: primary                # service name {{ pg_cluster }}-primary
    src_ip: "*"
    src_port: 5433
    dst_port: pgbouncer          # 5433 route to pgbouncer
    check_url: /primary          # primary health check, success when instance is primary
    selector: "[]"               # select all instance as primary service candidate

  - name: replica                # service name {{ pg_cluster }}-replica
    src_ip: "*"
    src_port: 5434
    dst_port: pgbouncer
    check_url: /read-only        # read-only health check. (including primary)
    selector: "[]"               # select all instance as replica service candidate
    selector_backup: "[? pg_role == `primary` || pg_role == `offline` ]"

  - name: default                # service's actual name is {{ pg_cluster }}-default
    src_ip: "*"                  # service bind ip address, * for all, vip for cluster virtual ip address
    src_port: 5436               # bind port, mandatory
    dst_port: postgres           # target port: postgres|pgbouncer|port_number , pgbouncer(6432) by default
    check_method: http           # health check method: only http is available for now
    check_port: patroni          # health check port:  patroni|pg_exporter|port_number , patroni by default
    check_url: /primary          # health check url path, / as default
    check_code: 200              # health check http code, 200 as default
    selector: "[]"               # instance selector
    haproxy:                     # haproxy specific fields
      maxconn: 3000              # default front-end connection
      balance: roundrobin        # load balance algorithm (roundrobin by default)
      default_server_options: 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'

  - name: offline                # service name {{ pg_cluster }}-offline
    src_ip: "*"
    src_port: 5438
    dst_port: postgres
    check_url: /replica          # offline MUST be a replica
    selector: "[? pg_role == `offline` || pg_offline_query ]"         # instances with pg_role == 'offline' or instance marked with 'pg_offline_query == true'
    selector_backup: "[? pg_role == `replica` && !pg_offline_query]"  # replica are used as backup server in offline service

服务定义对象构成的数组,定义了每一个数据库集群中对外暴露的服务。形式上与 pg_service_extra 保持一致。

haproxy_enabled

是否启用Haproxy, 类型:bool,层级:C/I,默认值为:true

Pigsty默认会在所有数据库节点上部署Haproxy,您可以通过覆盖实例级变量,仅在特定实例/节点上启用Haproxy负载均衡器。

haproxy_reload

是否重载Haproxy配置, 类型:bool,层级:A,默认值为:true

如果关闭,则Pigsty在渲染HAProxy配置文件后不会执行Reload操作,给用户手工介入检查确认的机会。

haproxy_auth_enabled

是否对Haproxy管理界面启用认证, 类型:bool,层级:G/C,默认值为:false

默认不启用,建议在生产环境启用,或在Nginx或其他接入层添加访问控制。

haproxy_admin_username

HAproxy管理员名称, 类型:string,层级:G,默认值为:"admin"

haproxy_admin_password

HAproxy管理员密码, 类型:string,层级:G,默认值为:"pigsty"

haproxy_exporter_port

HAproxy指标暴露器端口, 类型:int,层级:C,默认值为:9101

haproxy_client_timeout

HAproxy客户端超时, 类型:interval,层级:C,默认值为:"24h"

haproxy_server_timeout

HAproxy服务端超时, 类型:interval,层级:C,默认值为:"24h"

vip_mode

VIP模式:none, 类型:enum,层级:C,默认值为:"none"

  • none:不设置VIP,默认选项。
  • l2:配置绑定在主库上的二层VIP(需要所有成员位于同一个二层网络广播域中)
  • l4 :预留值,通过外部L4负载均衡器进行流量分发。(未纳入Pigsty当前实现中)

VIP用于确保读写服务负载均衡器的高可用,当使用L2 VIP时,Pigsty的VIP由vip-manager托管,会绑定在集群主库上。

这意味着您始终可以通过VIP访问集群主库,或者通过VIP访问主库上的负载均衡器(如果主库的压力很大,这样做可能会有性能压力)。

注意,使用二层VIP时,您必须保证VIP候选实例处于同一个二层网络(VLAN、交换机)下。

vip_reload

是否重载VIP配置, 类型:bool,层级:A,默认值为:true

vip_address

集群使用的VIP地址, 类型:string,层级:C,默认值为:

vip_cidrmask

VIP地址的网络CIDR掩码长度, 类型:int,层级:C,默认值为:

vip_interface

VIP使用的网卡, 类型:string,层级:C/I,默认值为:

dns_mode

DNS配置模式(保留参数), 类型:enum,层级:C,默认值为:

dns_selector

DNS解析对象选择器(保留参数), 类型:string,层级:C,默认值为:

30 - 配置:REDIS

从 Pigsty v1.5.1 标签恢复的历史文档。

配置 Redis数据库集群,控制REDIS剧本行为,详情参考Redis部署与监控教程

ID Name Section Type Level Comment
700 redis_cluster REDIS_IDENTITY string C Redis数据库集群名称
701 redis_node REDIS_IDENTITY int I Redis节点序列号
702 redis_instances REDIS_IDENTITY instance[] I Redis实例定义
723 redis_fs_main REDIS_NODE path C Redis主数据盘挂载点
741 redis_exporter_enabled REDIS_NODE bool C 是否启用Redis Exporter
742 redis_exporter_port REDIS_NODE int C Redis Exporter监听端口
743 redis_exporter_options REDIS_NODE string C/I Redis Exporter命令参数
726 redis_safeguard REDIS_PROVISION bool C 禁止抹除现存的Redis
725 redis_clean REDIS_PROVISION bool C 初始化Redis是否抹除现存实例
726 redis_rmdata REDIS_PROVISION bool C 清除Redis时是否抹除数据
721 redis_mode REDIS_PROVISION enum C Redis集群模式
722 redis_conf REDIS_PROVISION string C Redis配置文件模板
724 redis_bind_address REDIS_PROVISION ip C Redis监听地址
727 redis_max_memory REDIS_PROVISION size C/I Redis可用的最大内存
728 redis_mem_policy REDIS_PROVISION enum C 内存逐出策略
729 redis_password REDIS_PROVISION string C Redis密码
730 redis_rdb_save REDIS_PROVISION string[] C RDB保存指令
731 redis_aof_enabled REDIS_PROVISION bool C 是否启用AOF
732 redis_rename_commands REDIS_PROVISION object C 重命名危险命令列表
740 redis_cluster_replicas REDIS_PROVISION int C 集群每个主库带几个从库

REDIS_IDENTITY

身份参数是定义Redis集群时必须提供的信息,包括:

名称 属性 说明 例子
redis_cluster 必选,集群级别 集群名 redis-test
redis_node 必选,节点级别 节点编号 primary, replica
redis_instances 必选,节点级别 实例定义 { 6001 : {} ,6002 : {}}
  • redis_cluster 标识了Redis集群的名称,在集群层面进行配置,作为集群资源的顶层命名空间。
  • redis_node 标识了节点在集群中的序号
  • redis_instances 是一个JSON对象,Key为实例端口号,Value为一个JSON对象,包含实例特殊的配置

redis_cluster

Redis数据库集群名称, 类型:string,层级:C,默认值为:

REDIS数据库集群名称将用作集群内资源的命名空间,需要遵循特定命名规则:[a-z][a-z0-9-]*,以兼容不同约束对身份标识的要求。建议使用redis-作为集群名前缀。

身份参数,必填参数,集群级参数

redis_node

Redis节点序列号, 类型:int,层级:I,默认值为:

数据库节点的序号,在集群内部唯一,用于区别与标识集群内的不同节点,从0或1开始分配。

redis_instances

Redis实例定义, 类型:instance[],层级:I,默认值为:

部署在该数据库节点上的所有Redis实例,JSON KV对象格式。Key为数值类型端口号,Value为该实例特定的JSON配置项。

样例:

redis_instances: { 6501 : {} ,6502 : {} ,6503 : {} ,6504 : {} ,6505 : {} ,6506 : {} }
redis_instances:
    6501: {}
    6502: { replica_of: '10.10.10.13 6501' }
    6503: { replica_of: '10.10.10.13 6501' }

每一个Redis实例在对应节点上监听一个唯一端口,您可以为Redis实例配置独立的参数选项(目前只支持 replica_of,用于预构建主从复制)

身份参数,必填参数,实例级参数


REDIS_NODE

redis_fs_main

Redis使用的主数据盘挂载点, 类型:path,层级:C,默认值为:"/data"

Redis使用的主数据盘挂载点,默认为/data

Pigsty会在该目录下创建redis目录,用于存放Redis数据。例如/data/redis

详情请参考 FHS:Redis

redis_exporter_enabled

是否启用Redis监控, 类型:bool,层级:C,默认值为:true

Redis Exporter默认启用,在每个Redis节点上部署一个,默认监听9121端口。

redis_exporter_port

Redis Exporter监听端口, 类型:int,层级:C,默认值为:9121

注:如果您修改了该默认端口,则需要在Prometheus的相关配置规则文件中一并替换此端口。

redis_exporter_options

Redis Exporter命令参数, 类型:string,层级:C/I,默认值为:""


REDIS_PROVISION

redis_safeguard

安全保险,禁止清除存在的Redis实例, 类型:bool,层级:C/A,默认值为:false

如果为true,任何情况下,Pigsty剧本都不会移除运行中的 Redis 实例,包括 redis-remove.yml

详情请参考 保护机制

redis_clean

是否抹除运行中的Redis实例?类型:bool,层级:C/A,默认值为:true

针对 redis.yml 剧本的抹除豁免,如果指定该参数为真,那么在 redis.yml 剧本执行时,会自动抹除已有的Redis实例

这是危险操作;v1.5.1 随附配置已启用该项,生产使用前应明确复核。

当安全保险参数 redis_safeguard 打开时,本参数无效。

redis_rmdata

移除 Redis 实例时是否一并移除数据目录?类型:bool,层级:A,默认值为:true

如果不移除, 之前实例残留的RDB/AOF文件会被自动加载使用。

redis_mode

Redis集群模式, 类型:enum,层级:C,默认值为:"standalone"

指明该Redis集群的模式,有三种可选模式:

  • standalone:默认模式,部署一系列独立的Redis实例,(可以构建普通主从)
  • cluster: Redis原生集群模式
  • sentinel:Redis高可用组件:哨兵

当使用standalone模式时,Pigsty会根据 replica_of 参数额外设置Redis主从。 当使用cluster模式时,Pigsty会根据 redis_cluster_replicas 参数使用所有定义的实例创建原生Redis集群。

redis_conf

Redis配置文件模板, 类型:string,层级:C,默认值为:"redis.conf"

redis_bind_address

Redis监听地址, 类型:ip,层级:C,默认值为:"0.0.0.0"

Redis监听的IP地址,如果留空则为 inventory_hostname。默认监听有本地所有IPv4地址

redis_max_memory

Redis可用的最大内存, 类型:size,层级:C/I,默认值为:"1GB"

每个Redis实例使用的最大内存限制,默认为1GB,建议在集群层面配置此参数,保持集群实例配置一致。

redis_mem_policy

内存逐出策略, 类型:enum,层级:C,默认值为:"allkeys-lru"

其他可选策略包括:

  • volatile-lru
  • allkeys-lru
  • volatile-lfu
  • allkeys-lfu
  • volatile-random
  • allkeys-random
  • volatile-ttl
  • noeviction

redis_password

Redis密码, 类型:string,层级:C,默认值为:""

masterauth & requirepass 使用的密码,留空则禁用密码,默认禁用

警告

注意安全,请不要将无密码保护的Redis放置于公网上

redis_rdb_save

RDB保存指令, 类型:string[],层级:C,默认值为: [ "1200 1" ]

Redis SAVE命令,配置将启用RDB功能,每一条Save策略作为一个字符串。

redis_aof_enabled

是否启用AOF, 类型:bool,层级:C,默认值为:false

redis_rename_commands

重命名危险命令列表, 类型:object,层级:C,默认值为:{}

JSON字典,将Key表示的命令重命名为Value表示的命令,避免误操作危险命令。

redis_cluster_replicas

集群每个主库带几个从库, 类型:int,层级:C,默认值为:1

在Redis原生集群模式中,为每一个主库配置多少个从库?默认为1个。

/bin/redis-cli --cluster create --cluster-yes \
  --cluster-replicas {{ redis_cluster_replicas|default(1) }}

31 - 定制:PGSQL深度定制与修改

从 Pigsty v1.5.1 标签恢复的历史文档。

Patroni模板用于定制PostgreSQL集群的规格配置,而Postgres模板用于定制PostgreSQL集群的内容

Pigsty默认提供了近100关于PGSQL的参数,描述用户所需的PostgreSQL集群,通常可以满足绝大多数用户需求。

但如果您对Pigsty创建的数据库集群进行更深一步的定制,则可以参考本文内容,对Patroni模板Postgres模板进行定制

Patroni模板

Pigsty使用 Patroni 管理与初始化Postgres数据库集群。 如果用户希望修改PostgreSQL数据库集群的默认配置参数,规格与调优方案,高可用策略,DCS访问,管控API,可以通过修改Patroni模板的方式实现。

Pigsty使用Patroni完成供给的主体工作,即使用户选择了 无Patroni模式,拉起数据库集群也会由Patroni负责,并在创建完成后移除Patroni组件。 用户可以通过Patroni配置文件,完成大部分的PostgreSQL集群定制工作,Patroni配置文件格式详情请参考 Patroni官方文档

预制Patroni模板

Pigsty提供了几种预定义的初始化模板,初始化模板是用于初始化数据库集群的定义文件,默认位于roles/postgres/templates/。包括:

Conf CPU Mem Disk 说明
oltp 64 400GB 4TB 生产OLTP模板,默认配置,针对生产机型优化延迟与性能
olap 64 400GB 4TB 生产OLAP模板,提高并行度,针对吞吐量,长查询进行优化。
crit 64 400GB 4TB 生产核心业务模板,基于OLTP模板针对RPO、安全性、数据完整性进行优化,启用同步复制与数据校验和。
tiny 1 1GB 40GB 微型数据库模板,针对低资源场景进行优化,例如运行于虚拟机中的演示数据库集群。
mini 2 4GB 100GB 2C4G 机型OLTP模板
small 4 8GB 200GB 4C8G 机型OLTP模板
medium 8 16GB 500GB 8C16G 机型OLTP模板
large 16 32GB 1TB 16C32G 机型OLTP模板

通过 pg_conf 参数指定所需使用的模板路径,如果使用预制模板,则只需填入模板文件名称即可。如果使用定制的 Patroni配置模板,通常也应当针对机器节点使用配套的 节点优化模板

pg_conf:   tiny.yml      # 使用 tiny.yml 调优模板
node_tune: tiny          # 节点调优模式:oltp|olap|crit|tiny

在安装Pigsty进行Configure的过程中,Pigsty会检测根据当前机器(管理机)的规格,自动选择对应的默认规格。

定制Patroni模板

定制您自己的Patroni模板时,您可以用已有的几种基础模板作为基线,在此基础上进行修改。

并放置于templates/目录中,以<mode>.yml格式命名即可。

Patroni中的模板变量请保留,否则相关参数可能无法正常工作。例如 pg_libs

最后,在配置文件的 pg_conf 配置项,指定您新创建的模板名称即可,例如 olap-32C128G-nvme.yml

Postgres模板

可以使用 PG模板 配置项,对集群中的模板数据库 template1 进行定制,进而。

通过这种方式确保任何在该数据库集群中新创建的数据库都带有相同的默认配置:模式,扩展,默认权限。

相关文件

定制数据库模板时,相关参数会首先被渲染为SQL脚本后,在部署好的数据库集群上执行。

^---/pg/bin/pg-init
          |
          ^---(1)--- /pg/tmp/pg-init-roles.sql
          ^---(2)--- /pg/tmp/pg-init-template.sql
          ^---(3)--- <other customize logic in pg-init>

# 业务用户与数据库并不是在模版定制中创建的,但在此列出。
^-------------(4)--- /pg/tmp/pg-user-{{ user.name }}.sql
^-------------(5)--- /pg/tmp/pg-db-{{ db.name }}.sql

pg-init

pg-init是用于自定义初始化模板的Shell脚本路径,该脚本将以postgres用户身份,仅在主库上执行,执行时数据库集群主库已经被拉起,可以执行任意Shell命令,或通过psql执行任意SQL命令。

如果不指定该配置项,Pigsty会使用默认的pg-init Shell脚本,如下所示。

#!/usr/bin/env bash
set -uo pipefail


#==================================================================#
#                          Default Roles                           #
#==================================================================#
psql postgres -qAXwtf /pg/tmp/pg-init-roles.sql


#==================================================================#
#                          System Template                         #
#==================================================================#
# system default template
psql template1 -qAXwtf /pg/tmp/pg-init-template.sql

# make postgres same as templated database (optional)
psql postgres  -qAXwtf /pg/tmp/pg-init-template.sql



#==================================================================#
#                          Customize Logic                         #
#==================================================================#
# add your template logic here

如果用户需要执行复杂的定制逻辑,可在该脚本的基础上进行追加。注意 pg-init 用于定制数据库集群,通常这是通过修改 模板数据库 实现的。在该脚本执行时,数据库集群已经启动,但业务用户与业务数据库尚未创建。因此模板数据库的修改会反映在默认定义的业务数据库中。

32 - Pigsty Dashboards

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty由提供了专业且易用的PostgreSQL监控系统,浓缩了业界监控的最佳实践。

用户可以方便地进行修改与定制;复用监控基础设施,或与其他监控系统相集成。

Pigsty监控面板由几个相对独立的板块组成。

应用 说明
Home 首页
PGSQL PostgreSQL数据库监控
REDIS Redis数据库监控
NODES 主机节点监控
INFRA 基础设施监控/日志
APP 额外加装的应用

HOME

Pigsty的首页提供了对各个板块的导航。

PGSQL

PostgreSQL监控面板有着自己的层次,自顶向下分别为:

  • 全局:关注整个环境,大盘全局指标
  • 集群:专注单个数据库集群的聚合指标
  • 实例:专注单个实例对象:数据库实例,节点,负载均衡器,各类主题面板
  • 数据库(对象):数据库内的活动,表与查询的详细信息

大多数监控面板都可以通过表格,图元进行层级跳转,允许您快速上卷下钻。

REDIS

REDIS监控分为三个层次:全局总览,单个集群,单个实例

NODES

NODES监控分为三个层次:全局总览,单个节点集群,单个节点

INFRA

INFRA监控用于监控基础设施本身,包含以下Dashboards:

APP

Pigsty自带了一个典型的应用 PGLOG,用于分析PG本身的CSV日志样本。

访问 https://github.com/vonng/pigsty-app ,获取更多样例应用。

33 - 服务发现

从 Pigsty v1.5.1 标签恢复的历史文档。

服务发现有多种用途,本文介绍Pigsty监控系统Prometheus用于发现监控对象的机制。

服务发现的基础是身份标识,关于身份标识详情,请参阅实体一节

有了身份标识后,还需要在监控系统中将监控目标与身份标识相关联,Pigsty提供了两种实现方式:

静态文件是默认的服务发现机制,在v1.0.0以前,Consul是默认的服务发现方式,可以通过参数配置发现机制。

身份参数

所有的实例都具有身份(Identity)身份标识(Identifier)是与实例关联的元数据,用于标识实例。

身份参数是任何集群与实例都必须定义的唯一标识符。

名称 变量 缩写 类型 说明
集群 pg_cluster cls 核心身份参数 集群名称,集群内资源的顶层命名空间
角色 pg_role role 核心身份参数 实例角色,primary, replica, offline,…
标号 pg_seq seq 核心身份参数 实例序号,正整数,集群内唯一。
实例 pg_instance ins 衍生身份参数 ${pg_cluster}-${pg_seq}
服务 pg_service svc 衍生身份参数 ${pg_cluster}-${pg_role}

身份关联

为系统中的对象命名后,还需要将 身份信息 关联至具体的实例上。

身份信息属于业务赋予的元数据,数据库实例本身不会意识到这些身份信息,它不知道自己为谁而服务,从属于哪个业务,或者自己是集群中的几号实例。

身份赋予可以有多种形式,最朴素的身份关联方式就是运维人员的记忆:DBA在脑海中记住了IP地址为10.2.3.4上的数据库实例,是用于支付的实例,而另一台上的数据库实例则用于用户管理。更好的管理方式是通过配置文件,或者采用服务发现的方式来管理集群成员的身份。

Pigsty同时提供这两种身份管理的方式:基于Consul的服务发现,与基于配置文件的服务发现

参数 prometheus_sd_method 控制这一行为:

  • consul:基于Consul进行服务发现,默认配置
  • static:基于本地配置文件进行服务发现

Pigsty建议使用static服务发现,此方式更为简洁,且监控系统无需依赖Consul,具有更强的可靠性。

静态文件服务发现

静态文件服务发现是默认的监控对象发现方式,Pigsty默认使用以下配置拉取配置。

#------------------------------------------------------------------------------
# job: pgsql (database monitoring)
# node_exporter | pg_exporter | pgbouncer_exporter | haproxy(exporter)
# labels: [cls, ins, instance]
# path: targets/pgsql/*.yml
#------------------------------------------------------------------------------
- job_name: pgsql
  metrics_path: /metrics
  file_sd_configs:
    - refresh_interval: 10s
      files: [ /etc/prometheus/targets/pgsql/*.yml ]

/etc/prometheus/targets目录下存放有由Pigsty生成的监控对象定义文件,pgsql是默认环境的名称。

每一个实例由一个单独的文件定义,形如:

/etc/prometheus/targets/pgsql
                     ^-----pg-meta-1.yml
                     ^-----pg-test-1.yml
                     ^-----pg-test-2.yml
                     ^-----pg-test-3.yml

其内容为单个实例节点上的身份标识,与监控对象

# pg-meta-1 [primary] @ 10.10.10.10
- labels: { cls: pg-meta, ins: pg-meta-1 }
  targets: [10.10.10.10:9630, 10.10.10.10:9100, 10.10.10.10:9631, 10.10.10.10:9101]

静态文件服务发现的优点是没有额外的组件依赖,而且允许人工介入进行管理与调整,亦便于与第三方系统相互集成。

维护文件服务发现

使用静态文件服务发现时,所有集群扩容、缩容操作都会自动维护这些配置文件。

使用以下命令,将为环境中所有实例重新生成配置文件

./pgsql.yml -t register_prometheus

默认采集对象

每一个被管理的Postgres实例都包括有几个采集端口:

这些采集端口会被元节点上的Prometheus所采集。 此外,可选的Promtail用于收集Postgres,Patroni,Pgbouncer日志,是可选的额外安装组件。

默认情况下,所有监控端点都会被注册至Consul,但Prometheus默认会通过静态文件服务发现的方式管理这些任务。 用户可以通过配置 prometheus_sd_methodconsul 来使用Consul服务发现,动态管理实例。

Consul服务发现

Pigsty内置了基于DCS的配置管理与自动服务发现,用户可以直观地察看系统中的所有节点与服务信息,以及健康状态。Pigsty中的所有服务都会自动注册至DCS中,因此创建、销毁、修改数据库集群时,元数据会自动修正,监控系统能够自动发现监控目标,无需手动维护配置。

用户亦可通过Consul提供的DNS与服务发现机制,实现基于DNS的自动流量切换。

Consul采用了Client/Server架构,整个环境中存在1~5个不等的Consul Server,用于实际的元数据存储。所有节点上都部署有Consul Agent,代理本机服务与Consul Server的通信。Pigsty默认通过本地Consul配置文件的方式注册服务。

服务注册

在每个节点上,都运行有 consul agent。服务通过JSON配置文件的方式,由consul agent注册至DCS中。

JSON配置文件的默认位置是/etc/consul.d/,采用svc-<service>.json的命名规则,以postgres为例:

{
  "service": {
    "name": "postgres",
    "port": 5432,
    "tags": [
      "pgsql",
      "primary",
      "pg-meta"
    ],
    "meta": {
      "type": "postgres",
      "role": "primary",
      "seq": "1",
      "instance": "pg-meta-1",
      "service": "pg-meta-primary",
      "cluster": "pg-meta",
      "version": "13"
    },
    "check": {
      "args": ["/usr/pgsql/bin/pg_isready", "-p", "5432", "-U", "dbuser_monitor"],
      "interval": "15s",
      "timeout": "1s"
    }
  }
}

其中metatags部分是服务的元数据,存储有实例的身份信息

服务查询

用户可以通过Consul提供的DNS服务,或者直接调用Consul API发现注册到Consul中的服务

使用DNS API查阅consul服务的方式,请参阅Consul文档

服务发现

Prometheus会自动通过consul_sd_configs发现环境中的监控对象。同时带有pgexporter标签的服务会自动被识别为抓取对象:

- job_name: pg
  # https://prometheus.io/docs/prometheus/latest/configuration/configuration/#consul_sd_config
  consul_sd_configs:
    - server: localhost:8500
      refresh_interval: 5s
      tags:
        - pg
        - exporter

图:被Prometheus发现的服务,身份信息已关联至实例的指标维度上。

服务维护

有时候,因为数据库主从发生切换,导致注册的角色与数据库实例的实际角色出现偏差。这时候需要通过反熵过程处理这种异常。基于Patroni的故障切换可以正常地通过回调逻辑修正注册的角色,但人工完成的角色切换则需要人工介入处理。使用以下脚本可以自动检测并修复数据库的服务注册。建议在数据库实例上配置Crontab,或在元节点上设置定期巡检任务。

/pg/bin/pg-register $(pg-role)

标签

无论是通过Consul服务发现,还是静态文件服务发现。最终的效果是实现身份信息实例监控指标相互关联。

这一关联,是通过监控指标的维度标签实现的,并不是所有指标都具有以下标签。

但Pigsty中所有数据库集群相关的原始监控指标必定具有clsins两个标签,并在整个生命周期中保持不变。

身份参数 维度标签 取值样例
pg_cluster cls pg-test
pg_instance ins pg-test-1
pg_services svc pg-test-primary
pg_role role primary
node_ip ip 10.10.10.11

阅读下一节 监控指标 ,了解这些指标是如何通过标签组织起来的。

34 - 监控指标

从 Pigsty v1.5.1 标签恢复的历史文档。

指标(Metric) 是Pigsty监控系统的核心概念。

指标形式

指标在形式上是可累加的,原子性的逻辑计量单元,可在时间段上进行更新与统计汇总。

指标通常以 带有维度标签的时间序列 的形式存在。举个例子,Pigsty沙箱中的pg:ins:qps_realtime指展示了所有实例的实时QPS

pg:ins:qps_realtime{cls="pg-meta", ins="pg-meta-1", ip="10.10.10.10", role="primary"} 0
pg:ins:qps_realtime{cls="pg-test", ins="pg-test-1", ip="10.10.10.11", role="primary"} 327.6
pg:ins:qps_realtime{cls="pg-test", ins="pg-test-2", ip="10.10.10.12", role="replica"} 517.0
pg:ins:qps_realtime{cls="pg-test", ins="pg-test-3", ip="10.10.10.13", role="replica"} 0

用户可以对指标进行运算:求和、求导,聚合,等等。例如:

$ sum(pg:ins:qps_realtime) by (cls)        -- 查询按集群聚合的 实时实例QPS
{cls="pg-meta"} 0
{cls="pg-test"} 844.6

$ avg(pg:ins:qps_realtime) by (cls)        -- 查询每个集群中 所有实例的平均 实时实例QPS
{cls="pg-meta"} 0
{cls="pg-test"} 280

$ avg_over_time(pg:ins:qps_realtime[30m])  -- 过去30分钟内实例的平均QPS
pg:ins:qps_realtime{cls="pg-meta", ins="pg-meta-1", ip="10.10.10.10", role="primary"} 0
pg:ins:qps_realtime{cls="pg-test", ins="pg-test-1", ip="10.10.10.11", role="primary"} 130
pg:ins:qps_realtime{cls="pg-test", ins="pg-test-2", ip="10.10.10.12", role="replica"} 100
pg:ins:qps_realtime{cls="pg-test", ins="pg-test-3", ip="10.10.10.13", role="replica"} 0

指标模型

每一个指标(Metric),都是一数据,通常会对应多个时间序列(time series)。同一个指标对应的不同时间序列通过维度进行区分。

指标 + 维度,可以具体定位一个时间序列。每一个时间序列都是由 (时间戳,取值)二元组构成的数组。

Pigsty采用Prometheus的指标模型,其逻辑概念可以用以下的SQL DDL表示。

-- 指标表,指标与时间序列构成1:n关系
CREATE TABLE metrics (
    id   INT PRIMARY KEY,         -- 指标标识
    name TEXT UNIQUE              -- 指标名称,[...其他指标元数据,例如类型]
);

-- 时间序列表,每个时间序列都对应一个指标。
CREATE TABLE series (
    id        BIGINT PRIMARY KEY,               -- 时间序列标识
    metric_id INTEGER REFERENCES metrics (id),  -- 时间序列所属的指标
    dimension JSONB DEFAULT '{}'                -- 时间序列带有的维度信息,采用键值对的形式表示
);

-- 时序数据表,保存最终的采样数据点。每个采样点都属于一个时间序列
CREATE TABLE series_data (
    series_id BIGINT REFERENCES series(id),     -- 时间序列标识
    ts        TIMESTAMP,                        -- 采样点时间戳
    value     FLOAT,                            -- 采样点指标值
    PRIMARY KEY (series_id, ts)                 -- 每个采样点可以通过 所属时间序列 与 时间戳 唯一标识
);

这里我们以pg:ins:qps指标为例:

-- 样例指标数据
INSERT INTO metrics VALUES(1, 'pg:ins:qps');  -- 该指标名为 pg:ins:qps ,是一个 GAUGE。
INSERT INTO series VALUES                     -- 该指标包含有四个时间序列,通过维度标签区分
(1001, 1, '{"cls": "pg-meta", "ins": "pg-meta-1", "role": "primary", "other": "..."}'),
(1002, 1, '{"cls": "pg-test", "ins": "pg-test-1", "role": "primary", "other": "..."}'),
(1003, 1, '{"cls": "pg-test", "ins": "pg-test-2", "role": "replica", "other": "..."}'),
(1004, 1, '{"cls": "pg-test", "ins": "pg-test-3", "role": "replica", "other": "..."}');
INSERT INTO series_data VALUES                 -- 每个时间序列底层的采样点
(1001, now(), 1000),                           -- 实例 pg-meta-1 在当前时刻QPS为1000
(1002, now(), 1000),                           -- 实例 pg-test-1 在当前时刻QPS为1000
(1003, now(), 5000),                           -- 实例 pg-test-2 在当前时刻QPS为1000
(1004, now(), 5001);                           -- 实例 pg-test-3 在当前时刻QPS为5001
  • pg_up 是一个指标,包含有4个时间序列。记录了整个环境中所有实例的存活状态。
  • pg_up{ins": "pg-test-1", ...}是一个时间序列,记录了特定实例pg-test-1 的存活状态

指标来源

Pigsty的监控数据主要有四种主要来源: 数据库连接池操作系统负载均衡器。通过相应的exporter对外暴露。

完整来源包括:

  • PostgreSQL本身的监控指标
  • PostgreSQL日志中的统计指标
  • PostgreSQL系统目录信息
  • Pgbouncer连接池中间价的指标
  • PgExporter指标
  • 数据库工作节点Node的指标
  • 负载均衡器Haproxy指标
  • DCS(Consul)工作指标
  • 监控系统自身工作指标:Grafana,Prometheus,Nginx
  • Blackbox 探活指标(v1.5.1 中列为后续覆盖项)

关于全部可用的指标清单,请查阅 v1.5.1 PG Exporter 指标定义 一节

指标数量

那么,Pigsty总共包含了多少指标呢? 这里是一副各个指标来源占比的饼图。我们可以看到,右侧蓝绿黄对应的部分是数据库及数据库相关组件所暴露的指标,而左下方红橙色部分则对应着机器节点相关指标。左上方紫色部分则是负载均衡器的相关指标。

数据库指标中,与postgres本身有关的原始指标约230个,与中间件有关的原始指标约50个,基于这些原始指标,Pigsty又通过层次聚合与预计算,精心设计出约350个与DB相关的衍生指标。

因此,对于每个数据库集群来说,单纯针对数据库及其附件的监控指标就有621个。而机器原始指标281个,衍生指标83个一共364个。加上负载均衡器的170个指标,我Pigsty共有接近1200类指标。

注意,这里我们必须辨析一下指标(metric)与时间序列( Time-series)的区别。 这里我们使用的量词是 类 而不是个 。 因为一个指标可能对应多个时间序列。例如一个数据库中有20张表,那么 pg_table_index_scan 这样的指标就会对应有20个对应的时间序列。

截止至2021年,Pigsty的指标覆盖率在所有作者已知的开源/商业监控系统中一骑绝尘,详情请参考横向对比

指标层次

Pigsty还会基于现有指标进行加工处理,产出 衍生指标(Derived Metrics)

例如指标可以按照不同的层次进行聚合

实体 标识名 标识样例 标签
Environment job pgsql, redis, staging {job}
Shard pg-test-shard\d+ {job, cls*}
Cluster cls pg-meta, pg-test {job, cls}
Service pg-meta-primary, pg-test-replica {job, cls}
Instance ins pg-meta-1, pg-test-1 {job, cls, ins, ip, instance}
Database datname test {..., datname}
Object public.pgbench_accounts {..., datname, <object>}

从原始监控时间序列数据,到最终的成品图表,中间还有着若干道加工工序。

这里以TPS指标的衍生流程为例。

原始数据是从Pgbouncer抓取得到的事务计数器,集群中有四个实例,而每个实例上又有两个数据库,所以一个实例总共有8个DB层次的TPS指标。

而下面的图表,则是整个集群内每个实例的QPS横向对比,因此在这里,我们使用预定义的规则,首先对原始事务计数器求导获取8个DB层面的TPS指标,然后将8个DB层次的时间序列聚合为4个实例层次的TPS指标,最后再将这四个实例级别的TPS指标聚合为集群层次的TPS指标。

Pigsty共定义了360类衍生聚合指标,后续还会不断增加。衍生指标定义规则详见 指标层次

特殊指标

目录(Catalog) 是一种特殊的指标

Catalog与Metrics比较相似但又不完全相同,边界比较模糊。最简单的例子,一个表的页面数量和元组数量,应该算Catalog还是算Metrics?

跳过这种概念游戏,实践上Catalog和Metrics主要的区别是,Catalog里的信息通常是不怎么变化的,比如表的定义之类的,如果也像Metrics这样比如几秒抓一次,显然是一种浪费。所以我们会将这一类偏静态的信息划归Catalog。

Catalog主要由定时任务(例如巡检)负责抓取,而不由Prometheus采集。一些特别重要的Catalog信息,例如pg_class中的一些信息,也会转换为指标被Prometheus所采集。

Pigsty提供了 PGCAT 系列监控面板,可以直接从目标数据库的Catalog中采集并呈现信息。

小结

了解了Pigsty指标后,不妨了解一下Pigsty的 告警系统 是如何将这些指标数据用于实际生产用途的。

35 - 告警系统

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty有两套并行的告警系统:

两套系统功能等效,侧重能力不同,可同时使用,互为备份补充。

告警

告警对于日常故障响应,提高系统可用性至关重要。

漏报会导致可用性降低,误报会导致敏感性下降,有必要对告警规则进行审慎的设计。

  • 合理定义告警级别,以及相应的处理流程
  • 合理定义告警指标,去除重复告警项,补充缺失告警项
  • 根据历史监控数据科学配置告警阈值,减少误报率。
  • 合理疏理特例规则,消除维护工作,ETL,离线查询导致的误报。

告警分类学

按照来源模块分类

  • INFRA:基础设施类告警:Prometheus,Grafana,Consul,DNS,Nginx等基础设施软件等产生的告警。
  • NODES:主机节点告警,操作系统,硬件资源,基础设施软件,负载均衡等告警,通常由运维人员负责处理。
  • PGSQL:PostgreSQL数据库告警,数据库/连接池/负载均衡集群本身的告警,通常研发与DBA关注,DBA处理。
  • REDIS:Redis数据库告警,研发与DBA关注,DBA处理。
  • ……:应用板块告警,用告警由业务方自己负责,但DBA会为QPS,TPS,Rollback,Seasonality等业务指标设置告警
  • Pigsty使用category标签{infra,pgsql,nodes,redis,....}来标识告警的层次。

按紧急程度分类

  • P0:CRIT:产生重大场外影响的事故,需要紧急介入处理。例如主库宕机,复制中断。(事故)
  • P1:WARN:场外影响轻微,或有冗余处理的事故,需要在分钟级别内进行响应处理。(警告)
  • P2:INFO:即将产生影响,放任可能在小时级别内恶化,需在小时级别进行响应。(事件)
  • Pigsty使用与severity标签{CRIT,WARN,INFO}来标识告警的紧急程度。

按指标类型分类

  • 错误:PG Down, PGB Down, Exporter Down, 流复制中断,单集簇多主
  • 流量:QPS,TPS,Rollback,Seasonaility
  • 延迟: 平均响应时间,复制延迟
  • 饱和度:连接堆积,闲事务数,CPU,磁盘,年龄(事务号),缓冲区

告警可视化

在各类监控面板中,Pigsty使用时间轴状态图呈现告警信息。横轴代表时间段,一段色条代表告警事件。只有处于 激发(Firing) 状态的告警才会显示在告警图表中,处于Pending状态的告警通常会隐藏或以灰色显示。

告警规则

告警规则按类型可粗略分为四类:错误,延迟,饱和度,流量。其中:

  • 错误:主要关注各个组件的存活性(Aliveness),以及网络中断,脑裂等异常情况,级别通常较高(P0|P1)。
  • 延迟:主要关注查询响应时间,复制延迟,慢查询,长事务。
  • 饱和度:主要关注CPU,磁盘(这两个属于系统监控但对于DB非常重要所以纳入),连接池排队,数据库后端连接数,年龄(本质是可用事物号的饱和度),SSD寿命等。
  • 流量:QPS,TPS,Rollback(流量通常与业务指标有关属于业务监控范畴,但因为对于DB很重要所以纳入),QPS的季节性,TPS的突增。

Prometheus告警规则

告警规则使用Prometheus语法定义,完整的告警规则详见:

Pigsty典型告警

错误告警

数据库实例宕机将立刻触发P0报警。

# database server down
- alert: PostgresDown
  expr: pg_up < 1
  for: 1m
  labels: { level: 0, severity: CRIT, category: pgsql }
  annotations:
    summary: "CRIT PostgresDown {{ $labels.ins }}@{{ $labels.instance }}"
    description: |
      pg_up[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value }} < 1
      http://g.pigsty/d/pgsql-instance?var-ins={{ $labels.ins }}

在生产环境使用PostgreSQL时,Pgbouncer实例与Postgres是一一对应的命运共同体,Pgbouncer故障效果基本与Postgres故障等同,其存活性告警规则级别与Postgres统一。

# database connection pool down
- alert: PgbouncerDown
  expr: pgbouncer_up < 1
  for: 1m
  labels: { level: 0, severity: CRIT, category: pgsql }
  annotations:
    summary: "CRIT PostgresDown {{ $labels.ins }}@{{ $labels.instance }}"
    description: |
      pgbouncer_up[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value }} < 1
      http://g.pigsty/d/pgsql-instance?var-ins={{ $labels.ins }}

监控代理Exporter宕机通常预示着严重故障:HAProxy 与Node Exporter宕机通常意味着负载均衡器与数据库节点本身宕机,需要重点关注

#==============================================================#
#                       Agent Aliveness                        #
#==============================================================#
# node & haproxy aliveness are determined directly by exporter aliveness
# including: node_exporter, pg_exporter, pgbouncer_exporter, haproxy_exporter
- alert: AgentDown
  expr: agent_up < 1
  for: 1m
  labels: { level: 0, severity: CRIT, category: infra }
  annotations:
    summary: 'CRIT AgentDown {{ $labels.ins }}@{{ $labels.instance }}'
    description: |
      agent_up[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value  | printf "%.2f" }} < 1
      http://g.pigsty/d/pgsql-alert?viewPanel=22

所有存活性检测的持续时间阈值设定为1分钟,对15s的采集周期通常意味着连续4次探活失败。常规的快速重启操作通常不会触发存活性告警。

集群脑裂分区

一个数据库集群,应当有且仅有一个主库领导者实例。即集群正常情况下应当只有一个分区。如果集群的分区数量不为1(为0代表群龙无首,大于1代表群雄逐鹿)则代表集群进入了异常状态:不可写入或脑裂,会立即触发P0报警。因为检测阈值为1分钟,所以常规的Failover与Switchover通常不容易触发此告警。

# cluster partition: split brain
- alert: PostgresPartition
  expr: pg:cls:partition != 1
  for: 1m
  labels: { level: 0, severity: CRIT, category: pgsql }
  annotations:
    summary: "CRIT PostgresPartition {{ $labels.cls }}@{{ $labels.job }} {{ $value }}"
    description: |
      pg:cls:partition[cls={{ $labels.cls }}, job={{ $labels.job }}] = {{ $value }} != 1

延迟告警

与复制延迟有关的告警有二个:复制中断,复制延迟高,定级为P1警告。

  • 其中复制中断是一种错误,使用指标:pg_downstream_count{state="streaming"}进行判断,当前streaming状态的从库如果数量发生负向变动,则触发break告警。walsender会决定复制的状态,从库直接断开会产生此现象,缓冲区出现积压时会从streaming进入catchup状态也会触发此告警。此外,采用-Xs手工制作备份结束时也会产生此告警,此告警会在5分钟后自动Resolve。复制中断会导致客户端读到陈旧的数据,具有一定的场外影响,定级为P1。

  • 复制延迟可以使用延迟时间或者延迟字节数判定。以延迟字节数为权威指标。常规状态下,复制延迟时间在百毫秒量级,复制延迟字节在百KB量级均属于正常。根据历史经验数据,目前采用的是1MB与1s的时间告警阈值。

#==============================================================#
#                         Replication                          #
#==============================================================#
# replication break for 1m triggers a P1 alert (WARN: heal in 5m)
- alert: PostgresReplicationBreak
  expr: changes(pg_downstream_count{state="streaming"}[5m]) > 0
  # for: 1m
  labels: { level: 1, severity: WARN, category: pgsql }
  annotations:
    summary: "WARN PostgresReplicationBreak: {{ $labels.ins }}@{{ $labels.instance }}"
    description: |
      changes(pg_downstream_count{ins={{ $labels.ins }}, instance={{ $labels.instance }}, state="streaming"}[5m]) > 0


# replication lag bytes > 1MiB or lag seconds > 1s
- alert: PostgresReplicationLag
  expr: pg:ins:lag_bytes > 1048576 or pg:ins:lag_seconds > 1
  for: 1m
  labels: { level: 1, severity: WARN, category: pgsql }
  annotations:
    summary: "WARN PostgresReplicationLag: {{ $labels.ins }}@{{ $labels.instance }}"
    description: |
      pg:ins:lag_bytes[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value | printf "%.0f" }} > 1048576 or
      pg:ins:lag_seconds[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value | printf "%.2f" }} > 1

此外,查询延迟与磁盘延迟也有相应的报警规则:

例如,磁盘读写平均响应时间持续一分钟超过32ms,或Pgbouncer中平均查询RT超过16ms均会触发P1告警。


# read latency > 32ms (typical on pci-e ssd: 100µs)
- alert: NodeDiskSlow
  expr: node:dev:disk_read_rt_1m > 0.032 or node:dev:disk_write_rt_1m > 0.032
  for: 1m
  labels: { level: 1, severity: WARN, category: node }
  annotations:
    summary: 'WARN NodeReadSlow {{ $labels.ins }}@{{ $labels.instance }} {{ $value  | printf "%.6f" }}'
    description: |
      node:dev:disk_read_rt_1m[ins={{ $labels.ins }}] = {{ $value  | printf "%.6f" }} > 32ms


# pgbouncer avg response time > 16ms (database level)
- alert: PgbouncerQuerySlow
  expr: pgbouncer:db:query_rt_1m > 0.016
  for: 3m
  labels: { level: 1, severity: WARN, category: pgsql }
  annotations:
    summary: "WARN PgbouncerQuerySlow: {{ $labels.ins }}@{{ $labels.instance }} [{{ $labels.datname }}]"
    description: |
      pgbouncer:db:query_rt_1m[ins={{ $labels.ins }}, instance={{ $labels.instance }}, datname={{ $labels.datname }}] = {{ $value | printf "%.3f" }} > 0.016

饱和度告警

饱和度指标主要资源,包含很多系统级监控的指标。主要包括:CPU,磁盘(这两个属于系统监控但对于DB非常重要所以纳入),连接池排队,数据库后端连接数,年龄(本质是可用事物号的饱和度),SSD寿命等。

数据库压力

数据库压力是:机器CPU使用率,Pgbouncer时间利用率,Postgres时间利用率(14引入)的综合最大值(百分比,但过载时可以超过100%)。压力是Pigsty中最重要的指标,集中体现了数据库实例与集群的负载水位。

#==============================================================#
#                        Saturation                            #
#==============================================================#
# instance pressure higher than 70% for 1m triggers a P1 alert
- alert: PostgresPressureHigh
  expr: ins:pressure1 > 0.70
  for: 1m
  labels: { level: 1, severity: WARN, category: pgsql }
  annotations:
    summary: "WARN PostgresPressureHigh: {{ $labels.ins }}@{{ $labels.instance }}"
    description: |
      ins:pressure1[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value | printf "%.3f" }} > 0.70

堆积检测

堆积主要包含两类指标,一方面是PG本身的后端连接数与活跃连接数,另一方面是连接池的排队情况。

PGB排队是决定性的指标,它代表用户端可感知的阻塞已经出现,因此出现排队持续1分钟触发P0告警。

当使用Session Pooling模式时,可适当放宽此报警指标。

# pgbouncer client queue exists
- alert: PgbouncerClientQueue
  expr: pgbouncer:db:waiting_clients > 1
  for: 1m
  labels: { level: 0, severity: CRIT, category: pgsql }
  annotations:
    summary: "CRIT PgbouncerClientQueue: {{ $labels.ins }}@{{ $labels.instance }} [{{ $labels.datname }}]"
    description: |
      pgbouncer:db:waiting_clients[ins={{ $labels.ins }}, instance={{ $labels.instance }}, datname={{ $labels.datname }}] = {{ $value | printf "%.0f" }} > 1

后端连接数是一个重要的告警指标,如果后端连接持续达到最大连接数,往往也意味着雪崩。连接池的排队连接数也能反映这种情况,但不能覆盖应用直连数据库的情况。

目前,Pigsty使用连接使用率作为告警指标,即数据库可用连接数量已经使用的百分比,超过70%持续3分钟即出发P1告警。

# database connection usage > 70%
- alert: PostgresConnUsageHigh
  expr: pg:db:conn_usage > 0.70
  for: 3m
  labels: { level: 1, severity: WARN, category: pgsql }
  annotations:
    summary: "WARN PostgresConnUsageHigh: {{ $labels.ins }}@{{ $labels.instance }} [{{ $labels.datname }}]"
    description: |
      pg:db:conn_usage[ins={{ $labels.ins }}, instance={{ $labels.instance }}, datname={{ $labels.datname }}] = {{ $value | printf "%.3f" }} > 0.70

空闲事务

即数据库出现Idle in Transaction状态的连接数量,超过2条持续3分钟即出发P1告警。

# database connection usage > 70%
- alert: PostgresIdleInXact
  expr: pg:db:ixact_backends > 1
  for: 3m
  labels: { level: 2, severity: INFO, category: pgsql }
  annotations:
    summary: "Info PostgresIdleInXact: {{ $labels.ins }}@{{ $labels.instance }} [{{ $labels.datname }}]"
    description: |
      pg:db:ixact_backends[ins={{ $labels.ins }}, instance={{ $labels.instance }}, datname={{ $labels.datname }}] = {{ $value | printf "%.0f" }} > 1

资源告警

年龄(XID)使用量超过80%出发P0告警,这意味着系统快要消耗完事务号资源,进入XID Wraparound状态

# database age saturation > 80%
- alert: PostgresXidWarpAround
  expr: pg:db:age > 0.80
  for: 1m
  labels: { level: 0, severity: CRIT, category: pgsql }
  annotations:
    summary: "CRIT PostgresXidWarpAround: {{ $labels.ins }}@{{ $labels.instance }} [{{ $labels.datname }}]"
    description: |
      pg:db:age[ins={{ $labels.ins }}, instance={{ $labels.instance }}, datname={{ $labels.datname }}] = {{ $value | printf "%.0f" }} > 80%

36 - 扩展应用

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty除了用于部署、监控PostgreSQL,还可以用于制作,分发数据类应用(Application)。

Pigsty提供了几个样例应用:

  • pglog, 分析PostgreSQL CSV日志样本。
  • covid, 可视化WHO COVID-19数据,查阅各国疫情数据。
  • pglog, NOAA ISD,可以查询全球30000个地表气象站从1901年来的气象观测记录。

应用的结构

一个Pigsty应用通常包括以下内容中的至少一样或全部:

  • 图形界面(Grafana Dashboard定义) 放置于ui目录
  • 数据定义(PostgreSQL DDL File),放置于 sql 目录
  • 数据文件(各类资源,需要下载的文件),放置于data目录
  • 逻辑脚本(执行各类逻辑),放置于bin目录

一个Pigsty应用会在应用根目录提供一个安装脚本:install或相关快捷方式。您需要使用管理用户元节点执行安装。安装脚本会检测当前的环境(获取 METADB_URLPIGSTY_HOMEGRAFANA_ENDPOINT等信息以执行安装)

通常,带有APP标签的面板会被列入Pigsty Grafana首页导航中App下拉菜单中,带有APPOverview标签的面板则会列入首页面板导航中。

您可以从 https://github.com/Vonng/pigsty/releases/download/v1.5.1/app.tgz 下载带有基础数据的应用进行安装。

PGLOG

PGLOG是Pigsty自带的一个样例应用,固定使用MetaDB中pglog.sample表作为数据来源。您只需要将日志灌入该表,然后访问相关Dashboard即可。

Pigsty提供了一些趁手的命令,用于拉取csv日志,并灌入样本表中。在元节点上,默认提供下列快捷命令:

catlog  [node=localhost]  [date=today]   # 打印CSV日志到标准输出
pglog                                    # 从标准输入灌入CSVLOG
pglog12                                  # 灌入PG12格式的CSVLOG
pglog12                                  # 灌入PG13格式的CSVLOG
pglog12                                  # 灌入PG14格式的CSVLOG (=pglog)

catlog | pglog                       # 分析当前节点当日的日志
catlog node-1 '2021-07-15' | pglog   # 分析node-1在2021-07-15的csvlog

接下来,您可以访问以下的连接,查看样例日志分析界面。

  • PGLOG Overview: 呈现整份CSV日志样本详情,按多种维度聚合。
  • PGLOG Session: 呈现日志样本中一条具体连接的详细信息。

catlog命令从特定节点拉取特定日期的CSV数据库日志,写入stdout

默认情况下,catlog会拉取当前节点当日的日志,您可以通过参数指定节点与日期。

组合使用pglogcatlog,即可快速拉取数据库CSV日志进行分析。

catlog | pglog                       # 分析当前节点当日的日志
catlog node-1 '2021-07-15' | pglog   # 分析node-1在2021-07-15的csvlog

COVID

COVID是一个可视化WHO COVID-19数据,查阅各国疫情数据的应用样例。

公开演示:http://demo.pigsty.cc/d/covid-overview

安装方式

cd covid
make all         # 完整安装(会从WHO下载最新数据)
make all2        # 完整安装(会直接使用本地下载好的数据)

更精细的控制:

make ui          # 将covid dashboards安装至grafana
make sql         # 将covid 数据库表定义创建至metadb中
make download    # 下载WHO最新数据
make load        # 加载下载好的WHO数据
make reload      # download + load

如果已经下载了数据(例如,通过下载app.tgz获得应用程序),运行make all2代替,以跳过下载。

ISD

一个功能完成的数据应用,可以查询全球30000个地表气象站从1901年来的气象观测记录。

公开演示:http://demo.pigsty.cc/d/isd-overview

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

安装方式

cd isd
make all         # 完整安装(会从Github与NOAA下载最新数据)
make all2        # 完整安装(会直接使用本地下载好的数据)

更精细的控制:

make ui          # 将covid dashboards安装至grafana
make sql         # 将covid 数据库表定义创建至metadb中
make download    # 下载NOAA最新数据,ISD Parser,字典表
make baseline    # 使用下载好的数据初始化最基本的全局大盘功能
make reload      # 从NOAA下载最新的每日摘要并解析加载

37 - 容器指南

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty v1.5.1 带有Docker与Docker Compose部署支持,其中,Docker Daemon将默认在元节点上启用,以供安装更多SaaS服务

您可以使用Docker,快速部署启动软件应用,在容器中,您可以直接使用连接串访问部署于宿主机上的PostgreSQL/Redis数据库。

  • PgAdmin4 : 一个用于管理PostgreSQL数据库实例的GUI工具
  • PGWeb:一个自动根据PG数据库模式生成后端API服务的工具
  • PostgREST:一个自动根据PG数据库模式生成后端API服务的工具
  • ByteBase : 一个用于进行PostgreSQL模式变更的GUI工具
  • Gitea:Gitea私有Git托管服务
  • Jupyter Lab:一个开箱即用的数据分析与处理Python实验环境

您也可以使用Docker执行一些随用随抛的命令工具,例如:

  • SchemaSPY:生成数据库模式的详细可视化报表
  • Pgbadger:生成数据库日志报表

您也可以用Docker拉起一些开箱即用的开源SaaS服务:

  • Gitlab:开源代码托管平台。
  • Habour:开源镜像仓库
  • Jira:开源项目管理平台。
  • Confluence:开源知识托管平台。
  • Odoo:开源ERP
  • Mastodon:基于PG的社交网络
  • Discourse:基于PG与Redis的开源论坛

向Nginx添加新服务

本文介绍的大部分软件均对外提供Web界面,尽管您可以直接通过IP:Port的方式访问,但我们依然建议收敛访问入口,使用域名并统一从Nginx代理访问。使用以下配置与命令,向Nginx注册新的服务。

nginx_upstreams:
 - { name: postgrest , domain: api.pigsty.cc  , endpoint: "127.0.0.1:8884" }
 - { name: pgadmin   , domain: adm.pigsty.cc  , endpoint: "127.0.0.1:8885" }
 - { name: pgweb     , domain: cli.pigsty.cc  , endpoint: "127.0.0.1:8886" }
 - { name: bytebase  , domain: ddl.pigsty.cc  , endpoint: "127.0.0.1:8887" }
 - { name: jupyter   , domain: lab.pigsty.cc  , endpoint: "127.0.0.1:8888" }
 - { name: gitea     , domain: git.pigsty.cc  , endpoint: "127.0.0.1:8889" }
 - { name: minio     , domain: sss.pigsty.cc  , endpoint: "127.0.0.1:9000" }

./infra.yml -t nginx_config,nginx_restart    # 重新生成Nginx配置文件,并重启生效

Pull Image

docker pull kong                     # latest # 139MB
docker pull minio/minio              # latest # 227MB
docker pull alpine                   # latest # 5.57MB
docker pull registry                 # latest # 24.2MB
docker pull dpage/pgadmin4           # latest # 341MB
docker pull sosedoff/pgweb           # latest # 192MB
docker pull postgrest/postgrest      # latest # 16.3MB
docker pull swaggerapi/swagger-ui    # latest # 77MB
docker pull bytebase/bytebase:1.0.5  # 1.0.5  # 78.1MB
docker pull vonng/pg_exporter        # latest # 7.64B
docker pull gitea/gitea              # latest # 256MB
docker pull andrewjones/schemaspy-postgres # latest

PGADMIN

PgAdmin4 是一个实用的PostgreSQL管理工具,执行以下命令可在管理节点拉起 pgadmin服务:

cd ~/pigsty/app/pgadmin ; docker-compose up -d

默认分配 8885 端口,使用域名: http://adm.pigsty 访问, Demo:http://adm.pigsty.cc。

默认用户名:[email protected],密码:pigsty

PGWeb客户端工具

PGWeb是一款基于浏览器的PG客户端工具,使用以下命令,在元节点上拉起PGWEB服务,默认为主机8886端口。可使用域名: http://cli.pigsty 访问,公开Demo:http://cli.pigsty.cc。

# docker stop pgweb; docker rm pgweb
docker run --init --name pgweb --restart always --detach --publish 8886:8081 sosedoff/pgweb

用户需要自行填写数据库连接串,例如默认CMDB的连接串:

postgres://dbuser_dba:[email protected]:5432/meta?sslmode=disable

ByteBase

ByteBase是一个进行数据库模式变更的工具,以下命令将在元节点 8887 端口启动一个ByteBase。

mkdir -p /data/bytebase/data;
docker run --init --name bytebase --restart always --detach --publish 8887:8887 --volume /data/bytebase/data:/var/opt/bytebase \
    bytebase/bytebase:1.0.4 --data /var/opt/bytebase --host http://ddl.pigsty --port 8887

访问 http://10.10.10.10:8887/ 或 http://ddl.pigsty 即可使用 ByteBase,您需要依次创建项目、环境、实例、数据库,即可开始进行模式变更。 公开Demo地址: http://ddl.pigsty.cc

PostgREST

PostgREST是一个自动根据 PostgreSQL 数据库模式生成 REST API的二进制组件。

例如,以下命令将使用docker拉起 postgrest (本地 8884 端口,使用默认管理员用户,暴露Pigsty CMDB模式)

docker run --init --name postgrest --restart always --detach --publish 8884:8081 postgrest/postgrest

访问 http://10.10.10.10:8884 会展示所有自动生成API的定义,并自动使用 Swagger Editor 暴露API文档。

如果您想要进行增删改查,设计更精细的权限控制,请参考 Tutorial 1 - The Golden Key,生成一个签名JWT。

数据分析环境:Jupyter

Jupyter Lab 是一站式数据分析环境,下列命令将在 8887 端口启动一个Jupyter Server.

docker run -it --restart always --detach --name jupyter -p 8888:8888 -v "${PWD}":/tmp/notebook jupyter/scipy-notebook
docker logs jupyter # 打印日志,获取登陆的Token

访问 http://10.10.10.10:8888/ 即可使用 JupyterLab,(需要填入自动生成的Token)。

您也可以使用 infra-jupyter.yml 在管理节点裸机上启用Jupyter Notebook。

样例:数据库模式报表SchemaSPY

使用以下docker生成数据库模式报表,以CMDB为例:

docker run -v /www/schema/pg-meta/meta/pigsty:/output andrewjones/schemaspy-postgres:latest -host 10.10.10.10 -port 5432 -u dbuser_dba -p DBUser.DBA -db meta -s pigsty

然后访问 http://pigsty/schema/pg-meta/meta/pigsty 即可访问Schema报表

样例:开源代码仓库:Gitlab

请参考Gitlab Docker部署文档 完成Docker部署。

export GITLAB_HOME=/data/gitlab

sudo docker run --detach \
  --hostname gitlab.example.com \
  --publish 443:443 --publish 80:80 --publish 23:22 \
  --name gitlab \
  --restart always \
  --volume $GITLAB_HOME/config:/etc/gitlab \
  --volume $GITLAB_HOME/logs:/var/log/gitlab \
  --volume $GITLAB_HOME/data:/var/opt/gitlab \
  --shm-size 256m \
  gitlab/gitlab-ee:latest

sudo docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password

样例:开源技术论坛:Discourse

搭建开源论坛Discourse,需要调整配置 app.yml ,重点是SMTP部分的配置

Discourse配置样例
templates:
  - "templates/web.china.template.yml"
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
## Uncomment these two lines if you wish to add Lets Encrypt (https)
# - "templates/web.ssl.template.yml"
# - "templates/web.letsencrypt.ssl.template.yml"
expose:
  - "80:80"   # http
  - "443:443" # https
params:
  db_default_text_search_config: "pg_catalog.english"
  db_shared_buffers: "768MB"
env:
  LC_ALL: en_US.UTF-8
  LANG: en_US.UTF-8
  LANGUAGE: en_US.UTF-8
  EMBER_CLI_PROD_ASSETS: 1
  UNICORN_WORKERS: 4
  DISCOURSE_HOSTNAME: forum.pigsty
  DISCOURSE_DEVELOPER_EMAILS: '[email protected],[email protected]'
  DISCOURSE_SMTP_ENABLE_START_TLS: false
  DISCOURSE_SMTP_AUTHENTICATION: login
  DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none
  DISCOURSE_SMTP_ADDRESS: smtpdm.server.address
  DISCOURSE_SMTP_PORT: 80
  DISCOURSE_SMTP_USER_NAME: [email protected]
  DISCOURSE_SMTP_PASSWORD: "<password>"
  DISCOURSE_SMTP_DOMAIN: mail.pigsty.cc
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
run:
  - exec: echo "Beginning of custom commands"
  # - exec: rails r "SiteSetting.notification_email='[email protected]'"
  - exec: echo "End of custom commands"

然后,执行以下命令,拉起Discourse即可。

./launcher rebuild app

38 - 升级Grafana后端数据库

从 Pigsty v1.5.1 标签恢复的历史文档。

您可以使用 postgres 作为Grafana后端使用的数据库。

这是了解Pigsty部署系统使用方式的好机会,完成此教程,您会了解:

太长不看

vi pigsty.yml # 取消注释DB/User定义:dbuser_grafana  grafana
bin/createuser  pg-meta  dbuser_grafana
bin/createdb    pg-meta  grafana

psql postgres://dbuser_grafana:DBUser.Grafana@meta:5436/grafana -c \
  'CREATE TABLE t(); DROP TABLE t;' # 检查连接串可用性

vi /etc/grafana/grafana.ini # 修改 [database] type url
systemctl restart grafana-server

创建数据库集群

我们可以在pg-meta上定义一个新的数据库grafana, 也可以在新的机器节点上创建一个专用于Grafana的数据库集群:pg-grafana

定义集群

如果需要创建新的专用数据库集群pg-grafana,部署在10.10.10.1110.10.10.12两台机器上,可以使用以下配置文件:

pg-grafana:
  hosts:
    10.10.10.11: {pg_seq: 1, pg_role: primary}
    10.10.10.12: {pg_seq: 2, pg_role: replica}
  vars:
    pg_cluster: pg-grafana
    pg_databases:
      - name: grafana
        owner: dbuser_grafana
        revokeconn: true
        comment: grafana primary database
    pg_users:
      - name: dbuser_grafana
        password: DBUser.Grafana
        pgbouncer: true
        roles: [dbrole_admin]
        comment: admin user for grafana database

创建集群

使用以下命令完成数据库集群pg-grafana的创建:pgsql.yml

bin/createpg pg-grafana    # 初始化pg-grafana集群

该命令实际上调用了Ansible Playbook pgsql.yml 创建数据库集群。

./pgsql.yml -l pg-grafana  # 实际执行的等效Ansible剧本命令

定义在 pg_userspg_databases 中的业务用户与业务数据库会在集群初始化时自动创建,因此使用该配置时,集群创建完毕后,(在没有DNS支持的情况下)您可以使用以下连接串访问数据库(任一即可):

postgres://dbuser_grafana:[email protected]:5432/grafana # 主库直连
postgres://dbuser_grafana:[email protected]:5436/grafana # 直连default服务
postgres://dbuser_grafana:[email protected]:5433/grafana # 连接串读写服务

postgres://dbuser_grafana:[email protected]:5432/grafana # 主库直连
postgres://dbuser_grafana:[email protected]:5436/grafana # 直连default服务
postgres://dbuser_grafana:[email protected]:5433/grafana # 连接串读写服务

因为默认情况下Pigsty安装在单个元节点上,接下来的步骤我们会在已有的pg-meta数据库集群上创建Grafana所需的用户与数据库,而并非使用这里创建的pg-grafana集群。

创建Grafana业务用户

通常业务对象管理的惯例是:先创建用户,再创建数据库。 因为如果为数据库配置了owner,数据库对相应的用户存在依赖。

定义用户

要在pg-meta集群上创建用户dbuser_grafana,首先将以下用户定义添加至pg-meta集群定义中:

添加位置:all.children.pg-meta.vars.pg_users

- name: dbuser_grafana
  password: DBUser.Grafana
  comment: admin user for grafana database
  pgbouncer: true
  roles: [ dbrole_admin ]

如果您在这里定义了不同的密码,请在后续步骤中将相应参数替换为新密码

创建用户

使用以下命令完成dbuser_grafana用户的创建(任一均可)。

bin/createuser pg-meta dbuser_grafana # 在pg-meta集群上创建`dbuser_grafana`用户

实际上调用了Ansible Playbook pgsql-createuser.yml 创建用户

./pgsql-createuser.yml -l pg-meta -e pg_user=dbuser_grafana  # Ansible

dbrole_admin 角色具有在数据库中执行DDL变更的权限,这正是Grafana所需要的。

创建Grafana业务数据库

定义数据库

创建业务数据库的方式与业务用户一致,首先在pg-meta的集群定义中添加新数据库grafana定义

添加位置:all.children.pg-meta.vars.pg_databases

- { name: grafana, owner: dbuser_grafana, revokeconn: true }

创建数据库

使用以下命令完成grafana数据库的创建(任一均可)。

bin/createdb pg-meta grafana # 在`pg-meta`集群上创建`grafana`数据库

实际上调用了Ansible Playbook pgsql-createdb.yml 创建数据库

./pgsql-createdb.yml -l pg-meta -e pg_database=grafana # 实际执行的Ansible剧本

使用Grafana业务数据库

检查连接串可达性

您可以使用不同的服务接入方式访问数据库,例如:

postgres://dbuser_grafana:DBUser.Grafana@meta:5432/grafana # 直连
postgres://dbuser_grafana:DBUser.Grafana@meta:5436/grafana # default服务
postgres://dbuser_grafana:DBUser.Grafana@meta:5433/grafana # primary服务

这里,我们将使用通过负载均衡器直接访问主库的default服务访问数据库。

首先检查连接串是否可达,以及是否有权限执行DDL命令。

psql postgres://dbuser_grafana:DBUser.Grafana@meta:5436/grafana -c \
  'CREATE TABLE t(); DROP TABLE t;'

直接修改Grafana配置

为了让Grafana使用 Postgres 数据源,您需要编辑 /etc/grafana/grafana.ini,并修改配置项:

[database]
;type = sqlite3
;host = 127.0.0.1:3306
;name = grafana
;user = root
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
;password =
;url =

将默认的配置项修改为:

[database]
type = postgres
url =  postgres://dbuser_grafana:DBUser.Grafana@meta/grafana

随后重启Grafana即可:

systemctl restart grafana-server

从监控系统中看到新增的 grafana 数据库已经开始有活动,则说明Grafana已经开始使用Postgres作为首要后端数据库了。但一个新的问题是,Grafana中原有的Dashboards与Datasources都消失了!这里需要重新导入监控面板Postgres数据源

管理Grafana监控面板

您可以使用管理用户前往 Pigsty 目录下的files/ui目录,执行grafana.py init重新加载Pigsty监控面板。

cd ~/pigsty/files/ui
./grafana.py init    # 使用当前目录下的Dashboards初始化Grafana监控面板

执行结果:

vagrant@meta:~/pigsty/files/ui
$ ./grafana.py init
Grafana API: admin:pigsty @ http://10.10.10.10:3000
init dashboard : home.json
init folder pgcat
init dashboard: pgcat / pgcat-table.json
init dashboard: pgcat / pgcat-bloat.json
init dashboard: pgcat / pgcat-query.json
init folder pgsql
init dashboard: pgsql / pgsql-replication.json
init dashboard: pgsql / pgsql-table.json
init dashboard: pgsql / pgsql-activity.json
init dashboard: pgsql / pgsql-cluster.json
init dashboard: pgsql / pgsql-node.json
init dashboard: pgsql / pgsql-database.json
init dashboard: pgsql / pgsql-xacts.json
init dashboard: pgsql / pgsql-overview.json
init dashboard: pgsql / pgsql-session.json
init dashboard: pgsql / pgsql-tables.json
init dashboard: pgsql / pgsql-instance.json
init dashboard: pgsql / pgsql-queries.json
init dashboard: pgsql / pgsql-alert.json
init dashboard: pgsql / pgsql-service.json
init dashboard: pgsql / pgsql-persist.json
init dashboard: pgsql / pgsql-proxy.json
init dashboard: pgsql / pgsql-query.json
init folder pglog
init dashboard: pglog / pglog-instance.json
init dashboard: pglog / pglog-analysis.json
init dashboard: pglog / pglog-session.json

该脚本会侦测当前的环境(安装时定义于~/pigsty),获取Grafana的访问信息,并将监控面板中的URL连接占位符域名(*.pigsty)替换为真实使用的域名。

export GRAFANA_ENDPOINT=http://10.10.10.10:3000
export GRAFANA_USERNAME=admin
export GRAFANA_PASSWORD=pigsty

export NGINX_UPSTREAM_YUMREPO=yum.pigsty
export NGINX_UPSTREAM_CONSUL=c.pigsty
export NGINX_UPSTREAM_PROMETHEUS=p.pigsty
export NGINX_UPSTREAM_ALERTMANAGER=a.pigsty
export NGINX_UPSTREAM_GRAFANA=g.pigsty
export NGINX_UPSTREAM_HAPROXY=h.pigsty

题外话,使用grafana.py clean会清空目标监控面板,使用grafana.py load会加载当前目录下所有监控面板,当Pigsty的监控面板发生变更,可以使用这两个命令升级所有的监控面板。

管理Postgres数据源

当使用 pgsql.yml 创建新PostgreSQL集群,或使用pgsql-createdb.yml创建新业务数据库时,Pigsty会在Grafana中注册新的PostgreSQL数据源,您可以使用默认的监控用户通过Grafana直接访问目标数据库实例。应用pgcat的绝大部分功能有赖于此。

要注册Postgres数据库,可以使用pgsql.yml中的register_grafana任务:

./pgsql.yml -t register_grafana             # 重新注册当前环境中所有Postgres数据源
./pgsql.yml -t register_grafana -l pg-test  # 重新注册 pg-test 集群中所有的数据库

一步到位更新Grafana

您可以直接通过修改Pigsty配置文件,更改Grafana使用的后端数据源,一步到位的完成切换Grafana后端数据库的工作。编辑pigsty.ymlgrafana_databasegrafana_pgurl参数,将其修改为:

grafana_database: postgres
grafana_pgurl: postgres://dbuser_grafana:DBUser.Grafana@meta:5436/grafana

然后重新执行 infral.yml中的grafana任务,即可完成Grafana升级

./infra.yml -t grafana

39 - 部署教程:Jupyter Lab数据分析环境

从 Pigsty v1.5.1 标签恢复的历史文档。

太长不看

./infra-jupyter.yml # 在管理节点上安装 Jupyter Lab,使用8888端口,OS用户jupyter,默认密码 pigsty
./infra-jupyter.yml -e jupyter_port=8887 # 使用另一个端口(默认为8888)
./infra-jupyter.yml -e jupyter_username=osuser_jupyter jupyter_password=pigsty2 # 使用不同的操作系统用户与密码

Jupyter配置

ID Name Section Type Level Comment
220 jupyter_port JUPYTER G 是否启用JupyterLab
221 jupyter_username JUPYTER G Jupyter使用的操作系统用户
222 jupyter_password JUPYTER G Jupyter Lab的密码

Jupyter Lab 是基于 IPython Notebook 的完整数据科学研发环境,可用于数据分析与可视化。默认安装,但不会启用Web Server。

因为JupyterLab提供了Web Terminal功能,因此不建议在生产环境中开启,可以使用 infra-jupyter 在元节点上手动部署。

默认值 Values

jupyter_username: jupyter       # os user name, special names: default|root (dangerous!)
jupyter_password: pigsty        # default password for jupyter lab (important!)
jupyter_port: 8887              # default port for jupyter lab

jupyter_port

Jupyter监听端口, 类型:int,层级:G,默认值为:8888

启用JupyterLab时,Pigsty会使用jupyter_username 参数指定的用户运行本地Notebook服务器。 此外,需要确保配置node_packages_meta_pip 参数包含默认值 'jupyterlab'。 Jupyter Lab可以从Pigsty首页导航进入,或通过默认域名 lab.pigsty 访问,默认监听于8888端口。

jupyter_username

Jupyter使用的操作系统用户, 类型:bool,层级:G,默认值为:"jupyter"

其他用户名亦同理,但特殊用户名default会使用当前执行安装的用户(通常为管理员)运行 Jupyter Lab,这会更方便,但也更危险。

jupyter_password

Jupyter Lab的密码, 类型:bool,层级:G,默认值为:"pigsty"

如果启用Jupyter,强烈建议修改此密码。加盐混淆的密码默认会写入~jupyter/.jupyter/jupyter_server_config.json

Jupyter剧本

infra-jupyter

infra-jupyter.yml 剧本用于在元节点上加装 Jupyter Lab服务

Jupyter Lab 是非常实用的Python数据分析环境,但自带WebShell,风险较大。因此默认情况下,Demo环境,单机配置模板中会启用 JupyterLab,生产环境部署模版中默认不会启用JupyterLab

请参照:配置:Jupyter 中的说明调整配置清单,然后执行此剧本即可。

警告

如果您在生产环境中启用了Jupyter,请务必修改Jupyter的密码

40 - 备份与恢复

从 Pigsty v1.5.1 标签恢复的历史文档。

备份是DBA的安身立命之本,也是数据库管理中最为关键的工作之一。

故障大体可以分为两类:硬件故障/资源不足(坏盘/宕机),软件缺陷/人为错误(删库/删表)。基于主从复制的物理复制用于应对前者,延迟从库与冷备份通常用于应对后者。

Pigsty提供了完善的备份支持,无需配置即可使用开箱即用的主从物理复制,绝大多数物理故障均可自愈。同时,还提供了延迟备库与冷备份支持,用于应对软件故障与人为误操作。

物理复制

在Pigsty中,可以通过为集群中的数据库实例指定角色( pg_role ),即可以创建物理复制备份,用于从机器与硬件故障中恢复。例如以下配置声明了一个一主两从的高可用数据库集群。

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary } # 主库
    10.10.10.12: { pg_seq: 2, pg_role: replica } # 热备(承载在线只读流量)
    10.10.10.13: { pg_seq: 3, pg_role: offline } # 温备(不承载在线流量)
  vars:
    pg_cluster: pg-test

热备

replica = Hot Standby,承载只读流量,与主库保持实时同步,但可能存在微量复制延迟。

与主库保持一致,当主库出现故障时会接管主库的工作,同时也会用于承接线上只读流量。其中,采用同步复制与主库保持实时一致的热备又可以称为同步备份。正常情况下,物理复制的复制延迟视网络条件与负载水平,可能在1ms-100ms/几十KB ~ 几MB的范围。请参考主从集群

温备

offline = Warm Standby,温备,不承担在线流量。备用,或仅用于离线/分析查询。

温备(Warm Standby):与热备类似,但不承载线上流量。请参考离线从库部署

同步备库

standby = Sync Standby,与主库保持严格实时同步。

使用同步提交的从库,又称做同步备库,详情请参考同步从库部署

延迟从库

延迟从库相比是一种快速应对软件故障/人为错误的措施。延迟从库采用标准的主从流复制机制从主库实时接收变更,但会延迟一段特定时间(例如1小时,一天)后再执行应用。因此在状态上,是原始主库的历史状态副本。当出现诸如误删数据这类问题时,实时主从同步会立即将此类变更同步至所有物理副本,但延迟从库则提供了一个抢救时间窗口:您可以立即从延迟从库中查询出数据并回补原主库。

高可用与主从复制可以解决机器硬件故障带来的问题,但无法解决软件Bug与人为操作导致的故障,例如:误删库删表。误删数据通常需要用到冷备份,但另一种更优雅高效快速的方式是事先准备一个延迟从库。

您可以使用 备份集群 的功能创建延时从库,例如,现在您希望为pg-test 集群指定一个延时从库:pg-testdelay,该集群是pg-test1小时前的状态。因此如果出现了误删数据,您可以立即从延时从库中获取并回灌入原始集群中。

# pg-test是原始数据库
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-test
    pg_version: 14

# pg-testdelay 将作为 pg-test 库的延时从库
pg-testdelay:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary , pg_upstream: 10.10.10.11 } # 实际角色为 Standby Leader
  vars:
    pg_cluster: pg-testdelay
    pg_version: 14

创建完毕后,在元节点使用 pg edit-config pg-testdelay编辑延时集群的Patroni配置文件,修改 standby_cluster.recovery_min_apply_delay 为你期待的值,例如1h,应用即可。

 standby_cluster:
   create_replica_methods:
   - basebackup
   host: 10.10.10.11
   port: 5432
+  recovery_min_apply_delay: 1h

冷备份

冷备份是最后的兜底机制,您可能几年都用不上一次,但真用上的时候,可以救命。

冷备(Code Backup):冷备数据库以数据目录静态文件的形式存在,是数据库目录的二进制备份。便于制作,管理简单,便于放到其他AZ实现容灾。误删库误删表,或整集群/整机房出现灾难性故障时,数据备份(冷备)是最后的兜底。

Pigsty提供了一个制作冷备份的脚本 pg-backup,在数据库节点上以dbsu身份执行,即可创建当前实例的全量物理备份,并放置于 /pg/backup 目录中(默认位于 {{ pg_fs_bkup }}/backup)。 用户可以通过参数来指定备份的数据库URL,备份目录,文件名,加密方式,已有备份的保留策略等。

$ pg-backup # 不带任何参数执行备份脚本
[2021-08-05 17:41:35][INFO] ================================================================
[2021-08-05 17:41:35][INFO] [INIT] pg-backup begin, checking parameters
[2021-08-05 17:41:35][DEBUG] [INIT] #====== BINARY
[2021-08-05 17:41:35][DEBUG] [INIT] pg_basebackup     :   /usr/pgsql/bin/pg_basebackup
[2021-08-05 17:41:35][DEBUG] [INIT] openssl           :   /bin/openssl
[2021-08-05 17:41:35][DEBUG] [INIT] #====== PARAMETER
[2021-08-05 17:41:35][DEBUG] [INIT] filename  (-f)    :   backup_pg-meta_20210805.tar.lz4
[2021-08-05 17:41:35][DEBUG] [INIT] src       (-s)    :   postgres:///
[2021-08-05 17:41:35][DEBUG] [INIT] dst       (-d)    :   /pg/backup
[2021-08-05 17:41:35][DEBUG] [INIT] tag       (-t)    :   pg-meta
[2021-08-05 17:41:35][DEBUG] [INIT] key       (-k)    :   pg-meta
[2021-08-05 17:41:35][DEBUG] [INIT] encrypt   (-e)    :   false
[2021-08-05 17:41:35][DEBUG] [INIT] upload    (-u)    :   false
[2021-08-05 17:41:35][DEBUG] [INIT] remove    (-r)    :   -mmin +1200
[2021-08-05 17:41:35][INFO] [LOCK] acquire lock @ /tmp/backup.lock
[2021-08-05 17:41:35][INFO] [LOCK] lock acquired success on /tmp/backup.lock, pid=25438
[2021-08-05 17:41:35][INFO] [BKUP] backup begin, from postgres:/// to /pg/backup/backup_pg-meta_20210805.tar.lz4
[2021-08-05 17:41:35][INFO] [BKUP] backup in normal mode
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/6B000028 on timeline 1
pg_basebackup: write-ahead log end point: 0/6B000138
pg_basebackup: syncing data to disk ...
pg_basebackup: base backup completed
[2021-08-05 17:41:45][INFO] [BKUP] backup complete!
[2021-08-05 17:41:45][INFO] [RMBK] remove local obsolete backup: 1200
[2021-08-05 17:41:45][INFO] [BKUP] find obsolete backups: find /pg/backup/ -maxdepth 1 -type f -mmin +1200 -name 'backup*.lz4'
[2021-08-05 17:41:45][WARN] [BKUP] remove obsolete backups:
[2021-08-05 17:41:45][INFO] [RMBK] remove old backup complete
[2021-08-05 17:41:45][INFO] [LOCK] release lock @ /tmp/backup.lock
[2021-08-05 17:41:45][INFO] [DONE] backup procdure complete!
[2021-08-05 17:41:45][INFO] ================================================================

该脚本将使用 pg_basebackup 从指定的PGURL(默认为本地数据库实例)发起备份,使用tar归档与lz4压缩,并加以可选的openssl RC4流加密。

备份文件默认放置于/pg/backup/目录下,默认文件名由前缀,集群名,日期组成,形如:backup_pg-meta_20210805.tar.lz4

默认的备份清理策略是当最新备份完成时,会清理掉1200分钟(20小时前)的旧备份文件。

您需要根据自己的业务情况,使用该脚本制作备份并放置在合适的地方,例如专用的对象存储集群/NFS/或者本地备份盘。如果您希望将数据库回溯至任意时刻,而非仅仅回滚至数据库备份时刻,则还需要对集群WAL日志进行归档。因为此功能需要具体功能具体分析,因此Pigsty只提供工具与机制,不提供具体策略与实现。您可以使用配置于节点上的Crontab与本地目录作为最基本的冷备份实现。

node_crontab: # 每日凌晨1点执行一次全量备份
  - '00 01 * * * postgres /pg/bin/pg-backup 2>>/pg/log/backup.log'

从冷备份中恢复

需要使用该备份时,您需要将PG集群设置为维护模式(pg pause <cluster>),停止数据集群主库并清空数据集簇目录,然后冷备份文件解压至/pg/data中,相关命令如下所示。

# 找到最新的备份文件并打印信息
backup_dir="/pg/backup"
data_dir=/pg/data
backup_latest=$(ls -t ${backup_dir} | head -n1)
echo "backup ${backup_latest} will be used"

# 暂停Patroni,关停数据库,移除数据目录(危险)
pg pause pg-meta
pg_ctl -D /pg/data stop
rm -rf /pg/data/*     # 清空数据目录(危险)

# 解压备份至数据库目录
echo "unlz4 -d -c ${backup_dir}/${backup_latest} | tar -xC ${data_dir}"
unlz4 -d -c ${backup_dir}/${backup_latest} | tar -xC ${data_dir}    # 解压至数据库目录
# 可选:如果加密时设置了密码,则需要先解密再解压
openssl enc -rc4 -d -k ${PASSWORD} -in ${backup_latest} | unlz4 -d -c | tar -xC ${data_dir}

# 重新拉起数据库
systemctl restart patroni

# 重做集群的其他从库
pg reinit <cluster> # 依次重置集群的其他实例成员

您也可以使用冷备份创建新的集群进行PITR,或使用 pg_probackup 与 pg_backrest 等工具进行外部备份管理。

41 - 离线安装

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty是一个复杂的软件系统,为了确保系统的稳定,Pigsty会在初始化过程中从互联网下载所有依赖的软件包并建立本地仓库 (本地Yum源)。

所有依赖的软件总大小约1GB左右,下载速度取决于用户的网络情况。尽管Pigsty已经尽量使用镜像源以加速下载,但少量包的下载仍可能受到防火墙的阻挠,可能出现非常慢的情况。用户可以通过 proxy_env 配置项设置下载代理,以完成首次下载。

如果您使用了不同于CentOS 7.8的操作系统,通常建议用户采用完整的在线下载安装流程。并在首次初始化完成后缓存下载的软件,参见制作离线安装包

如果您希望跳过漫长的下载过程,或者执行控制的元节点没有互联网访问,则可以考虑下载预先打包好的离线安装包

离线安装包的内容

为了快速拉起Pigsty,建议使用离线下载软件包并上传的方式完成安装。

离线安装包收纳了本地Yum源的所有软件包。默认情况下,Pigsty会在基础设施初始化时创建本地Yum源,

{{ nginx_home }}
  |---- {{ repo_name }}.repo
  ^---- {{ repo_name}}/repo_complete
  ^---- {{ repo_name}}/**************.rpm

默认情况下,{{ nginx_home }} 是Nginx静态文件服务器的根目录,默认为/wwwrepo_name是自定义的本地源名称,默认为pigsty

以默认情况为例,/www/pigsty 目录包含了所有 RPM 软件包,离线安装包实际上就是 /www/pigsty 目录的压缩包 。

离线安装包的原理是,Pigsty在执行基础设施初始化的过程中,会检查本地Yum源相关文件是否已经存在。如果已经存在,则会跳过下载软件包及其依赖的过程。

检测所用的标记文件为{{ nginx_home }}/{{ repo_name }}/repo_complete,默认情况下为/www/pigsty/repo_complete,如果该标记文件存在,(通常是由Pigsty在创建本地源之后设置),则表示本地源已经建立完成,可以直接使用。否则,Pigsty会执行常规的下载逻辑。下载完毕后,您可以将该目录压缩复制归档,用于加速其他环境的初始化。

沙箱环境

下载离线安装包

Pigsty自带了一个沙箱环境,沙箱环境的离线安装包默认放置于files目录中,可以从Github Release页面下载。

curl -SL https://github.com/pgsty/pigsty/releases/download/v1.5.1/pkg.tgz -o dist/v1.5.1/pkg.tgz

Pigsty的官方CDN也提供最新版本的pkg.tgz下载,只需要执行以下命令即可。

make download
curl http://download.pigsty.cc/v1.5.1/pkg.tgz -o files/pkg.tgz

上传离线安装包

使用Pigsty沙箱时,下载离线安装包至本地files目录后,则可以直接使用 Makefile 提供的快捷指令make copy-pkg上传离线安装包至元节点上。

使用 make upload,也会将本地的离线安装包(Yum缓存)拷贝至元节点上。

# upload rpm cache to meta controller
upload:
	ssh -t meta "sudo rm -rf /tmp/pkg.tgz"
	scp -r files/pkg.tgz meta:/tmp/pkg.tgz
	ssh -t meta "sudo mkdir -p /www/pigsty/; sudo rm -rf /www/pigsty/*; sudo tar -xf /tmp/pkg.tgz --strip-component=1 -C /www/pigsty/"

制作离线安装包

使用 Pigsty 沙箱时,可以通过 make cache 将沙箱中元节点的缓存制为离线安装包,并拷贝到本地。

# cache rpm packages from meta controller
cache:
	rm -rf pkg/* && mkdir -p pkg;
	ssh -t meta "sudo tar -zcf /tmp/pkg.tgz -C /www pigsty; sudo chmod a+r /tmp/pkg.tgz"
	scp -r meta:/tmp/pkg.tgz files/pkg.tgz
	ssh -t meta "sudo rm -rf /tmp/pkg.tgz"

在生产环境离线安装包

在生产环境使用离线安装包前,您必须确保生产环境的操作系统与制作该离线安装包的机器操作系统一致。Pigsty提供的离线安装包默认使用CentOS 7.8。

使用不同操作系统版本的离线安装包可能会出错,也可能不会,我们强烈建议不要这么做。

如果需要在其他版本的操作系统(例如CentOS7.3,7.7等)上运行Pigsty,建议用户在安装有同版本操作系统的沙箱中完整执行一遍初始化流程,不使用离线安装包,而是直接从上游源下载的方式进行初始化。对于没有网络访问的生产环境元节点而言,制作离线软件包是至关重要的。

常规初始化完成后,用户可以通过make cache或手工执行相关命令,将特定操作系统的软件缓存打为离线安装包。供生产环境使用。

从初始化完成的本地元节点构建离线安装包:

tar -zcf /tmp/pkg.tgz -C /www pigsty     # 制作离线软件包

在生产环境使用离线安装包与沙箱环境类似,用户需要将pkg.tgz复制到元节点上,然后将离线安装包解压至目标地址。

这里以默认的 /www/pigsty 为例,将压缩包中的所有内容(RPM包,repo_complete标记文件,repodata 源的元数据库等)解压至目标目录/www/pigsty中,可以使用以下命令。

mkdir -p /www/pigsty/
sudo rm -rf /www/pigsty/*
sudo tar -xf /tmp/pkg.tgz --strip-component=1 -C /www/pigsty/

42 - 使用CMDB

从 Pigsty v1.5.1 标签恢复的历史文档。

您可以使用 postgres 作为 Pigsty 的配置源,替代静态配置文件。

使用 CMDB 作为 Ansible 的动态 Inventory具有一些优点:元数据以高度结构化的方式以数据表的形式呈现,并通过数据库约束确保一致性。同时CMDB允许您使用第三方的工具来编辑管理Pigsty元数据,便于与外部系统相互集成。

目前 Pigsty 的CMDB仅支持 PostgreSQL 集群,如果您的 pigsty.yml 中包含 Redis与MatrixDB,则会报错,建议使用单独的 pigsty.yml 配置文件管理Redis与Greenplum集群。

加载配置

Pigsty CMDB的模式会在pg-meta元数据库初始化时自动创建(files/cmdb.sql),位于meta数据库的pigsty 模式中。使用bin/inventory_load可以将静态配置文件加载至CMDB中。

警告

必须在元节点完整执行 infra.yml,安装完毕后,方可使用CMDB

usage: inventory_load [-h] [-p PATH] [-d CMDB_URL]

load config arguments

optional arguments:
  -h, --help            show this help message and exit„
  -p PATH, --path PATH  config path, ${PIGSTY_HOME}/pigsty.yml by default
  -d DATA, --data DATA  postgres cmdb pgurl, ${METADB_URL} by default

默认情况下,不带参数执行该脚本将会把$PIGSTY_HOME/pigsty.yml的名称载入默认CMDB中。

bin/inventory_load
bin/inventory_load -p files/conf/pigsty-demo.yml
bin/inventory_load -p files/conf/pigsty-dcs3.yml -d postgresql://dbuser_meta:[email protected]:5432/meta

使用CMDB作为配置源

当原有配置文件加载至CMDB作为初始数据后,即可配置Ansible使用CMDB作为配置源:

bin/inventory_cmdb

您可以切换回静态配置文件:

bin/inventory_conf

修改配置源实质上是编辑Pigsty目录下的 ansible.cfg 实现的。

---
inventory = pigsty.yml
+++
inventory = inventory.sh

43 - 数据库迁移教程

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty内置了一个 数据库在线迁移的辅助脚本:pgsql-migration.yml ,提供了一个开箱即用的基于逻辑复制的不停机数据库迁移方案。

填入源集群与宿集群相关信息,该剧本即会自动创建出迁移中所需的脚本,在数据库迁移时只需要依次执行即可,包括:

activate                          # 激活迁移上下文,注册环境变量
check-replica-identity            # 准备阶段:检查源集群所有表是否都具有复制身份(主键,或非空唯一候选键)
check-replica-identity-solution   # 准备阶段:针对没有合理复制身份表,生成修复SQL语句
check-special-object              # 准备阶段:检查物化视图,复合类型等特殊对象
compare                           # 比较:对源宿集群中的表进行快速比较(行数计算)
copy-schema                       # 存量迁移:将源集群中的模式复制到宿集群中(可以幂等执行)
create-pub                        # 存量迁移:在源集群中创建发布
create-sub                        # 存量迁移:在宿集群中创建订阅,建立源宿集群之间的逻辑复制
progress                          # 存量迁移:打印逻辑复制的进度
copy-seq                          # 存量/增量迁移:将源集群中的序列号复制到宿集群中(可以幂等执行,在切换时需要再次执行)
next-seq                          # 切换时刻:将宿集群的所有序列号紧急步进1000,以避免主键冲突。
remove-sub                        # 移除宿集群中的逻辑订阅

准备工作

准备源宿集群

现在假设我们希望迁移沙箱中的pg-meta集群(包含Pigsty元数据库与pgbench测试表)至pg-test集群。

pg-meta-1	10.10.10.10  --> pg-test-1	10.10.10.11 (10.10.10.12,10.10.10.13)

首先,新创建好空的目标集群pg-test,然后编辑pgsql-migration.yml 中的变量清单部分,填入相关信息(原宿集群主库的连接信息)

#--------------------------------------------------------------#
#                   MIGRATION CONTEXT                          #
#--------------------------------------------------------------#

# src cluster (the old cluster)
src_cls: pg-meta                       # src cluster name
src_db: meta                           # src database name
src_ip: 10.10.10.10                    # ip address of src cluster primary
src_list: [ ]                          # ip address list of src cluster members (non-primary)

#--------------------------------------------------------------#
# dst cluster (the new cluster)
dst_cls: pg-test                       # dst cluster name
dst_db: test                           # dst database name
dst_ip: 10.10.10.11                    # dst cluster leader ip addressh
dst_list: [ 10.10.10.12, 10.10.10.13 ] # dst cluster members (non-primary)

# dst cluster access information
dst_dns: pg-test                       # dst cluster dns records
dst_vip: 10.10.10.3                    # dst cluster vip records

#--------------------------------------------------------------#
# credential (assume .pgpass viable)
pg_admin_username: dbuser_dba          # superuser @ both side
pg_replicatoin_username: replicator    # repl user @ src to be used
migration_context_dir: ~/migration     # this dir will be created
#--------------------------------------------------------------#

执行pgsql-migration.yml,该脚本默认会在元节点上创建 ~/migration/pg-meta.meta 目录,包含有迁移使用的资源与脚本。

迁移模板

公告

准备工作

存量迁移

切换时刻

44 - SOP: 标准操作流程

从 Pigsty v1.5.1 标签恢复的历史文档。

本文给出了Pigsty中PGSQL数据库相关的常用运维操作命令

大多数集群管理操作都需要使用到元节点上的管理用户,并在Pigsty根目录执行相应Ansible Playbook。以下示例如无特殊说明,均以沙箱环境,三节点集群 pg-test作为演示对象。

操作命令速查表

集群实例管理

在元节点上使用管理用户执行以下命令管理PostgreSQL集群与实例:

bin/createpg   pg-test       # 初始化PGSQL集群 pg-test
bin/createpg   10.10.10.13   # 初始化PGSQL实例 10.10.10.13
bin/reloadha   pg-test       # 调整PGSQL集群 pg-test 的负载均衡配置
bin/reloadhba  pg-test       # 调整PGSQL集群 pg-test 的认证白名单配置
bin/createuser pg-test -e pg_user=test     # 在PG集群pg-test创建用户test
bin/createdb   pg-test -e pg_database=test # 在PG集群pg-test创建数据库test

底层的相应的Ansible剧本为:

# NODES集群创建/集群扩容
./nodes.yml -l pg-test       # 集群初始化
./nodes.yml -l 10.10.10.13   # 实例初始化

# PGSQL集群创建/集群扩容
./pgsql.yml -l pg-test       # 集群初始化
./pgsql.yml -l 10.10.10.13   # 实例初始化

# PGSQL集群销毁/实例销毁
./pgsql-remove.yml -l pg-test      # 集群销毁
./pgsql-remove.yml -l 10.10.10.13  # 实例销毁

# NODES集群销毁/实例销毁
./nodes-remove.yml -l pg-test      # 集群销毁
./nodes-remove.yml -l 10.10.10.13  # 实例销毁

# PGSQL业务数据库/用户创建
./pgsql-createuser.yml -l pg-test -e pg_user=test
./pgsql-createdb.yml   -l pg-test -e pg_database=test

# 成员身份调整
./pgsql.yml -l pg-test -t pg_hba   # 调整IP白名单
./pgsql.yml -l pg-test -t haproxy_config,haproxy_reload

# 服务注册信息调整
./pgsql.yml -l pg-test -t register_prometheus
./pgsql.yml -l pg-test -t register_grafana

Patroni数据库管理

Pigsty默认使用Patroni管理PostgreSQL实例数据库。这意味着您需要使用patronictl命令来管理Postgres集群,包括:集群配置变更,重启,Failover,Switchover,重做特定实例,切换自动/手动高可用模式等。

用户可以使用patronictl在元节点上的管理用户,或任意数据库节点的dbsu执行。快捷命令pg已经在所有托管的机器上创建,用户可以使用它对所有目标Postgres集群发起管理。

常用的管理命令如下所示,更多命令请参考pg --help

pg list        [cluster]             # 打印集群信息
pg edit-config [cluster]             # 编辑某个集群的配置文件

pg reload      [cluster] [instance]  # 重载某个集群或实例的配置
pg restart     [cluster] [instance]  # 重启某个集群或实例
pg reinit      [cluster] [instance]  # 重置某个集群中的实例(重新制作从库)

pg pause       [cluster]             # 进入维护模式(不会触发自动故障切换)
pg resume      [cluster]             # 退出维护模式

pg failover    [cluster]             # 手工触发某集群的Failover
pg switchover  [cluster]             # 手工触发某集群的Switchover

服务组件管理

在Pigsty的部署中,所有组件均由systemd管理;PostgreSQL除外,PostgreSQL由Patroni管理。

例外的例外:当 patroni_moderemove 时例外,Pigsty将直接使用systemd管理Postgres

systemctl stop patroni            # 关闭 Patroni & Postgres
systemctl stop pgbouncer          # 关闭 Pgbouncer
systemctl stop pg_exporter        # 关闭 PG Exporter
systemctl stop pgbouncer_exporter # 关闭 Pgbouncer Exporter
systemctl stop node_exporter      # 关闭 Node Exporter
systemctl stop haproxy            # 关闭 Haproxy
systemctl stop vip-manager        # 关闭 Vip-Manager
systemctl stop consul             # 关闭 Consul
systemctl stop postgres           # 关闭 Postgres (patroni_mode = remove )

以下组件可以通过 systemctl reload 重新加载配置

systemctl reload patroni             # 重载配置: Patroni
systemctl reload postgres            # 重载配置: Postgres (patroni_mode = remove)
systemctl reload pgbouncer           # 重载配置: Pgbouncer
systemctl reload pg_exporter         # 重载配置: PG Exporter
systemctl reload pgbouncer_exporter  # 重载配置: Pgbouncer Exporter
systemctl reload haproxy             # 重载配置: Haproxy
systemctl reload vip-manager         # 重载配置: vip-manager
systemctl reload consul              # 重载配置: Consul

在元节点上,还可以通过 systemctl reload 重新加载基础设施组件的配置:

systemctl reload nginx          # 重载配置: Nginx (更新Haproxy管理界面索引,以及外部访问域名)
systemctl reload prometheus     # 重载配置: Prometheus (更新预计算指标计算逻辑与告警规则)
systemctl reload alertmanager   # 重载配置: Alertmanager
systemctl reload grafana-server # 重载配置: Grafana

当Patroni管理Postgres时,请不要使用 pg_ctl 直接操作数据库集簇 (/pg/data)。

您可以通过pg pause <cluster>进入维护模式后再对数据库进行手工管理。

常用命令集锦

./infra.yml -t environ             # 重新在元节点上配置环境变量与访问凭证
./infra.yml -t repo_upstream       # 重新在元节点上添加上游repo
./infra.yml -t repo_download       # 重新在元节点上下载软件包
./infra.yml -t nginx_home          # 重新生成Nginx首页内容
./infra.yml -t nginx_config,nginx_restart # 重新生成Nginx配置文件并重启应用
./infra.yml -t prometheus_config   # 重置Prometheus配置
./infra.yml -t grafana_provision   # 重置Grafana监控面板
./pgsql.yml -l pg-test -t=pgsql       # 完成数据库部署:数据库、监控、服务
./pgsql.yml -l pg-test -t=postgres    # 完成数据库部署
./pgsql.yml -l pg-test -t=service     # 完成负载均衡的部署,(Haproxy & VIP)
./pgsql.yml -l pg-test -t=pg-exporter # 完成监控部署
./pgsql.yml -l pg-test -t=pg-register # 将服务注册至基础设施
./pgsql.yml -l pg-test -t=register_prometheus # 将监控对象注册至Prometheus
./pgsql.yml -l pg-test -t=register_grafana    # 将监控目标数据源注册至Grafana

Case 1:集群创建扩容

集群创建/扩容使用剧本 pgsql.yml创建集群使用集群名作为执行对象,创建新实例/集群扩容则以集群中的单个实例作为执行对象。在使用 pgsql.yml 部署PGSQL数据库前,目标节点应当已经被 nodes.yml 剧本初始化。您可以使用 bin/createpg一次性完成两者。

集群初始化

./nodes.yml -l pg-test      # 初始化 pg-test 包含的机器节点
./pgsql.yml -l pg-test      # 初始化 pg-test 数据库集群

上述两剧本可简化为:

bin/createpg pg-test

集群扩容

假设现在有测试集群pg-test,包含两实例10.10.10.1110.10.10.12,现额外扩容一台10.10.10.13

修改配置

首先需要修改配置清单(pigsty.yml或CMDB)中的相应配置。

警告

请一定注意集群中各实例的pg_seq 必须唯一,否则会出现身份重叠与重复。

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 3, pg_role: replica, pg_offline_query: true } # 新实例
  vars: { pg_cluster: pg-test }

执行变更

然后,执行以下命令,完成集群成员的初始化

./nodes.yml -l 10.10.10.13      # 初始化 pg-test 机器节点 10.10.10.13
./pgsql.yml -l 10.10.10.13      # 初始化 pg-test 的实例 pg-test-3

# 上述两命令可简化为:
bin/createpg 10.10.10.13

调整角色

集群扩容会导致集群成员变化,请参考 Case 8:集群角色调整 将流量分发至新实例。

常见问题

常见问题1:PGSQL数据库已经存在,执行中止

Pigsty使用安全保险机制来避免误删运行中的PGSQL数据库,请使用 pgsql-remove 剧本先完成数据库实例下线,再复用该节点。如需进行紧急覆盖式安装,可使用以下参数在安装过程中强制抹除运行中实例(危险!!!)

例如:./pgsql.yml -l pg-test -e pg_clean=true 将强制对 pg-test集群进行覆盖式安装。

常见问题2:Consul已经存在,执行中止

Pigsty使用安全保险机制来避免误删运行中的Consul实例,请使用 nodes-remove 剧本先完成节点下线,确保Consul已经移除,再复用该节点。如需进行紧急覆盖式安装,可使用以下参数在安装过程中强制抹除运行中实例(危险!!!)

常见问题3:数据库太大,扩容从库执行超时

当扩容操作卡在 Wait for postgres replica online 这一步并中止时,通常是因为已有数据库实例太大,超过了Ansible的超时等待时间。

如果报错中止,该实例仍然会继续在后台拉起从库实例,您可以使用 pg list pg-test 命令列出集群当前状态,当新从库的状态为running时,可以使用以下命令,从中止的地方继续执行Ansible Playbook:

./pgsql.yml -l 10.10.10.13 --start-at-task 'Wait for postgres replica online'

如果拉起新从库因某些意外而中止,请参考常见问题2。

常见问题4:集群处于维护模式 ,从库没有自动拉起

解决方案1,使用pg resume pg-test 将集群配置为自动切换模式,再执行从库创建操作。

解决方案2,使用pg reinit pg-test pg-test-3,手动完成实例初始化。该命令也可以用于重做集群中的现有实例

常见问题5:集群从库带有`clonefrom`标签,但因数据损坏不宜使用或拉取失败

找到问题机器,切换至postgres用户,修改 patroni 配置文件并重载生效

sudo su postgres
sed -ie 's/clonefrom: true/clonefrom: false/' /pg/bin/patroni.yml
sudo systemctl reload patroni
pg list -W # 查阅集群状态,确认故障实例没有clonefrom标签
常见问题6:如何使用现有用户创建固定的管理员用户

系统默认使用 dba 作为管理员用户,该用户应当可以从管理机通过ssh免密码登陆远程数据库节点,并免密码执行sudo命令。

如果分配的机器默认没有该用户,但您有其他的管理用户(例如vagrant)可以ssh登陆远程节点并执行sudo,则可以执行以下命令,使用其他的用户登陆远程机器并自动创建标准的管理用户:

./nodes.yml -t node_admin -l pg-test -e ansible_user=vagrant -k -K
SSH password:
BECOME password[defaults to SSH password]:

如果指定-k|--ask-pass -K|--ask-become-pass 参数,则在执行前应当输入该管理用户的SSH登陆密码与sudo密码。

执行完毕后,即可从元节点上的管理用户(默认为dba) 登陆目标数据库机器,并执行其他剧本。

偶见问题7:集群从库带有clonefrom标签,但因数据损坏不宜使用或拉取失败

找到问题机器,切换至postgres用户,修改 patroni 配置文件并重载生效

sudo su postgres
sed -ie 's/clonefrom: true/clonefrom: false/' /pg/bin/patroni.yml
sudo systemctl reload patroni
pg list -W # 查阅集群状态,确认故障实例没有clonefrom标签

Case 2:集群下线缩容

集群销毁/缩容使用专用剧本pgsql-remove ,针对集群使用时,将下线移除整个集群。针对集群中的单个实例使用时,将从集群中移除该实例。

注意,直接移除集群主库将导致集群Failover,故同时移除包含主库在内的多个实例时,建议先移除所有从库,再移除主库。

警告

注意,pgsql-remove 剧本不受 安全保险 参数影响,会直接移除数据库实例,谨慎使用!

集群销毁

# 销毁 pg-test 集群:先销毁所有非主库实例,最后销毁主库实例
./pgsql-remove.yml -l pg-test

# 销毁集群时,一并移除数据目录与软件包
./pgsql-remove.yml -l pg-test -e rm_pgdata=true -e rm_pgpkgs=true

# 移除 pg-test 包含的节点,可选
./nodes-remove.yml -l pg-test

集群缩容

./pgsql-remove.yml -l 10.10.10.13  # 实例销毁(缩容):销毁 pg-test 集群中的 10.10.10.13 节点
./nodes-remove.yml -l 10.10.10.13  # 从Pigsty中移除 10.10.10.13 节点(可选)

调整角色

注意:集群缩容会导致集群成员变化,缩容时,该实例健康检查为假,原本由该实例承载的流量将立刻转由其他成员承载。但您仍需参考参考 Case 8:集群角色调整 中的说明,将该下线实例从集群配置中彻底移除。

下线Offline实例

请注意在默认配置中,如果下线了所有 pg_role = offlinepg_offline_query](/zh/docs/v-pgsql/#pg_offline_query) = true 的实例,而集群中仅剩下 primary 实例。那么离线读取流量将没有实例可以承载


Case 3:集群配置变更重启

集群配置修改

修改PostgreSQL集群配置需要通过 pg edit-config <cluster> 进行,此外,还有一些特殊的控制参数需要通过Patroni进行配置与修改,例如:同步复制选项synchronous_mode,必须修改Patroni的配置项(.synchronous_mode),而非(postgresql.parameters.synchronous_mode等参数),类似的参数包括: 控制同步提交节点数量的synchronous_node_count,以及 standby_cluster.recovery_min_apply_delay

配置保存后,无需重启的配置可以通过确认生效。

请注意,pg edit-config修改的参数为集群参数,单个实例范畴的配置参数(例如Patroni的Clonefrom标签等配置)需要直接修改Patroni配置文件(/pg/bin/patroni.yml)并systemctl reload patroni生效。

警告

请注意在Pigsty中,HBA规则由剧本自动创建并维护,请不要使用Patroni来管理HBA规则。

集群重启

需要重启的配置则需要安排数据库重启。重启集群可以使用以下命令进行:

pg restart [cluster] [instance]  # 重启某个集群或实例

带有需重启生效的实例,在pg list <cluster>中会显示 pending restart 记号。


Case 4:集群业务用户创建

可以通过 pgsql-createuser.yml 在已有的数据库中创建新的业务用户

业务用户通常指生产环境中由软件程序所使用的用户,需要通过连接池访问数据库的用户必须通过这种方式管理。其它用户可以使用Pigsty创建与管理,亦可由用户自行维护管理。

# 在 pg-test 集群创建名为 test 的用户
./pgsql-createuser.yml -l pg-test -e pg_user=test

以上命令可以简写为:

bin/createuser pg-test test  # 在 pg-test 集群创建名为 test 的用户

如果数据库配置有OWNER,请先创建对应OWNER用户后再创建相应数据库。因此,如果需要同时创建业务用户与业务数据库,通常应当先创建业务用户。


Case 5:集群业务数据库创建

可以通过 pgsql-createdb.yml在已有的数据库集群中创建新的业务数据库

业务数据库指代由用户创建并使用的数据库对象。如果您希望通过连接池访问该数据库,则必须使用Pigsty提供的剧本进行创建,以维持连接池中的配置与PostgreSQL保持一致。

# 在 pg-test 集群创建名为 test 的数据库
./pgsql-createdb.yml   -l pg-test -e pg_database=test

以上命令可以简写为:

bin/createdb   pg-test test  # 在 pg-test 集群创建名为 test 的数据库

如果数据库配置有OWNER,请先创建对应OWNER用户后再创建相应数据库。

将新数据库注册为Grafana数据源

执行以下命令,会将pg-test集群中所有实例上所有的业务数据库作为 PostgreSQL 数据源注册入Grafana,供PGCAT应用使用。

./pgsql.yml -t register_grafana -l pg-test

Case 6:集群HBA规则调整

用户可以通过 pgsql.ymlpg_hba 子任务,调整现有的数据库集群/实例的HBA配置。

当集群发生Failover,Switchover,以及HBA规则调整时,应当重新执行此任务,将集群的IP黑白名单规则调整至期待的行为。

HBA配置由 pg_hba_rulespg_hba_rules_extra 合并生成,两者都是由规则配置对象组成的数组。样例如下:

- title: allow internal infra service direct access
  role: common
  rules:
    - host putong-confluence     dbuser_confluence     10.0.0.0/8  md5
    - host putong-jira           dbuser_jira           10.0.0.0/8  md5
    - host putong-newjira        dbuser_newjira        10.0.0.0/8  md5
    - host putong-gitlab         dbuser_gitlab         10.0.0.0/8  md5

执行以下命令,将重新生成HBA规则,并应用生效。

./pgsql.yml -t pg_hba -l pg-test

以上命令可以简写为:

bin/reloadhba pg-test

Pigsty强烈建议使用配置文件自动管理HBA规则,除非您清楚的知道自己在做什么。


Case 7:集群流量控制

Pigsty中PostgreSQL的集群流量默认由HAProxy控制,用户可以直接通过HAProxy提供的WebUI控制集群流量。

使用HAProxy Admin UI控制流量

Pigsty的HAProxy默认在9101端口(haproxy_exporter_port)提供了管理UI,该管理UI默认可以通过Pigsty的默认域名,后缀以实例名(pg_cluster-pg_seq)访问。管理界面带有可选的认证选项,由参数(haproxy_auth_enabled)启用。管理界面认证默认不启用,启用时则需要使用由 haproxy_admin_usernamehaproxy_admin_password的用户名与密码登陆。

使用浏览器访问 http://pigsty/<ins>(该域名因配置而变化,亦可从PGSQL Cluster Dashboard中点击前往),即可访问对应实例上的负载均衡器管理界面。样例界面

您可以在这里对每集群众一个服务,以及每一个后端服务器的流量进行控制。例如要将相应的Server排干,则可以选中该Server,设置 MAINT 状态并应用。如果您同时使用了多个HAProxy进行负载均衡,则需要依次在每一个负载均衡器上执行此动作。

修改集群配置

当集群发生成员变更时,您应当在合适的时候调整集群中所有成员的负载均衡配置,以如实反映集群架构变化,例如当发生主从切换后。

此外通过配置 pg_weight 参数,您可以显式地控制集群中各实例承担的负载比例,该变更需要重新生成集群中HAProxy的配置文件,并reload重载生效。例如,此配置将2号实例在所有服务中的相对权重从默认的100降为0

10.10.10.11: { pg_seq: 1, pg_role: primary}
10.10.10.12: { pg_seq: 2, pg_role: replica, pg_weight: 0 }
10.10.10.13: { pg_seq: 3, pg_role: replica,  }

使用以下命令调整集群配置并生效。

# 重新生成 pg-test 的HAProxy配置(但没有应用)
./pgsql.yml -l pg-test -t haproxy_config

# 重新加载 pg-test 的HAProxy配置并启用生效
./pgsql.yml -l pg-test -t haproxy_config,haproxy_reload -e haproxy_reload=true

配置与生效命令可以合并简写为:

bin/reloadha pg-test # 调整pg-test集群所有HAPROXY并重载配置,通常不会影响现有流量。

Case 8:集群角色调整

这里介绍Pigsty默认使用的HAProxy接入方式,如果您使用L4 VIP或其它方式接入,则可能与此不同。

当集群发生任何形式的角色变更,即配置清单中集群与实例的 pg_role 参数无法真实反映服务器状态时,便需要进行此项调整。

例如,集群缩容后,集群负载均衡会根据健康检查立刻重新分配流量,但不会移除下线实例的配置项

集群扩容后,已有实例的负载均衡器配置不会变化。即,您可以通过新实例上的HAProxy访问已有集群的所有成员,但旧实例上的HAProxy配置不变,因此不会将流量分发至新实例上。

1. 修改配置文件 pg_role

当集群发生了主从切换时,应当按照当前实际情况,调整集群成员的pg_role。例如,当pg-test发生了Failover或Switchover,导致pg-test-3实例变为新的集群领导者,则应当修改 pg-test-3 的角色为 primary,并将原主库 pg_role 配置为 replica

同时,您应当确保集群中至少存在一个实例能用于提供Offline服务,故为pg-test-1配置实例参数:pg_offline_query: true。 通常,非常不建议为集群配置一个以上的Offline实例,慢查询与长事务可能会导致在线只读流量受到影响。

10.10.10.11: { pg_seq: 1, pg_role: replica, pg_offline_query: true }
10.10.10.12: { pg_seq: 2, pg_role: replica }
10.10.10.13: { pg_seq: 3, pg_role: primary }

2. 调整集群实例HBA

当集群角色发生变化时,适用于不同角色的HBA规则也应当重新调整。

使用 Case 6:集群HBA规则调整 中介绍的方法,调整集群HBA规则

3. 调整集群负载均衡配置

HAProxy会根据集群中Patroni返回的健康检查结果来动态分发请求流量,因此节点故障并不会影响外部请求。但用户应当在合适的时间(比如早上睡醒后),调整集群负载均衡配置。例如:将故障彻底从集群配置中剔除,而不是以健康检查DOWN的状态继续僵死在集群中。

使用 Case 7:集群流量控制 中介绍的方法,调整集群负载均衡配置。

4.整合操作

您可以在修改配置后,使用以下命令,完成集群角色的调整。

./pgsql.yml -l pg-test -t pg_hba,haproxy_config,haproxy_reload

或使用等价的简写脚本

bin/reloadhba pg-test # 调整集群HBA配置
bin/reloadha  pg-test # 调整集群HAProxy配置

Case 9:监控对象调整

Pigsty默认使用静态文件服务发现的方式管理 Prometheus 监控对象,默认位置:/etc/prometheus/targets

使用 Consul 服务发现是可选项,在此模式下,通常无需手工管理监控对象。使用静态文件服务发现时,在执行实例上线下线时,所有的监控对象都会一并自动处理:注册或注销。但仍然有一些特殊的场景无法覆盖周全(例如修改集群名称)。

手动添加Prometheus监控对象

# 将 pg-test 集群所有成员注册为 prometheus 监控对象
./pgsql.yml -t register_prometheus -l pg-test

PostgreSQL的服务发现对象定义默认存储于所有元节点的 /etc/prometheus/targets/pgsql 目录中:每一个实例对应一个yml文件,包含目标的标签,与Exporter暴露的端口。

# pg-meta-1 [primary] @ 172.21.0.11
- labels: { cls: pg-meta, ins: pg-meta-1 }
  targets: [172.21.0.11:9630, 172.21.0.11:9100, 172.21.0.11:9631, 172.21.0.11:9101]

手工移除Prometheus监控对象

# 移除监控对象文件
rm -rf /etc/prometheus/targets/pgsql/pg-test-*.yml

手工添加Grafana数据源

# 将 pg-test 集群中的每一个数据库对象,注册为 grafana 的数据源
./pgsql.yml -t register_grafana -l pg-test

手工移除Grafana数据源

在Grafana中点击数据源管理,手工删除即可。


Case 10:集群主从切换

例如,想要在三节点演示集群 pg-test 上执行Failover,则可以执行以下命令:

pg failover <cluster>

然后按照向导提示,执行Failover即可,集群Failover后,应当参考 Case 8:集群角色调整 中的说明,修正集群角色。

执行Failover的操作记录
[08-05 17:00:30] postgres@pg-meta-1:~
$ pg list pg-test
+ Cluster: pg-test (6988888117682961035) -----+----+-----------+-----------------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Pending restart | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+-----------------+
| pg-test-1 | 172.21.0.3  | Leader  | running |  1 |           |                 | clonefrom: true |
| pg-test-2 | 172.21.0.4  | Replica | running |  1 |         0 | *               | clonefrom: true |
| pg-test-3 | 172.21.0.16 | Replica | running |  1 |         0 | *               | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+-----------------+

[08-05 17:00:34] postgres@pg-meta-1:~
$ pg failover pg-test
Candidate ['pg-test-2', 'pg-test-3'] []: pg-test-3
Current cluster topology
+ Cluster: pg-test (6988888117682961035) -----+----+-----------+-----------------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Pending restart | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+-----------------+
| pg-test-1 | 172.21.0.3  | Leader  | running |  1 |           |                 | clonefrom: true |
| pg-test-2 | 172.21.0.4  | Replica | running |  1 |         0 | *               | clonefrom: true |
| pg-test-3 | 172.21.0.16 | Replica | running |  1 |         0 | *               | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+-----------------+
Are you sure you want to failover cluster pg-test, demoting current master pg-test-1? [y/N]: y
2021-08-05 17:00:46.04144 Successfully failed over to "pg-test-3"
+ Cluster: pg-test (6988888117682961035) -----+----+-----------+-----------------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Pending restart | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+-----------------+
| pg-test-1 | 172.21.0.3  | Replica | stopped |    |   unknown |                 | clonefrom: true |
| pg-test-2 | 172.21.0.4  | Replica | running |  1 |         0 | *               | clonefrom: true |
| pg-test-3 | 172.21.0.16 | Leader  | running |  1 |           | *               | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+-----------------+

[08-05 17:00:46] postgres@pg-meta-1:~
$ pg list pg-test
+ Cluster: pg-test (6988888117682961035) -----+----+-----------+-----------------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Pending restart | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+-----------------+
| pg-test-1 | 172.21.0.3  | Replica | running |  2 |         0 | *               | clonefrom: true |
| pg-test-2 | 172.21.0.4  | Replica | running |  2 |         0 | *               | clonefrom: true |
| pg-test-3 | 172.21.0.16 | Leader  | running |  2 |           | *               | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+-----------------+

Case 11:重置组件

俗话说,重启可以解决90%的问题,而重装可以解决剩下的10%。

面对疑难杂症,重置问题组件是一种简单有效的止损手段。使用Pigsty的初始化剧本 infra.ymlpgsql.yml 可以重置基础设施与数据库集群,但通常我们只需要使用特定的子任务来重置特定组件即可。

基础设施重置

常用的基础设施重新配置命令包括:

./infra.yml -t repo_upstream       # 重新在元节点上添加上游repo
./infra.yml -t repo_download       # 重新在元节点上下载软件包
./infra.yml -t nginx_home          # 重新生成Nginx首页内容
./infra.yml -t prometheus_config   # 重置Prometheus配置
./infra.yml -t grafana_provision   # 重置Grafana监控面板

您也可以强行重新安装这些组件

./infra.yml -t nginx      # 重新配置Nginx
./infra.yml -t prometheus # 重新配置Prometheus
./infra.yml -t grafana    # 重新配置Grafana
./infra-jupyter.yml       # 重置Jupyterlab

此外,您可以使用以下命令重置数据库节点上的具体组件

# 较为常用,安全的重置命令,重装监控与重新注册不会影响服务
./pgsql.yml -l pg-test -t=monitor  # 重新部署监控
./pgsql.yml -l pg-test -t=register # 重新将服务注册至基础设施(Nginx, Prometheus, Grafana, CMDB...)
./nodes.yml -l pg-test -t=consul -e dcs_clean=true # 在维护模式下重置DCS Agent

# 略有风险的重置操作
./pgsql.yml -l pg-test -t=service    # 重新部署负载均衡,可能导致服务闪断
./pgsql.yml -l pg-test -t=pgbouncer  # 重新部署连接池,可能导致服务闪断

# 非常危险的重置任务
./pgsql.yml -l pg-test -t=postgres # 重置数据库(包括Patroni,Postgres,Pgbouncer)
./pgsql.yml -l pg-test -t=pgsql    # 重新完成完整的数据库部署:数据库、监控、服务
./nodes.yml -l pg-test -t=consul   # 当高可用自动切换模式启用时,直接重置DCS服务器

# 极度危险的重置任务
./nodes.yml -l pg-test -t=consul -e dcs_clean=true -e dcs_safeguard=false  # 强制抹除DCS服务器,可能导致所有DB集群不可写入

例如,如果集群的连接池出现问题,一种兜底的止损方式便是重启或重装Pgbouncer连接池。

./pgsql.yml -l pg-test -t=pgbouncer # 重装连接池(所有用户与DB会重新生成),手工修改的配置会丢失

Case 12:替换集群DCS服务器

DCS(Consul/Etcd)本身是非常可靠的服务,一旦出现问题,其影响也是非常显著的。

按照Patroni的工作逻辑,一旦集群主库发现DCS服务器不可达,会立即遵循Fencing逻辑,将自身降级为普通从库,无法写入。

维护模式

除非当前集群处于“维护模式”(使用pg pause <cluster>进入,使用pg resume <cluster>退出)

# 使目标集群进入维护模式
pg pause pg-test

# 将目标集群恢复为自动故障切换模式(可选)
pg resume pg-test

重置数据库节点的DCS服务

当DCS故障不可用,需要迁移至新的DCS(Consul)集群时,可以采用以下操作。

首先创建新DCS集群,然后编辑配置清单 dcs_servers 填入新DCS Servers的地址。

# 强制重置目标集群上的Consul Agent(因为HA处于维护模式,不会影响新数据库集群)
./nodes.yml -l pg-test -t consul -e dcs_clean=true

当Patroni完成重启后(维护模式中,Patroni重启不会导致Postgres关停),会将集群元数据KV写入新的Consul集群中,所以必须确保原主库上的Patroni服务首先完成重启。

# 重要!首先重启目标集群主库的Patroni,然后重启其余从库的Patroni
ansible pg-test-1 -b -a 'sudo systemctl reload patroni'
ansible pg-test-2,pg-test-3 -b -a 'sudo systemctl restart patroni'

45 - 目录结构

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty目录结构

#------------------------------------------------------------------------------
# pigsty
#  ^-----@app                    # extra demo application resources
#  ^-----@bin                    # bin scripts
#  ^-----@docs                   # document (can be docsified)
#  ^-----@files                  # ansible file resources
#            ^-----@conf         # config template files
#            ^-----@rule         # soft link to prometheus rules
#            ^-----@ui           # soft link to grafana dashboards
#  ^-----@roles                  # ansible business logic
#  ^-----@templates              # ansible templates
#  ^-----@vagrant                # sandbox resources
#  ^-----configure               # configure wizard script
#  ^-----ansible.cfg             # default ansible config file
#  ^-----pigsty.yml              # default config file
#  ^-----*.yml                   # ansible playbooks

#------------------------------------------------------------------------------
# /etc/pigsty/
#  ^-----@targets                # file based service discovery targets definition
#  ^-----@dashboards             # static grafana dashboards
#  ^-----@datasources            # static grafana datasources
#  ^-----@playbooks              # extra ansible playbooks
#------------------------------------------------------------------------------

Prometheus目录结构

#------------------------------------------------------------------------------
# Config FHS
#------------------------------------------------------------------------------
# /etc/prometheus/
#  ^-----prometheus.yml              # prometheus main config file
#  ^-----alertmanager.yml            # alertmanger main config file
#  ^-----@bin                        # util scripts: check,reload,status,new
#  ^-----@rules                      # record & alerting rules definition
#            ^-----@infra            # infrastructure rules & alert
#            ^-----@nodes            # nodes rules & alert
#            ^-----@pgsql            # pgsql rules & alert
#            ^-----@redis            # redis rules & alert
#            ^-----@..........       # etc...
#  ^-----@targets                    # file based service discovery targets definition
#            ^-----@infra            # infra static targets definition
#            ^-----@nodes            # nodes static targets definition
#            ^-----@pgsql            # pgsql static targets definition
#            ^-----@redis            # redis static targets definition
#            ^-----@.....            # other targets
#------------------------------------------------------------------------------

Postgres目录结构

以下参数与PostgreSQL数据库目录相关

  • pg_dbsu_home:Postgres默认用户的家目录,默认为/var/lib/pgsql
  • pg_bin_dir:Postgres二进制目录,默认为/usr/pgsql/bin/
  • pg_data:Postgres数据库目录,默认为/pg/data
  • pg_fs_main:Postgres主数据盘挂载点,默认为/export
  • pg_fs_bkup:Postgres备份盘挂载点,默认为/var/backups(可选,也可以选择备份到主数据盘上的子目录)
#------------------------------------------------------------------------------
# Create Directory
#------------------------------------------------------------------------------
# this assumes that
#   /pg is shortcut for postgres home
#   {{ pg_fs_main }} contains the main data             (MUST ALREADY MOUNTED)
#   {{ pg_fs_bkup }} contains archive and backup data   (MUST ALREADY MOUNTED)
#   cluster-version is the default parent folder for pgdata (e.g pg-test-12)
#------------------------------------------------------------------------------
# default variable:
#     pg_fs_main = /export           fast ssd
#     pg_fs_bkup = /var/backups      cheap hdd
#
#     /pg      -> /export/postgres/pg-test-12
#     /pg/data -> /export/postgres/pg-test-12/data
#------------------------------------------------------------------------------
- name: Create postgresql directories
  tags: pg_dir
  become: yes
  block:
    - name: Make sure main and backup dir exists
      file: path={{ item }} state=directory owner=root mode=0777
      with_items:
        - "{{ pg_fs_main }}"
        - "{{ pg_fs_bkup }}"

    # pg_cluster_dir:    "{{ pg_fs_main }}/postgres/{{ pg_cluster }}-{{ pg_version }}"
    - name: Create postgres directory structure
      file: path={{ item }} state=directory owner={{ pg_dbsu }} group=postgres mode=0700
      with_items:
        - "{{ pg_fs_main }}/postgres"
        - "{{ pg_cluster_dir }}"
        - "{{ pg_cluster_dir }}/bin"
        - "{{ pg_cluster_dir }}/log"
        - "{{ pg_cluster_dir }}/tmp"
        - "{{ pg_cluster_dir }}/conf"
        - "{{ pg_cluster_dir }}/data"
        - "{{ pg_cluster_dir }}/meta"
        - "{{ pg_cluster_dir }}/stat"
        - "{{ pg_cluster_dir }}/change"
        - "{{ pg_backup_dir }}/postgres"
        - "{{ pg_backup_dir }}/arcwal"
        - "{{ pg_backup_dir }}/backup"
        - "{{ pg_backup_dir }}/remote"

PG二进制目录结构

在RedHat/CentOS上,默认的Postgres发行版安装位置为

/usr/pgsql-${pg_version}/

安装剧本会自动创建指向当前安装版本的软连接,例如,如果安装了14版本的Postgres,则有:

/usr/pgsql -> /usr/pgsql-14

因此,默认的pg_bin_dir/usr/pgsql/bin/,该路径会在/etc/profile.d/pgsql.sh中添加至所有用户的PATH环境变量中。

PG数据目录结构

Pigsty假设用于部署数据库实例的单个节点上至少有一块主数据盘(pg_fs_main),以及一块可选的备份数据盘(pg_fs_bkup)。通常主数据盘是高性能SSD,而备份盘是大容量廉价HDD。

#------------------------------------------------------------------------------
# Create Directory
#------------------------------------------------------------------------------
# this assumes that
#   /pg is shortcut for postgres home
#   {{ pg_fs_main }} contains the main data             (MUST ALREADY MOUNTED)
#   {{ pg_fs_bkup }} contains archive and backup data   (MAYBE ALREADY MOUNTED)
#   {{ pg_cluster }}-{{ pg_version }} is the default parent folder
#    for pgdata (e.g pg-test-14)
#------------------------------------------------------------------------------
# default variable:
#     pg_fs_main = /export           fast ssd
#     pg_fs_bkup = /var/backups      cheap hdd
#
#     /pg      -> /export/postgres/pg-test-14
#     /pg/data -> /export/postgres/pg-test-14/data

PG数据库集簇目录结构

# basic
{{ pg_fs_main }}     /data                      # contains all business data (pg,consul,etc..)
{{ pg_dir_main }}    /data/postgres             # contains postgres main data
{{ pg_cluster_dir }} /data/postgres/pg-test-14  # contains cluster `pg-test` data (of version 13)
                     /data/postgres/pg-test-14/bin            # binary scripts
                     /data/postgres/pg-test-14/log            # misc logs
                     /data/postgres/pg-test-14/tmp            # tmp, sql files, records
                     /data/postgres/pg-test-14/conf           # configurations
                     /data/postgres/pg-test-14/data           # main data directory
                     /data/postgres/pg-test-14/meta           # identity information
                     /data/postgres/pg-test-14/stat           # stats information
                     /data/postgres/pg-test-14/change         # changing records

{{ pg_fs_bkup }}     /var/backups                      # contains all backup data (pg,consul,etc..)
{{ pg_dir_bkup }}    /var/backups/postgres             # contains postgres backup data
{{ pg_backup_dir }}  /var/backups/postgres/pg-test-14  # contains cluster `pg-test` backup (of version 13)
                     /var/backups/postgres/pg-test-14/backup   # base backup
                     /var/backups/postgres/pg-test-14/arcwal   # WAL archive
                     /var/backups/postgres/pg-test-14/remote   # mount NFS/S3 remote resources here

# links
/pg             -> /data/postgres/pg-test-14                 # pg root link
/pg/data        -> /data/postgres/pg-test-14/data            # real data dir
/pg/backup      -> /var/backups/postgres/pg-test-14/backup   # base backup
/pg/arcwal      -> /var/backups/postgres/pg-test-14/arcwal   # WAL archive
/pg/remote      -> /var/backups/postgres/pg-test-14/remote   # mount NFS/S3 remote resources here

Pgbouncer配置文件结构

Pgbouncer使用Postgres用户运行,配置文件位于/etc/pgbouncer。配置文件包括:

  • pgbouncer.ini,主配置文件
  • userlist.txt:列出连接池中的用户
  • pgb_hba.conf:列出连接池用户的访问权限
  • database.txt:列出连接池中的数据库

Redis文件结构

Pigsty提供了对Redis部署与监控对基础支持。

Redis二进制使用RPM包或复制二进制的方式安装于/bin/中,包括

redis-server
redis-server
redis-cli
redis-sentinel
redis-check-rdb
redis-check-aof
redis-benchmark
/usr/libexec/redis-shutdown

对于一个名为 redis-test-1-6379 的 Redis 实例,与其相关的资源如下所示:

/usr/lib/systemd/system/redis-test-1-6379.service               # 服务
/etc/redis/redis-test-1-6379.conf                               # 配置
/data/redis/redis-test-1-6379                                   # 数据库目录
/data/redis/redis-test-1-6379/redis-test-1-6379.rdb             # RDB文件
/data/redis/redis-test-1-6379/redis-test-1-6379.aof             # AOF文件
/var/log/redis/redis-test-1-6379.log                            # 日志
/var/run/redis/redis-test-1-6379.pid                            # PID

46 - 数据库高可用场景演练

从 Pigsty v1.5.1 标签恢复的历史文档。

您可以通过高可用场景演练,来加强对集群高可用能力的信心。

以下列出了24种典型的高可用故障场景,分为主库故障,从库故障,DCS故障三类,每类8个具体场景。

所有演练均假设高可用自动切换模式已启用,其中,Patroni应当正确处理主库故障与从库故障。

编号 案例名称 自动模式 手动切换
A 主库故障
1A 主库节点宕机 自动Failover 人工切换
2A 主库Postgres进程关停(pg_ctl or kill -9 自动Failover 人工重启
3A 主库Patroni进程正常关停(systemctl stop patroni 自动Failover 人工重启
4A 主库Patroni进程异常关停(kill -9 需要确认 无影响
5A 主库负载打满,假死(watchdog) 需要确认 无影响
6A 主库DCS Agent不可用(systemctl stop consul 集群主库降级 无影响
7A 主库网络抖动 超时自动Failover 需观察
8A 误删主库数据目录 自动Failover 手工切换
B 从库故障(1/n , n>1)
1B 从库节点宕机 无影响 无影响
2B 从库Postgres进程关停(pg_ctl or kill -9 无影响 无影响
3B 从库Postgres进程手工关停 (pg_ctl 无影响 无影响
4B 从库Patroni进程异常Kill(kill -9 无影响 无影响
5B 从库DCS Agent不可用(systemctl stop consul 无影响 无影响
6B 从库负载打满,假死 Depends Depends
7B 从库网络抖动 无影响 无影响
8B 误提升一个从库(pg_ctl promte 自动恢复 脑裂
C DCS故障
1C DCS Server完全不可用(多数节点不可用) 所有集群主库降级 无影响
2C DCS通主库,不通从库(1主1从) 无影响 无影响
3C DCS通主库,不通从库(1主n从,n>1) 无影响 无影响
4C DCS通从库,不通主库(1主1从) 无影响 无影响
5C DCS通从库,不通主库(1主n从,n>1) 自动Failover 无影响
6C DCS网络抖动:同时中断,
主库从库同时恢复,或主库先恢复
无影响 无影响
7C DCS网络抖动:同时中断,
从库先恢复,主库后恢复(1主1从)
无影响* 无影响
8C DCS网络抖动:同时中断,
从库先恢复,主库后恢复(1主n从,n>1)
超过TTL自动Failover 无影响

演练环境说明

以下以本地Pigsty 四节点沙箱作为演练对象。

准备负载

在演练中,您可以使用pgbench生成虚拟负载,观察负载流量在各种故障下的状态。

make test-ri     # 在 pg-test集群初始化 pgbench 表
make test-rw     # 生成 pgbench 写入流量
make test-ro     # 生成 pgbench 只读流量

如果您希望仿真其他样式的流量,可以直接调整负载生成的命令并执行。

# 4条连接,总计64读写TPS
while true; do pgbench -nv -P1 -c4 --rate=64 -T10 postgres://test:test@pg-test:5433/test; done

# 8条连接,总计512只读TPS
while true; do pgbench -nv -P1 -c8 --select-only --rate=512 -T10 postgres://test:test@pg-test:5434/test; done

观察状态

PGSQL Cluster 面板提供了关于pg-test集群的重要监控信息,您可以查阅最近5-15分钟的指标,并设置为每5秒自动刷新。

Pigsty的监控指标采集周期默认为10秒,而Patroni主从切换的典型耗时通常在几秒到十几秒之间。您可以使用patronictl来获取亚秒级别的观测精度:

pg list pg-test          # 查看 pg-test 集群状态(在单独的窗口中)
pg list pg-test -w 0.1   # 查看 pg-test 集群状态,每0.1s刷新一次

您可以开启四个Terminal窗口,分别用于:

  • 在元节点上执行管理命令(用来触发模拟故障的命令)
  • 发起并观察读写请求负载(pgbench
  • 发起并观察只读请求负载(pgbench --select-only
  • 实时查阅集群主从状态(pg list

主库故障演练

1A-主库节点宕机

操作说明

ssh 10.10.10.3 sudo reboot    # 直接将 pg-test-1 主节点重启(VIP指向实际主节点)

操作结果

Patroni可以正常处理主库宕机,执行自动Failover。

当集群处于维护模式时,则需要人工介入处理(人工执行pg failover <cluster>

patronictl list 结果
# 正常情况:pg-test-3 是当前集群主库,时间线为3(此集群已经经历过两次Failover)
+ Cluster: pg-test (7037005266924312648) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Replica | running |  3 |         0 | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Replica | running |  3 |         0 | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Leader  | running |  3 |           | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# ssh 10.10.10.13 sudo reboot 将 pg-test-3 主实例所在节点重启,pg-test-3 实例的Patroni从集群中消失
# 下线超过TTL后,pg-test-1实例抢到Leader Key,成为新的集群领导者。
+ Cluster: pg-test (7037005266924312648) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  3 |           | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Replica | running |  3 |         0 | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# pg-test-1实例完成Promote,成为集群的新领导者,时间线变为4
+ Cluster: pg-test (7037005266924312648) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  4 |           | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Replica | running |  3 |         0 | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# pg-test-2 实例将自己的上游修改为新领导者 pg-test-1 ,时间线由3变为4,进入新时代,看齐新核心。
+ Cluster: pg-test (7037005266924312648) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  4 |           | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Replica | running |  4 |         0 | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# pg-test-3 完成重启,Postgres处于停止状态,Patroni重新加入集群中
+ Cluster: pg-test (7037005266924312648) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  4 |           | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Replica | running |  4 |         1 | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | stopped |    |   unknown | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# pg-test-3 上的Postgres以从库身份被拉起,从新主库 pg-test-1 同步数据。
+ Cluster: pg-test (7037005266924312648) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  4 |           | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Replica | running |  4 |         1 | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | running |  3 |        10 | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# pg-test-3 追赶上新领导者,时间线进入4,与新领导保持同步。
+ Cluster: pg-test (7037005266924312648) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  4 |           | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Replica | running |  4 |         1 | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | running |  4 |         0 | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

2A-主库Postgres进程关停

操作说明

采用两种不同的方式关停主库 Postgres 实例:常规的 pg_ctl 与暴力的 kill -9

# 关停主库上的Postgres主进程
ssh 10.10.10.3 'sudo -iu postgres /usr/pgsql/bin/pg_ctl -D /pg/data stop'

# 查询主库PID并强行Kill
ssh 10.10.10.3 'sudo kill -9 $(sudo cat /pg/data/postmaster.pid | head -n1)'

操作结果

关停 Postgres 后,Patroni 会尝试重新拉起 Postgres 进程。如果成功,则集群恢复正常。

如果无法正常拉起 PostgreSQL 进程,则集群会自动进行Failover。

patronictl list 结果
# 主库实例被强制Kill后,状态显示为crashed,而后立刻被重新拉起,恢复为Running
+ Cluster: pg-test (7037005266924312648) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Leader  | crashed |    |           | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Replica | running |  7 |         0 | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | running |  7 |         0 | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# 如果持续Kill主库,导致主库拉起失败(状态变为start failed),那么就会触发Failover
+ Cluster: pg-test (7037005266924312648) ----------+----+-----------+-----------------+
| Member    | Host        | Role    | State        | TL | Lag in MB | Tags            |
+-----------+-------------+---------+--------------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Replica | running      | 11 |         0 | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Leader  | running      | 12 |           | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | start failed |    |   unknown | clonefrom: true |
+-----------+-------------+---------+--------------+----+-----------+-----------------+

3A-主库Patroni进程正常关停

操作说明

# 关停主库上的Postgres主进程
ssh 10.10.10.3 'sudo systemctl stop patroni'

操作结果

通过常规方式关停主库Patroni,会导致Patroni所管理PostgreSQL实例一并关闭,并立即触发集群Failover。

在维护模式下通过正常方式关停Patroni,关闭Patroni不会影响所托管的PostgreSQL实例,这可以用于重启Patroni以重载配置(例如更换使用的DCS)。

patronictl list 结果
# 主库Patroni (pg-test-3) 关停后
+ Cluster: pg-test (7037370797549923387) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Replica | running |  2 |         0 | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Replica | running |  2 |         0 | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Leader  | running |  2 |           | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# pg-test-3 进入 stopped 状态
+ Cluster: pg-test (7037370797549923387) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Replica | running |  2 |         0 | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Replica | running |  2 |         0 | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | stopped |    |   unknown | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# 新主库 pg-test-2 当选,时间线从2进入3
+ Cluster: pg-test (7037370797549923387) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Replica | running |  2 |         0 | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Leader  | running |  3 |           | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | stopped |    |   unknown | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# 另一个健康从库 pg-test-1 重新追随新主库 pg-test-2 进入时间线3,老主库 pg-test-3 在一段时间后,从集群中消失
+ Cluster: pg-test (7037370797549923387) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Replica | running |  3 |         0 | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Leader  | running |  3 |           | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# 使用 systemctl start patroni 重新拉起老主库 pg-test-3,该实例自动进入复制模式,追随新领导者。
+ Cluster: pg-test (7037370797549923387) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Replica | running |  3 |         0 | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Leader  | running |  3 |           | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | running |  3 |         0 | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

4A-主库Patroni进程异常关停

警告

这种情况需要特别关注!

如果使用Kill -9 强行杀死主库Patroni,则主库Patroni有大概率无法关停所管理的PostgreSQL主库实例。这会导致原主库PostgreSQL 实例在Patroni死亡后继续存活,而剩余的集群从库则会进行领导选举选出新的主库来,从而导致脑裂

操作说明

# 关停主库上的Patroni主进程
ssh 10.10.10.3 "ps aux | grep /usr/bin/patroni | grep -v grep | awk '{print $2}'"
ssh 10.10.10.3 'sudo kill -9 723'

操作结果

该操作可能导致集群脑裂:因为Patroni暴死,无暇杀死自己管理的PostgreSQL进程。而其他集群成员则会在TTL超时后进行新一轮选举,选出新的主库。

如果您采用标准的基于负载均衡健康检查的服务接入机制,不会有问题,因为原主库 Patroni已死,健康检查为假。即使该主库存活,负载均衡器也不会将流量分发至此实例。但如果您通过其他方式继续写入该主库,则可能会出现脑裂

Patroni使用Watchdog机制对这种情况进行兜底,您需要视情况使用(参数 patroni_watchdog_mode )。启用watchdog时,如果原主库因为各种原因(Patroni暴死,机器负载假死,虚拟机调度,PG关机太慢)等原因,无法在Failover中及时关停PG主库以避免脑裂,则会使用Linux内核模块softdog强制关机以免脑裂。

patronictl list 结果
# 使用Kill -9 强杀 主库Patroni (pg-test-2)
+ Cluster: pg-test (7037370797549923387) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Replica | running |  3 |         0 | clonefrom: true |
| pg-test-2 | 10.10.10.12 | Leader  | running |  3 |           | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | running |  3 |         0 | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+
# 因为Patroni暴死,PostgreSQL进程通常仍然会存活并且为主库状态
# 因为Patroni暴死,原主库的健康检查会立刻失败,导致主库流量没有实例承载,集群不可写入。

# 因为Patroni暴死,无暇释放 DCS中的Leader Key,因此上面的状态会保持TTL的时间。
# 直到 DCS 中的 Leader Lease 因为超时被释放(约15s),集群才意识到主库已死,发起Failover
+ Cluster: pg-test (7037370797549923387) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Replica | running |  3 |         0 | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | running |  3 |         0 | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# 集群触发Failover,pg-test-1 成为新的集群领导者,开始承载只读流量,集群写入服务恢复
+ Cluster: pg-test (7037370797549923387) -----+----+-----------+-----------------+
| Member    | Host        | Role    | State   | TL | Lag in MB | Tags            |
+-----------+-------------+---------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  4 |           | clonefrom: true |
| pg-test-3 | 10.10.10.13 | Replica | running |  3 |         0 | clonefrom: true |
+-----------+-------------+---------+---------+----+-----------+-----------------+

# 此时必须注意!原集群主库仍然存活并允许写入!!!
# 如果您采用标准的基于负载均衡健康检查的流量分发机制则不会有问题,因为Patroni已死,健康检查为假。
# 该主库存活,但负载均衡器不会将流量分发至此实例。但如果您通过其他方式直接写入该主库,则会出现脑裂!
$ psql -AXtwh 10.10.10.12 -d postgres -c 'select pg_is_in_recovery();'
t

从这种情况中恢复

当Patroni暴死时,您应当首先手工关闭由其管理的,仍在运行的原PostgreSQL主库实例。然后再重新启动Patroni,并由Patroni拉起PostgreSQL实例,如下所示:

/usr/pgsql/bin/pg_ctl -D /pg/data stop
systemctl restart patroni

如若不然,则可能出现Patroni无法正常启动的错误:

2021-12-03 14:16:18 +0800 INFO:  stderr=2021-12-03 14:16:18.752 HKT [7852] FATAL:  lock file "postmaster.pid" already exists
2021-12-03 14:16:18.752 HKT [7852] HINT:  Is another postmaster (PID 887) running in data directory "/pg/data"?

参数 patroni_watchdog_mode 的说明:

  • 如果模式为 required,但/dev/watchdog不可用,不会影响Patroni启动,只会影响当前实例的领导候选人资格。
  • 如果模式为 required,但/dev/watchdog不可用,那么该实例无法作为合格的主库候选人,即无法参与Failover,即使手工强制指定也不行:会出现Switchover failed, details: 412, switchover is not possible: no good candidates have been found 的错误。若想解决此问题,修改/pg/bin/patroni.yml文件的patroni_watchdog选项为automatic|off即可。
  • 如果模式为automatic,则没有限制,无论/dev/watchdog可不可用,该实例都可以正常参选主库选举。
  • /dev/watchdog 可用需要两个条件,加载softdog内核模块,/dev/watchdog的属主为postgres(dbsu)

5A-主库DCS Agent不可用

在这种情况下,主库上的Patroni会因为无法连接至DCS服务,将自身降级为普通从库,但如果从库Patroni仍然意识到主库存活(例如,流复制仍然正常进行),并不会触发Failover!

在这种情况下,Pigsty的接入机制会因为原主库健康检查为假,而导致整个集群进入无主状态,无法写入,需要特别关注

在维护模式下,不会有变化发生。

6A-主库负载打满,假死

v1.5.1 源文档保留了这一故障场景,但没有提供额外处置步骤。

7A-主库网络抖动

8A-误删主库数据目录


从库故障演练

1B-从库节点宕机

操作说明

ssh 10.10.10.3 sudo reboot    # 直接将 pg-test-1 主节点重启(VIP指向实际主节点)

操作结果

从库宕机会导致该节点上的 HAPorxy PatroniPostgres 等服务不可用。通常业务侧会察觉到极少量的瞬时报错(与故障实例的连接会中断),而后集群中的其他负载均衡器会将此故障节点从后端列表中摘除。

请注意,如果集群为一主一从结构,且唯一一台从库宕机,那么离线查询服务可能会受到影响(没有可用承载实例)。

节点重启完成后,Patroni服务会自动拉起,实例会自动重新加入集群中。

2B-从库Postgres进程关停

操作说明

采用两种不同的方式关停从库 Postgres 实例:常规的 pg_ctl 与暴力的 kill -9

# 关停从库上的Postgres主进程
ssh 10.10.10.3 'sudo -iu postgres /usr/pgsql/bin/pg_ctl -D /pg/data stop'

# 查询从库PID并强行Kill
ssh 10.10.10.3 'sudo kill -9 $(sudo cat /pg/data/postmaster.pid | head -n1)'

操作结果

关停 Postgres 后,Patroni 会尝试重新拉起 Postgres 进程。如果成功,则集群恢复正常。如果

从库 宕机会导致该实例健康检查为Down,集群的负载均衡器不会将流量再分发至该实例,应用只读请求会有少量瞬时报错。

3B-从库Postgres进程手工关停

4B-从库Patroni进程异常Kill

5B-从库DCS Agent不可用

6B-从库负载打满,假死

7B-从库网络抖动

8B-误提升一个从库


DCS故障演练

1C-DCS Server完全不可用

DCS完全不可用是一个极其严重的故障,默认情况下将导致所有数据库集群不可写入。 如果您使用L2 VIP接入,则默认绑定于主库节点的L2 VIP亦不可用,这意味着整集群可能都无法读写!您应当尽全力避免此种故障!

好在DCS本身便是为了解决此问题而生:本身采用分布式架构,并有可靠的容灾机制,能容忍各种常见的硬件故障。例如,3节点的DCS集群允许一台服务器出现故障,而5节点的DCS集群则最多允许两个服务器节点同时出现故障。

有一些方式可以缓解此问题。

关停 Consul 后,所有 启用高可用自动切换模式的数据库集群主库会触发降级逻辑(因为主库的Patroni意识不到其他集群成员的存在,须假定其他从库已经构成一个法定多数的分区并进行选举,因而要将自身降级为从库避免脑裂)

操作说明

关停元节点上的DCS Server,如果有3台,至少应当关停2台,如果有5台,至少应当关停3台。

systemctl stop consul

解决方案

  1. 在维护模式下,用户失去了自动Failover的能力,但DCS故障不会导致主库不可写入。(仍可以手工快速切换)
  2. 使用更多的DCS实例确保DCS的可用性(DCS本身便是为了解决此问题而生)
  3. 为Patroni配置足够长的超时重试时间,并为DCS故障设置最高的响应优先级

2C-DCS通主库,不通从库(1主1从)

3C-DCS通主库,不通从库(1主n从,n>1)

4C-DCS通从库,不通主库(1主1从)

5C-DCS通从库,不通主库(1主n从,n>1)

6C-DCS网络抖动:同时中断,主库从库同时恢复,或主库先恢复

7C-DCS网络抖动:同时中断,从库先恢复,主库后恢复(1主1从)

8C-DCS网络抖动:同时中断,从库先恢复,主库后恢复(1主n从,n>1)

47 - 数据库常见故障诊断与处理

从 Pigsty v1.5.1 标签恢复的历史文档。

硬件故障

编号 名称 症状 处理
H01 Primary节点宕机 pg_up = 0 持续1-3分钟 无需立即介入。
事后补充实例
从接入域名摘除
执行 Case 8:集群角色调整
H02 Replica节点宕机 pg_up = 0 持续1-3分钟 无需立即介入。
事后补充实例,
从接入域名摘除
执行 Case 8:集群角色调整
H03 Primary节点网络分区 失去 主实例所有监控数据,网路不可达 确认Failover情况
必要时强制Fencing旧主库
H04 Replica节点网络分区 失去 从实例所有监控数据,网路不可达 通常无影响,等待恢复
联系运维与网络工程师处理
H05 TCP重传率过高 TCP Retrans长时间居高不下,大量Conn Reset,大量查询请求失败 找运维与网络工程师处理
H06 节点内存错误 EDAC计数器增长,系统错误日志 确认从库内存无错后
执行Case 10:集群主从切换
H07 磁盘坏块,数据腐坏 查询结果与日志出现 can’t read block 等错误信息 执行Case 10:集群主从切换
使用数据恢复工具,人工恢复数据
R01 CPU使用率高 CPU / Load / Pressure指标高 top确认大CPU占比程序并清理
如为雪崩,执行杀查询止损。
R02 出现OOM 出现进程Failure,OOM消息,内存使用高,开始使用SWAP 确认内存,确认SWAP
top确认大内存占用程序并清理
重新拉起被杀进程
紧急添加SWAP分区
R03 磁盘满 磁盘写满
数据库Crash
大量shell命令无法执行
移除 /pg/dummy 释放应急空间
检查并处理WAL堆积
检查并处理大量Log文件
确认业务是否有可清理数据
R06 磁盘/网卡IO过高 磁盘/网卡 BandWidth过大
磁盘 > 2GB/s
网络 > 1 GB/s
检查使用网络/磁盘的应用程序,如备份,添加限速。

软件故障

编号 名称 症状 处理
SP1 数据库进程中止 ps aux 找不到postgres进程 检查Postgres,Patroni状态
确认Failover结果,或手工执行Failover
SP2 连接池进程中止 systemctl status pgbouncer Failure 重启服务组件重置服务组件
SP3 Primary Patroni进程中止 systemctl status patroni Failure 同上,进入维护模式,重启或重置 Patroni
SP4 Primary Consul进程中止 systemctl status consul Failure 同上,进入维护模式,重启或重置 Consul
S05 HAProxy进程中止 systemctl status haproxy Failure 同上,重启或重置 Haproxy
S06 连接池污染 出现类似于 Cannot execute xxx on readonly transactions 的报错 重启Pgbouncer连接池
或配置 server_reset_query
S07 连接池无法连接至数据库 pgbouncer can not connect to server 检查用户、密码、HBA配置是否正确
执行 Case 4:集群业务用户创建 刷新用户
S08 连接池达到QPS瓶颈 PGbouncer QPS 达到 3~4W,CPU使用率达到100% 使用多个Pgbouncer(不推荐)
使用Default服务绕开Pgbouncer
通知业务方限速
S09 DCS Server不可用 自动切换模式下,所有主库将在TTL后进入不可写状态 立即将所有集群设置为维护模式
S10 DCS Agent不可用 若为从库无影响,若为主库,会降级为从库,集群不可写入 立即将该集群设置为维护模式
S11 XID Wraparound 年龄剩余1000w时,进入保护模式。 应通过监控提前避免此问题
定位年龄过大的数据库与表,执行紧急清理
迅速定位阻塞Vacuum的原因并解决
进入单用户模式下恢复
S12 WAL堆积 WAL大小持续增长 多次执行CHECKPOINT
确认WAL归档状态
确认从库上是否有未结束超长事务
确认是否有复制槽阻止WAL回收

人为问题

编号 名称 症状 处理
M01 误删数据库集群 数据库集群没了 使用冷备恢复集群
准备跑路
M02 误将某实例提升为主库 脑裂 自动模式下无需处理,否则脑裂
M03 误删数据 数据没了 停止VACUUM,使用 pg_dirtyread提取。
从延迟备库中提取
从冷备份中提取并恢复
M04 误删表 表没了 从延迟备库中提取
从冷备份中提取并恢复
M05 整型序列号溢出 Sequence超出INTMAX 参考整型主键在线升级手册处理
M06 插入数据因主键序列号重复而冲突 violate constratint … 增长序列号值(如+100000)
M07 慢查询堆积/雪崩 大量慢查询日志 使用 pg_terminate_backend 周期性清理慢查询(如每1秒)
M08 死锁堆积/雪崩 锁堆积 使用 pg_terminate_backend 周期性清理查询(如每1秒)
M09 HBA拒绝访问 no hba entry for xxx Case 6:集群HBA规则调整
M10 用户密码错误 password auth failure for xxx Case 4:集群业务用户创建
M11 访问权限不足 permission denied for x 检查用户是否使用正确的管理员创建对象
参考 Default Privilege 手工修正对象权限

48 - 社区

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty有一个活跃的用户社群,搜索微信号 pigsty-cc ,添加 Pigsty小助手入群。

大多数问题都可以在 常见问题/FAQ 中找到解答,如果这里没有解决您的问题,可以在社群求助。询问时请详细描述以下内容:

  • 执行的操作内容
  • 操作执行的结果 (完整截图或描述)
  • 执行命令的环境:
    • 操作系统是否为 CentOS 7.8 ?
    • 是本地物理机/虚拟机还是云厂商服务器 ?
    • 是否使用全新安装的独占节点 ?
    • 是否使用了离线软件安装包 pkg.tgz
      • 如果使用,离线包是否放置于 /tmp/pkg.tgz ?在执行make install安装前是否执行了configure ?
      • 如果没有,使用离线软件安装包,如果直接从原始上游软件源安装,您的节点是否可以访问网络?并翻墙访问Github?
    • 是否有特殊的安全限制?(SSH/Sudo/DNS/Firewall等)

如果您发现了可复现的Bug,我们非常欢迎您在 Github 上提交 IssuePull Request

微信群

  • 搜索微信号 pigsty-cc ,添加 Pigsty小助手入群。

邮件

Github Issues

Telegram

Discord

https://discord.gg/wDzt5VyWEz

49 - 路线图

从 Pigsty v1.5.1 标签恢复的历史文档。

历史

时间 说明 版本
2019-05-15 概念验证 v0.0.1
2020-04-30 首次提交 v0.0.2
2020-06-20 测试环境验证 v0.1.0
2020-06-22 界面增强 v0.0.3
2020-07-10 PGSQL 监控 v6 正式可用 v0.2.0
2020-07-27 将剧本重构为 Ansible 角色 v0.0.4
2020-08-19 离线安装模式 v0.0.5
2020-10-22 置备方案正式可用 v0.3.0
2020-12-14 支持 PostgreSQL 13,发布正式文档 v0.4.0
2021-01-07 数据库定制模板 v0.5.0
2021-02-19 架构增强 v0.6.0
2021-03-01 仅监控部署 v0.7.0
2021-03-28 服务置备 v0.8.0
2021-04-04 GUI、CLI 与日志集成 v0.9.0
2021-04-20 可访问性与扩展性增强 v0.9.1
2021-07-26 v1 正式版,监控系统重构 v1.0.0
2021-10-12 主页、JupyterLab、PGWeb、Pev2 与 Pgbadger v1.1.0
2021-11-03 默认 PostgreSQL 14,支持监控已有 PG v1.2.0
2021-11-30 PGCAT 重构、PGSQL 增强与 Redis Beta v1.3.0
2022-03-31 MatrixDB;拆分 INFRA、NODES、PGSQL、REDIS v1.4.0
2022-04-20 缺陷修复与英文文档完整翻译 v1.4.1
2022-05-31 Docker 应用 v1.5.0
2022-06-18 PostgreSQL 14.4 与 Grafana 安全更新 v1.5.1

时间线

50 - 开发日志与发布说明

从 Pigsty v1.5.1 标签恢复的历史文档。

本页根据 v1.5.1 产品标签、冻结版本的英文开发日志,以及同一站点的中文发布档案重建。v1.5 分支的当前正式版本为 v1.5.1

Pigsty v1.5.1

亮点

重要:修复了 PG14.0-14.3 中 CREATE INDEX|REINDEX CONCURRENTLY 可能导致索引数据损坏的问题。

Pigsty v1.5.1 升级默认 PostgreSQL 版本至 14.4 强烈建议尽快更新。

软件升级

  • postgres 升级至 to 14.4
  • haproxy 升级至 to 2.6.0
  • grafana 升级至 to 9.0.0
  • prometheus 升级至 2.36.0
  • patroni 升级至 2.1.4

问题修复

  • 修复了 pgsql-migration.yml 中的 TYPO
  • 移除了 HAProxy 配置文件中的 PID 配置项
  • 移除了默认软件包中的 i686 软件包
  • 默认启用所有 Systemd Redis Service
  • 默认启用所有 Systemd Patroni Service

API 变更

  • grafana_databasegrafana_pgurl 被标记为过时 API,将从后续版本移除

New Apps

  • wiki.js : 使用 Postgres 搭建本地维基百科
  • FerretDB: 使用 Postgres 提供 MongoDB API

信息来源

Pigsty v1.5.0

亮点概述

  • 完善的 Docker 支持:在管理节点上默认启用并提供诸多开箱即用的软件模板:bytebase, pgadmin, pgweb, postgrest, minio 等。
  • 基础设施自我监控:Nginx, ETCD, Consul, Prometheus, Grafana, Loki 自我监控
  • CMDB 升级:兼容性改善,支持 Redis 集群/Greenplum 集群元数据,配置文件可视化。
  • 服务发现改进:可以使用 Consul 自动发现所有待监控对象,并纳入 Prometheus 中。
  • 更好的冷备份支持:默认定时备份任务,添加 pg_probackup 备份工具,一键创建延时从库。
  • ETCD 现在可以用作 PostgreSQL/Patroni 的 DCS 服务,作为 Consul 的备选项。
  • Redis 剧本/角色改善:现在允许对单个 Redis 实例,而非整个 Redis 节点进行初始化与移除。

详细变更列表

监控面板

  • CMDB Overview:可视化 Pigsty CMDB Inventory。
  • DCS Overview:查阅 Consul 与 ETCD 集群的监控指标。
  • Nginx Overview:查阅 Pigsty Web 访问指标与访问日志。
  • Grafana Overview:Grafana 自我监控
  • Prometheus Overview:Prometheus 自我监控
  • INFRA Dashboard 进行重制,反映基础设施整体状态

监控架构

  • 现在允许使用 Consul 进行服务发现(当所有服务注册至 Consul 时)
  • 现在所有的 Infra 组件会启用自我监控,并通过 infra_register 角色注册至 Prometheus 与 Consul 中。
  • 指标收集器 pg_exporter 更新至 v0.5.0,添加新功能,scaledefault,允许为指标指定一个倍乘因子,以及指定默认值。
  • pg_bgwriter, pg_wal, pg_query, pg_db, pgbouncer_stat 关于时间的指标,单位由默认的毫秒或微秒统一缩放至秒。
  • pg_table 中的相关计数器指标,现在配置有默认值 0,替代原有的 NaN
  • pg_class 指标收集器默认移除,相关指标添加至 pg_tablepg_index 收集器中。
  • pg_table_size 指标收集器现在默认启用,默认设置有300秒的缓存时间。

部署方案

  • 新增可选软件包 docker.tgz,带有常用应用镜像:Pgadmin, Pgweb, Postgrest, ByteBase, Kong, Minio 等。
  • 新增角色 ETCD,可以在 DCS Servers 指定的节点上自动部署 ETCD 服务,并自动纳入监控。
  • 允许通过 pg_dcs_type 指定 PG 高可用使用的 DCS 服务,Consul(默认),ETCD(备选)
  • 允许通过 node_crontab 参数,为节点配置定时任务,例如数据库备份、VACUUM,统计收集等。
  • 新增了 pg_checksum 选项,启用时,数据库集群将启用数据校验和(此前只有 crit 模板默认启用)
  • 新增了 pg_delay 选项,当实例为 Standby Cluster Leader 时,此参数可以用于配置一个 延迟从库
  • 新增了软件包 pg_probackup,默认角色 replicator 现在默认赋予了备份相关函数所需的权限。
  • Redis 部署现在拆分为两个部分:Redis 节点与 Redis 实例,通过 redis_port 参数可以精确控制一个具体实例。
  • Loki 与 Promtail 现在使用 frpm 制作的 RPM 软件包进行安装。
  • DCS3 配置模板现在使用一个3节点的 pg-meta 集群,与一个单节点的延迟从库。

软件升级

  • 升级 PostgreSQL 至 14.3
  • 升级 Redis 至 6.2.7
  • 升级 PG Exporter 至 0.5.0
  • 升级 Consul 至 1.12.0
  • 升级 vip-manager 至 v1.0.2
  • 升级 Grafana 至 v8.5.2
  • 升级 Loki & Promtail 至 v2.5.0,使用 frpm 打包。

问题修复

  • 修复了 Loki 与 Promtail 默认配置文件名的问题
  • 修复了 Loki 与 Promtail 环境变量无法正确展开的问题
  • 对英文文档进行了一次完整的翻译与修缮,文档依赖的 JS 资源现在直接从本地获取,无需互联网访问。

API 变化

新参数

  • node_data_dir:主要的数据挂载路径,如果不存在会被创建。
  • node_crontab_overwrite:覆盖 /etc/crontab 而非追加内容。
  • node_crontab:要被追加或覆盖的 node crontab 内容。
  • nameserver_enabled:在这个基础设施节节点上启用 nameserver 吗?
  • prometheus_enabled:在这个基础设施节节点上启用 prometheus 吗?
  • grafana_enabled:在这个基础设施节节点上启用 grafana 吗?
  • loki_enabled:在这个基础设施节节点上启用 loki 吗?
  • docker_enable:在这个基础设施节点上启用 docker 吗?
  • consul_enable:启用 consul 服务器/代理吗?
  • etcd_enable:启用 etcd 服务器/客户端吗?
  • pg_checksum:启用 pg 集群数据校验和吗?
  • pg_delay:备份集群主库复制重放时的应用延迟。

参数重制

现在 *_clean 是布尔类型的参数,用于在初始化期间清除现有实例。

*_safeguard 也是布尔类型的参数,用于在执行任何剧本时,避免清除正在运行的实例。

  • pg_exists_action -> pg_clean
  • pg_disable_purge -> pg_safeguard
  • dcs_exists_action -> dcs_clean
  • dcs_disable_purge -> dcs_safeguard

参数重命名

  • node_ntp_config -> node_ntp_enabled
  • node_admin_setup -> node_admin_enabled
  • node_admin_pks -> node_admin_pk_list
  • node_dns_hosts -> node_etc_hosts_default
  • node_dns_hosts_extra -> node_etc_hosts
  • node_dns_server -> node_dns_method
  • node_local_repo_url -> node_repo_local_urls
  • node_packages -> node_packages_default
  • node_extra_packages -> node_packages
  • node_packages_meta -> node_packages_meta
  • node_meta_pip_install -> node_packages_meta_pip
  • node_sysctl_params -> node_tune_params
  • app_list -> nginx_indexes
  • grafana_plugin -> grafana_plugin_method
  • grafana_cache -> grafana_plugin_cache
  • grafana_plugins -> grafana_plugin_list
  • grafana_git_plugin_git -> grafana_plugin_git
  • haproxy_admin_auth_enabled -> haproxy_auth_enabled
  • pg_shared_libraries -> pg_libs
  • dcs_type -> pg_dcs_type

信息来源

51 - 为什么使用 Pigsty

从 Pigsty v1.5.1 标签恢复的历史文档。

为什么要使用Pigsty?

我们的理念是:用好数据库用好数据库,让天下没有难用的数据库!

数据库是信息系统的核心组件,关系型数据库是数据库的绝对主力,PostgreSQL是世界上最先进的开源关系型数据库。

PG提供了一个足够完美的数据库内核,但真要用好它,可没有那么简单,而我们帮助用户做到这一点。

用户痛点

传统企业,特别是中小企业信息化,需要什么样的数据库? 是分布式云原生湖仓一体流批时空超融合HTAP数据库吗?

不是,大多数企业的数据库需求,甚至Excel便足以解决!痛点不在于数据库内核牛不牛,而是 用户能不能用得上!

99% 的企业,完整生命周期的数据需求, 单机PostgreSQL足矣!

痛点需求

软件吞噬世界,而开源吞噬软件。云厂商白嫖开源,却不见螳螂捕蝉,终将被多云部署干翻。

个人搭建玩具Demo使用数据库是一回事,在生产环境部署维护数据库则是完全不同的另一回事:安装部署,运维管理,配套设施,平台搭建,服务接入,高可用,故障切换,负载均衡, 连接池,分库分表,监控,日志,审计,备份,恢复,升级策略,模式变更……,有无数的实际问题需要解决,可不仅仅是yum install postgresql14* && systemctl start postgresql 这么简单。

PostgreSQL已经提供了一个足够完美的数据库内核,但正如Linux用户直接接触的是诸如RedHat,SUSE,Ubuntu这样的操作系统发行版而不是Linux内核一样。用户需要完整的解决方案 —— 数据库发行版,而不是一个单纯的数据库内核。

如果说PostgreSQL这个数据库内核是一台发动机,那么用户真正需要的是整车,即完整的、开箱即用的完整解决方案。我们构建的,就是这样一辆车:稳定可靠,经过长时间生产环境打磨与验证;自动驾驶,带有智能态势感知。

更重要的是,Pigsty完全开源免费!Pigsty在提供类似甚至超过云厂商RDS使用体验的前提下,可将数据库的综合持有成本降低50% ~ 80% 。

产品定位

开箱即用的发行版

RedHat for Linux

  • Pigsty打包PostgreSQL 14.4,集成强力的地理空间插件 PostGIS 3.2、时序数据库插件 TimescaleDB 2.7、分布式扩展插件 Citus 11.0,以及上百功能扩展,全部一键安装,开箱即用。

  • Pigsty集成了完整的大规模数据库监控管控解决方案:Grafana,Prometheus,Loki,Ansible,CMDB。亦可作为生产级应用运行时直接使用,监控管理其他数据库与应用。

  • Pigsty集成了数据分析生态的常用工具:Jupyter,Echarts,Grafana,PostgREST,Postgres。可以低代码的方式,开发交互性数据应用与数据可视化作品。快速产出作品原型,并以标准的方式分享,演示与交付。

简单易用的开发者工具

HashiCorp for Database!

  • Pigsty采用Infra as Data的设计理念,用户描述自己想要什么样的数据库集群,而Pigsty自动为您创建!Just like Kubernetes!

  • Pigsty带有终极的可观测性,以BI的思路设计监控系统,从最顶层的全局洞察到最细节的每一个对象,都可以获取实时数据,支持决策。

  • Pigsty提供灵活丰富的部署支持,本地沙箱,云端,多云部署。无论是高规格物理机还是1核1G虚机均可运行,保持生产、预发、开发、测试环境高度一致。

智能省钱的SRE解决方案

Alternative for RDS!

  • 高可用数据库集群:Pigsty集成了久经考验的生产级高可用数据库架构方案:主从异地容灾,故障自愈,高可用自动切换,自带连接池与负载均衡器,提供分布式数据库般的体验。

  • Pigsty提供了完整的备份解决方案,一键部署自动驾驶的高可用主从集群,硬件故障可以自愈,极大简化运维工作。冷备份与延时从库可有效应对各类软件故障与人为故障,确保系统稳定运行。

  • Pigsty还可以作为完整的SRE解决方案:主机监控,应用部署,并将逐步添加其他数据库的部署与监控:Redis/Greenplum/Kafka/Minio,或支持其他SaaS服务,制作POC,交付Demo等。

VS 云数据库RDS

云数据库/RDS,是另一种"开箱即用"的解决方案,但它交出的答卷,远不足以称得上令专业用户满意:

成本高昂

  • RDS的成本,比起IDC托管自建高出 5~10倍,即使比起云虚拟机自建,也要高出 2~3倍
  • RDS的价格或许相对商业数据库有优势,但在自建面前依然高的离谱。

命不由己

  • 云厂商有能力访问您的各类数据,且很多云厂商并不是真正中立的第三方运营商。
  • 云厂商故障并不鲜见,您能拥有的补偿通常只有可怜的时长代金券。

功能受限

  • 您没有RDS的真正的超级用户权限,一些高级功能无法实现。
  • ‘流复制’,‘高可用’这些本该是标配的东西往往作为增值项出售。

体验有限

  • 云厂商RDS提供的可观测性往往只有零星的几个监控指标,缺乏全局整合与上帝视角。
  • 安装,部署,访问,使用仍然需要大量UI交互与操作。

52 - 用户界面

从 Pigsty v1.5.1 标签恢复的历史文档。

用户界面

完成安装后,可以通过浏览器访问Pigsty提供的图形用户界面。

http://g.pigsty -> http://10.10.10.10:80 (nginx) -> http://10.10.10.10:3000 (grafana)

访问 http://<node_ip>:3000 即可浏览 Pigsty 主页 (用户名: admin, 密码: pigsty)

您可以访问 http://demo.pigsty.cc 来查看公开Pigsty Demo,并浏览Pigsty监控系统提供的功能。

Web服务

Pigsty会通过一系列端口对外提供服务,Web服务会通过Nginx 80端口统一访问。

组件 端口 默认域名 说明
Grafana 3000 g.pigsty Pigsty监控系统图形界面
Prometheus 9090 p.pigsty 监控时序数据库
Loki 3100 l.pigsty 日志收集服务端(无界面)
AlertManager 9093 a.pigsty 报警聚合管理组件
Consul 8500 c.pigsty 分布式配置管理,服务发现
Consul DNS 8600 - Consul提供的DNS服务
Nginx 80 pigsty 所有服务的入口代理
Yum Repo 80 yum.pigsty 本地Yum源
Haproxy Index 80 h.pigsty 所有Haproxy管理界面的访问代理
NTP 123 n.pigsty 环境统一使用的NTP时间服务器
Dnsmasq 53 - 环境统一使用的DNS域名解析服务器

用户可以为这些服务配置自己已有的域名,或使用make dns快捷方式将默认的域名写入/etc/hosts。 用户仍然可以使用 IP:Port 的方式直接访问大部分服务,例如,Pigsty监控系统的入口即为元节点IP+3000端口。

警告

注意,如果使用了Consul作为DSC,Consul UI 必须 通过Nginx域名的方式访问。Consul监听127.0.0.1端口,这是一个出于安全性考量而特意做出的设计:Consul包含了敏感的元数据,不宜直接对外暴露。

53 - Pigsty部署

从 Pigsty v1.5.1 标签恢复的历史文档。

部署Pigsty分为三步:准备工作修改配置执行剧本

Pigsty在部署前需要进行一些准备工作:配置带有正确权限配置的节点,下载安装相关软件。置备完成后,用户应当按照自己的需求修改配置,并执行剧本将系统调整至配置描述的状态。其中,配置是部署Pigsty的重点所在。

部署方式

  • 标准部署:您自己准备全新节点,完成标准Pigsty部署流程。
  • 沙箱部署 : 通过预制的vagrant模板一键拉起本地虚拟机沙箱环境。
  • 多云部署:使用terraform模板在云服务供应商处拉起所需虚拟机资源,并执行部署。
  • 仅监控部署 : 使用单节点Pigsty监控现有数据库集群。

无论何种部署,其流程都分为三步:准备资源修改配置执行剧本。Pigsty在部署前需要进行一些准备工作:配置带有正确权限配置的节点,下载安装相关软件。置备完成后,用户应当按照自己的需求修改配置,并执行剧本将系统调整至配置描述的状态。其中准备与执行这两个步骤非常简单,配置 是部署Pigsty的关键点所在。

准备工作

修改配置

执行剧本

54 - 定制 PostgreSQL 模板

从 Pigsty v1.5.1 标签恢复的历史文档。

Patroni模板用于定制PostgreSQL集群的规格配置,而Postgres模板用于定制PostgreSQL集群的内容

Pigsty默认提供了近100关于PGSQL的参数,描述用户所需的PostgreSQL集群,通常可以满足绝大多数用户需求。

但如果您对Pigsty创建的数据库集群进行更深一步的定制,则可以参考本文内容,对Patroni模板Postgres模板进行定制

Patroni模板

Pigsty使用 Patroni 管理与初始化Postgres数据库集群。 如果用户希望修改PostgreSQL数据库集群的默认配置参数,规格与调优方案,高可用策略,DCS访问,管控API,可以通过修改Patroni模板的方式实现。

Pigsty使用Patroni完成供给的主体工作,即使用户选择了 无Patroni模式,拉起数据库集群也会由Patroni负责,并在创建完成后移除Patroni组件。 用户可以通过Patroni配置文件,完成大部分的PostgreSQL集群定制工作,Patroni配置文件格式详情请参考 Patroni官方文档

预制Patroni模板

Pigsty提供了几种预定义的初始化模板,初始化模板是用于初始化数据库集群的定义文件,默认位于roles/postgres/templates/。包括:

Conf CPU Mem Disk 说明
oltp 64 400GB 4TB 生产OLTP模板,默认配置,针对生产机型优化延迟与性能
olap 64 400GB 4TB 生产OLAP模板,提高并行度,针对吞吐量,长查询进行优化。
crit 64 400GB 4TB 生产核心业务模板,基于OLTP模板针对RPO、安全性、数据完整性进行优化,启用同步复制与数据校验和。
tiny 1 1GB 40GB 微型数据库模板,针对低资源场景进行优化,例如运行于虚拟机中的演示数据库集群。
mini 2 4GB 100GB 2C4G 机型OLTP模板
small 4 8GB 200GB 4C8G 机型OLTP模板
medium 8 16GB 500GB 8C16G 机型OLTP模板
large 16 32GB 1TB 16C32G 机型OLTP模板

通过 pg_conf 参数指定所需使用的模板路径,如果使用预制模板,则只需填入模板文件名称即可。如果使用定制的 Patroni配置模板,通常也应当针对机器节点使用配套的 节点优化模板

pg_conf:   tiny.yml      # 使用 tiny.yml 调优模板
node_tune: tiny          # 节点调优模式:oltp|olap|crit|tiny

在安装Pigsty进行Configure的过程中,Pigsty会检测根据当前机器(管理机)的规格,自动选择对应的默认规格。

定制Patroni模板

定制您自己的Patroni模板时,您可以用已有的几种基础模板作为基线,在此基础上进行修改。

并放置于templates/目录中,以<mode>.yml格式命名即可。

Patroni中的模板变量请保留,否则相关参数可能无法正常工作。例如 pg_libs

最后,在配置文件的 pg_conf 配置项,指定您新创建的模板名称即可,例如 olap-32C128G-nvme.yml

Postgres模板

可以使用 PG模板 配置项,对集群中的模板数据库 template1 进行定制,进而。

通过这种方式确保任何在该数据库集群中新创建的数据库都带有相同的默认配置:模式,扩展,默认权限。

相关文件

定制数据库模板时,相关参数会首先被渲染为SQL脚本后,在部署好的数据库集群上执行。

^---/pg/bin/pg-init
          |
          ^---(1)--- /pg/tmp/pg-init-roles.sql
          ^---(2)--- /pg/tmp/pg-init-template.sql
          ^---(3)--- <other customize logic in pg-init>

# 业务用户与数据库并不是在模版定制中创建的,但在此列出。
^-------------(4)--- /pg/tmp/pg-user-{{ user.name }}.sql
^-------------(5)--- /pg/tmp/pg-db-{{ db.name }}.sql

pg-init

pg-init是用于自定义初始化模板的Shell脚本路径,该脚本将以postgres用户身份,仅在主库上执行,执行时数据库集群主库已经被拉起,可以执行任意Shell命令,或通过psql执行任意SQL命令。

如果不指定该配置项,Pigsty会使用默认的pg-init Shell脚本,如下所示。

#!/usr/bin/env bash
set -uo pipefail


#==================================================================#
#                          Default Roles                           #
#==================================================================#
psql postgres -qAXwtf /pg/tmp/pg-init-roles.sql


#==================================================================#
#                          System Template                         #
#==================================================================#
# system default template
psql template1 -qAXwtf /pg/tmp/pg-init-template.sql

# make postgres same as templated database (optional)
psql postgres  -qAXwtf /pg/tmp/pg-init-template.sql



#==================================================================#
#                          Customize Logic                         #
#==================================================================#
# add your template logic here

如果用户需要执行复杂的定制逻辑,可在该脚本的基础上进行追加。注意 pg-init 用于定制数据库集群,通常这是通过修改 模板数据库 实现的。在该脚本执行时,数据库集群已经启动,但业务用户与业务数据库尚未创建。因此模板数据库的修改会反映在默认定义的业务数据库中。

v1.5.1 冻结示例附录

以下脚本与配置块来自英文 t-pgsql-customize.md 冻结页。代码保持原样,分别对应初始化文件关系、pg-init、角色初始化 SQL、模板初始化 SQL,以及完整 Patroni 模板。

初始化文件关系

^---/pg/bin/pg-init
          |
          ^---(1)--- /pg/tmp/pg-init-roles.sql
          ^---(2)--- /pg/tmp/pg-init-template.sql
          ^---(3)--- <other customize logic in pg-init>

# user & database are not created during templating
^-------------(4)--- /pg/tmp/pg-user-{{ user.name }}.sql
^-------------(5)--- /pg/tmp/pg-db-{{ db.name }}.sql

pg-init

#!/usr/bin/env bash
set -uo pipefail


#==================================================================#
#                          Default Roles                           #
#==================================================================#
psql postgres -qAXwtf /pg/tmp/pg-init-roles.sql


#==================================================================#
#                          System Template                         #
#==================================================================#
# system default template
psql template1 -qAXwtf /pg/tmp/pg-init-template.sql

# make postgres same as templated database (optional)
psql postgres  -qAXwtf /pg/tmp/pg-init-template.sql



#==================================================================#
#                          Customize Logic                         #
#==================================================================#
# add your template logic here

默认角色初始化 SQL

----------------------------------------------------------------------
-- File      :   pg-init-roles.sql
-- Path      :   /pg/tmp/pg-init-roles
-- Time      :   2021-07-26 18:17
-- Note      :   managed by ansible, DO NOT CHANGE
-- Desc      :   creation sql script for default roles
----------------------------------------------------------------------


--###################################################################--
--                         dbrole_readonly                           --
--###################################################################--
-- run as dbsu (postgres by default)
-- createuser -w -p 5432 --no-login'dbrole_readonly';
-- psql -p 5432 -AXtwqf /pg/tmp/pg-user-dbrole_readonly.sql

--==================================================================--
--                           CREATE USER                            --
--==================================================================--
CREATE USER "dbrole_readonly"  NOLOGIN;

--==================================================================--
--                           ALTER USER                             --
--==================================================================--
-- options
ALTER USER "dbrole_readonly"  NOLOGIN;

-- password

-- expire

-- conn limit

-- parameters

-- comment
COMMENT ON ROLE "dbrole_readonly" IS 'role for global read-only access';


--==================================================================--
--                           GRANT ROLE                             --
--==================================================================--


--==================================================================--
--                          PGBOUNCER USER                          --
--==================================================================--
-- user will not be added to pgbouncer user list by default,
-- unless pgbouncer is explicitly set to 'true', which means production user

-- User 'dbrole_readonly' will NOT be added to /etc/pgbouncer/userlist.txt

--==================================================================--




--###################################################################--
--                         dbrole_readwrite                           --
--###################################################################--
-- run as dbsu (postgres by default)
-- createuser -w -p 5432 --no-login'dbrole_readwrite';
-- psql -p 5432 -AXtwqf /pg/tmp/pg-user-dbrole_readwrite.sql

--==================================================================--
--                           CREATE USER                            --
--==================================================================--
CREATE USER "dbrole_readwrite"  NOLOGIN;

--==================================================================--
--                           ALTER USER                             --
--==================================================================--
-- options
ALTER USER "dbrole_readwrite"  NOLOGIN;

-- password

-- expire

-- conn limit

-- parameters

-- comment
COMMENT ON ROLE "dbrole_readwrite" IS 'role for global read-write access';


--==================================================================--
--                           GRANT ROLE                             --
--==================================================================--
GRANT "dbrole_readonly" TO "dbrole_readwrite";


--==================================================================--
--                          PGBOUNCER USER                          --
--==================================================================--
-- user will not be added to pgbouncer user list by default,
-- unless pgbouncer is explicitly set to 'true', which means production user

-- User 'dbrole_readwrite' will NOT be added to /etc/pgbouncer/userlist.txt

--==================================================================--




--###################################################################--
--                         dbrole_offline                           --
--###################################################################--
-- run as dbsu (postgres by default)
-- createuser -w -p 5432 --no-login'dbrole_offline';
-- psql -p 5432 -AXtwqf /pg/tmp/pg-user-dbrole_offline.sql

--==================================================================--
--                           CREATE USER                            --
--==================================================================--
CREATE USER "dbrole_offline"  NOLOGIN;

--==================================================================--
--                           ALTER USER                             --
--==================================================================--
-- options
ALTER USER "dbrole_offline"  NOLOGIN;

-- password

-- expire

-- conn limit

-- parameters

-- comment
COMMENT ON ROLE "dbrole_offline" IS 'role for restricted read-only access (offline instance)';


--==================================================================--
--                           GRANT ROLE                             --
--==================================================================--


--==================================================================--
--                          PGBOUNCER USER                          --
--==================================================================--
-- user will not be added to pgbouncer user list by default,
-- unless pgbouncer is explicitly set to 'true', which means production user

-- User 'dbrole_offline' will NOT be added to /etc/pgbouncer/userlist.txt

--==================================================================--




--###################################################################--
--                         dbrole_admin                           --
--###################################################################--
-- run as dbsu (postgres by default)
-- createuser -w -p 5432 --no-login'dbrole_admin';
-- psql -p 5432 -AXtwqf /pg/tmp/pg-user-dbrole_admin.sql

--==================================================================--
--                           CREATE USER                            --
--==================================================================--
CREATE USER "dbrole_admin"  NOLOGIN;

--==================================================================--
--                           ALTER USER                             --
--==================================================================--
-- options
ALTER USER "dbrole_admin"  NOLOGIN;

-- password

-- expire

-- conn limit

-- parameters

-- comment
COMMENT ON ROLE "dbrole_admin" IS 'role for object creation';


--==================================================================--
--                           GRANT ROLE                             --
--==================================================================--
GRANT "pg_monitor" TO "dbrole_admin";
GRANT "dbrole_readwrite" TO "dbrole_admin";


--==================================================================--
--                          PGBOUNCER USER                          --
--==================================================================--
-- user will not be added to pgbouncer user list by default,
-- unless pgbouncer is explicitly set to 'true', which means production user

-- User 'dbrole_admin' will NOT be added to /etc/pgbouncer/userlist.txt

--==================================================================--




--###################################################################--
--                         postgres                           --
--###################################################################--
-- run as dbsu (postgres by default)
-- createuser -w -p 5432  --superuser'postgres';
-- psql -p 5432 -AXtwqf /pg/tmp/pg-user-postgres.sql

--==================================================================--
--                           CREATE USER                            --
--==================================================================--
CREATE USER "postgres"  SUPERUSER;

--==================================================================--
--                           ALTER USER                             --
--==================================================================--
-- options
ALTER USER "postgres"  SUPERUSER;

-- password

-- expire

-- conn limit

-- parameters

-- comment
COMMENT ON ROLE "postgres" IS 'system superuser';


--==================================================================--
--                           GRANT ROLE                             --
--==================================================================--


--==================================================================--
--                          PGBOUNCER USER                          --
--==================================================================--
-- user will not be added to pgbouncer user list by default,
-- unless pgbouncer is explicitly set to 'true', which means production user

-- User 'postgres' will NOT be added to /etc/pgbouncer/userlist.txt

--==================================================================--




--###################################################################--
--                         dbuser_dba                           --
--###################################################################--
-- run as dbsu (postgres by default)
-- createuser -w -p 5432  --superuser'dbuser_dba';
-- psql -p 5432 -AXtwqf /pg/tmp/pg-user-dbuser_dba.sql

--==================================================================--
--                           CREATE USER                            --
--==================================================================--
CREATE USER "dbuser_dba"  SUPERUSER;

--==================================================================--
--                           ALTER USER                             --
--==================================================================--
-- options
ALTER USER "dbuser_dba"  SUPERUSER;

-- password

-- expire

-- conn limit

-- parameters

-- comment
COMMENT ON ROLE "dbuser_dba" IS 'system admin user';


--==================================================================--
--                           GRANT ROLE                             --
--==================================================================--
GRANT "dbrole_admin" TO "dbuser_dba";


--==================================================================--
--                          PGBOUNCER USER                          --
--==================================================================--
-- user will not be added to pgbouncer user list by default,
-- unless pgbouncer is explicitly set to 'true', which means production user

-- User 'dbuser_dba' will NOT be added to /etc/pgbouncer/userlist.txt

--==================================================================--




--###################################################################--
--                         replicator                           --
--###################################################################--
-- run as dbsu (postgres by default)
-- createuser -w -p 5432  --replication'replicator';
-- psql -p 5432 -AXtwqf /pg/tmp/pg-user-replicator.sql

--==================================================================--
--                           CREATE USER                            --
--==================================================================--
CREATE USER "replicator"  REPLICATION BYPASSRLS;

--==================================================================--
--                           ALTER USER                             --
--==================================================================--
-- options
ALTER USER "replicator"  REPLICATION BYPASSRLS;

-- password

-- expire

-- conn limit

-- parameters

-- comment
COMMENT ON ROLE "replicator" IS 'system replicator';


--==================================================================--
--                           GRANT ROLE                             --
--==================================================================--
GRANT "pg_monitor" TO "replicator";
GRANT "dbrole_readonly" TO "replicator";


--==================================================================--
--                          PGBOUNCER USER                          --
--==================================================================--
-- user will not be added to pgbouncer user list by default,
-- unless pgbouncer is explicitly set to 'true', which means production user

-- User 'replicator' will NOT be added to /etc/pgbouncer/userlist.txt

--==================================================================--




--###################################################################--
--                         dbuser_monitor                           --
--###################################################################--
-- run as dbsu (postgres by default)
-- createuser -w -p 5432 'dbuser_monitor';
-- psql -p 5432 -AXtwqf /pg/tmp/pg-user-dbuser_monitor.sql

--==================================================================--
--                           CREATE USER                            --
--==================================================================--
CREATE USER "dbuser_monitor" ;

--==================================================================--
--                           ALTER USER                             --
--==================================================================--
-- options
ALTER USER "dbuser_monitor" ;

-- password

-- expire

-- conn limit

-- parameters
ALTER USER "dbuser_monitor" SET log_min_duration_statement = 1000;

-- comment
COMMENT ON ROLE "dbuser_monitor" IS 'system monitor user';


--==================================================================--
--                           GRANT ROLE                             --
--==================================================================--
GRANT "pg_monitor" TO "dbuser_monitor";
GRANT "dbrole_readonly" TO "dbuser_monitor";


--==================================================================--
--                          PGBOUNCER USER                          --
--==================================================================--
-- user will not be added to pgbouncer user list by default,
-- unless pgbouncer is explicitly set to 'true', which means production user

-- User 'dbuser_monitor' will NOT be added to /etc/pgbouncer/userlist.txt

--==================================================================--




--###################################################################--
--                         dbuser_stats                           --
--###################################################################--
-- run as dbsu (postgres by default)
-- createuser -w -p 5432 'dbuser_stats';
-- psql -p 5432 -AXtwqf /pg/tmp/pg-user-dbuser_stats.sql

--==================================================================--
--                           CREATE USER                            --
--==================================================================--
CREATE USER "dbuser_stats" ;

--==================================================================--
--                           ALTER USER                             --
--==================================================================--
-- options
ALTER USER "dbuser_stats" ;

-- password
ALTER USER "dbuser_stats" PASSWORD 'DBUser.Stats';

-- expire

-- conn limit

-- parameters

-- comment
COMMENT ON ROLE "dbuser_stats" IS 'business offline user for offline queries and ETL';


--==================================================================--
--                           GRANT ROLE                             --
--==================================================================--
GRANT "dbrole_offline" TO "dbuser_stats";


--==================================================================--
--                          PGBOUNCER USER                          --
--==================================================================--
-- user will not be added to pgbouncer user list by default,
-- unless pgbouncer is explicitly set to 'true', which means production user

-- User 'dbuser_stats' will NOT be added to /etc/pgbouncer/userlist.txt

--==================================================================--






--==================================================================--
--                       PASSWORD OVERWRITE                         --
--==================================================================--
ALTER ROLE "replicator" PASSWORD 'DBUser.Replicator';
ALTER ROLE "dbuser_monitor" PASSWORD 'DBUser.Monitor';
ALTER ROLE "dbuser_dba" PASSWORD 'DBUser.DBA';
--==================================================================--

template1 初始化 SQL

----------------------------------------------------------------------
-- File      :   pg-init-template.sql
-- Ctime     :   2018-10-30
-- Mtime     :   2021-02-27
-- Desc      :   init postgres cluster template
-- Path      :   /pg/tmp/pg-init-template.sql
-- Author    :   Vonng([email protected])
-- Copyright (C) 2018-2022 Ruohang Feng
----------------------------------------------------------------------


--==================================================================--
--                           Executions                             --
--==================================================================--
-- psql template1 -AXtwqf /pg/tmp/pg-init-template.sql
-- this sql scripts is responsible for post-init procedure
-- it will
--    * create system users such as replicator, monitor user, admin user
--    * create system default roles
--    * create schema, extensions in template1 & postgres
--    * create monitor views in template1 & postgres


--==================================================================--
--                          Default Privileges                      --
--==================================================================--
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT USAGE                         ON SCHEMAS   TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT SELECT                        ON TABLES    TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT SELECT                        ON SEQUENCES TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT EXECUTE                       ON FUNCTIONS TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT USAGE                         ON SCHEMAS   TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT SELECT                        ON TABLES    TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT SELECT                        ON SEQUENCES TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT EXECUTE                       ON FUNCTIONS TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT INSERT, UPDATE, DELETE        ON TABLES    TO dbrole_readwrite;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT USAGE, UPDATE                 ON SEQUENCES TO dbrole_readwrite;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT TRUNCATE, REFERENCES, TRIGGER ON TABLES    TO dbrole_admin;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT CREATE                        ON SCHEMAS   TO dbrole_admin;

ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT USAGE                         ON SCHEMAS   TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT SELECT                        ON TABLES    TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT SELECT                        ON SEQUENCES TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT EXECUTE                       ON FUNCTIONS TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT USAGE                         ON SCHEMAS   TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT SELECT                        ON TABLES    TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT SELECT                        ON SEQUENCES TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT EXECUTE                       ON FUNCTIONS TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT INSERT, UPDATE, DELETE        ON TABLES    TO dbrole_readwrite;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT USAGE, UPDATE                 ON SEQUENCES TO dbrole_readwrite;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT TRUNCATE, REFERENCES, TRIGGER ON TABLES    TO dbrole_admin;
ALTER DEFAULT PRIVILEGES FOR ROLE dbuser_dba GRANT CREATE                        ON SCHEMAS   TO dbrole_admin;

-- for additional business admin, they can SET ROLE to dbrole_admin
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT USAGE                         ON SCHEMAS   TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT SELECT                        ON TABLES    TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT SELECT                        ON SEQUENCES TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT EXECUTE                       ON FUNCTIONS TO dbrole_readonly;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT USAGE                         ON SCHEMAS   TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT SELECT                        ON TABLES    TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT SELECT                        ON SEQUENCES TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT EXECUTE                       ON FUNCTIONS TO dbrole_offline;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT INSERT, UPDATE, DELETE        ON TABLES    TO dbrole_readwrite;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT USAGE, UPDATE                 ON SEQUENCES TO dbrole_readwrite;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT TRUNCATE, REFERENCES, TRIGGER ON TABLES    TO dbrole_admin;
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" GRANT CREATE                        ON SCHEMAS   TO dbrole_admin;

--==================================================================--
--                              Schemas                             --
--==================================================================--
CREATE SCHEMA IF NOT EXISTS "monitor";

-- revoke public creation
REVOKE CREATE ON SCHEMA public FROM PUBLIC;

--==================================================================--
--                             Extensions                           --
--==================================================================--
CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pgstattuple" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_qualstats" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_buffercache" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pageinspect" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_prewarm" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_visibility" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_freespacemap" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "pg_repack" WITH SCHEMA "monitor";
CREATE EXTENSION IF NOT EXISTS "postgres_fdw";
CREATE EXTENSION IF NOT EXISTS "file_fdw";
CREATE EXTENSION IF NOT EXISTS "btree_gist";
CREATE EXTENSION IF NOT EXISTS "btree_gin";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
CREATE EXTENSION IF NOT EXISTS "intagg";
CREATE EXTENSION IF NOT EXISTS "intarray";



--==================================================================--
--                            Monitor Views                         --
--==================================================================--

----------------------------------------------------------------------
-- cleanse
----------------------------------------------------------------------
CREATE SCHEMA IF NOT EXISTS monitor;
GRANT USAGE ON SCHEMA monitor TO "dbuser_monitor";
GRANT USAGE ON SCHEMA monitor TO "dbuser_dba";
GRANT USAGE ON SCHEMA monitor TO "replicator";

DROP VIEW IF EXISTS monitor.pg_table_bloat_human;
DROP VIEW IF EXISTS monitor.pg_index_bloat_human;
DROP VIEW IF EXISTS monitor.pg_table_bloat;
DROP VIEW IF EXISTS monitor.pg_index_bloat;
DROP VIEW IF EXISTS monitor.pg_session;
DROP VIEW IF EXISTS monitor.pg_kill;
DROP VIEW IF EXISTS monitor.pg_cancel;
DROP VIEW IF EXISTS monitor.pg_seq_scan;


----------------------------------------------------------------------
-- Table bloat estimate
----------------------------------------------------------------------
CREATE OR REPLACE VIEW monitor.pg_table_bloat AS
    SELECT CURRENT_CATALOG AS datname, nspname, relname , bs * tblpages AS size,
           CASE WHEN tblpages - est_tblpages_ff > 0 THEN (tblpages - est_tblpages_ff)/tblpages::FLOAT ELSE 0 END AS ratio
    FROM (
             SELECT ceil( reltuples / ( (bs-page_hdr)*fillfactor/(tpl_size*100) ) ) + ceil( toasttuples / 4 ) AS est_tblpages_ff,
                    tblpages, fillfactor, bs, tblid, nspname, relname, is_na
             FROM (
                      SELECT
                          ( 4 + tpl_hdr_size + tpl_data_size + (2 * ma)
                              - CASE WHEN tpl_hdr_size % ma = 0 THEN ma ELSE tpl_hdr_size % ma END
                              - CASE WHEN ceil(tpl_data_size)::INT % ma = 0 THEN ma ELSE ceil(tpl_data_size)::INT % ma END
                              ) AS tpl_size, (heappages + toastpages) AS tblpages, heappages,
                          toastpages, reltuples, toasttuples, bs, page_hdr, tblid, nspname, relname, fillfactor, is_na
                      FROM (
                               SELECT
                                   tbl.oid AS tblid, ns.nspname , tbl.relname, tbl.reltuples,
                                   tbl.relpages AS heappages, coalesce(toast.relpages, 0) AS toastpages,
                                   coalesce(toast.reltuples, 0) AS toasttuples,
                                   coalesce(substring(array_to_string(tbl.reloptions, ' ') FROM 'fillfactor=([0-9]+)')::smallint, 100) AS fillfactor,
                                   current_setting('block_size')::numeric AS bs,
                                   CASE WHEN version()~'mingw32' OR version()~'64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END AS ma,
                                   24 AS page_hdr,
                                   23 + CASE WHEN MAX(coalesce(s.null_frac,0)) > 0 THEN ( 7 + count(s.attname) ) / 8 ELSE 0::int END
                                       + CASE WHEN bool_or(att.attname = 'oid' and att.attnum < 0) THEN 4 ELSE 0 END AS tpl_hdr_size,
                                   sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 0) ) AS tpl_data_size,
                                   bool_or(att.atttypid = 'pg_catalog.name'::regtype)
                                       OR sum(CASE WHEN att.attnum > 0 THEN 1 ELSE 0 END) <> count(s.attname) AS is_na
                               FROM pg_attribute AS att
                                        JOIN pg_class AS tbl ON att.attrelid = tbl.oid
                                        JOIN pg_namespace AS ns ON ns.oid = tbl.relnamespace
                                        LEFT JOIN pg_stats AS s ON s.schemaname=ns.nspname AND s.tablename = tbl.relname AND s.inherited=false AND s.attname=att.attname
                                        LEFT JOIN pg_class AS toast ON tbl.reltoastrelid = toast.oid
                               WHERE NOT att.attisdropped AND tbl.relkind = 'r' AND nspname NOT IN ('pg_catalog','information_schema')
                               GROUP BY 1,2,3,4,5,6,7,8,9,10
                           ) AS s
                  ) AS s2
         ) AS s3
    WHERE NOT is_na;
COMMENT ON VIEW monitor.pg_table_bloat IS 'postgres table bloat estimate';

----------------------------------------------------------------------
-- Index bloat estimate
----------------------------------------------------------------------
CREATE OR REPLACE VIEW monitor.pg_index_bloat AS
    SELECT CURRENT_CATALOG AS datname, nspname, idxname AS relname, relpages::BIGINT * bs AS size,
           COALESCE((relpages - ( reltuples * (6 + ma - (CASE WHEN index_tuple_hdr % ma = 0 THEN ma ELSE index_tuple_hdr % ma END)
                                                   + nulldatawidth + ma - (CASE WHEN nulldatawidth % ma = 0 THEN ma ELSE nulldatawidth % ma END))
                                      / (bs - pagehdr)::FLOAT  + 1 )), 0) / relpages::FLOAT AS ratio
    FROM (
             SELECT nspname,
                    idxname,
                    reltuples,
                    relpages,
                    current_setting('block_size')::INTEGER                                                               AS bs,
                    (CASE WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END)  AS ma,
                    24                                                                                                   AS pagehdr,
                    (CASE WHEN max(COALESCE(pg_stats.null_frac, 0)) = 0 THEN 2 ELSE 6 END)                               AS index_tuple_hdr,
                    sum((1.0 - COALESCE(pg_stats.null_frac, 0.0)) *
                        COALESCE(pg_stats.avg_width, 1024))::INTEGER                                                     AS nulldatawidth
             FROM pg_attribute
                      JOIN (
                 SELECT pg_namespace.nspname,
                        ic.relname                                                   AS idxname,
                        ic.reltuples,
                        ic.relpages,
                        pg_index.indrelid,
                        pg_index.indexrelid,
                        tc.relname                                                   AS tablename,
                        regexp_split_to_table(pg_index.indkey::TEXT, ' ') :: INTEGER AS attnum,
                        pg_index.indexrelid                                          AS index_oid
                 FROM pg_index
                          JOIN pg_class ic ON pg_index.indexrelid = ic.oid
                          JOIN pg_class tc ON pg_index.indrelid = tc.oid
                          JOIN pg_namespace ON pg_namespace.oid = ic.relnamespace
                          JOIN pg_am ON ic.relam = pg_am.oid
                 WHERE pg_am.amname = 'btree' AND ic.relpages > 0 AND nspname NOT IN ('pg_catalog', 'information_schema')
             ) ind_atts ON pg_attribute.attrelid = ind_atts.indexrelid AND pg_attribute.attnum = ind_atts.attnum
                      JOIN pg_stats ON pg_stats.schemaname = ind_atts.nspname
                 AND ((pg_stats.tablename = ind_atts.tablename AND pg_stats.attname = pg_get_indexdef(pg_attribute.attrelid, pg_attribute.attnum, TRUE))
                     OR (pg_stats.tablename = ind_atts.idxname AND pg_stats.attname = pg_attribute.attname))
             WHERE pg_attribute.attnum > 0
             GROUP BY 1, 2, 3, 4, 5, 6
         ) est
    LIMIT 512;
COMMENT ON VIEW monitor.pg_index_bloat IS 'postgres index bloat estimate (btree-only)';

----------------------------------------------------------------------
-- table bloat pretty
----------------------------------------------------------------------
CREATE OR REPLACE VIEW monitor.pg_table_bloat_human AS
SELECT nspname || '.' || relname AS name,
       pg_size_pretty(size)      AS size,
       pg_size_pretty((size * ratio)::BIGINT) AS wasted,
       round(100 * ratio::NUMERIC, 2)  as ratio
FROM monitor.pg_table_bloat ORDER BY wasted DESC NULLS LAST;
COMMENT ON VIEW monitor.pg_table_bloat_human IS 'postgres table bloat pretty';

----------------------------------------------------------------------
-- index bloat pretty
----------------------------------------------------------------------
CREATE OR REPLACE VIEW monitor.pg_index_bloat_human AS
SELECT nspname || '.' || relname              AS name,
       pg_size_pretty(size)                   AS size,
       pg_size_pretty((size * ratio)::BIGINT) AS wasted,
       round(100 * ratio::NUMERIC, 2)         as ratio
FROM monitor.pg_index_bloat;
COMMENT ON VIEW monitor.pg_index_bloat_human IS 'postgres index bloat pretty';


----------------------------------------------------------------------
-- pg session
----------------------------------------------------------------------
CREATE OR REPLACE VIEW monitor.pg_session AS
SELECT coalesce(datname, 'all') AS datname,
       numbackends,
       active,
       idle,
       ixact,
       max_duration,
       max_tx_duration,
       max_conn_duration
FROM (
         SELECT datname,
                count(*)                                         AS numbackends,
                count(*) FILTER ( WHERE state = 'active' )       AS active,
                count(*) FILTER ( WHERE state = 'idle' )         AS idle,
                count(*) FILTER ( WHERE state = 'idle in transaction'
                    OR state = 'idle in transaction (aborted)' ) AS ixact,
                max(extract(epoch from now() - state_change))
                FILTER ( WHERE state = 'active' )                AS max_duration,
                max(extract(epoch from now() - xact_start))      AS max_tx_duration,
                max(extract(epoch from now() - backend_start))   AS max_conn_duration
         FROM pg_stat_activity
         WHERE backend_type = 'client backend'
           AND pid <> pg_backend_pid()
         GROUP BY ROLLUP (1)
         ORDER BY 1 NULLS FIRST
     ) t;
COMMENT ON VIEW monitor.pg_session IS 'postgres session stats';


----------------------------------------------------------------------
-- pg kill
----------------------------------------------------------------------
CREATE OR REPLACE VIEW monitor.pg_kill AS
SELECT pid,
       pg_terminate_backend(pid)                 AS killed,
       datname                                   AS dat,
       usename                                   AS usr,
       application_name                          AS app,
       client_addr                               AS addr,
       state,
       extract(epoch from now() - state_change)  AS query_time,
       extract(epoch from now() - xact_start)    AS xact_time,
       extract(epoch from now() - backend_start) AS conn_time,
       substring(query, 1, 40)                   AS query
FROM pg_stat_activity
WHERE backend_type = 'client backend'
  AND pid <> pg_backend_pid();
COMMENT ON VIEW monitor.pg_kill IS 'kill all backend session';


----------------------------------------------------------------------
-- quick cancel view
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_cancel;
CREATE OR REPLACE VIEW monitor.pg_cancel AS
SELECT pid,
       pg_cancel_backend(pid)                    AS cancel,
       datname                                   AS dat,
       usename                                   AS usr,
       application_name                          AS app,
       client_addr                               AS addr,
       state,
       extract(epoch from now() - state_change)  AS query_time,
       extract(epoch from now() - xact_start)    AS xact_time,
       extract(epoch from now() - backend_start) AS conn_time,
       substring(query, 1, 40)
FROM pg_stat_activity
WHERE state = 'active'
  AND backend_type = 'client backend'
  and pid <> pg_backend_pid();
COMMENT ON VIEW monitor.pg_cancel IS 'cancel backend queries';


----------------------------------------------------------------------
-- seq scan
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_seq_scan;
CREATE OR REPLACE VIEW monitor.pg_seq_scan AS
SELECT schemaname                             AS nspname,
       relname,
       seq_scan,
       seq_tup_read,
       seq_tup_read / seq_scan                AS seq_tup_avg,
       idx_scan,
       n_live_tup + n_dead_tup                AS tuples,
       n_live_tup / (n_live_tup + n_dead_tup) AS dead_ratio
FROM pg_stat_user_tables
WHERE seq_scan > 0
  and (n_live_tup + n_dead_tup) > 0
ORDER BY seq_tup_read DESC
LIMIT 50;
COMMENT ON VIEW monitor.pg_seq_scan IS 'table that have seq scan';


----------------------------------------------------------------------
-- pg_shmem auxiliary function
-- PG 13 ONLY!
----------------------------------------------------------------------
CREATE OR REPLACE FUNCTION monitor.pg_shmem() RETURNS SETOF
    pg_shmem_allocations AS $$ SELECT * FROM pg_shmem_allocations;$$ LANGUAGE SQL SECURITY DEFINER;
COMMENT ON FUNCTION monitor.pg_shmem() IS 'security wrapper for pg_shmem';


--==================================================================--
--                          Customize Logic                         --
--==================================================================--
-- This script will be execute on primary instance among a newly created
-- postgres cluster. it will be executed as dbsu on template1 database
-- put your own customize logic here
-- make sure they are idempotent

Patroni 模板

#!/usr/bin/env patroni
#==============================================================#
# File      :   patroni.yml
# Ctime     :   2020-04-08
# Mtime     :   2020-12-22
# Desc      :   patroni cluster definition for {{ pg_cluster }} (oltp)
# Path      :   /pg/bin/patroni.yml
# Real Path :   /pg/conf/{{ pg_instance }}.yml
# Link      :   /pg/bin/patroni.yml -> /pg/conf/{{ pg_instance}}.yml
# Note      :   Transactional Database Cluster Template
# Doc       :   https://patroni.readthedocs.io/en/latest/SETTINGS.html
# Copyright (C) 2018-2022 Ruohang Feng
#==============================================================#

# OLTP database are optimized for performance, rt latency
# typical spec: 64 Core | 400 GB RAM | PCI-E SSD xTB

---
#------------------------------------------------------------------------------
# identity
#------------------------------------------------------------------------------
namespace: {{ pg_namespace }}/          # namespace
scope: {{ pg_cluster }}                 # cluster name
name: {{ pg_instance }}                 # instance name

#------------------------------------------------------------------------------
# log
#------------------------------------------------------------------------------
log:
  level: INFO                           #  NOTEST|DEBUG|INFO|WARNING|ERROR|CRITICAL
  dir: /pg/log/                         #  default log file: /pg/log/patroni.log
  file_size: 33554432                   #  32MB log triggers log rotation
  file_num: 20                          #  keep at most 30x32MB = 1GB log
  dateformat: '%Y-%m-%d %H:%M:%S %z'    #  IMPORTANT: discard milli timestamp
  format: '%(asctime)s %(levelname)s: %(message)s'

#------------------------------------------------------------------------------
# dcs
#------------------------------------------------------------------------------
consul:
  host: 127.0.0.1:8500
  consistency: default         # default|consistent|stale
  register_service: true
  service_check_interval: 15s
  service_tags:
    - {{ pg_cluster }}

#------------------------------------------------------------------------------
# api
#------------------------------------------------------------------------------
# how to expose patroni service
# listen on all ipv4, connect via public ip, use same credential as dbuser_monitor
restapi:
  listen: 0.0.0.0:{{ patroni_port }}
  connect_address: {{ inventory_hostname }}:{{ patroni_port }}
  authentication:
    verify_client: none                 # none|optional|required
    username: {{ pg_monitor_username }}
    password: '{{ pg_monitor_password }}'

#------------------------------------------------------------------------------
# ctl
#------------------------------------------------------------------------------
ctl:
  optional:
    insecure: true
    # cacert: '/path/to/ca/cert'
    # certfile: '/path/to/cert/file'
    # keyfile: '/path/to/key/file'

#------------------------------------------------------------------------------
# tags
#------------------------------------------------------------------------------
tags:
  nofailover: false
  clonefrom: true
  noloadbalance: false
  nosync: false
{% if pg_upstream is defined %}
  replicatefrom: {{ pg_upstream }}    # clone from another replica rather than primary
{% endif %}

#------------------------------------------------------------------------------
# watchdog
#------------------------------------------------------------------------------
# available mode: off|automatic|required
watchdog:
  mode: {{ patroni_watchdog_mode }}
  device: /dev/watchdog
  # safety_margin: 10s

#------------------------------------------------------------------------------
# bootstrap
#------------------------------------------------------------------------------
bootstrap:

  #----------------------------------------------------------------------------
  # bootstrap method
  #----------------------------------------------------------------------------
  method: initdb
  # add custom bootstrap method here

  # default bootstrap method: initdb
  initdb:
{% if pg_encoding != '' %}
    - encoding: {{ pg_encoding }}
{% endif %}
{% if pg_locale != '' %}
    - locale: {{ pg_locale }}
{% endif %}
{% if pg_lc_collate != '' %}
    - lc-collate: {{ pg_lc_collate }}
{% endif %}
{% if pg_lc_ctype != '' %}
    - lc-ctype: {{ pg_lc_ctype }}
{% endif %}

  #----------------------------------------------------------------------------
  # bootstrap users
  #---------------------------------------------------------------------------
  # additional users which need to be created after initializing new cluster
  # replication user and monitor user are required
  users:
    {{ pg_replication_username }}:
      password: '{{ pg_replication_password }}'
    {{ pg_monitor_username }}:
      password: '{{ pg_monitor_password }}'
    {{ pg_admin_username }}:
      password: '{{ pg_admin_password }}'

  # bootstrap hba, allow local and intranet password access & replication
  # will be overwritten later
  pg_hba:
    - local   all             postgres                                ident
    - local   all             all                                     md5
    - host    all             all            0.0.0.0/0                md5
    - local   replication     postgres                                ident
    - local   replication     all                                     md5
    - host    replication     all            0.0.0.0/0                md5


  #----------------------------------------------------------------------------
  # template
  #---------------------------------------------------------------------------
  # post_init: /pg/bin/pg-init

  #----------------------------------------------------------------------------
  # bootstrap config
  #---------------------------------------------------------------------------
  # this section will be written to /{{ pg_namespace }}/{{ pg_cluster }}/config
  # if will NOT take any effect after cluster bootstrap
  dcs:

{% if pg_role == 'primary' and pg_upstream is defined %}
    #----------------------------------------------------------------------------
    # standby cluster definition
    #---------------------------------------------------------------------------
    standby_cluster:
      host: {{ pg_upstream }}
      port: {{ pg_port }}
      # primary_slot_name: patroni     # must be create manually on upstream server, if specified
      create_replica_methods:
        - basebackup
{% endif %}

    #----------------------------------------------------------------------------
    # important parameters
    #---------------------------------------------------------------------------
    # constraint: ttl >: loop_wait + retry_timeout * 2

    # the number of seconds the loop will sleep. Default value: 10
    # this is patroni check loop interval
    loop_wait: 10

    # the TTL to acquire the leader lock (in seconds). Think of it as the length of time before initiation of the automatic failover process. Default value: 30
    # config this according to your network condition to avoid false-positive failover
    ttl: 30

    # timeout for DCS and PostgreSQL operation retries (in seconds). DCS or network issues shorter than this will not cause Patroni to demote the leader. Default value: 10
    retry_timeout: 10

    # the amount of time a master is allowed to recover from failures before failover is triggered (in seconds)
    # Max RTO: 2 loop wait + master_start_timeout
    master_start_timeout: 10

    # import: candidate will not be promoted if replication lag is higher than this
    # maximum RPO: 1MB
    maximum_lag_on_failover: 1048576

    # The number of seconds Patroni is allowed to wait when stopping Postgres and effective only when synchronous_mode is enabled
    master_stop_timeout: 30

    # turns on synchronous replication mode. In this mode a replica will be chosen as synchronous and only the latest leader and synchronous replica are able to participate in leader election
    # set to true for RPO mode
    synchronous_mode: false

    # prevents disabling synchronous replication if no synchronous replicas are available, blocking all client writes to the master
    synchronous_mode_strict: false


    #----------------------------------------------------------------------------
    # postgres parameters
    #---------------------------------------------------------------------------
    postgresql:
      use_slots: true
      use_pg_rewind: true
      remove_data_directory_on_rewind_failure: true


      parameters:
        #----------------------------------------------------------------------
        # IMPORTANT PARAMETERS
        #----------------------------------------------------------------------
        max_connections: 800                    # 100 -> 800
        superuser_reserved_connections: 10      # reserve 10 connection for su
        max_locks_per_transaction: 128          # 64 -> 128
        max_prepared_transactions: 0            # 0 disable 2PC
        track_commit_timestamp: on              # enabled xact timestamp
        max_worker_processes: 64                # default 8 -> 64, set to cpu core 64
        wal_level: logical                      # logical
        wal_log_hints: on                       # wal log hints to support rewind
        max_wal_senders: 24                     # 10 -> 24
        max_replication_slots: 16               # 10 -> 16
        wal_keep_size: 100GB                    # keep at least 100GB WAL
        password_encryption: md5                # use traditional md5 auth

        #----------------------------------------------------------------------
        # RESOURCE USAGE (except WAL)
        #----------------------------------------------------------------------
        # memory: shared_buffers and maintenance_work_mem will be dynamically set
        shared_buffers: {{ pg_shared_buffers }}
        maintenance_work_mem: {{ pg_maintenance_work_mem }}
        work_mem: 32MB                          # 4MB -> 32MB
        huge_pages: try                         # try huge pages
        temp_file_limit: 100GB                  # 0 -> 100GB
        vacuum_cost_delay: 2ms                  # wait 2ms per 10000 cost
        vacuum_cost_limit: 10000                # 10000 cost each round
        bgwriter_delay: 10ms                    # check dirty page every 10ms
        bgwriter_lru_maxpages: 800              # 100 -> 800
        bgwriter_lru_multiplier: 5.0            # 2.0 -> 5.0  more cushion buffer
        max_parallel_workers: 32                # default 8 -> 32, limit by max_worker_processes
        max_parallel_maintenance_workers: 8     # default 2 -> 8, limit by parallel worker
        max_parallel_workers_per_gather: 0      # default 2 -> 0, disable parallel query in OLTP mode

        #----------------------------------------------------------------------
        # WAL
        #----------------------------------------------------------------------
        wal_buffers: 16MB                       # max to 16MB
        wal_writer_delay: 20ms                  # wait period
        wal_writer_flush_after: 1MB             # max allowed data loss
        min_wal_size: 100GB                     # at least 100GB WAL
        max_wal_size: 400GB                     # at most 400GB WAL
        commit_delay: 20                        # 200ms -> 20ms, increase speed
        commit_siblings: 10                     # 5 -> 10
        checkpoint_timeout: 60min               # checkpoint 5min -> 1h
        checkpoint_completion_target: 0.95      # 0.5 -> 0.95
        archive_mode: on
        archive_command: 'wal_dir=/pg/arcwal; [[ $(date +%H%M) == 1200 ]] && rm -rf ${wal_dir}/$(date -d"yesterday" +%Y%m%d); /bin/mkdir -p ${wal_dir}/$(date +%Y%m%d) && /usr/bin/lz4 -q -z %p > ${wal_dir}/$(date +%Y%m%d)/%f.lz4'

        #----------------------------------------------------------------------
        # REPLICATION
        #----------------------------------------------------------------------
        # synchronous_standby_names: ''
        vacuum_defer_cleanup_age: 50000         # 0->50000 last 50000 xact changes will not be vacuumed
        promote_trigger_file: promote.signal    # default promote trigger file path
        max_standby_archive_delay: 10min        # max delay before canceling queries when reading WAL from archive;
        max_standby_streaming_delay: 3min       # max delay before canceling queries when reading streaming WAL;
        wal_receiver_status_interval: 1s        # send replies at least this often
        hot_standby_feedback: on                # send info from standby to prevent query conflicts
        wal_receiver_timeout: 60s               # time that receiver waits for
        max_logical_replication_workers: 8      # 4 -> 8, 6 sync worker + 1~2 apply worker
        max_sync_workers_per_subscription: 6    # 2 -> 6, 6 sync worker

        #----------------------------------------------------------------------
        # QUERY TUNING
        #----------------------------------------------------------------------
        # planner
        # enable_partitionwise_join: on
        random_page_cost: 1.1                   # 4 for HDD, 1.1 for SSD
        effective_cache_size: 320GB             # max mem - shared buffer
        default_statistics_target: 1000         # stat bucket 100 -> 1000

        #----------------------------------------------------------------------
        # REPORTING AND LOGGING
        #----------------------------------------------------------------------
        log_destination: csvlog                 # use standard csv log
        logging_collector: on                   # enable csvlog
        log_directory: log                      # default log dir: /pg/data/log
        # log_filename: 'postgresql-%a.log'     # weekly auto-recycle
        log_filename: 'postgresql-%Y-%m-%d.log' # YYYY-MM-DD full log retention
        log_checkpoints: on                     # log checkpoint info
        log_lock_waits: on                      # log lock wait info
        log_replication_commands: on            # log replication info
        log_statement: ddl                      # log ddl change
        log_min_duration_statement: 100         # log slow query (>100ms)

        #----------------------------------------------------------------------
        # STATISTICS
        #----------------------------------------------------------------------
        track_io_timing: on                     # collect io statistics
        track_functions: all                    # track all functions (none|pl|all)
        track_activity_query_size: 8192         # max query length in pg_stat_activity

        #----------------------------------------------------------------------
        # AUTOVACUUM
        #----------------------------------------------------------------------
        log_autovacuum_min_duration: 1s         # log autovacuum activity take more than 1s
        autovacuum_max_workers: 3               # default autovacuum worker 3
        autovacuum_naptime: 1min                # default autovacuum naptime 1min
        autovacuum_vacuum_scale_factor: 0.08    # fraction of table size before vacuum   20% -> 8%
        autovacuum_analyze_scale_factor: 0.04   # fraction of table size before analyze  10% -> 4%
        autovacuum_vacuum_cost_delay: -1        # default vacuum cost delay: same as vacuum_cost_delay
        autovacuum_vacuum_cost_limit: -1        # default vacuum cost limit: same as vacuum_cost_limit
        autovacuum_freeze_max_age: 1000000000   # age > 1 billion triggers force vacuum

        #----------------------------------------------------------------------
        # CLIENT
        #----------------------------------------------------------------------
        deadlock_timeout: 50ms                  # 50ms for deadlock
        idle_in_transaction_session_timeout: 10min  # 10min timeout for idle in transaction

        #----------------------------------------------------------------------
        # CUSTOMIZED OPTIONS
        #----------------------------------------------------------------------
        # extensions
        shared_preload_libraries: '{{ pg_libs | default("pg_stat_statements, auto_explain") }}'

        # auto_explain
        auto_explain.log_min_duration: 1s       # auto explain query slower than 1s
        auto_explain.log_analyze: true          # explain analyze
        auto_explain.log_verbose: true          # explain verbose
        auto_explain.log_timing: true           # explain timing
        auto_explain.log_nested_statements: true

        # pg_stat_statements
        pg_stat_statements.max: 10000           # 5000 -> 10000 queries
        pg_stat_statements.track: all           # track all statements (all|top|none)
        pg_stat_statements.track_utility: off   # do not track query other than CRUD
        pg_stat_statements.track_planning: off  # do not track planning metrics


#------------------------------------------------------------------------------
# postgres
#------------------------------------------------------------------------------
postgresql:

  #----------------------------------------------------------------------------
  # how to connect to postgres
  #----------------------------------------------------------------------------
  bin_dir: {{ pg_bin_dir }}
  data_dir: {{ pg_data }}
  config_dir: {{ pg_data }}
  pgpass: {{ pg_dbsu_home }}/.pgpass
  listen: {{ pg_listen }}:{{ pg_port }}
  connect_address: {{ inventory_hostname }}:{{ pg_port }}
  use_unix_socket: true # default: /var/run/postgresql, /tmp

  #----------------------------------------------------------------------------
  # who to connect to postgres
  #----------------------------------------------------------------------------
  authentication:
    superuser:
      username: {{ pg_dbsu }}
    replication:
      username: {{ pg_replication_username }}
      password: '{{ pg_replication_password }}'
    rewind:
      username: {{ pg_replication_username }}
      password: '{{ pg_replication_password }}'

  #----------------------------------------------------------------------------
  # how to react to database operations
  #----------------------------------------------------------------------------
  # event callback script log: /pg/log/callback.log
  callbacks:
    on_start: /pg/bin/pg-failover-callback
    on_stop: /pg/bin/pg-failover-callback
    on_reload: /pg/bin/pg-failover-callback
    on_restart: /pg/bin/pg-failover-callback
    on_role_change: /pg/bin/pg-failover-callback

  # rewind policy: data checksum should be enabled before using rewind
  use_pg_rewind: true
  remove_data_directory_on_rewind_failure: true
  remove_data_directory_on_diverged_timelines: false

  #----------------------------------------------------------------------------
  # how to create replica
  #----------------------------------------------------------------------------
  # create replica method: default pg_basebackup
  create_replica_methods:
    - basebackup
  basebackup:
    - max-rate: '1000M'
    - checkpoint: fast
    - status-interva: 1s
    - verbose
    - progress

  #----------------------------------------------------------------------------
  # ad hoc parameters (overwrite with default)
  #----------------------------------------------------------------------------
  # parameters:

  #----------------------------------------------------------------------------
  # host based authentication, overwrite default pg_hba.conf
  #----------------------------------------------------------------------------
  # pg_hba:
  #   - local   all             postgres                                ident
  #   - local   all             all                                     md5
  #   - host    all             all            0.0.0.0/0                md5
  #   - local   replication     postgres                                ident
  #   - local   replication     all                                     md5
  #   - host    replication     all            0.0.0.0/0                md5

...

55 - 部署与监控Redis

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty是一个PostgreSQL发行版,也是一个通用应用运行时。您可以用它管理、部署、监控其他应用与数据库,例如Redis。

与PostgreSQL类似,部署Redis同样需要两个步骤:

  1. 声明/定义Redis集群
  2. 执行Playbook创建Redis集群

定义Redis集群

redis配置参数

Redis实体概念模型

Redis的实体概念模型与PostgreSQL几乎相同,同样包括 集群(Cluster)实例(Instance) 的概念。注意这里的Cluster概念指的不是 Redis原生集群方案中的集群。

核心的区别在于,Redis通常采用单机多实例部署,一个物理/虚拟机节点上通常会部署多个 Redis实例,以充分利用多核CPU。因此,定义Redis实例的方式与PGSQL稍有不同。

在Pigsty管理的Redis中,节点完全隶属于集群,即目前尚不允许在一个节点上部署两个不同集群的Redis实例,但这并不影响您在在一个节点上部署多个独立Redis实例。

Redis身份参数

身份参数是定义Redis集群时必须提供的信息,包括:

名称 属性 说明 例子
redis_cluster 必选,集群级别 集群名 redis-test
redis_node 必选,节点级别 节点编号 1,2
redis_instances 必选,节点级别 实例定义 { 6001 : {} ,6002 : {}}
  • redis_cluster 标识了Redis集群的名称,在集群层面进行配置,作为集群资源的顶层命名空间。
  • redis_node 标识了节点在集群中的序号
  • redis_instances 是一个JSON对象,Key为实例端口号,Value为一个JSON对象,包含实例特殊的配置

Redis集群定义

下面给出了三个Redis集群的精简定义,包括:

  • 一个1节点,3实例的Redis Sentinel集群 redis-sentinel
  • 一个2节点,12实例的的Redis Cluster集群 redis-cluster
  • 一个1节点,一主两从的Redis Standalone集群 redis-standalone

您需要在节点上为Redis实例分配唯一的端口号。

#----------------------------------#
# sentinel example                 #
#----------------------------------#
redis-sentinel:
  hosts:
    10.10.10.10:
      redis_node: 1
      redis_instances:  { 6001 : {} ,6002 : {} , 6003 : {} }
  vars:
    redis_cluster: redis-sentinel
    redis_mode: sentinel
    redis_max_memory: 128MB

#----------------------------------#
# cluster example                  #
#----------------------------------#
redis-cluster:
  hosts:
    10.10.10.11:
      redis_node: 1
      redis_instances: { 6501 : {} ,6502 : {} ,6503 : {} ,6504 : {} ,6505 : {} ,6506 : {} }
    10.10.10.12:
      redis_node: 2
      redis_instances: { 6501 : {} ,6502 : {} ,6503 : {} ,6504 : {} ,6505 : {} ,6506 : {} }
  vars:
    redis_cluster: redis-cluster        # name of this redis 'cluster'
    redis_mode: cluster                 # standalone,cluster,sentinel
    redis_max_memory: 64MB              # max memory used by each redis instance
    redis_mem_policy: allkeys-lru       # memory eviction policy

#----------------------------------#
# standalone example               #
#----------------------------------#
redis-standalone:
  hosts:
    10.10.10.13:
      redis_node: 1
      redis_instances:
        6501: {}
        6502: { replica_of: '10.10.10.13 6501' }
        6503: { replica_of: '10.10.10.13 6501' }
  vars:
    redis_cluster: redis-standalone     # name of this redis 'cluster'
    redis_mode: standalone              # standalone,cluster,sentinel
    redis_max_memory: 64MB              # max memory used by each redis instance

创建Redis集群

部署剧本

使用剧本redis.yml创建Redis实例/集群

./redis.yml -l redis-sentinel
./redis.yml -l redis-cluster
./redis.yml -l redis-standalone

其他注意事项

尽管这样做并不是推荐的行为,您可以将PostgreSQL与Redis进行混合部署,以充分利用机器资源。

redis.yml 剧本会在机器上同时部署Redis监控Exporter,包括redis_exporternode_exporter(可选)

在此过程中,如果机器的node_exporter存在,将会被重新部署。

Prometheus默认会使用"多目标抓取"模式,使用节点上9121端口的Redis Exporter抓取该节点上所有的Redis实例。

查阅Redis监控

目前Pigsty提供了3个Redis监控面板,作为一个独立监控应用 REDIS的组成部分,分别为:

  • Redis Overview:提供整个环境中Redis的全局概览
  • Redis Cluster: 关注单个Redis业务集群的监控信息
  • Redis Instance:关注单个Redis实例的详细监控信息

您可以使用自带的 redis-benchmark 测试

其他功能

Pigsty v1.5.1 支持 Redis 集群整体部署与监控;标签中的 redis.yml / redis-remove.yml 也可通过 -e redis_port=<port> 操作单个实例。 下线,扩容、缩容,单实例管理等功能将在后续版本中逐步提供。

56 - PGWeb

从 Pigsty v1.5.1 标签恢复的历史文档。

Pigsty v1.5.1 已不再提供旧 infra-pgweb.yml 剧本,也没有 pgweb_enabled / pgweb_username 清单参数;该标签通过 app/pgweb 提供 PGWeb Docker 应用。

运行 PGWeb

v1.5.1 随附清单默认在元节点启用 Docker。使用标签内的应用定义启动 PGWeb:

cd ~/pigsty/app/pgweb
docker-compose up -d

标签内 Compose 文件将宿主机 8886 端口映射至容器 8081 端口。请在 PGWeb 界面中填写数据库连接串,例如在按需替换凭据后使用 postgres://dbuser_dba:[email protected]:5432/meta

如需经 Nginx 暴露服务,请为 127.0.0.1:8886 添加 nginx_upstreams 条目,并重新执行 ./infra.yml -t nginx_config,nginx_restart。冻结版本的应用背景见 Docker 应用

57 - 使用TimescaleDB存储Prometheus数据

从 Pigsty v1.5.1 标签恢复的历史文档。

您可以使用 postgres 作为 Prometheus 后端使用的远程存储数据库。

虽然这并不是推荐的行为,但这是了解Pigsty部署系统使用方式的好机会。

准备Postgres数据库

vi pigsty.yml # 取消注释DB/User定义:dbuser_prometheus  prometheus

pg_databases:                           # define business users/roles on this cluster, array of user definition
  - { name: prometheus, owner: dbuser_prometheus , revokeconn: true, comment: prometheus primary database }
pg_users:                           # define business users/roles on this cluster, array of user definition
  - {name: dbuser_prometheus , password: DBUser.Prometheus ,pgbouncer: true , createrole: true,  roles: [dbrole_admin], comment: admin user for prometheus database }

创建 Prometheus 业务数据库与业务用户。

bin/createuser  pg-meta  dbuser_prometheus
bin/createdb    pg-meta  prometheus

检查数据库可用性并创建扩展

psql postgres://dbuser_prometheus:[email protected]:5432/prometheus -c 'CREATE EXTENSION timescaledb;'

配置Promscale

在元节点上执行以下命令安装 promscale

yum install -y promscale

如果默认软件包中没有,可以直接下载:

wget https://github.com/timescale/promscale/releases/download/0.6.1/promscale_0.6.1_Linux_x86_64.rpm
sudo rpm -ivh promscale_0.6.1_Linux_x86_64.rpm

编辑 promscale 的配置文件 /etc/sysconfig/promscale.conf

PROMSCALE_DB_HOST="127.0.0.1"
PROMSCALE_DB_NAME="prometheus"
PROMSCALE_DB_PASSWORD="DBUser.Prometheus"
PROMSCALE_DB_PORT="5432"
PROMSCALE_DB_SSL_MODE="disable"
PROMSCALE_DB_USER="dbuser_prometheus"

最后启动promscale,它会访问安装有 timescaledb 的数据库实例,并创建所需的schema

# launch
cat /usr/lib/systemd/system/promscale.service
systemctl start promscale && systemctl status promscale

配置Prometheus

Prometheus可以使用Remote Write/ Remote Read的方式,通过Promscale,使用Postgres作为远程存储。

编辑Prometheus配置文件:

vi /etc/prometheus/prometheus.yml

添加以下记录:

remote_write:
  - url: "http://127.0.0.1:9201/write"
remote_read:
  - url: "http://127.0.0.1:9201/read"

重启Prometheus后,监控数据即可放入Postgres中。

systemctl restart prometheus