多页打印视图 点击此处打印.

返回常规视图.

Pigsty中文文档 v2.0

此处中文文档(v2.0)仍在修缮中,请以英文文档为准,最新文档请参阅: https://vonng.github.io/pigsty

最新版本: v2.0.0

Github Repo | Live Demo

中文文档 | English Docs

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

Pigsty还是自动驾驶的运维解决方案,带有全面专业的监控系统,与开箱即用的高可用 与时间点恢复能力。Pigsty 提供声明式的API 与 Database as Code 的能力:用户只需声明自己想要什么样的数据库,即可将其一键创建:PostgreSQL / Redis / MinIO / ETCD

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

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

更多介绍,请参考亮点特性

快速上手

准备一个使用 Linux x86_64 EL 7,8,9 兼容系统的全新节点,使用带有免密 sudo 权限的用户执行:

curl http://download.pigsty.cc/get | bash 

安装完成后,您可以通过 80 端口访问 WEB 界面,通过 5432 端口访问默认的 PostgreSQL 数据库服务,详见安装

安装脚本的输出样例
$ curl http://download.pigsty.cc/get | bash
...
[Checking] ===========================================
[ OK ] SOURCE from CDN due to GFW
FROM CDN    : bash -c "$(curl -fsSL http://download.pigsty.cc/get)"
FROM GITHUB : bash -c "$(curl -fsSL https://raw.githubusercontent.com/Vonng/pigsty/master/bin/get)"
[Downloading] ===========================================
[ OK ] download pigsty source code from CDN
[ OK ] $ curl -SL http://download.pigsty.cc/v2.0.0/pigsty-v2.0.0.tgz
...
MD5: 78a6ae5ff9ab0b8aa3848805aeadd1d8  /tmp/pigsty-v2.0.0.tgz
[Extracting] ===========================================
[ OK ] extract '/tmp/pigsty-v2.0.0.tgz' to '/root/pigsty'
[ OK ] $ tar -xf /tmp/pigsty-v2.0.0.tgz -C ~;
cd ~/pigsty      # entering pigsty home directory before proceeding
[Proceeding] ===========================================
./bootstrap      # install ansible & download the optional offline packages
./configure      # preflight-check and generate config according to your env
./install.yml    # install pigsty on this node and init it as the admin node
[Reference] ===========================================
Get Started:     https://vonng.github.io/pigsty/#/INSTALL
Documentation:   https://vonng.github.io/pigsty
Github Repo:     https://github.com/Vonng/pigsty
Public Demo:     http://demo.pigsty.cc
Official Site:   https://pigsty.cc

根据提示依次进行:下载准备安装 三个步骤即可完成安装。

./bootstrap      # 确保 Ansible 正常安装,如果存在 /tmp/pkg.tgz 离线软件包,便使用它。
./configure      # 执行环境检测,并生成相应的推荐配置文件,如果你知道如何配置 Pigsty 可以跳过
./install.yml    # 根据生成的配置文件开始在当前节点上执行安装,使用离线安装包大概需要10分钟完成
其他下载安装方式

您还可以使用 gitcurl 直接从 Github Release 或 CDN 下载 Pigsty的源码与离线软件包

# get from GitHub
bash -c "$(curl -fsSL https://raw.githubusercontent.com/Vonng/pigsty/master/bin/get)"

# 使用 curl 从 Github 下载
curl -L https://github.com/Vonng/pigsty/releases/download/v2.0.0/pigsty-v2.0.0.tgz -o ~/pigsty.tgz                 # SRC
curl -L https://github.com/Vonng/pigsty/releases/download/v2.0.0/pigsty-pkg-v2.0.0.el9.x86_64.tgz -o /tmp/pkg.tgz  # EL9
curl -L https://github.com/Vonng/pigsty/releases/download/v2.0.0/pigsty-pkg-v2.0.0.el8.x86_64.tgz -o /tmp/pkg.tgz  # EL8
curl -L https://github.com/Vonng/pigsty/releases/download/v2.0.0/pigsty-pkg-v2.0.0.el7.x86_64.tgz -o /tmp/pkg.tgz  # EL7

# 如果 curl 不可用,git clone 也可以
git clone https://github.com/Vonng/pigsty; cd pigsty; git checkout v2.0.0

关于

Pigsty的名字是 “PostgreSQL In Great STYle” 的缩写,即 “全盛状态的 Postgres”。

pigsty 一词的的英文本意是猪圈,读作 Pig Style (/ˈpɪɡˌstaɪ/) 。

Pigsty基于AGPL 3.0协议 开源,可免费用于商业目的,亦提供专业的订阅服务支持。

1 - 快速上手

如何快速下载、配置、安装 Pigsty ?

安装 Pigsty 有四个步骤:下载, Bootstrap, 配置 and 安装.

快速上手

准备一个使用 Linux x86_64 EL 7,8,9 兼容系统的全新节点,使用带有免密 sudo 权限的用户执行:

curl http://download.pigsty.cc/get | bash 

该命令会下载并解压 Pigsty 源码至家目录,按提示完成 Bootstrap配置安装三个步骤即可完成安装。

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

安装完成后,您可以通过 80 端口访问 WEB 界面,通过 5432 端口访问默认的 PostgreSQL 数据库服务。

安装脚本的输出样例
$ curl http://download.pigsty.cc/get | bash
...
[Checking] ===========================================
[ OK ] SOURCE from CDN due to GFW
FROM CDN    : bash -c "$(curl -fsSL http://download.pigsty.cc/get)"
FROM GITHUB : bash -c "$(curl -fsSL https://raw.githubusercontent.com/Vonng/pigsty/master/bin/get)"
[Downloading] ===========================================
[ OK ] download pigsty source code from CDN
[ OK ] $ curl -SL http://download.pigsty.cc/v2.0.0/pigsty-v2.0.0.tgz
...
MD5: 78a6ae5ff9ab0b8aa3848805aeadd1d8  /tmp/pigsty-v2.0.0.tgz
[Extracting] ===========================================
[ OK ] extract '/tmp/pigsty-v2.0.0.tgz' to '/root/pigsty'
[ OK ] $ tar -xf /tmp/pigsty-v2.0.0.tgz -C ~;
cd ~/pigsty      # entering pigsty home directory before proceeding
[Proceeding] ===========================================
./bootstrap      # install ansible & download the optional offline packages
./configure      # preflight-check and generate config according to your env
./install.yml    # install pigsty on this node and init it as the admin node
[Reference] ===========================================
Get Started:     https://vonng.github.io/pigsty/#/INSTALL
Documentation:   https://vonng.github.io/pigsty
Github Repo:     https://github.com/Vonng/pigsty
Public Demo:     http://demo.pigsty.cc
Official Site:   https://pigsty.cc

环境要求

操作系统

  • Linux RHEL 或其他兼容的操作系统发行版
  • Vendor: RHEL, CentOS, Rocky, AlmaLinux, …
  • Version: el7, el8, el9, 或其他兼容的版本
  • 请使用全新的节点,以避免无谓的麻烦,1核云虚拟机也就几毛钱一小时。
  • 建议使用 RockyLinux 9.0 / RockyLinux 8.6 / CentOS 7.9 ,这是 Pigsty 的构建与测试环境。

机器节点

  • x86_64 架构 (目前暂不支持 aarch64/arm 等架构)
  • 管理节点最低1核2G,自动根据节点规格优化,支持到 128C 512G 规格节点。
  • 普通节点最低 1核1G,推荐 2C4G 以上,支持到 128C 512G 规格节点。
  • 需要有公钥免密的 ssh 访问,且在目标节点上有免密sudoroot权限。
  • 一个严肃的生产部署最少需要三个节点,目前最大部署规模为 1000+ 节点。

Ansible

  • Ansible 是Pigsty的核心依赖,会在 Bootstrap 过程中自动安装
  • 你也可以使用 yum 直接手动安装,但需要先启用 epel-release

下载

您可以使用以下命令获取 Pigsty 源码包:

curl http://download.pigsty.cc/get  | bash

提示: 如果您需要下载最新的测试版本(Alpha/Beta/RC),请使用 getb 替代 get

如果您的安装环境没有互联网访问,您也可以提前下载好特定版本的源码包手工上传。

# 从 CDN 或 Github 下载源码包
curl -L http://download.pigsty.cc/v2.0.0/pigsty-v2.0.0.tgz
curl -L https://github.com/Vonng/pigsty/releases/download/v2.0.0/pigsty-v2.0.0.tgz

# 如果 curl 不可用,git clone 也可以
git clone https://github.com/Vonng/pigsty; cd pigsty; git checkout v2.0.0

离线软件包

正常情况下,Pigsty 会从互联网上游下载所需的 RPM 包,但如果您的安装环境没有互联网访问,您可以提前下载好特定版本的离线软件包手工上传。

离线软件包可以极快地加速 Pigsty 的安装过程,省却几十分钟的下载时间,对于没有互联网访问的环境更是有用。它里面包含了 Pigsty 所需的软件及其依赖,大小在 1GB 左右。

Pigsty 会在 bootstrap 时,提示下载对应的离线软件包,您也可以手工下载对应系统的离线软件包以加速安装。下载后的软件包应当放置于 /tmp/pkg.tgz

# CDN EL 7,8,9
curl -L http://download.pigsty.cc/v2.0.0/pigsty-pkg-v2.0.0.el9.x86_64.tgz -o /tmp/pkg.tgz  # EL9
curl -L http://download.pigsty.cc/v2.0.0/pigsty-pkg-v2.0.0.el8.x86_64.tgz -o /tmp/pkg.tgz  # EL8
curl -L http://download.pigsty.cc/v2.0.0/pigsty-pkg-v2.0.0.el7.x86_64.tgz -o /tmp/pkg.tgz  # EL7

# GITHUB EL 7,8,9
curl -L https://github.com/Vonng/pigsty/releases/download/v2.0.0/pigsty-pkg-v2.0.0.el9.x86_64.tgz -o /tmp/pkg.tgz  # EL9
curl -L https://github.com/Vonng/pigsty/releases/download/v2.0.0/pigsty-pkg-v2.0.0.el8.x86_64.tgz -o /tmp/pkg.tgz  # EL8
curl -L https://github.com/Vonng/pigsty/releases/download/v2.0.0/pigsty-pkg-v2.0.0.el7.x86_64.tgz -o /tmp/pkg.tgz  # EL7

Bootstrap

bootstrap 脚本的核心任务是确保:ansible 能用,并尽可能尝试使用离线软件包搭建本地 Yum 源。

Bootstrap 过程会用各种方式安装 ansible,如果需要的话,会提示您下载离线软件包(Ansible本身亦包含其中)。

./boostrap [-p <path>=/tmp/pkg.tgz]   # 离线软件包的下载地址 (默认是/tmp/pkg.tgz,通常不需修改)
           [-y|--yes] [-n|--no]       # 直接决定 是/否 下载离线软件包 (如果不指定,会交互式询问)

提示: 如果您决定直接从上游(互联网)安装所有软件包,bootstrap 过程是可选的。

Bootstrap 的详细逻辑如下:

  1. 检查安装的前提条件是否满足

  2. 检查本地离线安装包(/tmp/pkg.tgz)是否存在?

  • 是 -> 解压到 /www/pigsty 并通过 /etc/yum.repos.d/pigsty-local.repo 来启用它
  • 否 -> 进一步决定是否从互联网下载离线软件包?
    • 是 -> 从 Github 或 CDN 下载离线软件包并解压
    • 否 -> 是否添加操作系统基础的上游源地址以供从互联网下载 ?
      • 是 -> 根据地区与EL版本写入对应的上游源:/etc/yum.repos.d/
      • 否 -> 用户自己搞定,或者当前系统的默认配置就带有 Ansible
    • 现在,我们有了一个可用的 yum repo,可以用来安装 pigsty 所需的软件包了,特别是 Ansible。
    • 优先级顺序: 本地的 pkg.tgz > 下载的 pkg.tgz > 原始上游 > 默认配置
  1. 从上一步配置的软件源中,安装一些基本的重要软件,不同版本的软件略有不同:
  • el7: ansible createrepo_c unzip wget yum-utils createrepo_c sshpass
  • el8: ansible python39-jmespath createrepo_c unzip wget yum-utils createrepo_c sshpass modulemd-tools
  • el8: ansible python3-jmespath createrepo_c unzip wget yum-utils createrepo_c sshpass modulemd-tools
  1. 检查 ansible 是否成功安装。
