这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

声明式配置 —— 基础设施即代码(IaC)

Pigsty 使用基础设施即代码(IaC)的理念管理所有组件,针对大规模集群提供声明式管理能力。

Pigsty 遵循 IaC 与 GitOPS 的理念:使用声明式的 配置清单 描述整个环境,并通过 幂等剧本 来实现。

用户用声明的方式通过 参数 来描述自己期望的状态,而剧本则以幂等的方式调整目标节点以达到这个状态。 这类似于 Kubernetes 的 CRD & Operator,然而 Pigsty 在裸机和虚拟机上,通过 Ansible 实现了这样的功能。

Pigsty 诞生之初是为了解决超大规模 PostgreSQL 集群的运维管理问题,背后的想法很简单 —— 我们需要有在十分钟内在就绪的服务器上复刻整套基础设施(100+数据库集群 + PG/Redis + 可观测性)的能力。 任何 GUI + ClickOps 都无法在如此短的时间内完成如此复杂的任务,这让 CLI + IaC 成为唯一的选择 —— 它提供了精确,高效的控制能力。

配置清单 pigsty.yml 文件描述了整个部署的状态,无论是 生产环境(prod),预发环境(staging), 测试环境(test),还是 开发环境(devbox), 基础设施的区别仅在于配置清单的不同,而部署交付的逻辑则是完全相同的。

您可以使用 git 对这份部署的 “种子/基因” 进行版本控制与审计,而且,Pigsty 甚至支持将配置清单以数据库表的形式存储在 PostgreSQL CMDB 中,更进一步实现 Infra as Data 的能力。 无缝与您现有的工作流程集成与对接。

IaC 面向专业用户与企业场景而设计,但也针对个人开发者,SMB 进行了深度优化。 即使您并非专业 DBA,也无需了解这几百个调节开关与旋钮,所有参数都带有表现良好的默认值, 您完全可以在 零配置 的情况下,获得一个开箱即用的单机数据库节点; 简单地再添加两行 IP 地址,就能获得一套企业级的高可用的 PostgreSQL 集群。


声明模块

以下面的默认配置片段为例,这段配置描述了一个节点 10.10.10.10,其上安装了 INFRANODEETCDPGSQL 模块。

# 监控、告警、DNS、NTP 等基础设施集群...
infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }

# minio 集群,兼容 s3 的对象存储
minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }

# etcd 集群,用作 PostgreSQL 高可用所需的 DCS
etcd: { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }

# PGSQL 示例集群: pg-meta
pg-meta: { hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary }, vars: { pg_cluster: pg-meta } }

要真正安装这些模块,执行以下剧本:

./infra.yml -l 10.10.10.10  # 在节点 10.10.10.10 上初始化 infra 模块
./etcd.yml  -l 10.10.10.10  # 在节点 10.10.10.10 上初始化 etcd 模块
./minio.yml -l 10.10.10.10  # 在节点 10.10.10.10 上初始化 minio 模块
./pgsql.yml -l 10.10.10.10  # 在节点 10.10.10.10 上初始化 pgsql 模块

声明集群

您可以声明 PostgreSQL 数据库集群,在多个节点上安装 PGSQL 模块,并使其成为一个服务单元:

例如,要在以下三个已被 Pigsty 纳管的节点上,部署一个使用流复制组建的三节点高可用 PostgreSQL 集群, 您可以在配置文件 pigsty.ymlall.children 中添加以下定义:

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 }

定义完后,可以使用 剧本 将集群创建:

bin/pgsql-add pg-test   # 创建 pg-test 集群 

pigsty-iac.jpg

你可以使用不同的的实例角色,例如 主库(primary),从库(replica),离线从库(offline),延迟从库(delayed),同步备库(sync standby); 以及不同的集群:例如 备份集群(Standby Cluster),Citus集群,甚至是 Redis / MinIO / Etcd 集群


定制集群内容

您不仅可以使用声明式的方式定义集群,还可以定义集群中的数据库、用户、服务、HBA 规则等内容,例如,下面的配置文件对默认的 pg-meta 单节点数据库集群的内容进行了深度定制:

包括:声明了六个业务数据库与七个业务用户,添加了一个额外的 standby 服务(同步备库,提供无复制延迟的读取能力),定义了一些额外的 pg_hba 规则,一个指向集群主库的 L2 VIP 地址,与自定义的备份策略。

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary , pg_offline_query: true } }
  vars:
    pg_cluster: pg-meta
    pg_databases:                       # define business databases on this cluster, array of database definition
      - 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/)
        pgbouncer: true                 # optional, add this database to pgbouncer database list? true by default
        schemas: [pigsty]               # optional, additional schemas to be created, array of schema names
        extensions:                     # optional, additional extensions to be installed: array of `{name[,schema]}`
          - { name: postgis , schema: public }
          - { name: timescaledb }
        comment: pigsty meta database   # optional, comment string for this database
        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)
        register_datasource: true      # optional, register this database to grafana datasources? true by default
        connlimit: -1                  # optional, database connection limit, default -1 disable limit
        pool_auth_user: dbuser_meta    # optional, all connection to this pgbouncer database will be authenticated by this user
        pool_mode: transaction         # optional, pgbouncer pool mode at database level, default transaction
        pool_size: 64                  # optional, pgbouncer pool size at database level, default 64
        pool_size_reserve: 32          # optional, pgbouncer pool size reserve at database level, default 32
        pool_size_min: 0               # optional, pgbouncer pool size min at database level, default 0
        pool_max_db_conn: 100          # optional, max database connections at database level, default 100
      - { name: grafana  ,owner: dbuser_grafana  ,revokeconn: true ,comment: grafana primary database }
      - { name: bytebase ,owner: dbuser_bytebase ,revokeconn: true ,comment: bytebase primary database }
      - { name: kong     ,owner: dbuser_kong     ,revokeconn: true ,comment: kong the api gateway database }
      - { name: gitea    ,owner: dbuser_gitea    ,revokeconn: true ,comment: gitea meta database }
      - { name: wiki     ,owner: dbuser_wiki     ,revokeconn: true ,comment: wiki meta database }
    pg_users:                           # define business users/roles on this cluster, array of user definition
      - name: dbuser_meta               # REQUIRED, `name` is the only mandatory field of a user definition
        password: DBUser.Meta           # optional, password, can be a scram-sha-256 hash string or plain text
        login: true                     # optional, can log in, 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`
        pool_mode: transaction          # optional, pgbouncer pool mode at user level, transaction by default
        pool_connlimit: -1              # optional, max database connections at user level, default -1 disable limit
      - {name: dbuser_view     ,password: DBUser.Viewer   ,pgbouncer: true ,roles: [dbrole_readonly], comment: read-only viewer for meta database}
      - {name: dbuser_grafana  ,password: DBUser.Grafana  ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for grafana database   }
      - {name: dbuser_bytebase ,password: DBUser.Bytebase ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for bytebase database  }
      - {name: dbuser_kong     ,password: DBUser.Kong     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for kong api gateway   }
      - {name: dbuser_gitea    ,password: DBUser.Gitea    ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for gitea service      }
      - {name: dbuser_wiki     ,password: DBUser.Wiki     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for wiki.js service    }
    pg_services:                        # extra services in addition to pg_default_services, array of service definition
      # 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
        port: 5435                      # required, service exposed port (work as kubernetes service node port mode)
        ip: "*"                         # optional, service bind ip address, `*` for all ip by default
        selector: "[]"                  # required, service member selector, use JMESPath to filter inventory
        dest: default                   # optional, destination port, default|postgres|pgbouncer|<port_number>, 'default' by default
        check: /sync                    # optional, health check url path, / by default
        backup: "[? pg_role == `primary`]"  # backup server selector
        maxconn: 3000                   # optional, max allowed front-end connection
        balance: roundrobin             # optional, haproxy load balance algorithm (roundrobin by default, other: leastconn)
        options: '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:
      - {user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes'}
    pg_vip_enabled: true
    pg_vip_address: 10.10.10.2/24
    pg_vip_interface: eth1
    node_crontab:  # make a full backup 1 am everyday
      - '00 01 * * * postgres /pg/bin/pg-backup full'

声明访问控制

您还可以通过声明式的配置,深度定制 Pigsty 的访问控制能力。例如下面的配置文件对 pg-meta 集群进行了深度安全定制:

使用三节点核心集群模板:crit.yml,确保数据一致性有限,故障切换数据零丢失。 启用了 L2 VIP,并将数据库与连接池的监听地址限制在了 本地环回IP + 内网IP + VIP 三个特定地址。 模板强制启用了 Patroni 的 SSL API,与 Pgbouncer 的 SSL,并在 HBA 规则中强制要求使用 SSL 访问数据库集群。 同时还在 pg_libs 中启用了 $libdir/passwordcheck 扩展,来强制执行密码强度安全策略。

最后,还单独声明了一个 pg-meta-delay 集群,作为 pg-meta 在一个小时前的延迟镜像从库,用于紧急数据误删恢复。

pg-meta:      # 3 instance postgres cluster `pg-meta`
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary }
    10.10.10.11: { pg_seq: 2, pg_role: replica }
    10.10.10.12: { pg_seq: 3, pg_role: replica , pg_offline_query: true }
  vars:
    pg_cluster: pg-meta
    pg_conf: crit.yml
    pg_users:
      - { name: dbuser_meta , password: DBUser.Meta   , pgbouncer: true , roles: [ dbrole_admin ] , comment: pigsty admin user }
      - { name: dbuser_view , password: DBUser.Viewer , pgbouncer: true , roles: [ dbrole_readonly ] , comment: read-only viewer for meta database }
    pg_databases:
      - {name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [{name: postgis, schema: public}, {name: timescaledb}]}
    pg_default_service_dest: postgres
    pg_services:
      - { name: standby ,src_ip: "*" ,port: 5435 , dest: default ,selector: "[]" , backup: "[? pg_role == `primary`]" }
    pg_vip_enabled: true
    pg_vip_address: 10.10.10.2/24
    pg_vip_interface: eth1
    pg_listen: '${ip},${vip},${lo}'
    patroni_ssl_enabled: true
    pgbouncer_sslmode: require
    pgbackrest_method: minio
    pg_libs: 'timescaledb, $libdir/passwordcheck, pg_stat_statements, auto_explain' # add passwordcheck extension to enforce strong password
    pg_default_roles:                 # default roles and users in postgres cluster
      - { name: dbrole_readonly  ,login: false ,comment: role for global read-only access     }
      - { name: dbrole_offline   ,login: false ,comment: role for restricted read-only access }
      - { name: dbrole_readwrite ,login: false ,roles: [dbrole_readonly]               ,comment: role for global read-write access }
      - { name: dbrole_admin     ,login: false ,roles: [pg_monitor, dbrole_readwrite]  ,comment: role for object creation }
      - { name: postgres     ,superuser: true  ,expire_in: 7300                        ,comment: system superuser }
      - { name: replicator ,replication: true  ,expire_in: 7300 ,roles: [pg_monitor, dbrole_readonly]   ,comment: system replicator }
      - { name: dbuser_dba   ,superuser: true  ,expire_in: 7300 ,roles: [dbrole_admin]  ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 , comment: pgsql admin user }
      - { name: dbuser_monitor ,roles: [pg_monitor] ,expire_in: 7300 ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }
    pg_default_hba_rules:             # postgres host-based auth rules by default
      - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  }
      - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' }
      - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: ssl   ,title: 'replicator replication from localhost'}
      - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: ssl   ,title: 'replicator replication from intranet' }
      - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: ssl   ,title: 'replicator postgres db from intranet' }
      - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' }
      - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: ssl   ,title: 'monitor from infra host with password'}
      - {user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'   }
      - {user: '${admin}'   ,db: all         ,addr: world     ,auth: cert  ,title: 'admin @ everywhere with ssl & cert'   }
      - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: ssl   ,title: 'pgbouncer read/write via local socket'}
      - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: ssl   ,title: 'read/write biz user via password'     }
      - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: ssl   ,title: 'allow etl offline tasks from intranet'}
    pgb_default_hba_rules:            # pgbouncer host-based authentication rules
      - {user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident'}
      - {user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd' }
      - {user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: ssl   ,title: 'monitor access via intranet with pwd' }
      - {user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr' }
      - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: ssl   ,title: 'admin access via intranet with pwd'   }
      - {user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'   }
      - {user: 'all'        ,db: all         ,addr: intra     ,auth: ssl   ,title: 'allow all user intra access with pwd' }

# OPTIONAL delayed cluster for pg-meta
pg-meta-delay:                    # delayed instance for pg-meta (1 hour ago)
  hosts: { 10.10.10.13: { pg_seq: 1, pg_role: primary, pg_upstream: 10.10.10.10, pg_delay: 1h } }
  vars: { pg_cluster: pg-meta-delay }

Citus分布式集群

下面是一个四节点的 Citus 分布式集群的声明式配置:

all:
  children:
    pg-citus0: # citus coordinator, pg_group = 0
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus0 , pg_group: 0 }
    pg-citus1: # citus data node 1
      hosts: { 10.10.10.11: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus1 , pg_group: 1 }
    pg-citus2: # citus data node 2
      hosts: { 10.10.10.12: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus2 , pg_group: 2 }
    pg-citus3: # citus data node 3, with an extra replica
      hosts:
        10.10.10.13: { pg_seq: 1, pg_role: primary }
        10.10.10.14: { pg_seq: 2, pg_role: replica }
      vars: { pg_cluster: pg-citus3 , pg_group: 3 }
  vars:                               # global parameters for all citus clusters
    pg_mode: citus                    # pgsql cluster mode: citus
    pg_shard: pg-citus                # citus shard name: pg-citus
    patroni_citus_db: meta            # citus distributed database name
    pg_dbsu_password: DBUser.Postgres # all dbsu password access for citus cluster
    pg_users: [ { name: dbuser_meta ,password: DBUser.Meta ,pgbouncer: true ,roles: [ dbrole_admin ] } ]
    pg_databases: [ { name: meta ,extensions: [ { name: citus }, { name: postgis }, { name: timescaledb } ] } ]
    pg_hba_rules:
      - { user: 'all' ,db: all  ,addr: 127.0.0.1/32 ,auth: ssl ,title: 'all user ssl access from localhost' }
      - { user: 'all' ,db: all  ,addr: intra        ,auth: ssl ,title: 'all user ssl access from intranet'  }

Redis集群

下面给出了 Redis 主从集群、哨兵集群、以及 Redis Cluster 的声明配置样例

redis-ms: # redis classic primary & replica
  hosts: { 10.10.10.10: { redis_node: 1 , redis_instances: { 6379: { }, 6380: { replica_of: '10.10.10.10 6379' } } } }
  vars: { redis_cluster: redis-ms ,redis_password: 'redis.ms' ,redis_max_memory: 64MB }

redis-meta: # redis sentinel x 3
  hosts: { 10.10.10.11: { redis_node: 1 , redis_instances: { 26379: { } ,26380: { } ,26381: { } } } }
  vars:
    redis_cluster: redis-meta
    redis_password: 'redis.meta'
    redis_mode: sentinel
    redis_max_memory: 16MB
    redis_sentinel_monitor: # primary list for redis sentinel, use cls as name, primary ip:port
      - { name: redis-ms, host: 10.10.10.10, port: 6379 ,password: redis.ms, quorum: 2 }

redis-test: # redis native cluster: 3m x 3s
  hosts:
    10.10.10.12: { redis_node: 1 ,redis_instances: { 6379: { } ,6380: { } ,6381: { } } }
    10.10.10.13: { redis_node: 2 ,redis_instances: { 6379: { } ,6380: { } ,6381: { } } }
  vars: { redis_cluster: redis-test ,redis_password: 'redis.test' ,redis_mode: cluster, redis_max_memory: 32MB }

ETCD集群

下面给出了一个三节点的 Etcd 集群声明式配置样例:

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

MinIO集群

下面给出了一个三节点的 MinIO 集群声明式配置样例:

minio:
  hosts:
    10.10.10.10: { minio_seq: 1 }
    10.10.10.11: { minio_seq: 2 }
    10.10.10.12: { minio_seq: 3 }
  vars:
    minio_cluster: minio
    minio_data: '/data{1...2}'          # 每个节点使用两块磁盘
    minio_node: '${minio_cluster}-${minio_seq}.pigsty' # 节点名称的模式
    haproxy_services:
      - name: minio                     # [必选] 服务名称,需要唯一
        port: 9002                      # [必选] 服务端口,需要唯一
        options:
          - option httpchk
          - option http-keep-alive
          - http-check send meth OPTIONS uri /minio/health/live
          - http-check expect status 200
        servers:
          - { name: minio-1 ,ip: 10.10.10.10 , port: 9000 , options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
          - { name: minio-2 ,ip: 10.10.10.11 , port: 9000 , options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
          - { name: minio-3 ,ip: 10.10.10.12 , port: 9000 , options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }

1 - 配置清单

使用声明式的配置文件描述你需要的基础设施与集群

每一套 Pigsty 部署都对应着一份 配置清单 (Inventory),描述了基础设施与数据库集群的关键属性。


配置文件

Pigsty 默认使用 Ansible YAML 配置格式, 使用一个单一 YAML 配置文件 pigsty.yml 作为配置清单。

~/pigsty
  ^---- pigsty.yml   # <---- 默认配置文件

您可以直接修改该配置文件来定制您的部署,或者使用 Pigsty 提供的 配置向导 configure 脚本自动生成合适的配置文件。


配置结构

配置清单使用标准的 Ansible YAML 配置格式,由两部分组成:全局参数all.vars)和多个 all.children)。

您可以在 all.children 中定义新集群,并使用全局变量描述基础设施:all.vars,它看起来像这样:

all:                  # 顶级对象:all
  vars: {...}         # 全局参数
  children:           # 组定义
    infra:            # 组定义:'infra'
      hosts: {...}        # 组成员:'infra'
      vars:  {...}        # 组参数:'infra'
    etcd:    {...}    # 组定义:'etcd'
    pg-meta: {...}    # 组定义:'pg-meta'
    pg-test: {...}    # 组定义:'pg-test'
    redis-test: {...} # 组定义:'redis-test'
    # ...

集群定义

每个 Ansible 组可能代表一个集群,可以是节点集群、PostgreSQL 集群、Redis 集群、Etcd 集群或 MinIO 集群等…

集群定义由两部分组成:集群成员hosts)与 集群参数vars)。 您可以在 <cls>.hosts 中定义集群成员,并在 <cls>.vars 中使用 配置参数 描述集群。 下面是一个 3 节点高可用 PostgreSQL 集群的定义示例:

all:
  children:    # ansible 组列表
    pg-test:   # ansible 组名
      hosts:   # ansible 组内实例(集群成员)
        10.10.10.11: { pg_seq: 1, pg_role: primary } # 主机 1
        10.10.10.12: { pg_seq: 2, pg_role: replica } # 主机 2
        10.10.10.13: { pg_seq: 3, pg_role: offline } # 主机 3
      vars:    # ansible 组变量(集群参数)
        pg_cluster: pg-test

集群级别的 vars (集群参数)将覆盖全局参数,实例级别的 vars 将覆盖集群参数和全局参数。


拆分配置

如果您的部署规模较大,或者希望更好地组织配置文件, 可以将配置清单 拆分为多个文件,便于管理与维护。

inventory/
├── hosts.yml              # 主机和集群定义
├── group_vars/
│   ├── all.yml            # 全局默认变量 (对应 all.vars)
│   ├── infra.yml          # infra 组变量
│   ├── etcd.yml           # etcd 组变量
│   └── pg-meta.yml        # pg-meta 集群变量
└── host_vars/
    ├── 10.10.10.10.yml    # 特定主机变量
    └── 10.10.10.11.yml

您可以将集群成员定义放在 hosts.yml 文件中,将集群层面的 配置参数 放在 group_vars 目录下的对应文件中。


切换配置

您可以在执行剧本的时候,通过 -i 参数,临时指定另外的配置清单文件。

./pgsql.yml -i another_config.yml
./infra.yml -i nginx_config.yml

此外,Ansible 支持多种配置方式,您可以使用本地 yaml|ini 配置文件,或者是 CMDB 与任意的动态配置脚本作为配置源。

在 Pigsty 中,我们通过 Pigsty 主目录中的 ansible.cfg 指定同目录下的 pigsty.yml 作为默认的 配置清单,您可按需修改。

[defaults]
inventory = pigsty.yml