从本地离线软件包 Bootstrap 的样例输出

如果离线软件包存在于 /tmp/pkg.tgz, bootstrap 会直接使用它:

bootstrap pigsty v2.0.0 begin
[ OK ] region = china
[ OK ] kernel = Linux
[ OK ] machine = x86_64
[ OK ] release = 7.9.2009
[ OK ] sudo = vagrant ok
[ OK ] cache = /tmp/pkg.tgz exists
[ OK ] repo = extract from /tmp/pkg.tgz
[ OK ] repo file = use /etc/yum.repos.d/pigsty-local.repo
[ OK ] repo cache = created
[ OK ] install el7 utils
....(yum install ansible output)
[ OK ] ansible = ansible 2.9.27
[ OK ] boostrap pigsty complete
proceed with ./configure
从互联网下载离线软件包的 Bootstrap 样例输出

从 Github/CDN 下载 pkg.tgz 并解压使用:

bootstrap pigsty v2.0.0 begin
[ OK ] region = china
[ OK ] kernel = Linux
[ OK ] machine = x86_64
[ OK ] release = 7.9.2009
[ OK ] sudo = vagrant ok
[ IN ] Cache /tmp/pkg.tgz not exists, download? (y/n):
=> y
[ OK ] download from Github http://download.pigsty.cc/v2.0.0/pigsty-pkg-v2.0.0.el7.x86_64.tgz to /tmp/pkg.tgz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  913M  100  913M    0     0   661k      0  0:23:33  0:23:33 --:--:--  834k
[ OK ] repo = extract from /tmp/pkg.tgz
[ OK ] repo file = use /etc/yum.repos.d/pigsty-local.repo
[ OK ] repo cache = created
[ OK ] install el7 utils
...... (yum install createrepo_c sshpass unzip output) 
==================================================================================================================
 Package                        Arch                Version                       Repository                 Size
==================================================================================================================
Installing:
 createrepo_c                   x86_64              0.10.0-20.el7                 pigsty-local               65 k
 sshpass                        x86_64              1.06-2.el7                    pigsty-local               21 k
 unzip                          x86_64              6.0-24.el7_9                  pigsty-local              172 k
Installing for dependencies:
 createrepo_c-libs              x86_64              0.10.0-20.el7                 pigsty-local               89 k

Transaction Summary
==================================================================================================================
...... (yum install ansible output)
==================================================================================================================
 Package                                      Arch            Version                 Repository             Size
==================================================================================================================
Installing:
 ansible                                      noarch          2.9.27-1.el7            pigsty-local           17 M
Installing for dependencies:
 PyYAML                                       x86_64          3.10-11.el7             pigsty-local          153 k
 libyaml                                      x86_64          0.1.4-11.el7_0          pigsty-local           55 k
 python-babel                                 noarch          0.9.6-8.el7             pigsty-local          1.4 M
 python-backports                             x86_64          1.0-8.el7               pigsty-local          5.8 k
 python-backports-ssl_match_hostname          noarch          3.5.0.1-1.el7           pigsty-local           13 k
 python-cffi                                  x86_64          1.6.0-5.el7             pigsty-local          218 k
 python-enum34                                noarch          1.0.4-1.el7             pigsty-local           52 k
 python-idna                                  noarch          2.4-1.el7               pigsty-local           94 k
 python-ipaddress                             noarch          1.0.16-2.el7            pigsty-local           34 k
 python-jinja2                                noarch          2.7.2-4.el7             pigsty-local          519 k
 python-markupsafe                            x86_64          0.11-10.el7             pigsty-local           25 k
 python-paramiko                              noarch          2.1.1-9.el7             pigsty-local          269 k
 python-ply                                   noarch          3.4-11.el7              pigsty-local          123 k
 python-pycparser                             noarch          2.14-1.el7              pigsty-local          104 k
 python-setuptools                            noarch          0.9.8-7.el7             pigsty-local          397 k
 python-six                                   noarch          1.9.0-2.el7             pigsty-local           29 k
 python2-cryptography                         x86_64          1.7.2-2.el7             pigsty-local          502 k
 python2-httplib2                             noarch          0.18.1-3.el7            pigsty-local          125 k
 python2-jmespath                             noarch          0.9.4-2.el7             pigsty-local           41 k
 python2-pyasn1                               noarch          0.1.9-7.el7             pigsty-local          100 k

Transaction Summary
==================================================================================================================
...
Complete!
[ OK ] ansible = ansible 2.9.27
[ OK ] boostrap pigsty complete
proceed with ./configure

配置

configure 会根据您当前的环境,自动生成一个 pigsty.yml 配置文件。

./configure [-n|--non-interactive] [-i|--ip <ipaddr>] [-m|--mode <name>] [-r|--region <default|china|europe>]
  • -m|--mode: 直接指定配置模板 : (auto|demo|sec|citus|el8|el9|...)
  • -i|--ip: 用于替换IP地址占位符 10.10.10.10 的IP地址,即当前主机的首要内网IP地址(特别是在有多块网卡与多个IP地址时)
  • -r|--region: 用于指定上游源的区域: (default|china|europe)
  • -n|--non-interactive: 直接使用命令行参数提供首要IP地址,跳过交互式向导。

当使用 -n|--non-interactive 参数时,您需要使用 -i|--ip <ipaddr> 指定当前节点的首要IP地址,特别是在有多块网卡与多个IP地址时。

提示: 如果您已经了解了如何配置 Pigsty, configure 这个步骤是可选的。

请注意,在一个严肃的生产部署中,您应当修改配置文件中所有 password 类的参数。

configure 的样例输出
[vagrant@meta pigsty]$ ./configure
configure pigsty v2.0.0 begin
[ OK ] region = china
[ OK ] kernel = Linux
[ OK ] machine = x86_64
[ OK ] sudo = vagrant ok
[ OK ] ssh = vagrant@127.0.0.1 ok
[WARN] Multiple IP address candidates found:
    (1) 10.0.2.15	    inet 10.0.2.15/24 brd 10.0.2.255 scope global noprefixroute dynamic 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 = vagrant@10.10.10.10 ok
[ OK ] mode = demo (vagrant demo)
[ OK ] config = demo @ 10.10.10.10
[ OK ] ansible = ansible 2.9.27
[ OK ] configure pigsty done
proceed with ./install.yml

安装

使用 install.yml 剧本,默认在当前节点上完成标准的单节点 Pigsty 安装。

./install.yml    # install everything in one-pass

这是一个标准的 Ansible 剧本,您可以使用以下参数控制其执行的目标、任务、并传递额外的命令参数:

  • -l: 限制执行的目标对象
  • -t: 限制要执行的任务
  • -e: 传入额外的命令行参数

警告: 在已经初始化的环境中再次运行 install.yml 会重置整个环境,所以请小心谨慎。

您可以 chmod a-x install.yml 避免误执行此剧本。

安装过程的样例输出
[vagrant@meta pigsty]$ ./install.yml

PLAY [IDENTITY] ********************************************************************************************************************************

TASK [node_id : get node fact] *****************************************************************************************************************
changed: [10.10.10.12]
changed: [10.10.10.11]
changed: [10.10.10.13]
changed: [10.10.10.10]
...
...
PLAY RECAP **************************************************************************************************************************************************************************
10.10.10.10                : ok=288  changed=215  unreachable=0    failed=0    skipped=64   rescued=0    ignored=0
10.10.10.11                : ok=263  changed=194  unreachable=0    failed=0    skipped=88   rescued=0    ignored=1
10.10.10.12                : ok=263  changed=194  unreachable=0    failed=0    skipped=88   rescued=0    ignored=1
10.10.10.13                : ok=153  changed=121  unreachable=0    failed=0    skipped=53   rescued=0    ignored=1
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=4    rescued=0    ignored=0

用户界面

当安装完成后,当前节点会安装有四个模块: INFRA, NODE, ETCD , PGSQL

  • INFRA: Pigsty Web界面可以通过80端口访问 http://<ip>:80 (如果第一次访问提示错误,请多刷新几次页面)
  • PGSQL: 您可以使用默认连接串访问PGSQL数据库: postgres://dbuser_meta:DBUser.Meta@<ip>:5432/meta

一些基础设施服务组件会使用 Nginx 对外暴露 WebUI ( 可通过参数 infra_portal 进行配置):

组件 端口 域名 说明 Demo地址
Nginx 80 h.pigsty Web Service Portal, Repo home.pigsty.cc
AlertManager 9093 a.pigsty Alter Aggregator a.pigsty.cc
Grafana 3000 g.pigsty Grafana Dashboard Home demo.pigsty.cc
Prometheus 9090 p.pigsty Prometheus Web UI p.pigsty.cc

您可以通过 IP地址 + 端口的方式直接访问这些服务,也可以通过域名来访问。我们强烈建议您通过 Nginx 域名代理访问所有组件,并对所有的端口权限进行访问控制,以避免未经授权的访问。

使用域名访问 Pigsty WebUI 时,您需要配置 DNS 服务器,或者修改 /etc/hosts 文件, 如果您使用本地沙箱, sudo make dns 会将所需的本地域名写入 /etc/hosts

例如,当您使用 http://g.pigsty 访问 Grafana 监控主页时,实际上是通过 Nginx 代理访问了 Grafana 的 WebUI:

http://g.pigsty ️-> http://10.10.10.10:80 (nginx) -> http://10.10.10.10:3000 (grafana)

Grafana 的默认密码为: username: admin, password: pigsty

如何使用 HTTPS 访问 Pigsty WebUI

Pigsty默认使用自动生成的自签名的CA证书为Nginx启用SSL,如果您希望使用 HTTPS 访问这些页面,而不弹窗提示"不安全",通常有三个选择:

  • 在您的浏览器或操作系统中信任Pigsty自签名的CA证书: files/pki/ca/ca.crt
  • 如果您使用 Chrome,可以在提示不安全的窗口键盘输入 thisisunsafe 跳过提示
  • 您可以考虑使用 Let’s Encrypt 或其他免费的CA证书服务,为 Pigsty Nginx 生成正式的CA证书

更多

你可以使用 Pigsty 部署更多的集群,管理更多的节点,例如

bin/node-add   pg-test      # 将集群 pg-test 的3个节点纳入 Pigsty 管理
bin/pgsql-add  pg-test      # 初始化一个3节点的 pg-test 高可用PG集群
bin/redis-add  redis-ms     # 初始化 Redis 集群: redis-ms

更多细节请参见: PGSQL, NODE, and REDIS.

2 - 亮点特性

Pigsty 可以为您解决哪些问题 ?

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

  • 开箱即用的 PostgreSQL 发行版,深度整合地理时序分布式三大核心扩展: PostGIS, TimescaleDB, Citus
  • 基于现代的 PrometheusGrafana 技术栈,提供令人惊艳,无可比拟的数据库观测能力:Public Demo
  • 基于 patroni, haproxy, 与etcd,打造故障自愈的高可用架构:硬件故障自动切换,流量无缝衔接。
  • 基于 pgBackRest 与可选的 MinIO 集群提供开箱即用的 PITR 时间点恢复,为软件缺陷与人为删库兜底。
  • 基于 Ansible 提供声明式的 API 对复杂度进行抽象,以 Database-as-Code 的方式极大简化了日常运维管理操作。
  • Pigsty用途广泛,可用作完整应用运行时,开发演示数据/可视化应用,大量使用 PG 的软件可使用 Docker 模板一键拉起。
  • 提供基于 Vagrant 的本地开发测试沙箱环境,与基于 Terraform 的云端自动部署方案,开发测试生产保持环境一致。

强力的发行版

彻底释放世界上最先进的关系型数据库的力量!

PostgreSQL 是一个足够完美的数据库内核,但它需要更多工具与系统的配合,才能成为一个足够好的数据库服务(RDS),而 Pigsty 帮助 PostgreSQL 完成这一步飞跃。

Pigsty 深度整合了 PostgreSQL 生态的三大核心扩展插件 PostGIS,TimescaleDB,Citus,并确保它们可以协同工作,提供分布式的时序地理空间数据库能力。 Pigsty 还提供了运行企业级 RDS 服务的所需软件,打包所有依赖为离线软件包,所有组件均可在无需互联网访问的情况下一键完成安装部署,进入生产可用状态。

在 Pigsty 中功能组件被抽象 模块,可以自由组合以应对多变的需求场景。INFRA 模块带有完整的现代监控技术栈,而 NODE 模块则将节点调谐至指定状态并纳入监控。 在多个节点上安装 PGSQL 模块会自动组建出一个基于主从复制的高可用数据库集群,而同样的 ETCD 模块则为数据库高可用提供共识与元数据存储。可选的 MINIO模块可以用作图像视频等大文件存储并可选用为数据库备份仓库。 与 PG 有着极佳相性的 REDIS 亦为 Pigsty 所支持,更多的模块(如GPSQL, MYSQL, KAFKA)将会在后续加入,你也可以开发自己的模块并自行扩展 Pigsty 的能力。

pigsty-distro

惊艳的观测能力

使用现代开源可观测性技术栈,提供无与伦比的监控最佳实践!

Pigsty 提供了基于开源的 Grafana / Prometheus 可观测性技术栈做监控的最佳实践:Prometheus 用于收集监控指标,Grafana 负责可视化呈现,Loki 用于日志收集与查询,Alertmanager 用于告警通知。 PushGateway 用于批处理任务监控,Blackbox Exporter 负责检查服务可用性。整套系统同样被设计为一键拉起,开箱即用的 INFRA 模块。

Pigsty 所管理的任何组件都会被自动纳入监控之中,包括主机节点,负载均衡 HAProxy,数据库 Postgres,连接池 Pgbouncer,元数据库 ETCD,KV缓存 Redis,对象存储 MinIO,……,以及整套监控基础设施本身。大量的 Grafana 监控面板与预置告警规则会让你的系统观测能力有质的提升,当然,这套系统也可以被复用于您的应用监控基础设施,或者监控已有的数据库实例或 RDS。

无论是故障分析还是慢查询优化、无论是水位评估还是资源规划,Pigsty 为您提供全面的数据支撑,真正做到数据驱动。在 Pigsty 中,超过三千类监控指标被用于描述整个系统的方方面面,并被进一步加工、聚合、处理、分析、提炼并以符合直觉的可视化模式呈现在您的面前。从全局大盘总揽,到某个数据库实例中单个对象(表,索引,函数)的增删改查详情都能一览无余。您可以随意上卷下钻横向跳转,浏览系统现状与历史趋势,并预测未来的演变。详见公开演示

pigsty-dashboards

久经考验的可靠性

开箱即用的高可用与时间点恢复能力,确保你的数据库坚如磐石!

对于软件缺陷或人为误操作造成的删表删库,Pigsty 提供了开箱即用的 PITR 时间点恢复能力,无需额外配置即默认启用。只要存储空间管够,基于 pgBackRest 的基础备份与 WAL 归档让您拥有快速回到过去任意时间点的能力。您可以使用本地目录/磁盘,亦或专用的 MinIO 集群或 S3 对象存储服务保留更长的回溯期限,丰俭由人。

更重要的是,Pigsty 让高可用与故障自愈成为 PostgreSQL 集群的标配,基于 patroni, etcd, 与 haproxy 打造的故障自愈架构,让您在面对硬件故障时游刃有余:主库故障自动切换的 RTO < 30s,一致性优先模式下确保数据零损失 RPO = 0。只要集群中有任意实例存活,集群就可以对外提供完整的服务,而客户端只要连接至集群中的任意节点,即可获得完整的服务。

Pigsty 内置了 HAProxy 负载均衡器用于自动流量切换,提供 DNS/VIP/LVS 等多种接入方式供客户端选用。故障切换与主动切换对业务侧除零星闪断外几乎无感知,应用不需要修改连接串重启。极小的维护窗口需求带来了极大的灵活便利:您完全可以在无需应用配合的情况下滚动维护升级整个集群。硬件故障可以等到第二天再抽空善后处置的特性,让研发,运维与 DBA 都能安心睡个好觉。 许多大型组织与核心机构已经在生产环境中长时间使用 Pigsty ,最大的部署有 25K CPU 核心与 200+ PostgreSQL 实例,在这一部署案例中, Pigsty 在三年内经历了数十次硬件故障与各类事故,但依然可以保持 99.999% 以上的整体可用性。

pigsty-ha

简单易用可维护

Infra as Code, 数据库即代码,声明式的API将数据库管理的复杂度来封装。

Pigsty 使用声明式的接口对外提供服务,将系统的可控制性拔高到一个全新水平:用户通过配置清单告诉 Pigsty “我想要什么样的数据库集群”,而不用去操心到底需要怎样去做。从效果上讲,这类似于 K8S 中的 CRD 与 Operator,但 Pigsty 可用于任何节点上的数据库与基础设施:不论是容器,虚拟机,还是物理机。

无论是创建/销毁集群,添加/移除从库,还是新增数据库/用户/服务/扩展/黑白名单规则,您只需要修改配置清单并运行 Pigsty 提供的幂等剧本,而 Pigsty 负责将系统调整到您期望的状态。 用户无需操心配置的细节,Pigsty将自动根据机器的硬件配置进行调优,您只需要关心诸如集群叫什么名字,有几个实例放在哪几台机器上,使用什么配置模版:事务/分析/核心/微型,这些基础信息,研发也可以自助服务。但如果您愿意跳入兔子洞中,Pigsty 也提供了丰富且精细的控制参数,满足最龟毛 DBA 的苛刻定制需求。

除此之外,Pigsty 本身的安装部署也是一键傻瓜式的,所有依赖被预先打包,在安装时可以无需互联网访问。而安装所需的机器资源,也可以通过 Vagrant 或 Terraform 模板自动获取,让您在十几分钟内就可以从零在本地笔记本或云端虚拟机上拉起一套完整的 Pigsty 部署。本地沙箱环境可以跑在1核2G的微型虚拟机中,提供与生产环境完全一致的功能模拟,可以用于开发、测试、演示与学习。

pigsty-iac

扎实的安全性

加密备份一应俱全,只要硬件与密钥安全,您无需操心数据库的安全性。

每套 Pigsty 部署都会创建一套自签名的 CA 用于证书签发,所有的网络通信都可以使用 SSL 加密。数据库密码使用合规的 scram-sha-256 算法加密存储,远端备份会使用 AES-256 算法加密。此外还针对 PGSQL 提供了一套开箱即用的的访问控制体系,足以应对绝大多数应用场景下的安全需求。

Pigsty 针对 PostgreSQL 提供了一套开箱即用,简单易用,精炼灵活的,便于扩展的访问控制体系,包括职能分离的四类默认角色:读(DQL) / 写(DML) / 管理(DDL) / 离线(ETL) ,与四个默认用户:dbsu / replicator / monitor / admin。 所有数据库模板都针对这些角色与用户配置有合理的默认权限,而任何新建的数据库对象也会自动遵循这套权限体系,而客户端的访问则受到一套基于最小权限原则的设计的 HBA 规则组限制,任何敏感操作都会记入日志审计。

任何网络通信都可以使用 SSL 加密,需要保护的敏感管理页面与API端点都受到多重保护:使用用户名与密码进行认证,限制从管理节点/基础设施节点IP地址/网段访问,要求使用 HTTPS 加密网络流量。Patroni API 与 Pgbouncer 因为性能因素默认不启用 SSL ,但亦提供安全开关便于您在需要时开启。 合理配置的系统通过等保三级毫无问题,只要您遵循安全性最佳实践,内网部署并合理配置安全组与防火墙,数据库安全性将不再是您的痛点。

pigsty-dashboard2

广泛的应用场景

使用预置的Docker模板,一键拉起使用PostgreSQL的海量软件!

在各类数据密集型应用中,数据库往往是最为棘手的部分。例如 Gitlab 企业版与社区版的核心区别就是底层 PostgreSQL 数据库的监控与高可用,如果您已经有了足够好的本地 PG RDS,又为什么要用软件自带的土法手造组件掏钱?

Pigsty 提供了 Docker 模块与大量开箱即用的 Compose 模板。您可以使用 Pigsty 管理的高可用 PostgreSQL (以及 Redis 与 MinIO )作为后端存储,以无状态的模式一键拉起这些软件: Gitlab、Gitea、Wiki.js、Odoo、Jira、Confluence、Habour、Mastodon、Discourse、KeyCloak 等等。如果您的应用需要一个靠谱的 PostgreSQL 数据库, Pigsty 也许是最简单的获取方案。

Pigsty 也提供了与 PostgreSQL 紧密联系的应用开发工具集:PGAdmin4、PGWeb、ByteBase、PostgREST、Kong、以及 EdgeDB、FerretDB、Supabase 这些使用 PostgreSQL 作为存储的"上层数据库"。更奇妙的是,您完全可以基于 Pigsty 内置了的 Grafana 与 Postgres ,以低代码的方式快速搭建起一个交互式的数据应用来,甚至还可以使用 Pigsty 内置的 ECharts 面板创造更有表现力的交互可视化作品。

pigsty-app

开源免费的自由软件

Pigsty是基于 AGPLv3 开源的自由软件,由热爱 PostgreSQL 的社区成员用热情浇灌

Pigsty 是完全开源免费的自由软件,它允许您在缺乏数据库专家的情况下,用几乎接近纯硬件的成本来运行企业级的 PostgreSQL 数据库服务。作为对比,公有云厂商提供的 RDS 会收取底层硬件资源几倍到十几倍不等的溢价作为 “服务费”。

很多用户选择上云,正是因为自己搞不定数据库;很多用户使用 RDS,是因为别无他选。我们将打破云厂商的垄断,为用户提供一个云中立的,更好的 RDS 开源替代: Pigsty 紧跟 PostgreSQL 上游主干,不会有供应商锁定,不会有恼人的 “授权费”,不会有节点数量限制,不会收集您的任何数据。您的所有的核心资产 —— 数据,都能"自主可控",掌握在自己手中。

Pigsty 本身旨在用数据库自动驾驶软件,替代大量无趣的人肉数据库运维工作,但再好的软件也没法解决所有的问题。总会有一些的冷门低频疑难杂症需要专家介入处理。这也是为什么我们也提供专业的订阅服务,来为有需要的企业级用户使用 PostgreSQL 提供兜底。几万块的订阅咨询费不到顶尖 DBA 每年工资的几十分之一,让您彻底免除后顾之忧,把成本真正花在刀刃上。当然对于社区用户,我们亦用爱发电,提供免费的支持与日常答疑。

pigsty-cost

3 - 概念

使用Pigsty时需要了解的一些概念与定义

3.1 - 系统架构

介绍Pigsty的系统架构

实体概念模型

一套完整的Pigsty系统,可称为一个部署(Deployment)/ 环境(Environment) ,例如:生产环境,测试环境,预发环境等。

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

基础设施

基础设施(Infra) 部署于元节点上,监控,DNS,NTP,DCS,Yum源等。

集群

集群 可以是主机节点集群,PostgreSQL数据库集群,Redis数据库集群等……,部署于节点上。

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

模块

无论是基础设施,还是主机节点,或者是PGSQL与REDIS数据库,都通过模块的方式进行组织,并通过剧本的方式进行安装。

目前Pigsty有四个核心模块:INFRANODESPGSQLREDIS