此外,Pigsty 还支持使用 CMDB 元数据库 来存储配置清单,便于与现有系统对接整合。

2 - 配置向导

使用 configure 脚本根据当前环境自动生成推荐的配置文件。

Pigsty 提供了一个 configure 脚本作为 配置向导,它能根据当前环境,自动生成合适的 pigsty.yml 配置文件。

这是一个 可选 的脚本:如果您已经了解了如何配置 Pigsty,大可以直接编辑 pigsty.yml 配置文件,跳过向导。


快速开始

进入 pigsty 源码家目录中,执行 ./configure 即可自动运行配置向导。不带任何参数时,默认使用 meta 单节点配置模板:

cd ~/pigsty
./configure          # 交互式配置向导,自动检测环境并生成配置

该命令会以选定的模板为基础,检测当前节点的 IP 地址与区域,并生成适合当前环境的 pigsty.yml 配置文件。

功能说明

configure 脚本会根据环境与输入执行以下调整,并在当前目录下生成 pigsty.yml 配置文件。

  • 检测当前节点 IP 地址,如果有多个 IP,则要求用户输入一个 首要的 IP 地址 作为当前节点的身份标识
  • 使用 IP 地址替换配置模板中的占位符 10.10.10.10,并将其配置为 admin_ip 参数的值。
  • 检测当前区域,将 region 设置为 default (全球默认仓库)或 china (使用中国镜像仓库)
  • 针对小微实例(vCPU < 4),为 node_tunepg_conf 参数使用 tiny 参数模板,优化资源使用。
  • 如果指定了 -v PG 大版本,将 pg_version 以及所有 PG 别名参数设置为对应大版本。
  • 如果指定了 -g 参数,将所有默认密码替换为随机生成的强密码,提升安全性。(强烈推荐
  • 当 PG 大版本 ≥ 17 时优先使用内置的 C.UTF-8 Locale,次选由操作系统支持的 C.UTF-8
  • 检测当前环境中,用于执行部署的核心依赖 ansible 是否可用
  • 同时检测部署目标节点是否 ssh 可达,并可以使用 sudo 执行命令。(-s 跳过)

使用示例

# 基本用法
./configure                       # 交互式配置向导
./configure -i 10.10.10.10        # 指定主 IP 地址

# 指定配置模板
./configure -c meta               # 使用默认单节点模板(默认)
./configure -c rich               # 使用功能丰富的单节点模板
./configure -c slim               # 使用精简模板(仅 PGSQL + ETCD)
./configure -c ha/full            # 使用 4 节点高可用沙箱模板
./configure -c ha/trio            # 使用 3 节点高可用模板
./configure -c app/supa           # 使用 Supabase 自托管模板

# 指定 PostgreSQL 版本
./configure -v 17                 # 使用 PostgreSQL 17
./configure -v 16                 # 使用 PostgreSQL 16
./configure -c rich -v 16         # rich 模板 + PG 16

# 区域与代理
./configure -r china              # 使用中国镜像源
./configure -r europe             # 使用欧洲镜像源
./configure -x                    # 导入当前代理环境变量

# 跳过与自动化
./configure -s                    # 跳过 IP 探测,保留占位符
./configure -n -i 10.10.10.10     # 非交互模式,指定 IP
./configure -c ha/full -s         # 4 节点模板,跳过 IP 替换

# 安全增强
./configure -g                    # 生成随机密码
./configure -c meta -g -i 10.10.10.10  # 完整生产配置

# 指定输出与 SSH 端口
./configure -o prod.yml           # 输出到 prod.yml
./configure -p 2222               # 使用 SSH 端口 2222

命令参数

./configure
    [-c|--conf <template>]      # 配置模板名称(meta|rich|slim|ha/full|...)
    [-i|--ip <ipaddr>]          # 指定主 IP 地址
    [-v|--version <pgver>]      # PostgreSQL 大版本号(13|14|15|16|17|18)
    [-r|--region <region>]      # 上游软件仓库区域(default|china|europe)
    [-o|--output <file>]        # 输出配置文件路径(默认:pigsty.yml)
    [-s|--skip]                 # 跳过 IP 地址探测与替换
    [-x|--proxy]                # 从环境变量导入代理设置
    [-n|--non-interactive]      # 非交互模式(不询问任何问题)
    [-p|--port <port>]          # 指定 SSH 端口
    [-g|--generate]             # 生成随机密码
    [-h|--help]                 # 显示帮助信息

参数详解

参数说明
-c, --confconf/<template>.yml 生成配置文件,支持子目录如 ha/full
-i, --ip用指定 IP 替换配置模板中的占位符 10.10.10.10
-v, --version指定 PostgreSQL 大版本号(13-18),不指定时保持模板默认值
-r, --region设置软件仓库镜像区域:default(默认)、china(中国镜像)、europe(欧洲镜像)
-o, --output指定输出文件路径,默认为 pigsty.yml
-s, --skip跳过 IP 地址探测与替换,保留模板中的 10.10.10.10 占位符
-x, --proxy将当前环境的代理变量(HTTP_PROXYHTTPS_PROXYALL_PROXYNO_PROXY)写入配置
-n, --non-interactive非交互模式,不询问任何问题(需配合 -i 指定 IP)
-p, --port指定 SSH 端口(非默认 22 端口时使用)
-g, --generate为配置文件中的密码生成随机值,提高安全性(强烈推荐)

执行流程

configure 脚本按照以下顺序执行检测与配置:

┌─────────────────────────────────────────────────────────────┐
│                    configure 执行流程                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. check_region          检测网络区域(GFW 检测)              │
│         ↓                                                   │
│  2. check_version         验证 PostgreSQL 版本号              │
│         ↓                                                   │
│  3. check_kernel          检测操作系统内核(Linux/Darwin)       │
│         ↓                                                   │
│  4. check_machine         检测 CPU 架构(x86_64/aarch64)      │
│         ↓                                                   │
│  5. check_package_manager 检测包管理器(dnf/yum/apt)           │
│         ↓                                                   │
│  6. check_vendor_version  检测 OS 发行版与版本                  │
│         ↓                                                   │
│  7. check_sudo            检测免密 sudo 权限                   │
│         ↓                                                   │
│  8. check_ssh             检测免密 SSH 到本机                   │
│         ↓                                                   │
│  9. check_proxy           处理代理环境变量                      │
│         ↓                                                   │
│ 10. check_ipaddr          探测/输入主 IP 地址                   │
│         ↓                                                   │
│ 11. check_admin           验证管理员 SSH + Sudo 权限            │
│         ↓                                                   │
│ 12. check_conf            选择配置模板                         │
│         ↓                                                   │
│ 13. check_config          生成配置文件                         │
│         ↓                                                   │
│ 14. check_utils           检测 Ansible 等工具是否安装           │
│         ↓                                                   │
│     ✓ 配置完成,输出 pigsty.yml                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

自动化行为

区域检测

脚本会自动检测网络环境,判断是否在中国大陆(GFW 内):

# 通过访问 Google 判断网络环境
curl -I -s --connect-timeout 1 www.google.com
  • 如果无法访问 Google,自动设置 region: china 使用国内镜像
  • 如果可以访问,使用 region: default 默认镜像
  • 可通过 -r 参数手动指定区域

IP 地址处理

脚本按以下优先级确定主 IP 地址:

  1. 命令行参数:如果通过 -i 指定了 IP,直接使用
  2. 单 IP 探测:如果当前节点只有一个 IP,自动使用
  3. 演示 IP 检测:如果检测到 10.10.10.10,自动选择(用于沙箱环境)
  4. 交互式输入:多个 IP 时,提示用户选择或输入
[WARN] Multiple IP address candidates found:
    (1) 192.168.1.100   inet 192.168.1.100/24 scope global eth0
    (2) 10.10.10.10     inet 10.10.10.10/24 scope global eth1
[ IN ] INPUT primary_ip address (of current meta node, e.g 10.10.10.10):
=> 10.10.10.10

低端硬件优化

当检测到 CPU 核心数 ≤ 4 时,脚本会自动调整配置:

[WARN] replace oltp template with tiny due to cpu < 4

这样可以确保在低配虚拟机上也能顺利运行。

Locale 设置

脚本会在以下情况自动启用 C.UTF-8 作为默认 Locale:

  • PostgreSQL 版本 ≥ 17(内置 Locale Provider 支持)
  • 或者 当前系统支持 C.UTF-8 / C.utf8 Locale
pg_locale: C.UTF-8
pg_lc_collate: C.UTF-8
pg_lc_ctype: C.UTF-8

中国区特殊处理

当区域设置为 china 时,脚本会自动:

  • 启用 docker_registry_mirrors Docker 镜像加速
  • 启用 PIP_MIRROR_URL Python 镜像加速

密码生成

使用 -g 参数时,脚本会为以下密码生成 24 位随机字符串:

密码参数说明
grafana_admin_passwordGrafana 管理员密码
pg_admin_passwordPostgreSQL 管理员密码
pg_monitor_passwordPostgreSQL 监控用户密码
pg_replication_passwordPostgreSQL 复制用户密码
patroni_passwordPatroni API 密码
haproxy_admin_passwordHAProxy 管理密码
minio_secret_keyMinIO Secret Key
etcd_root_passwordETCD Root 密码

同时还会替换以下占位符密码:

  • DBUser.Meta → 随机密码
  • DBUser.Viewer → 随机密码
  • S3User.Backup → 随机密码
  • S3User.Meta → 随机密码
  • S3User.Data → 随机密码
$ ./configure -g
[INFO] generating random passwords...
    grafana_admin_password   : xK9mL2nP4qR7sT1vW3yZ5bD8
    pg_admin_password        : aB3cD5eF7gH9iJ1kL2mN4oP6
    ...
[INFO] random passwords generated, check and save them

配置模板

脚本从 conf/ 目录读取配置模板,支持以下模板:

核心模板

模板说明
meta默认模板:单节点安装,包含 INFRA + NODE + ETCD + PGSQL
rich功能丰富版:包含几乎所有扩展、MinIO、本地仓库
slim精简版:仅 PostgreSQL + ETCD,无监控基础设施
fat完整版:rich 基础上安装更多扩展
pgsql纯 PostgreSQL 模板
infra纯基础设施模板

高可用模板 (ha/)

模板说明
ha/dual2 节点高可用集群
ha/trio3 节点高可用集群
ha/full4 节点完整沙箱环境
ha/safe安全加固版高可用配置
ha/simu42 节点大规模仿真环境

应用模板 (app/)

模板说明
supabaseSupabase 自托管配置
app/difyDify AI 平台配置
app/odooOdoo ERP 配置
app/teableTeable 表格数据库配置
app/registryDocker Registry 配置

特殊内核模板

模板说明
ivoryIvorySQL:Oracle 兼容 PostgreSQL
mssqlBabelfish:SQL Server 兼容 PostgreSQL
polarPolarDB:阿里云开源分布式 PostgreSQL
citusCitus:分布式 PostgreSQL
orioleOrioleDB:新一代存储引擎

演示模板 (demo/)

模板说明
demo/demo演示环境配置
demo/redisRedis 集群演示
demo/minioMinIO 集群演示

输出示例

$ ./configure
configure pigsty v4.0.0 begin
[ OK ] region = china
[ OK ] kernel  = Linux
[ OK ] machine = x86_64
[ OK ] package = rpm,dnf
[ OK ] vendor  = rocky (Rocky Linux)
[ OK ] version = 9 (9.5)
[ OK ] sudo = vagrant ok
[ OK ] ssh = [email protected] ok
[WARN] Multiple IP address candidates found:
    (1) 192.168.121.193	    inet 192.168.121.193/24 brd 192.168.121.255 scope global dynamic noprefixroute eth0
    (2) 10.10.10.10	    inet 10.10.10.10/24 brd 10.10.10.255 scope global noprefixroute eth1
[ OK ] primary_ip = 10.10.10.10 (from demo)
[ OK ] admin = [email protected] ok
[ OK ] mode = meta (el9)
[ OK ] locale  = C.UTF-8
[ OK ] ansible = ready
[ OK ] pigsty configured
[WARN] don't forget to check it and change passwords!
proceed with ./deploy.yml

环境变量

脚本支持以下环境变量:

环境变量说明默认值
PIGSTY_HOMEPigsty 安装目录~/pigsty
METADB_URL元数据库连接 URLservice=meta
HTTP_PROXYHTTP 代理-
HTTPS_PROXYHTTPS 代理-
ALL_PROXY通用代理-
NO_PROXY代理白名单内置默认值

注意事项

  1. 免密访问:运行 configure 前,确保当前用户具有免密 sudo 权限和免密 SSH 到本机的能力。可以通过 bootstrap 脚本自动配置。

  2. IP 地址选择:请选择内网 IP 作为主 IP 地址,不要使用公网 IP 或 127.0.0.1

  3. 密码安全:生产环境务必修改配置文件中的默认密码,或使用 -g 参数生成随机密码。

  4. 配置检查:脚本执行完成后,建议检查生成的 pigsty.yml 文件,确认配置符合预期。

  5. 多次执行:可以多次运行 configure 重新生成配置,每次会覆盖现有的 pigsty.yml

  6. macOS 限制:在 macOS 上运行时,脚本会跳过部分 Linux 特有的检测,并使用占位符 IP 10.10.10.10。macOS 只能作为管理节点使用。


常见问题

如何使用自定义配置模板?

将您的配置文件放到 conf/ 目录下,然后使用 -c 参数指定:

cp my-config.yml ~/pigsty/conf/myconf.yml
./configure -c myconf

如何为多集群生成不同配置?

使用 -o 参数指定不同的输出文件:

./configure -c ha/full -o cluster-a.yml
./configure -c ha/trio -o cluster-b.yml

然后在执行剧本时指定配置文件:

./deploy.yml -i cluster-a.yml

非交互模式下如何处理多 IP?

必须使用 -i 参数明确指定 IP 地址:

./configure -n -i 10.10.10.10

如何保留模板中的占位符 IP?

使用 -s 参数跳过 IP 替换:

./configure -c ha/full -s   # 保留 10.10.10.10 占位符

相关文档

3 - 配置参数

使用配置参数对 Pigsty 进行精细化定制

配置清单 中,您可以使用各种参数对 Pigsty 进行精细化定制。这些参数涵盖了从基础设施设置到数据库配置的各个方面。


参数列表

Pigsty 提供了约 380+ 个配置参数,分布在 8 个默认模块中,用于精细控制系统的各个方面,完整列表见 参考-参数列表

模块参数组参数数说明
PGSQL9123PostgreSQL 数据库集群的核心配置
INFRA1082基础设施组件:软件源、Nginx、DNS、监控、Grafana 等
NODE1183主机节点调优:身份、DNS、包、调优、安全、管理员、时间、VIP等
ETCD213分布式配置存储与服务发现
REDIS121Redis 缓存与数据结构服务器
MINIO221S3 兼容对象存储服务
FERRET19MongoDB 兼容数据库 FerretDB
DOCKER18Docker 容器引擎

参数形式

参数 是用于描述实体的 键值对(Key)是字符串,(Value)可以是五种类型之一:布尔值、字符串、数字、数组或对象。

all:                            # <------- 顶级对象:all
  vars: 
    admin_ip: 10.10.10.10       # <------- 全局配置参数
  children:
    pg-meta:                    # <------- pg-meta 分组
      vars:
        pg_cluster: pg-meta     # <------- 集群级别参数
      hosts:
        10.10.10.10:            # <------- 主机节点 IP
          pg_seq: 1
          pg_role: primary      # <------- 实例级别参数
  

参数优先级

参数可以在不同级别设置,具有以下优先级:

级别位置描述优先级
命令行-e 命令行参数通过命令行传入最高 (5)
主机/实例<group>.hosts.<host>特定于单个主机的参数较高 (4)
分组/集群<group>.vars组/集群中主机共享的参数中等 (3)
全局all.vars所有主机共享的参数较低 (2)
默认<roles>/default/main.yml角色实现默认值最低 (1)

以下是关于参数优先级的一些示例:

  • 执行剧本时,使用命令行参数 -e grafana_clean=true 来抹除 Grafana 数据
  • 使用主机变量上的实例级别参数 pg_role 覆盖 pg 实例角色
  • 使用组变量上的集群级别参数 pg_cluster 覆盖 pg 集群名称。
  • 使用全局变量上的全局参数 node_ntp_servers 指定全局 NTP 服务器
  • 如果没有设置 pg_version,Pigsty 将使用 pgsql 角色实现的默认值(默认为 18

除了身份参数 外,每个参数都有适当的默认值,因此无需显式设置。


身份参数

身份参数是特殊的参数,它们会作为实体的 ID 标识符,因此 没有默认值,必须 显式设置

模块身份参数
PGSQLpg_cluster, pg_seq, pg_role, …
NODEnodename, node_cluster
ETCDetcd_cluster, etcd_seq
MINIOminio_cluster, minio_seq
REDISredis_cluster, redis_node, redis_instances
INFRAinfra_seq

例外是,etcd_clusterminio_cluster 有默认值。 它假设每套部署只有一套 etcd 集群用于 DCS,和一套可选 MinIO 集群用于集中备份存储,因此为其分配了默认的集群名称 etcdminio。 但您依然可以使用其他名称部署多套 etcd 或 MinIO 集群。

4 - 配置模板

使用预制的配置模板,快速生成适配当前环境的配置文件

在 Pigsty 中,部署的蓝图细节由 配置清单 所定义,也就是 pigsty.yml 配置文件,您可以通过声明式配置进行定制。

然而,直接编写配置文件可能会让新用户望而生畏。为此,我们提供了一些开箱即用的配置模板,涵盖了常见的使用场景。

每一个模板都是一个预定义的 pigsty.yml 配置文件,包含了适用于特定场景的合理默认值。

您可以根据自己的需要,选择一个模板作为定制起点,然后根据需要进行修改,以满足您的具体需求。


使用模板

Pigsty 提供了 configure 脚本作为可选的配置向导,它将根据您的环境和输入,生成具有良好默认值的 配置清单

使用 ./configure -c <conf> 指定配置模板,其中 <conf> 是相对于 conf 目录的路径(可省略 .yml 后缀)。

./configure                     # 默认使用 meta.yml 配置模板
./configure -c meta             # 显式指定使用 meta.yml 单节点模板
./configure -c rich             # 使用包含全部扩展与 MinIO 的富功能模板
./configure -c slim             # 使用最小化的单节点模板

# 使用不同的数据库内核
./configure -c pgsql            # 原生 PostgreSQL 内核,基础功能 (13~18)
./configure -c citus            # Citus 分布式高可用 PostgreSQL (14~17)
./configure -c mssql            # Babelfish 内核,兼容 SQL Server 协议 (15)
./configure -c polar            # PolarDB PG 内核,Aurora/RAC 风格 (15)
./configure -c ivory            # IvorySQL 内核,兼容 Oracle 语法 (18)
./configure -c mysql            # OpenHalo 内核,兼容 MySQL (14)
./configure -c pgtde            # Percona PostgreSQL Server 透明加密 (18)
./configure -c oriole           # OrioleDB 内核,OLTP 增强 (17)
./configure -c supabase         # Supabase 自托管配置 (15~18)

# 使用多节点高可用模板
./configure -c ha/dual          # 使用 2 节点高可用模板
./configure -c ha/trio          # 使用 3 节点高可用模板
./configure -c ha/full          # 使用 4 节点高可用模板

如果不指定模板,Pigsty 默认使用 meta.yml 单节点配置模板。


模板列表

主要模板

以下是单节点配置模板,可用于在单台服务器上安装 Pigsty:

模板说明
meta.yml默认模板,单节点 PostgreSQL 在线安装
rich.yml富功能模板,包含本地软件源、MinIO 及更多示例
slim.yml精简模板,仅安装 PostgreSQL,不含监控与基础设施

数据库内核模板

适用于各类数据库管理系统与内核的模板:

模板说明
pgsql.yml原生 PostgreSQL 内核,基础功能 (13~18)
citus.ymlCitus 分布式高可用 PostgreSQL (14~17)
mssql.ymlBabelfish 内核,兼容 SQL Server 协议 (15)
polar.ymlPolarDB PG 内核,Aurora/RAC 风格 (15)
ivory.ymlIvorySQL 内核,兼容 Oracle 语法 (17)
mysql.ymlOpenHalo 内核,兼容 MySQL (14)
pgtde.ymlPercona PostgreSQL Server 透明加密 (17)
oriole.ymlOrioleDB 内核,OLTP 增强 (17,Debian 包暂缺)
supabase.ymlSupabase 自托管配置 (15~17)

您可以后续添加更多节点,或使用 高可用模板 在一开始就规划好集群。


高可用模板

您可以配置 Pigsty 在多节点上运行,组成高可用(HA)集群:

模板说明
dual.yml2 节点半高可用部署
trio.yml3 节点标准高可用部署
full.yml4 节点标准部署
safe.yml4 节点安全增强部署,含延迟从库
simu.yml20 节点生产环境模拟

应用模板

您可以使用以下模板运行 Docker 应用/软件:

模板说明
supa.yml启动单节点 Supabase
odoo.yml启动 Odoo ERP 系统
dify.yml启动 Dify AI 工作流系统
electric.yml启动 Electric 同步引擎

演示模板

除主要模板外,Pigsty 还提供了一组面向不同场景的演示模板:

模板说明
el.ymlEL 8/9 系统的全参数配置文件
debian.ymlDebian/Ubuntu 系统的全参数配置文件
remote.yml监控远程 PostgreSQL 集群或 RDS 的示例配置
redis.ymlRedis 集群示例配置
minio.yml3 节点 MinIO 集群示例配置
demo.ymlPigsty 公开演示站 的配置文件

构建模板

以下配置模板用于开发和测试目的:

模板说明
build.ymlEL 9/10、Debian 12/13、Ubuntu 22.04/24.04 开源构建配置

5 - 元数据库

使用 PostgreSQL 作为 CMDB 元数据库,存储 Ansible 配置清单。

Pigsty 允许您使用 PostgreSQL 元数据库 作为动态配置源,取代静态的 YAML 配置文件,实现更强大的配置管理能力。


概览

CMDB(Configuration Management Database,配置管理数据库)是一种将配置信息存储在数据库中进行管理的方式。

在 Pigsty 中,默认的配置源是一个静态 YAML 文件 pigsty.yml, 它作为 Ansible 的 配置清单 使用。

这种方式简单直接,但当基础设施规模扩大、需要复杂精细的管理与外部集成时,单一的静态文件难以满足需求。

特性静态 YAML 文件CMDB 元数据库
查询能力手工搜索/grepSQL 任意条件查询,聚合分析
版本控制依赖 Git 或手工备份数据库事务,审计日志,时间旅行快照
权限控制文件系统权限,粗粒度PostgreSQL 数据库精细访问控制
并发编辑需要锁文件或合并冲突数据库事务天然支持并发
外部集成需要解析 YAML标准 SQL 接口,任意语言轻松对接
规模扩展文件过大时难以维护管理规模伸缩至物理极限
动态生成静态文件,修改后需手动应用即时生效,实时反映配置变更

Pigsty 在样板数据库 pg-meta.meta 的模式基线定义中,提供了 Pigsty CMDB 的数据库模式。


工作原理

CMDB 的核心思想是用一个 动态脚本 替换静态配置文件。 Ansible 支持使用可执行脚本作为配置清单,只要脚本输出符合 JSON 格式的清单数据即可。 当您启用 CMDB 后,Pigsty 会创建一个名为 inventory.sh 的动态清单脚本:

#!/bin/bash
psql ${METADB_URL} -AXtwc 'SELECT text FROM pigsty.inventory;'

这个脚本的作用很简单:每次 Ansible 需要读取配置清单时,它会从 PostgreSQL 数据库的 pigsty.inventory 视图中查询配置数据,并以 JSON 格式返回。

整体架构如下:

flowchart LR
    conf["bin/inventory_conf"]
    tocmdb["bin/inventory_cmdb"]
    load["bin/inventory_load"]
    ansible["🚀 Ansible"]

    subgraph static["📄 静态配置模式"]
        yml[("pigsty.yml")]
    end

    subgraph dynamic["🗄️ CMDB 动态模式"]
        sh["inventory.sh"]
        cmdb[("PostgreSQL CMDB")]
    end

    conf -->|"切换"| yml
    yml -->|"加载配置"| load
    load -->|"写入"| cmdb
    tocmdb -->|"切换"| sh
    sh --> cmdb

    yml --> ansible
    cmdb --> ansible

数据模型

CMDB 的数据库模式定义在 files/cmdb.sql 文件中,所有对象都位于 pigsty 模式下。

核心数据表

表名说明主键
pigsty.group集群/分组定义,对应 Ansible 的 groupcls
pigsty.host主机定义,属于某个分组(cls, ip)
pigsty.global_var全局变量,对应 all.varskey
pigsty.group_var分组变量,对应 all.children.<cls>.vars(cls, key)
pigsty.host_var主机变量,对应主机级别的变量(cls, ip, key)
pigsty.default_var默认变量定义,存储参数的元信息key
pigsty.job作业记录表,记录执行的任务id

表结构详解

集群表 pigsty.group

CREATE TABLE pigsty.group (
    cls     TEXT PRIMARY KEY,        -- 集群名称,主键
    ctime   TIMESTAMPTZ DEFAULT now(), -- 创建时间
    mtime   TIMESTAMPTZ DEFAULT now()  -- 修改时间
);

主机表 pigsty.host

CREATE TABLE pigsty.host (
    cls    TEXT NOT NULL REFERENCES pigsty.group(cls),  -- 所属集群
    ip     INET NOT NULL,                               -- 主机 IP 地址
    ctime  TIMESTAMPTZ DEFAULT now(),
    mtime  TIMESTAMPTZ DEFAULT now(),
    PRIMARY KEY (cls, ip)
);

全局变量表 pigsty.global_var

CREATE TABLE pigsty.global_var (
    key   TEXT PRIMARY KEY,           -- 变量名
    value JSONB NULL,                 -- 变量值(JSON 格式)
    mtime TIMESTAMPTZ DEFAULT now()   -- 修改时间
);

分组变量表 pigsty.group_var

CREATE TABLE pigsty.group_var (
    cls   TEXT NOT NULL REFERENCES pigsty.group(cls),
    key   TEXT NOT NULL,
    value JSONB NULL,
    mtime TIMESTAMPTZ DEFAULT now(),
    PRIMARY KEY (cls, key)
);

主机变量表 pigsty.host_var

CREATE TABLE pigsty.host_var (
    cls   TEXT NOT NULL,
    ip    INET NOT NULL,
    key   TEXT NOT NULL,
    value JSONB NULL,
    mtime TIMESTAMPTZ DEFAULT now(),
    PRIMARY KEY (cls, ip, key),
    FOREIGN KEY (cls, ip) REFERENCES pigsty.host(cls, ip)
);

核心视图

CMDB 提供了一系列视图,用于查询和展示配置数据:

视图名说明
pigsty.inventory核心视图:生成 Ansible 动态清单 JSON
pigsty.raw_config原始配置的 JSON 格式展示
pigsty.global_config全局配置视图,合并默认值和全局变量
pigsty.group_config分组配置视图,包含主机列表和分组变量
pigsty.host_config主机配置视图,合并分组和主机级别变量
pigsty.pg_clusterPostgreSQL 集群视图
pigsty.pg_instancePostgreSQL 实例视图
pigsty.pg_databasePostgreSQL 数据库定义视图
pigsty.pg_usersPostgreSQL 用户定义视图
pigsty.pg_servicePostgreSQL 服务定义视图
pigsty.pg_hbaPostgreSQL HBA 规则视图
pigsty.pg_remote远程 PostgreSQL 实例视图

pigsty.inventory 是最核心的视图,它将数据库中的配置数据转换为 Ansible 所需的 JSON 格式:

SELECT text FROM pigsty.inventory;

工具脚本

Pigsty 提供了三个便利脚本来管理 CMDB:

脚本功能
bin/inventory_load将 YAML 配置文件加载到 PostgreSQL 数据库中
bin/inventory_cmdb切换配置源为 CMDB(动态清单脚本)
bin/inventory_conf切换配置源为静态配置文件 pigsty.yml

inventory_load

将 YAML 配置文件解析并导入到 CMDB 中:

bin/inventory_load                     # 加载默认的 pigsty.yml 到默认 CMDB
bin/inventory_load -p /path/to/conf.yml  # 指定配置文件路径
bin/inventory_load -d "postgres://..."   # 指定数据库连接 URL
bin/inventory_load -n myconfig           # 指定配置名称

脚本会执行以下操作:

  1. 清空 pigsty 模式中的现有数据
  2. 解析 YAML 配置文件
  3. 将全局变量写入 global_var
  4. 将集群定义写入 group
  5. 将集群变量写入 group_var
  6. 将主机定义写入 host
  7. 将主机变量写入 host_var

环境变量

  • PIGSTY_HOME:Pigsty 安装目录,默认为 ~/pigsty
  • METADB_URL:数据库连接 URL,默认为 service=meta

inventory_cmdb

切换 Ansible 使用 CMDB 作为配置源:

bin/inventory_cmdb

脚本会执行以下操作:

  1. 创建动态清单脚本 ${PIGSTY_HOME}/inventory.sh
  2. 修改 ansible.cfginventory 设置为 inventory.sh

生成的 inventory.sh 内容如下:

#!/bin/bash
psql ${METADB_URL} -AXtwc 'SELECT text FROM pigsty.inventory;'

inventory_conf

切换回使用静态 YAML 配置文件:

bin/inventory_conf

脚本会修改 ansible.cfginventory 设置回 pigsty.yml


使用流程

首次启用 CMDB

  1. 初始化 CMDB 模式(通常在安装 Pigsty 时已自动完成):
psql -f ~/pigsty/files/cmdb.sql
  1. 加载配置到数据库
bin/inventory_load
  1. 切换到 CMDB 模式
bin/inventory_cmdb
  1. 验证配置
ansible all --list-hosts          # 列出所有主机
ansible-inventory --list          # 查看完整清单

查询配置

启用 CMDB 后,您可以使用 SQL 灵活查询配置:

-- 查看所有集群
SELECT cls FROM pigsty.group;

-- 查看某集群的所有主机
SELECT ip FROM pigsty.host WHERE cls = 'pg-meta';

-- 查看全局变量
SELECT key, value FROM pigsty.global_var;

-- 查看某集群的变量
SELECT key, value FROM pigsty.group_var WHERE cls = 'pg-meta';

-- 查看所有 PostgreSQL 集群
SELECT cls, name, pg_databases, pg_users FROM pigsty.pg_cluster;

-- 查看所有 PostgreSQL 实例
SELECT cls, ins, ip, seq, role FROM pigsty.pg_instance;

-- 查看所有数据库定义
SELECT cls, datname, owner, encoding FROM pigsty.pg_database;

-- 查看所有用户定义
SELECT cls, name, login, superuser FROM pigsty.pg_users;

修改配置

您可以直接通过 SQL 修改配置:

-- 添加新集群
INSERT INTO pigsty.group (cls) VALUES ('pg-new');

-- 添加集群变量
INSERT INTO pigsty.group_var (cls, key, value)
VALUES ('pg-new', 'pg_cluster', '"pg-new"');

-- 添加主机
INSERT INTO pigsty.host (cls, ip) VALUES ('pg-new', '10.10.10.20');

-- 添加主机变量
INSERT INTO pigsty.host_var (cls, ip, key, value)
VALUES ('pg-new', '10.10.10.20', 'pg_seq', '1'),
       ('pg-new', '10.10.10.20', 'pg_role', '"primary"');

-- 修改全局变量
UPDATE pigsty.global_var SET value = '"new-value"' WHERE key = 'some_param';

-- 删除集群(级联删除主机和变量)
DELETE FROM pigsty.group WHERE cls = 'pg-old';

修改后立即生效,无需重新加载或重启任何服务。

切换回静态配置

如需切换回静态配置文件模式:

bin/inventory_conf

高级用法

配置导出

将 CMDB 中的配置导出为 YAML 格式:

psql service=meta -AXtwc "SELECT jsonb_pretty(jsonb_build_object('all', jsonb_build_object('children', children, 'vars', vars))) FROM pigsty.raw_config;"

或者使用 ansible-inventory 命令:

ansible-inventory --list --yaml > exported_config.yml

配置审计

利用 mtime 字段追踪配置变更:

-- 查看最近修改的全局变量
SELECT key, value, mtime FROM pigsty.global_var
ORDER BY mtime DESC LIMIT 10;

-- 查看某时间点之后的变更
SELECT * FROM pigsty.group_var
WHERE mtime > '2024-01-01'::timestamptz;

与外部系统集成

CMDB 使用标准 PostgreSQL,可以轻松与其他系统集成:

  • Web 管理界面:通过 REST API(如 PostgREST)暴露配置数据
  • CI/CD 流水线:在部署脚本中直接读写数据库
  • 监控告警:基于配置数据生成监控规则
  • ITSM 系统:与企业 CMDB 系统同步

注意事项

  1. 数据一致性:修改配置后,需要重新执行相应的 Ansible 剧本才能将变更应用到实际环境

  2. 备份:CMDB 中的配置数据非常重要,请确保定期备份

  3. 权限:建议为 CMDB 配置适当的数据库访问权限,避免误操作

  4. 事务:批量修改配置时,建议在事务中进行,以便出错时回滚

  5. 连接池inventory.sh 脚本每次执行都会建立新连接,如果 Ansible 执行频繁,建议考虑使用连接池


小结

CMDB 是 Pigsty 配置管理的高级方案,适用于需要管理大量集群、复杂查询、外部集成或精细权限控制的场景。通过将配置数据存储在 PostgreSQL 中,您可以充分利用数据库的强大能力来管理基础设施配置。

功能说明
数据存储PostgreSQL pigsty 模式
动态清单inventory.sh 脚本
配置加载bin/inventory_load
切换到 CMDBbin/inventory_cmdb
切换到 YAMLbin/inventory_conf
核心视图pigsty.inventory