各种模块可以根据用户的需求自由排列组合: 如果您想将Pigsty当作开箱即用的单机PostgreSQL发行版来使用,那么在一台机器上依次安装 INFRA, NODES, PGSQL 三个模块,就会有一个立即可用的,自我监控管理的数据库实例。 如果您想要一个生产环境的大规模主机监控系统,那么在一台机器上安装 INFRA 模块,在所有被监控的机器节点上安装NODES模块即可 如果您想部署管理大量的PostgreSQL集群,在这些纳入Pigsty管理的节点上再加装 PGSQL 模块即可。

3.2 - 模块组件

介绍Pigsty内置的的四个核心模块:INFRANODESPGSQLREDIS

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

  • INFRA 是Pigsty的基础设施部分,包括监控/告警/可视化/日志/DNS/NTP等公共组件。
  • NODES 是主机节点管理模块,用于配置节点,安装软件,收集监控指标与日志。
  • PGSQL 是PostgreSQL数据库部署管控模块,包括各种类型的PG集群部署与监控。
  • REDIS 是Redis数据库部署管控模块,包括Redis 主从/集群/哨兵部署与监控
模块 概念 部署 配置 剧本
INFRA 概念: INFRA 部署: INFRA 配置: INFRA 剧本: INFRA
NODES 概念: NODES 部署: NODES 配置: NODES 剧本: NODES
PGSQL 概念: PGSQL 部署: PGSQL 配置: PGSQL 剧本: PGSQL
REDIS 概念: REDIS 部署: 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集簇,使用 pigsty-matrixdb.yml 部署 Greenplum/MatrixDB 数据仓库。

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

3.3 - 配置文件

Pigsty采用声明式配置:用户配置描述状态,而Pigsty负责将真实组件调整至所期待的状态。

配置Pigsty

Pigsty采用声明式配置:用户配置描述状态,而Pigsty负责将真实组件调整至所期待的状态。

Pigsty通过配置清单(Inventory)来定义基础设施与数据库集群,每一套Pigsty部署都有一份对应的配置:无论是几百集群的生产环境,还是1核1GB的本地沙箱,在Pigsty中除了配置内容外没有任何区别。Pigsty的配置采用"Infra as Data"的哲学:用户通过声明式的配置描述自己的需求,而Pigsty负责将真实组件调整至所期待的状态。

在形式上,配置清单的具体实现可以是默认的本地配置文件,也可以是来自CMDB中的动态配置数据,本文介绍时均以默认YAML配置文件pigsty.yml 为例。在 配置过程 中,Pigsty会检测当前节点环境,并自动生成推荐的配置文件。

配置清单的内容主要是配置项,Pigsty提供了220个配置参数,可以在多个层次进行配置,大多数参数可以直接使用默认值。配置项按照类目可以分为四大类: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 = root@127.0.0.1 ok
[ OK ] primary_ip = 10.10.10.10  (from probe)
[ OK ] admin = root@10.10.10.10 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>/default/main.yml中。
  • 参数:当用户通过命令行传入参数时,参数指定的配置项具有最高优先级,将覆盖一切层次的配置。一些配置项只能通过命令行参数的方式指定与使用。
层级 来源 优先级 说明 位置
Default 默认 最低 代码逻辑定义的默认值 roles/<role>/default/main.yml
Global 全局 在同一套部署环境内一致 all.vars.xxx
Cluster 集群 在同一套集群内保持一致 all.children.<cls>.vars.xxx
Instance 实例 最细粒度的配置层次 all.children.<cls>.hosts.<ins>.xxx
Argument 参数 最高 通过命令行参数传入 -e

配置类目

Pigsty包含了220个固定配置项,分为四个部分: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_EXPORTER REDIS指标暴露器 3

3.4 - 预置剧本

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
infra-pgweb 在元节点上加装可选的Web客户端工具PGWeb 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-audit 生成PostgreSQL审计合规报告(Beta) src
pgsql-matrix 复用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   +docker +consul +etcd
[nodes.yml]  ./nodes.yml -l pg-test                 +docker +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可执行命令,可使用包管理器安装Ansible,Ansible的安装由Pigsty自动处理,用户通常无需操心。

执行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=clean        # 在安装PG时,强制抹除已有运行中数据库实例(危险)
./infra-remove.yml -e rm_metadata=true       # 在卸载Pigsty时,一并移除数据
./infra-remove.yml -e rm_metadpkgs=true      # 在卸载Pigsty时,一并卸载软件
./nodes-remove.yml -e rm_dcs_server=true     # 在移除节点时,即使上面有DCS Server也强制移除
./pgsql-remove.yml -e rm_pgdata=true         # 在移除PG时,一并移除数据
./pgsql-remove.yml -e rm_pgpkgs=true         # 在移除PG时,一并卸载软件

4 - 部署

将Pigsty部署至您自己的服务器与虚拟机上

部署Pigsty分为两步:准备资源,与配置部署

准备资源

安装Pigsty前,您需要准备符合要求的环境软件

配置部署

您需要参考组件部署指南进行筹划,通过配置清单向Pigsty表明自己的需求,并通过剧本贯彻意图。

部署样例

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

4.1 - 环境准备

部署Pigsty所需的环境准备:主机节点,管理员用户,SSH,Sudo与DNS

4.1.1 - 节点置备

在部署Pigsty前,用户需要准备机器节点资源。

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

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

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

元节点本身也是一个普通的节点。

节点数量

如果您计划将Pigsty用作开箱即用的PostgreSQL数据库实例,则一台节点足矣。

对于部署生产环境的高可用PostgreSQL数据库集群来说,您最少需要三个节点,我们建议使用4个节点。

如果您还计划将Pigsty用作更多主机/数据库的管控,则可以准备更多的节点备用。

置备节点

您可以参考 本地虚拟机置备 教程,使用Vagrant与Virtualbox一键在本地 x86_64 笔记上拉起沙箱环境所需的四台虚拟机。 您也可以参考 云端虚拟机置备 教程,使用Terraform在云供应商上创建沙箱环境所需的四台虚拟机。

4.1.2 - 元节点置备

Pigsty需要至少元节点作为整个环境的控制中心。

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

元节点的数量最少为1个,沙箱环境默认使用1个元节点。

默认情况下,Pigsty的基础设施以副本的形式部署在多个元节点上,DCS(Consul/Etcd)例外,DCS以Quorum的形式存在。

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

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

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

4.1.3 - 管理用户置备

如何准备所需的管理员用户,配置SSH免密登陆,与免密sudo

Pigsty需要一个管理用户,该用户能够从元节点免密码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免密访问

在元节点上,假设执行命令的用户名为vagrant

生成密钥

vagrant用户的身份执行以ssh-keygen一路回车,会为vagrant生成公私钥对,用于登陆。

[vagrant@node-3 ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/vagrant/.ssh/id_rsa):
/home/vagrant/.ssh/id_rsa already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/vagrant/.ssh/id_rsa.
Your public key has been saved in /home/vagrant/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:nys41SqjxFcQYDJO2WkT/ZOB2rlechcOztPEZhrYSR0 vagrant@node-3
The key's randomart image is:
+---[RSA 2048]----+
|  +o+=.. .E.     |
| o.+= o.o .      |
|  .. +.* =       |
|    . +.O *      |
|       +S% .     |
|   .  o.O.=.     |
|    o..* +o      |
|   . .* o  .     |
|    .. + ..      |
+----[SHA256]-----+
[vagrant@node-3 ~]$
[vagrant@node-3 ~]$
  • 默认公钥:~/.ssh/id_rsa.pub
  • 默认私钥:~/.ssh/id_rsa

安装密钥

将公钥添加至需要登陆机器的对应用户上:/home/vagrant/.ssh/authorized_keys

如果您已经可以直接通过密码访问远程机器,可以直接通过ssh-copy-id的方式拷贝公钥。

# 输入密码以完成公钥拷贝
ssh-copy-id <ip>

# 直接将密码嵌入命令中,避免交互式密码输入
sshpass -p <password> ssh-copy-id <ip>

然后便可以通过该用户免密码SSH登陆远程机器。

配置免密SUDO

假设用户名为vagrant,则通过visudo 命令,或创建/etc/sudoers.d/vagrant 文件添加以下记录:

%vagrant ALL=(ALL) NOPASSWD: ALL

则 vagrant 用户即可免密sudo执行所有命令

4.1.4 - 本地虚拟机置备

如何使用Vagrant与Virtualbox迅速在本机创建Pigsty部署所需的虚拟机资源

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

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

太长;不看

对于MacOS用户,直接使用homebrew命令行一键安装Vagrant与Virtualbox即可,安装完毕后,一键拉起4台虚拟机。

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

其他操作系统与平台请参考 VagrantVirtualbox 图形安装指南。

实际上底下真正管事的命令是:

# 安装Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 安装Vagrant与Virtualbox
brew install vagrant virtualbox ansible

# 拉起由Vagrantfile预先定义的4台虚拟机
cd vagrant; vagrant up

Vagrant安装

这里介绍了图形界面下下载、安装Vagrant的过程

访问Vagrant官网

https://www.vagrantup.com/downloads

下载Vagrant

最新版本为2.2.19

安装Vagrant

点击 vagrant.pkg 执行安装,安装过程需要输入密码。https://www.virtualbox.org/

在MacOS上安装Virtualbox非常简单,其他操作系统上与之类似。

Virtualbox安装

这里介绍了图形界面下下载、安装Virtualbox的过程

前往Virtualbox官网https://www.virtualbox.org/

下载Virtualbox

最新版本为6.1.24

安装Virtualbox

点击 VirtualBox.pkg 执行安装,安装过程需要输入密码并重启。

如果安装失败,请检查您的 系统偏好设置 - 安全性与隐私 - 通用 - 允许以下位置的App中点击“允许”按钮。

Vagrant配置文件

https://github.com/Vonng/pigsty/blob/master/vagrant/Vagrantfile 提供了一个Vagrantfile样例。

这是Pigsty沙箱所使用的Vagrantfile,定义了四台虚拟机,包括一台2核/4GB的中控机/元节点,和3台 1核/1GB 的数据库节点

vagrant 二进制程序根据 Vagrantfile 中的定义,默认调用 Virtualbox 完成本地虚拟机的创建工作。

进入Pigsty根目录下的vagrant目录,执行vagrant up,即可拉起所有的四台虚拟机。

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

如果用户的机器配置不足,则可以考虑使用更小的N值,减少数据库节点的数量。如果只希望运行单个元节点,将其修改为0即可。

用户还可以修改每台机器的CPU核数和内存资源等,如配置文件中的注释所述,详情参阅Vagrant与Pigsty文档。

沙箱环境默认使用IMAGE_NAME = "centos/7",首次执行时会从vagrant官方下载centos 7.8 virtualbox 镜像,确保宿主机拥有合适的网络访问权限(科学上网)!

快捷方式

Pigsty已经提供了对常用vagrant命令的包装,用户可以在项目的Makefile中看到虚拟机管理的相关命令:

make        # 启动集群
make new4   # 销毁并创建新集群
make dns    # 将Pigsty域名记录写入本机/etc/hosts (需要sudo权限)
make ssh    # 将虚拟机SSH配置信息写入 ~/.ssh/config

更多信息,请参考Makefile

#------------------------------#
# vagrant vm management
#------------------------------#
# default node (meta)
up:
	cd vagrant && vagrant up meta
dw:
	cd vagrant && vagrant halt meta
del:
	cd vagrant && vagrant destroy -f meta
new: del up
#------------------------------#
# extra nodes: node-{1,2,3}
up-test:
	cd vagrant && vagrant up node-1 node-2 node-3
dw-test:
	cd vagrant && vagrant halt node-1 node-2 node-3
del-test:
	cd vagrant && vagrant destroy -f node-1 node-2 node-3
new-test: del-test up-test
#------------------------------#
# all nodes (meta, node-1, node-2, node-3)
up4:
	cd vagrant && vagrant up
dw4:
	cd vagrant && vagrant halt
del4:
	cd vagrant && vagrant destroy -f
new4: del4 up4
clean: del4
#------------------------------#
# status
st: status
status:
	cd vagrant && vagrant status
suspend:
	cd vagrant && vagrant suspend
resume:
	cd vagrant && vagrant resume
#------------------------------#

4.1.5 - 云端虚拟机置备

如何使用Terraform迅速在阿里云创建Pigsty部署所需的虚拟机资源

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

Terraform

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

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

TF配置文件

项目根目录 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 

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

特殊注意事项

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

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

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

4.1.6 - DNS域名配置

为Pigsty Web服务配置自定义域名

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

因为有一些Web服务(例如Consul)监听的地址是 127.0.0.1 而非 0.0.0.0,因此您只能通过本机上的Nginx代理访问,并使用域名来区分。

太长;不看

在MacOS与Linux中,执行以下命令 bin/dns,配置Pigsty所需的DNS记录

sudo make dns

实际上是将以下记录写入 /etc/hosts 中(需要输入sudo密码),在Windows中则自行添加至:C:\Windows\System32\drivers\etc\hosts中。

# pigsty dns records
10.10.10.10 meta pigsty p.pigsty g.pigsty a.pigsty c.pigsty l.pigsty
10.10.10.10 api.pigsty adm.pigsty cli.pigsty ddl.pigsty lab.pigsty git.pigsty sss.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

默认域名

默认情况下,Pigsty使用的域名包括:

10.10.10.10 meta pigsty p.pigsty g.pigsty a.pigsty c.pigsty l.pigsty                      # 必选
10.10.10.10 api.pigsty adm.pigsty cli.pigsty ddl.pigsty lab.pigsty git.pigsty sss.pigsty

所有Web服务的域名均通过 nginx_upstream 进行配置,例如,沙箱demo的域名配置如下:

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"   } #== ^ required ==#
  - { name: postgrest    , domain: api.pigsty , endpoint: "127.0.0.1:8884"   } #== v optional ==#
  - { name: pgadmin      , domain: adm.pigsty , endpoint: "127.0.0.1:8885"   }
  - { name: pgweb        , domain: cli.pigsty , endpoint: "127.0.0.1:8886"   }
  - { name: bytebase     , domain: ddl.pigsty , endpoint: "127.0.0.1:8887"   }
  - { name: jupyter      , domain: lab.pigsty , endpoint: "127.0.0.1:8888"   }
  - { name: gitea        , domain: git.pigsty , endpoint: "127.0.0.1:8889"   }
  - { name: minio        , domain: sss.pigsty , endpoint: "127.0.0.1:9000"   }

配置自定义域名

您可以定制Pigsty各自系统使用的域名,例如在Pigsty的公开Demo中,就使用了不同的域名,并由互联网DNS服务商负责解析

nginx_upstream:                   # domain names and upstream servers
  - { name: home         , domain: home.pigsty.cc , endpoint: "10.10.10.10:80"   }  # default -> index.html (80)
  - { name: grafana      , domain: demo.pigsty.cc , endpoint: "10.10.10.10:3000" }  # pigsty grafana (3000)
  - { name: loki         , domain: l.pigsty.cc    , endpoint: "10.10.10.10:3100" }  # pigsty loki (3100)
  - { name: prometheus   , domain: p.pigsty.cc    , endpoint: "10.10.10.10:9090" }  # pigsty prometheus (9090)
  - { name: alertmanager , domain: a.pigsty.cc    , endpoint: "10.10.10.10:9093" }  # pigsty alertmanager (9093)
  - { name: consul       , domain: c.pigsty.cc    , endpoint: "127.0.0.1:8500"   }  # pigsty consul UI (8500) (domain required)
  - { name: postgrest    , domain: api.pigsty.cc  , endpoint: "127.0.0.1:8884"   }  #== v optional ==#
  - { 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"   }

如果您没有购买互联网域名,则可以自定义的域名配置到您自己网络的DNS服务器中,或者干脆写入需要访问Pigsty Web服务的服务器的静态解析记录中。

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

4.2 - 软件准备

部署Pigsty所需的软件,安装包,以及如何在没有互联网访问的环境中进行离线安装

4.2.1 - Pigsty 软件下载

Pigsty 软件资源列表,以及从哪里获取它们。

Pigsty的唯一权威发布地址为 Github 仓库: Vonng/pigsty,所有软件发行版都位于该项目 Release 页面

太长不看

# 使用此命令下载 pigsty.tgz 源码包,该脚本将区分墙内墙外,在大陆使用CDN加速下载
bash -c "$(curl -fsSL http://download.pigsty.cc/get)"  # get latest pigsty source

# 进入Pigsty源码目录,使用自带脚本下载离线软件包,同样区分墙内墙外环境。
cd pigsty; ./download pkg

软件包列表

当前,一个发行版本包含以下软件内容:

  • pigsty.tgz必选项,Pigsty源代码
  • pkg.tgz可选项,基于CentOS 7.8.2003 提前制作的离线软件安装包;如需离线安装Pigsty,需要下载此软件包。
  • matrix.tgz可选项,如果需要安装Greenplum与MatrixDB,请额外下载此软件包
  • docker.tgz可选项,如果需要使用一些基于Docker的扩展软件应用,可下载此软件包
  • app.tgz可选项,如果想要下载Pigsty自带的可视化应用Applet样例,可下载此软件包

除了源码包 pigsty.tgz 为必选项目,其他软件包均为可选。例如,如果不下载 pkg.tgz,Pigsty就会在基础设施初始化时,直接通过互联网从 repo_upstream 下载所需的所有软件包。

下载脚本

Pigsty本身提供了一个下载脚本:download,来下载这些软件包

$ ./download
    download and extract pigsty packages: pigsty.tgz pkg.tgz app.tgz matrix.tgz
    usage:
        download pigsty pkg   # download pigsty essentials

        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 docker.tgz   # download docker images cache

        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

此脚本会自动检测当前主机网络环境(by ping google),正常从Github下载Release,墙内则通过腾讯CDN下载软件包。

4.2.2 - Pigsty 离线安装

如何在没有互联网访问的环境中离线安装Pigsty

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页面下载。

VERSION=v1.5.1
curl -SL https://github.com/Vonng/pigsty/releases/download/${VERSION}/pkg.tgz -o /tmp/pkg.tgz

Pigsty的官方CDN也提供最新版本的pkg.tgz下载,只需要执行以下命令即可。

curl http://download.pigsty.cc/v1.5.1/pkg.tgz -o /tmp/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/

4.2.3 - Pigsty源码包

如何下载并使用可选的Pigsty Docker扩展离线镜像包

用户需要将Pigsty项目下载至元节点。

如果您是软件开发者,贡献者,则请使用Github克隆Master主干。如果您是软件用户,请务必使用具体的版本,而非Github Master分支,该分支可能处于开发中途的不一致状态中。

下载Pigsty源码

用户可以从 Github Release 页面下载最新版本的Pigsty源码包:

VERSION=v1.5.1
https://github.com/Vonng/pigsty/releases/download/${VERSION}/pigsty.tgz 

也可以从 Pigsty CDN 下载最新版本的Pigsty源代码

VERSION=v1.5.1
http://download.pigsty.cc/${VERSION}/pigsty.tgz

执行以下脚本,将自动获取最新稳定版本的Pigsty:

bash -c "$(curl -fsSL http://download.pigsty.cc/get)"

Pigsty 源码包自带的下载脚本 download 也可以用于下载特定版本的Pigsty源码包本身

./download pigsty.tgz  # 下载最新稳定版本的离线软件包至 /tmp/pigsty.tgz
./download pigsty      # 不仅下载 /tmp/pigsty.tgz ,还将其解压至 ~/pigsty ,如果目标目录已经存在则跳过解压

克隆Pigsty源代码

git clone https://github.com/Vonng/pigsty
git clone git@github.com:Vonng/pigsty.git

4.2.4 - Pigsty pkg.tgz 离线软件包

如何下载并使用可选的Pigsty离线软件包

Pigsty提供了基于 CentOS 7.8.2003 环境下制作的离线软件包,如果您正好使用此系统镜像,则可以确保无需互联网即可成功安装。

离线软件包的默认下载放置路径为/tmp/pkg.tgz,Pigsty在执行 ./configure 的过程中,如果没有发现该路径下存在可用的离线软件包,会提示您下载,您也可以跳过,直接从原始上游下载。

不使用离线软件包时,Pigsty默认会从互联网上游Repo中直接下载所需软件(约1GB),这一过程耗时取决于您的网络条件,一些来自Github或墙外的软件包可能下载速度非常缓慢,甚至完全无法访问。

如果您使用的操作系统是其他 EL7 兼容发行版,则可能存在 极个别 RPM 软件包版本不兼容问题,您可以参考 Pigsty离线安装 或 FAQ 介绍的方法,从原始上游下载替换带有问题的RPM软件包。

下载离线软件包

从Github下载最新、权威的软件包

VERSION=v1.5.1
wget https://github.com/Vonng/pigsty/releases/download/${VERSION}/pkg.tgz -o /tmp/pkg.tgz 

中国大陆可以使用CDN下载:

VERSION=v1.5.1
curl http://download.pigsty.cc/${VERSION}/pkg.tgz -o  /tmp/pkg.tgz

更简洁的方式是使用 Pigsty 源码包自带的下载脚本 download

./download pkg.tgz  # 下载最新稳定版本的离线软件包至 /tmp/pkg.tgz
./download pkg      # 不仅下载 /tmp/pkg.tgz ,还将其解压至 /www/pigsty 并配置本地静态文件源,开箱即用。

离线软件安装包快捷命令

copy-pkg:
	scp dist/${VERSION}/pkg.tgz meta:/tmp/pkg.tgz

use-pkg:
	ssh meta '/home/vagrant/pigsty/configure --ip 10.10.10.10 --non-interactive --download -m demo'

load-docker:
	ssh meta 'cat /tmp/docker.tgz | gzip -d -c - | docker load'

release-pkg: cache
	scp meta:/tmp/pkg.tgz dist/${VERSION}/pkg.tgz

rp: release-pkg

4.2.5 - Pigsty Docker扩展镜像包

如何下载并使用可选的Pigsty Docker扩展离线镜像包

Docker是开箱即用的容器基础设施,您可以使用Docker拉起开箱即用的软件容器,而无需过多关心安装、部署等运维管理细节。

Pigsty带有一些Docker应用样例,这些Docker应用都可以直接从DockerHub或其他镜像站点直接拉取。

对于没有互联网访问的场景,Pigsty制作了几个常用容器镜像的软件包:docker.tgz,这是一个可选项,包含的软件如下:

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 save kong alpine registry dpage/pgadmin4 sosedoff/pgweb postgrest/postgrest swaggerapi/swagger-ui minio/minio bytebase/bytebase:1.0.5 vonng/pg_exporter gitea/gitea | gzip -9 -c > /tmp/docker.tgz  

您可以直接使用 cat /tmp/docker.tgz | gzip -d -c - | docker load 的方式加载这些镜像,或者在初始化节点前,将其放置于 /tmp/docker.tgz ,则Pigsty在部署Docker时,会自动加载此位置的镜像压缩包。

下载Docker扩展软件包

从Github下载最新、权威的软件包

VERSION=v1.5.1
wget https://github.com/Vonng/pigsty/releases/download/${VERSION}/docker.tgz -o /tmp/docker.tgz 

中国大陆可以使用CDN下载:

VERSION=v1.5.1
curl http://download.pigsty.cc/${VERSION}/docker.tgz -o /tmp/docker.tgz

更简洁的方式是使用 Pigsty 源码包自带的下载脚本 download

./download docker.tgz  # 下载最新稳定版本的docker扩展软件包至 /tmp/docker.tgz

Docker扩展软件包快捷方式

copy-docker:
	scp dist/${VERSION}/docker.tgz meta:/tmp/docker.tgz

load-docker:
	ssh meta 'cat /tmp/docker.tgz | gzip -d -c - | docker load'

release-docker:
	ssh meta 'docker save kong alpine registry dpage/pgadmin4 sosedoff/pgweb postgrest/postgrest swaggerapi/swagger-ui minio/minio bytebase/bytebase:1.0.5 vonng/pg_exporter gitea/gitea | gzip -9 -c > /tmp/docker.tgz'
	scp meta:/tmp/docker.tgz dist/${VERSION}/docker.tgz

rp3: release-docker

4.2.6 - Pigsty Applet扩展软件包

如何下载并使用可选的 Pigsty 可视化小应用演示样例包 app.tgz

GitHub Repo : Vonng/pigsty-app

Pigsty提供了基于了一些可视化应用样例,这些样例及其基础数据被制成了一个单独的,可选的软件包 app.tgz,大小约 70MB。

下载应用Applet演示包

从Github下载最新、权威的软件包

VERSION=v1.5.1
wget https://github.com/Vonng/pigsty/releases/download/${VERSION}/app.tgz -o /tmp/app.tgz 

中国大陆可以使用CDN下载:

VERSION=v1.5.1
curl http://download.pigsty.cc/${VERSION}/app.tgz -o files/app.tgz

更简洁的方式是使用 Pigsty 源码包自带的下载脚本 download

./download app.tgz  # 下载最新稳定版本的离线软件包至 /tmp/app.tgz
./download app      # 不仅下载 /tmp/app.tgz ,还将其解压至 ~/app

4.2.7 - Pigsty MatrixDB扩展软件包

如何下载并使用可选的 Pigsty MatrixDB扩展离线软件包

Pigsty v1.4 引入了 MatrixDB 部署支持,这是Greenplum7 (尚未发布)的一个功能超集版本。

但并不是所有用户都会用到数据仓库,因此在Pigsty中,与Greenplum/MatrixDB相关的软件包被单独打包为一个扩展软件包 matrix.tgz

当您需要使用 MatrixDB 或 Greenplum 时,可以参考 pigsty-mxdb 配置文件直接从原始上游下载,或下载 matrix.tgz 并解压至管理节点 /www/matrix 使用。

下载离线软件包

从Github下载最新、权威的软件包

VERSION=v1.5.1
wget https://github.com/Vonng/pigsty/releases/download/${VERSION}/matrix.tgz -o /tmp/matrix.tgz 

中国大陆可以使用CDN下载:

VERSION=v1.5.1
curl http://download.pigsty.cc/${VERSION}/matrix.tgz -o  /tmp/matrix.tgz

更简洁的方式是使用 Pigsty 源码包自带的下载脚本 download

./download matrix.tgz  # 下载最新稳定版本的离线软件包至 /tmp/matrix.tgz
./download matrix      # 不仅下载 /tmp/matrix.tgz ,还将其解压至 /www/matrix 并配置本地静态文件源,开箱即用。

制作MatrixDB扩展软件包

copy-matrix:
	scp dist/${VERSION}/matrix.tgz meta:/tmp/matrix.tgz

use-matrix:
	ssh meta 'sudo tar -xf /tmp/matrix.tgz -C /www'
	scp files/matrix.repo meta:/tmp/matrix.repo
	ssh meta sudo mv -f /tmp/matrix.repo /www/matrix.repo

rp2: release-matrix
release-matrix:
	#ssh meta 'sudo cp -r /www/matrix /tmp/matrix; sudo chmod -R a+r /www/matrix'
	ssh meta sudo tar zcvf /tmp/matrix.tgz -C /www matrix
	scp meta:/tmp/matrix.tgz dist/${VERSION}/matrix.tgz`

4.2.8 - Ansible

Pigsty剧本使用Ansible编写,但用户无需了解此软件的使用细节。

Ansible剧本需要使用ansible-playbook可执行命令,Ansible可以通过包管理器安装:

# 在EL7兼容系统中可通过以下命令安装 Ansible。
yum install ansible

# 在MacOS中可以使用Homebrew安装 Ansible
brew install ansible

安装后,可以检查安装的软件版本:

$ echo $(ansible --version)
ansible 2.10.3

当使用离线软件包时,Pigsty会在配置过程中尝试从离线软件包中安装ansible。

Pigsty依赖Ansible进行环境初始化。但如果元节点本身没有安装Ansible,也没有互联网访问怎么办?

离线软件包中本身带有 Ansible,可以直接通过本地文件Yum源的方式使用。

手工从离线软件包中安装Ansible

假设用户已经将离线安装包解压至默认位置:/www/pigsty

那么将以下Repo文件写入/etc/yum.repos.d/pigsty-local.repo 中,就可以直接使用该源。

[pigsty-local]
name=Local Yum Repo pigsty
baseurl=file:///www/pigsty
skip_if_unavailable = 1
enabled = 1
priority = 1
gpgcheck = 0

执行以下命令,在元节点上离线安装Ansible

yum clean all
yum makecache
yum install ansible

4.3 - 沙箱环境

介绍Pigsty的沙箱环境,一个配置规格、对象标识符、与默认数据库预先确定的环境,用于教学演示之用。

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设计了一个标准的,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数据库集群 配置剧本

./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的节点
./pigsty-matrixdb.yml        # 在上述节点上安装MatrixDB

4.4 - 监控系统部署

如何使用Pigsty监控已有的PostgreSQL实例?如RDS for PG

对于由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:pass@rds.pg.hongkong.xxx: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';

4.5 - 安全考量

生产网段隔离 + Pigsty默认的权限模型通常足以满足一般安全要求

Pigsty依赖的工作假设是,部署位于内网工作环境。

如果您在带有公网IP网卡的机器上安装部署Pigsty,需要特别注意网络防火墙相关配置。

通常建议您开启外网网卡上的防火墙进行端口过滤,只允许 80 端口的Web服务入站流量,请尽可能避免直接通过公网端口使用数据库。

依赖内网网络安全,辅以Pigsty默认的权限模型,通常足以满足一般安全要求。

通常不建议您自行折腾CA,SSL,除非您真的知道自己在做什么。

网络安全

  • 确保生产网段与开发、公网隔离
  • 确保元节带有合理的访问控制机制(严格限制仅DBA可登录)

数据库安全

元数据安全

  • 限制Consul UI界面访问权限
  • 限制ETCD访问
  • 为Consul启用SSL
  • 为ETCD启用SSL

4.6 - 部署样例

在实际环境中部署Pigsty的几个例子

4.6.1 - Vagrant沙箱环境

针对本地Vagrant沙箱的Pigsty配置示例

Pigsty自带一个基于Vagrant的沙箱环境

该沙箱所使用的配置文件即Pigsty根目录中的 pigsty.yml ,Github原地址为:https://github.com/Vonng/pigsty/blob/master/pigsty.yml

该配置文件可作为一个标准的学习样例,例如使用相同规格的虚拟机环境部署时,通常只需要在这份配置文件的基础上进行极少量修改就可以直接使用。

4.6.2 - 腾讯云VPC部署

使用腾讯云VPC虚拟机部署Pigsty

本样例将基于腾讯云VPC部署Pigsty

资源准备

申请虚拟机

买几台虚拟机,如下图所示,其中11这一台作为元节点,带有公网IP,数据库节点3台,普通1核1G即可。

配置SSH远程登录

现在假设我们的管理用户名为vonng,就是我啦!现在首先配置我在元节点上到其他三台节点的ssh免密码访问。

# vonng@172.21.0.11           # meta
ssh-copy-id root@172.21.0.3   # pg-test-1
ssh-copy-id root@172.21.0.4   # pg-test-2
ssh-copy-id root@172.21.0.16  # pg-test-3
scp ~/.ssh/id_rsa.pub root@172.21.0.3:/tmp/
scp ~/.ssh/id_rsa.pub root@172.21.0.4:/tmp/
scp ~/.ssh/id_rsa.pub root@172.21.0.16:/tmp/
ssh root@172.21.0.3 'useradd vonng; mkdir -m 700 -p /home/vonng/.ssh; mv /tmp/id_rsa.pub /home/vonng/.ssh/authorized_keys; chown -R vonng /home/vonng; chmod 0600 /home/vonng/.ssh/authorized_keys;'
ssh root@172.21.0.4 'useradd vonng; mkdir -m 700 -p /home/vonng/.ssh; mv /tmp/id_rsa.pub /home/vonng/.ssh/authorized_keys; chown -R vonng /home/vonng; chmod 0600 /home/vonng/.ssh/authorized_keys;'
ssh root@172.21.0.16 'useradd vonng; mkdir -m 700 -p /home/vonng/.ssh; mv /tmp/id_rsa.pub /home/vonng/.ssh/authorized_keys; chown -R vonng /home/vonng; chmod 0600 /home/vonng/.ssh/authorized_keys;'

然后配置该用户免密码执行sudo的权限:

ssh root@172.21.0.3  "echo '%vonng ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/vonng"
ssh root@172.21.0.4  "echo '%vonng ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/vonng"
ssh root@172.21.0.16 "echo '%vonng ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/vonng"

# 校验配置是否成功
ssh 172.21.0.3 'sudo ls'
ssh 172.21.0.4 'sudo ls'
ssh 172.21.0.16 'sudo ls'

下载项目

# 从Github克隆代码
git clone https://github.com/Vonng/pigsty

# 如果您不能访问Github,也可以使用Pigsty CDN下载代码包
curl http://pigsty-1304147732.cos.accelerate.myqcloud.com/latest/pigsty.tar.gz -o pigsty.tgz && tar -xf pigsty.tgz && cd pigsty 

下载离线安装包

# 从Github Release页面下载
# https://github.com/Vonng/pigsty

# 如果您不能访问Github,也可以使用Pigsty CDN下载离线软件包
curl http://pigsty-1304147732.cos.accelerate.myqcloud.com/latest/pkg.tgz -o files/pkg.tgz

# 将离线安装包解压至元节点指定位置 (也许要sudo)
mv -rf /www/pigsty /www/pigsty-backup && mkdir -p /www/pigsty
tar -xf files/pkg.tgz --strip-component=1 -C /www/pigsty/

调整配置

我们可以基于Pigsty沙箱的配置文件进行调整。因为都是普通低配虚拟机,因此不需要任何实质配置修改,只需要修改连接参数与节点信息即可。简单的说,只要改IP地址就可以了!

现在将沙箱中的IP地址全部替换为云环境中的实际IP地址。(如果使用了L2 VIP,VIP也需要替换为合理的地址)

说明 沙箱IP 虚拟机IP
元节点 10.10.10.10 172.21.0.11
数据库节点1 10.10.10.11 172.21.0.3
数据库节点2 10.10.10.12 172.21.0.4
数据库节点3 10.10.10.13 172.21.0.16
pg-meta VIP 10.10.10.2 172.21.0.8
pg-test VIP 10.10.10.3 172.21.0.9

编辑配置文件:pigsty.yml,如果都是规格差不多的虚拟机,通常您只需要修改IP地址即可。特别需要注意的是在沙箱中我们是通过SSH Alias来连接的(诸如meta, node-1之类),记得移除所有ansible_host配置,我们将直接使用IP地址连接目标节点。

cat pigsty.yml | \
	sed 's/10.10.10.10/172.21.0.11/g' |\
	sed 's/10.10.10.11/172.21.0.3/g' |\
	sed 's/10.10.10.12/172.21.0.4/g' |\
	sed 's/10.10.10.13/172.21.0.16/g' |\
	sed 's/10.10.10.2/172.21.0.8/g' |\
	sed 's/10.10.10.3/172.21.0.9/g' |\
	sed 's/10.10.10.3/172.21.0.9/g' |\
	sed 's/, ansible_host: meta//g' |\
	sed 's/ansible_host: meta//g' |\
	sed 's/, ansible_host: node-[123]//g' |\
	sed 's/vip_interface: eth1/vip_interface: eth0/g' |\
	sed 's/vip_cidrmask: 8/vip_cidrmask: 24/g' > pigsty2.yml
mv pigsty.yml pigsty-backup.yml; mv pigsty2.yml pigsty.yml

就这?

是的,配置文件已经修改完了!我们可以看看到底修改了什么东西

$ diff pigsty.yml pigsty-backup.yml
38c38
<       hosts: {172.21.0.11: {}}
---
>       hosts: {10.10.10.10: {ansible_host: meta}}
46c46
<         172.21.0.11: {pg_seq: 1, pg_role: primary}
---
>         10.10.10.10: {pg_seq: 1, pg_role: primary, ansible_host: meta}
109,111c109,111
<         vip_address: 172.21.0.8             # virtual ip address
<         vip_cidrmask: 24                     # cidr network mask length
<         vip_interface: eth0                 # interface to add virtual ip
---
>         vip_address: 10.10.10.2             # virtual ip address
>         vip_cidrmask: 8                     # cidr network mask length
>         vip_interface: eth1                 # interface to add virtual ip
120,122c120,122
<         172.21.0.3: {pg_seq: 1, pg_role: primary}
<         172.21.0.4: {pg_seq: 2, pg_role: replica}
<         172.21.0.16: {pg_seq: 3, pg_role: offline}
---
>         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}
147,149c147,149
<         vip_address: 172.21.0.9             # virtual ip address
<         vip_cidrmask: 24                     # cidr network mask length
<         vip_interface: eth0                 # interface to add virtual ip
---
>         vip_address: 10.10.10.3             # virtual ip address
>         vip_cidrmask: 8                     # cidr network mask length
>         vip_interface: eth1                 # interface to add virtual ip
326c326
<       - 172.21.0.11 yum.pigsty
---
>       - 10.10.10.10 yum.pigsty
329c329
<       - 172.21.0.11
---
>       - 10.10.10.10
393c393
<       - server 172.21.0.11 iburst
---
>       - server 10.10.10.10 iburst
417,430c417,430
<       - 172.21.0.8  pg-meta                       # sandbox vip for pg-meta
<       - 172.21.0.9  pg-test                       # sandbox vip for pg-test
<       - 172.21.0.11 meta-1                        # sandbox node meta-1 (node-0)
<       - 172.21.0.3 node-1                        # sandbox node node-1
<       - 172.21.0.4 node-2                        # sandbox node node-2
<       - 172.21.0.16 node-3                        # sandbox node node-3
<       - 172.21.0.11 pigsty
<       - 172.21.0.11 y.pigsty yum.pigsty
<       - 172.21.0.11 c.pigsty consul.pigsty
<       - 172.21.0.11 g.pigsty grafana.pigsty
<       - 172.21.0.11 p.pigsty prometheus.pigsty
<       - 172.21.0.11 a.pigsty alertmanager.pigsty
<       - 172.21.0.11 n.pigsty ntp.pigsty
<       - 172.21.0.11 h.pigsty haproxy.pigsty
---
>       - 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 (node-0)
>       - 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 pigsty
>       - 10.10.10.10 y.pigsty yum.pigsty
>       - 10.10.10.10 c.pigsty consul.pigsty
>       - 10.10.10.10 g.pigsty grafana.pigsty
>       - 10.10.10.10 p.pigsty prometheus.pigsty
>       - 10.10.10.10 a.pigsty alertmanager.pigsty
>       - 10.10.10.10 n.pigsty ntp.pigsty
>       - 10.10.10.10 h.pigsty haproxy.pigsty
442c442
<     grafana_url: http://admin:admin@172.21.0.11:3000 # grafana url
---
>     grafana_url: http://admin:admin@10.10.10.10:3000 # grafana url
478,480c478,480
<       meta-1: 172.21.0.11                         # you could use existing dcs cluster
<       # meta-2: 172.21.0.3                       # host which have their IP listed here will be init as server
<       # meta-3: 172.21.0.4                       # 3 or 5 dcs nodes are recommend for production environment
---
>       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 recommend for production environment
692c692
<           - host    all     all                         172.21.0.11/32      md5
---
>           - host    all     all                         10.10.10.10/32      md5

执行剧本

您可以使用同样的 沙箱初始化 来完成 基础设施和数据库集群的初始化。

其输出结果除了IP地址,与沙箱并无区别。参考输出

访问Demo

现在,您可以通过公网IP访问元节点上的服务了!请注意做好信息安全工作。

与沙箱环境不同的是,如果您需要从公网访问Pigsty管理界面,需要自己把定义的域名写入/etc/hosts中,或者使用真正申请的域名。

否则就只能通过IP端口直连的方式访问,例如: http://<meta_node_public_ip>:3000

Nginx监听的域名可以通过可以通过 nginx_upstream 选项。

nginx_upstream:
  - { name: home,          host: pigsty.cc,   url: "127.0.0.1:3000"}
  - { name: consul,        host: c.pigsty.cc, url: "127.0.0.1:8500" }
  - { name: grafana,       host: g.pigsty.cc, url: "127.0.0.1:3000" }
  - { name: prometheus,    host: p.pigsty.cc, url: "127.0.0.1:9090" }
  - { name: alertmanager,  host: a.pigsty.cc, url: "127.0.0.1:9093" }
  - { name: haproxy,       host: h.pigsty.cc, url: "127.0.0.1:9091" }

4.6.3 - 生产环境部署

基于高规格硬件执行生产环境部署

5 - 模块:INFRA

在元节点提供基础设施组件服务

5.1 - INFRA概览

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的空虚拟机空实例,故显示内容较为单薄,请以实际效果为准。

5.2 - INFRA配置

使用配置文件与参数描述基础设施

使用 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:password@proxy.address.com'
  https_proxy: 'http://username:password@proxy.address.com'
  all_proxy: 'http://username:password@proxy.address.com'
  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.5.7/haproxy-2.5.7-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,默认值为: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 --enable-feature=promql-negative-offset"

默认参数会允许Prometheus启用负时间偏移量功能,并默认保留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,默认值为:"10s"

每隔本参数指定的时长,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 ,但ETCD尚未正式支持。

CONSUL

Consul用于服务网格,健康监测,传递共识,代理DCS Server访问。

dcs_safeguard

安全保险,禁止清除存在的Consul实例,类型:bool,层级:C/A,默认值为:false

如果为true,任何情况下,Pigsty剧本都不会移除运行中的Consul实例,包括 nodes-remove.yml

详情请参考 保护机制

dcs_clean

是否在初始化时抹除现存Consul实例?类型:bool,层级:C/A,默认值为:false

针对 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"

5.3 - INFRA剧本

使用infra系列剧本在元节点上安装Pigsty,并加装可选功能。
剧本 功能 链接
infra 在元节点上完整安装Pigsty src
infra-demo 一次性完整初始化四节点演示沙箱环境的特殊剧本 src
infra-remove 在元节点上卸载Pigsty src
infra-jupyter 在元节点上加装可选数据分析服务组件组件Jupyter Lab src
infra-pgweb 在元节点上加装可选的Web客户端工具PGWeb 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
./infra-pgweb.yml        # 在元节点加装 PgWeb
./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服务

5.4 - INFRA监控

Pigsty中关于基础设施的Grafana监控面板

5.4.1 - Home

Home监控面板是整个Pigsty监控系统的默认主页与导航入口

Live Demo地址:http://demo.pigsty.cc

5.4.2 - INFRA Overview

INFRA Overview 展现Pigsty整体概览,并提供到具体基础设施监控的导航

INFRA Overview 展现Pigsty整体概览,并提供到具体基础设施监控的导航

Live Demo地址:http://demo.pigsty.cc/d/infra-overview

5.4.3 - Nginx Overview

Nginx Overview 展现Pigsty中Nginx访问端点的指标与日志

Nginx Overview 展现Pigsty中访问端点Web服务器Nginx的指标与日志。

Live Demo地址:http://demo.pigsty.cc/d/nginx-overview

5.4.4 - Grafana Overview

Grafana Overview 展现Pigsty中监控面板组件Grafana的监控指标。

Grafana Overview 展现Pigsty中监控面板组件Grafana的监控指标。

Live Demo地址:http://demo.pigsty.cc/d/grafana-overview

5.4.5 - Prometheus Overview

Prometheus Overview 展现Pigsty中时序数据库Prometheus的监控指标。

Prometheus Overview 展现Pigsty中时序数据库Prometheus的监控指标。

Live Demo地址:http://demo.pigsty.cc/d/prometheus-overview

5.4.6 - Loki Overview

Loki Overview 展现Pigsty中日志数据库Loki的监控指标。

Loki Overview 展现Pigsty中日志数据库Loki的监控指标。

Live Demo地址:http://demo.pigsty.cc/d/loki-overview

5.4.7 - DCS Overview

DCS Overview 展现Pigsty中Consul与ETCD的状态。

DCS Overview 展现Pigsty中时序数据库Consul与ETCD的监控指标

Live Demo地址:http://demo.pigsty.cc/d/dcs-overview

5.4.8 - CMDB Overview

CMDB Overview 展现Pigsty中Postgres CMDB的配置清单内容

CMDB Overview 展现Pigsty中Postgres CMDB的配置清单内容

Live Demo地址:http://demo.pigsty.cc/d/cmdb-overview

6 - 模块:NODES

将更多主机节点纳入Pigsty管理。

6.1 - NODES概览

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

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

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

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

元节点也是一个普通的节点:节点是元节点的父类,元节点是节点的超集。

6.1.1 - 节点

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

您可以使用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

6.1.2 - 元节点

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

元节点即完整安装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个节点。如果您只有两个节点,建议主库故障时人工介入以避免脑裂出现。

6.1.3 - 节点交互

以单个 元节点 和 单个 节点 构成的环境为例介绍两者间的交互。

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

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

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

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

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

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

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

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

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

6.1.4 - 节点身份

节点的身份参数与标识符

每个节点都有身份参数,通过在<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

6.2 - NODES配置

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 int C docker cgroup驱动
372 docker_registry_mirrors DOCKER string C docker镜像仓库地址
373 docker_image_cache DOCKER string 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

节点身份参数

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

NTP时区设置, 类型:string,层级:C,默认值为空。

在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,默认为:/www/pigsty/docker.tar.lz4

如果存在时,配置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 指定的文件中。

6.3 - NODES剧本

使用 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_clean:默认关闭,当打开时,初始化节点/nodes.yml 会抹除掉现有Consul实例(有可能影响PG主库写入)

当遇到现存实例时,nodes.yml 剧本会有以下行为表现:

dcs_safeguard / pg_clean dcs_clean=true dcs_clean=false
dcs_safeguard=true 中止执行 中止执行
dcs_safeguard=false 抹除实例 中止执行

当遇到现存实例时, nodes-remove.yml剧本会有以下行为表现:

dcs_safeguard / pg_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=dcs-init        # 在节点上初始化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=clean   # 在节点上强制抹除重新配置consul

./nodes.yml --tags=node_exporter   # 在节点上配置 node_exporter 并注册
./nodes.yml --tags=node_deregister # 将节点监控从元节点上取消注册
./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.yml                      # 移除所有节点(危险!)
./nodes.yml -l nodes-test        # 移除 nodes-test 分组下的机器
./nodes.yml -l 10.10.10.11       # 移除 10.10.10.11这台机器节点
./nodes.yml -l 10.10.10.10 -e rm_dcs_servers=true # 如果节点为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 rm_dcs_servers=true # 移除Consul服务(包括Server!)

6.4 - NODES监控

Pigsty中关于主机节点的Grafana监控面板

6.4.1 - NODES Overview

提供主机节点全局监控指标概览

NODES Overview 展现所有环境中主机节点的汇总指标,集群之间的核心指标水平对比,并提供到实例与集群的快速导航

Live Demo地址:http://demo.pigsty.cc/d/nodes-overview

6.4.2 - NODES Alert

提供主机节点全局监控告警指标总览

NODES Alerts 展现所有与主机节点 NODES 模块有关的告警信息:活跃的告警,告警时间线,以及相关指标数据

Live Demo地址:http://demo.pigsty.cc/d/nodes-alert

6.4.3 - NODES Cluster

提供针对单个节点集群的指标洞察

NODES Cluster关注单个主机集群,提供集群级别的汇总指标展示,节点级别的指标水平对比,以及到所有集群成员的快速导航。

Live Demo地址:http://demo.pigsty.cc/d/nodes-cluster

6.4.4 - NODES Instance

提供针对单个节点的指标洞察

Nodes Instance关注单个主机节点的监控指标,使用频率非常高。

Live Demo地址:http://demo.pigsty.cc/d/nodes-instance

7 - 模块:PGSQL

置备高可用PostgreSQL数据库集群!

7.1 - 概念

关于Pigsty创建的PostgreSQL数据库,用户需要了解的概念。

7.1.1 - PostgreSQL 实体模型

Pigsty中关于PostgreSQL数据库的逻辑概念模型:ER实体关系模型。

在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上。
  • 四个服务:

集群

**集群(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 的普通读取请求。

7.1.2 - PostgreSQL 身份参数

如何为Pigsty中的PostgreSQL数据库分配标识符,指定身份参数。

核心身份参数是定义 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集群同样有效。

7.1.3 - PostgreSQL 架构

Pigsty所采用的高可用PostgreSQL数据库集群架构

高可用

主库故障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与节点日志

7.1.4 - 命名

PostgreSQL实体命名原则

名之必可言也,言之必可行也。

概念及其命名是非常重要的东西,命名风格体现了工程师对系统架构的认知。定义不清的概念将导致沟通困惑,随意设定的名称将产生意想不到的额外负担。因此需要审慎地设计。本文介绍 Pigsty 中的相关实体,以及其命名所遵循的原则。

TL;DR

Pigsty中,核心的四类实体为:集群(Cluster)服务(Service)实例(Instance)节点(Node)

  • 集群(Cluster) 是基本自治单元,由用户指定唯一标识,表达业务含义,作为顶层命名空间。
  • 集群在硬件层面上包含一系列的节点(Node),即物理机,虚机(或Pod),可以通过IP唯一标识。
  • 集群在软件层面上包含一系列的实例(Instance),即软件服务器,可以通过IP:Port唯一标识。
  • 集群在服务层面上包含一系列的服务(Service),即可访问的域名与端点,可以通过域名唯一标识。
  • 集群的命名可以使用任意满足DNS域名规范的名称,不能带点([a-zA-Z0-9-]+)。
  • 节点命名采用集群名称作为前缀,后接-,再接一个整数序号(建议从0开始分配,与k8s保持一致)
  • 因为Pigsty采用独占式部署,节点与实例一一对应。则实例命名可与节点命名保持一致,即${cluster}-${seq}的方式。
  • 服务命名亦采用集群名称作为前缀,后接-连接服务具体内容,如primary, replica,offline,delayed等。

entity-naming.png

以上图为例,用于测试的数据库集群名为“pg-test”,该集群由一主两从三个数据库服务器实例组成,部署在集群所属的三个节点上。pg-test集群集群对外提供两种服务,读写服务pg-test-primary与只读副本服务pg-test-replica

实体

在Postgres集群管理中,有如下实体概念:

集群(Cluster)

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

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

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

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

节点(Node)

节点是对硬件资源的一种抽象,通常指代一台工作机器,无论是物理机(bare metal)还是虚拟机(vm),或者是k8s中的Pod。这里注意k8s中Node是硬件资源的抽象,但在实际管理使用上,是k8s中的Pod而不是Node更类似于这里Node概念。总之,节点的关键要素是:

  • 节点是硬件资源的抽象,可以运行一系列的软件服务
  • 节点可以使用IP地址作为唯一标识符

尽管可以使用lan_ip地址作为节点唯一标识符,但为了便于管理,节点应当拥有一个人类可读的充满意义的名称作为节点的Hostname,作为另一个常用的节点唯一标识。

服务(Service)

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

  • 可以寻址访问的服务名称,用于对外提供接入,例如:
    • 一个DNS域名(pg-test-primary
    • 一个Nginx/Haproxy Endpoint
  • 服务流量路由解析与负载均衡机制,用于决定哪个实例负责处理请求,例如:
    • DNS L7:DNS解析记录
    • HTTP Proxy:Nginx/Ingress L7:Nginx Upstream配置
    • TCP Proxy:Haproxy L4:Haproxy Backend配置
    • Kubernetes:Ingress:Pod Selector 选择器

同一个数据集簇中通常包括主库与从库,两者分别提供读写服务(primary)和只读副本服务(replica)。

实例(Instance)

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

  • 可以通过IP:Port唯一标识
  • 具有处理请求的能力

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

实例隶属于集群,每个实例在集群范围内都有着自己的唯一标识用于区分。

实例由服务负责解析,实例提供被寻址的能力,而Service将请求流量解析到具体的实例组上。

命名规则

一个对象可以有很多组标签(Tag)与元数据(Metadata/Annotation),但通常只能有一个名字(Name)

管理数据库和软件与管理宠物类似,都需要花心思照顾。而起名字就是其中非常重要的一项工作。肆意的名字(例如 XÆA-12,NULL,史珍香)很可能会引入不必要的麻烦(额外复杂度),而设计得当的名字则可能会有意想不到的惊喜效果。

总体而言,对象起名应当遵循一些原则:

  • 简洁直白,人类可读:名字是给人看的,因此要好记,便于使用。

  • 体现功能,反映特征:名字需要反映对象的关键特征

  • 独一无二,唯一标识:名字在命名空间内,自己的类目下应当是独一无二,可以惟一标识寻址的。

  • 不要把太多无关的东西塞到名字里去:在名字中嵌入很多重要元数据是一个很有吸引力的想法,但维护起来会非常痛苦,例如反例:pg:user:profile:10.11.12.13:5432:replica:13

集群命名

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

集群命名的形式,建议采用符合DNS标准 RFC1034 的命名规则,以免给后续改造埋坑。例如哪一天想要搬到云上去,发现以前用的名字不支持,那就要再改一遍名,成本巨大。

我认为更好的方式是采用更为严格的限制:集群的名称不应该包括点(dot)。应当仅使用小写字母,数字,以及减号连字符(hyphen)-。这样,集群中的所有对象都可以使用这个名称作为前缀,用于各种各样的地方,而不用担心打破某些约束。即集群命名规则为:

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

之所以强调不要在集群名称中用,是因为以前很流行一种命名方式,例如com.foo.bar。即由点分割的层次结构命名法。这种命名方式虽然简洁名快,但有一个问题,就是用户给出的名字里可能有任意多的层次,数量不可控。如果集群需要与外部系统交互,而外部系统对于命名有一些约束,那么这样的名字就会带来麻烦。一个最直观的例子是K8s中的Pod,Pod的命名规则中不允许出现.

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

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

比如:pg-test-tt就表示tt 业务线下的test集群,类型为pgpg-user-fin表示fin业务线下的user服务。

节点命名

节点命名建议采用与k8s Pod一致的命名规则,即

<cluster_name>-<seq>

Node的名称会在集群资源分配阶段确定下来,每个节点都会分配到一个序号${seq},从0开始的自增整型。这个与k8s中StatefulSet的命名规则保持一致,因此能够做到云上云下一致管理。

例如,集群pg-test有三个节点,那么这三个节点就可以命名为:

pg-test-1, pg-test-2pg-test-3

节点的命名,在整个集群的生命周期中保持不变,便于监控与管理。

实例命名

对于数据库来说,通常都会采用独占式部署方式,一个实例占用整个机器节点。PG实例与Node是一一对应的关系,因此可以简单地采用Node的标识符作为Instance的标识符。例如,节点pg-test-1上的PG实例名即为:pg-test-1,以此类推。

采用独占部署的方式有很大优势,一个节点即一个实例,这样能最小化管理复杂度。混部的需求通常来自资源利用率的压力,但虚拟机或者云平台可以有效解决这种问题。通过vm或pod的抽象,即使是每个redis(1核1G)实例也可以有一个独占的节点环境。

作为一种约定,每个集群中的0号节点(Pod),会作为默认主库。因为它是初始化时第一个分配的节点。

服务命名

通常来说,数据库对外提供两种基础服务:primary 读写服务,与replica只读副本服务。

那么服务就可以采用一种简单的命名规则:

<cluster_name>-<service_name>

例如这里pg-test集群就包含两个服务:读写服务pg-test-primary与只读副本服务pg-test-replica

一种流行的实例/节点命名规则:<cluster_name>-<service_role>-<sequence>,即把数据库的主从身份嵌入到实例名称中。这种命名方式有好处也有坏处。好处是管理的时候一眼就能看出来哪一个实例/节点是主库,哪些是从库。缺点是一但发生Failover,实例与节点的名称必须进行调整才能维持一执性,这就带来的额外的维护工作。此外,服务与节点实例是相对独立的概念,这种Embedding命名方式扭曲了这一关系,将实例唯一隶属至服务。但复杂的场景下这一假设可能并不满足。例如,集群可能有几种不同的服务划分方式,而不同的划分方式之间很可能会出现重叠。

  • 可读从库(解析至包含主库在内的所有实例)
  • 同步从库(解析至采用同步提交的备库)
  • 延迟从库,备份实例(解析至特定具体实例)

因此不要把服务角色嵌入实例名称,而是在服务中维护目标实例列表。毕竟名字并非全能,不要把太多非必要的信息嵌入到对象名称中。

7.1.5 - PostgreSQL 业务用户

业务用户是由CREATE USER/ROLE创建的顶层对象,本文介绍如何定义与创建Pigsty中的业务用户

在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          # 使用空密码

7.1.6 - PostgreSQL 业务数据库

业务数据库是由CREATE DATABASE创建的顶层抽象对象,本文介绍如何定义与创建Pigsty中的业务数据库

这里的 数据库(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

7.1.7 - PostgreSQL 服务

服务(Service)提供了对数据库功能与访问方式的抽象:例如只读、读写、同步读取、离线跑批,走连接池等

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

单机用户

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

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

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

psql postgres://dbuser_dba:DBUser.DBA@10.10.10.10/meta         # 默认超级用户 直连
psql postgres://dbuser_meta:DBUser.Meta@10.10.10.10/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)的私有实现。两者相互等效,各有优势。详情请参考接入一节。

7.1.8 - PostgreSQL 接入

接入(Access)解决客户端如何稳定地访问正确PostgreSQL服务的问题,Pigsty默认使用L2 VIP + HAProxy接入。

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

个人用户可直接用连接串 postgres://dbuser_dba:DBUser.DBA@10.10.10.10: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://test@10.10.10.3:5432/test            # L2 VIP -> 主库直连
postgres://test@10.10.10.3:6432/test            # L2 VIP -> 主库连接池 -> 主库
postgres://test@10.10.10.3:5433/test            # L2 VIP -> HAProxy -> 主库连接池 -> 主库
postgres://test@10.10.10.3:5434/test            # L2 VIP -> HAProxy -> 从库连接池 -> 从库
postgres://dbuser_dba@10.10.10.3:5436/test      # L2 VIP -> HAProxy -> 主库直连(管理用)
postgres://dbuser_stats@10.10.10.3::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://test@10.10.10.11:5432/test           # 数据库实例直连 (直接指定实例,无自动流量分发)
postgres://test@10.10.10.11:6432/test           # 连接池 -> 数据库
postgres://test@10.10.10.11:5433/test           # HAProxy -> 连接池 -> 数据库读写
postgres://test@10.10.10.11:5434/test           # HAProxy -> 连接池 -> 数据库只读
postgres://dbuser_dba@10.10.10.11:5436/test     # HAProxy -> 数据库直连
postgres://dbuser_stats@10.10.10.11:5438/test   # HAProxy -> 数据库离线读写

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

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

# 智能客户端自动读写分离(数据库)
postgres://test@10.10.10.11:5432,10.10.10.12:5432,10.10.10.13:5432/test?target_session_attrs=primary
postgres://test@10.10.10.11: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接入

方案优越性

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

方案局限性

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

7.1.9 - PostgreSQL 角色体系

Pigsty的默认角色体系包含四个默认角色,以及四个默认用户,涵盖了基础的访问控制需求。

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 角色,部分监控系统功能会不可用。

7.1.10 - PostgreSQL 认证与HBA

认证是数据库验证来访连接身份的过程。Pigsty默认使用PG的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

7.1.11 - PostgreSQL ACL权限

Pigsty提供一套开箱即用的ACL模型,可以对读、写、DDL、离线访问进行区分,满足基本访问控制需求。

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_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 </