告警规则

    Pigsty有两套并行的告警系统:

    两套系统功能等效,侧重能力不同,可同时使用,互为备份补充。

    告警对于日常故障响应,提高系统可用性至关重要。

    漏报会导致可用性降低,误报会导致敏感性下降,有必要对告警规则进行审慎的设计。

    • 合理定义告警级别,以及相应的处理流程
    • 合理定义告警指标,去除重复告警项,补充缺失告警项
    • 根据历史监控数据科学配置告警阈值,减少误报率。
    • 合理疏理特例规则,消除维护工作,ETL,离线查询导致的误报。

    告警分类学

    按照来源模块分类

    • :基础设施类告警:Prometheus,Grafana,Consul,DNS,Nginx等基础设施软件等产生的告警。
    • NODES:主机节点告警,操作系统,硬件资源,基础设施软件,负载均衡等告警,通常由运维人员负责处理。
    • PGSQL:PostgreSQL数据库告警,数据库/连接池/负载均衡集群本身的告警,通常研发与DBA关注,DBA处理。
    • REDIS:Redis数据库告警,研发与DBA关注,DBA处理。
    • ……:应用板块告警,用告警由业务方自己负责,但DBA会为QPS,TPS,Rollback,Seasonality等业务指标设置告警
    • Pigsty使用category标签{infra,pgsql,nodes,redis,....}来标识告警的层次。

    按紧急程度分类

    • P0:CRIT:产生重大场外影响的事故,需要紧急介入处理。例如主库宕机,复制中断。(事故)
    • P1:WARN:场外影响轻微,或有冗余处理的事故,需要在分钟级别内进行响应处理。(警告)
    • P2:INFO:即将产生影响,放任可能在小时级别内恶化,需在小时级别进行响应。(事件)
    • Pigsty使用与severity标签{CRIT,WARN,INFO}来标识告警的紧急程度。

    按指标类型分类

    • 错误:PG Down, PGB Down, Exporter Down, 流复制中断,单集簇多主
    • 流量:QPS,TPS,Rollback,Seasonaility
    • 延迟: 平均响应时间,复制延迟
    • 饱和度:连接堆积,闲事务数,CPU,磁盘,年龄(事务号),缓冲区

    在各类监控面板中,Pigsty使用时间轴状态图呈现告警信息。横轴代表时间段,一段色条代表告警事件。只有处于 激发(Firing) 状态的告警才会显示在告警图表中,处于Pending状态的告警通常会隐藏或以灰色显示。

    告警规则

    告警规则按类型可粗略分为四类:错误,延迟,饱和度,流量。其中:

    • 错误:主要关注各个组件的存活性(Aliveness),以及网络中断,脑裂等异常情况,级别通常较高(P0|P1)。
    • 延迟:主要关注查询响应时间,复制延迟,慢查询,长事务。
    • 饱和度:主要关注CPU,磁盘(这两个属于系统监控但对于DB非常重要所以纳入),连接池排队,数据库后端连接数,年龄(本质是可用事物号的饱和度),SSD寿命等。
    • 流量:QPS,TPS,Rollback(流量通常与业务指标有关属于业务监控范畴,但因为对于DB很重要所以纳入),QPS的季节性,TPS的突增。

    告警规则使用Prometheus语法定义,完整的告警规则详见:

    Pigsty典型告警

    在生产环境使用PostgreSQL时,Pgbouncer实例与Postgres是一一对应的命运共同体,Pgbouncer故障效果基本与Postgres故障等同,其存活性告警规则级别与Postgres统一。

    1. # database connection pool down
    2. - alert: PgbouncerDown
    3. expr: pgbouncer_up < 1
    4. for: 1m
    5. labels: { level: 0, severity: CRIT, category: pgsql }
    6. annotations:
    7. summary: "CRIT PostgresDown {{ $labels.ins }}@{{ $labels.instance }}"
    8. pgbouncer_up[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value }} < 1
    9. http://g.pigsty/d/pgsql-instance?var-ins={{ $labels.ins }}

    监控代理Exporter宕机通常预示着严重故障:HAProxy 与Node Exporter宕机通常意味着负载均衡器与数据库节点本身宕机,需要重点关注

    1. #==============================================================#
    2. # Agent Aliveness #
    3. #==============================================================#
    4. # node & haproxy aliveness are determined directly by exporter aliveness
    5. # including: node_exporter, pg_exporter, pgbouncer_exporter, haproxy_exporter
    6. - alert: AgentDown
    7. expr: agent_up < 1
    8. for: 1m
    9. labels: { level: 0, severity: CRIT, category: infra }
    10. annotations:
    11. summary: 'CRIT AgentDown {{ $labels.ins }}@{{ $labels.instance }}'
    12. description: |
    13. agent_up[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value | printf "%.2f" }} < 1
    14. http://g.pigsty/d/pgsql-alert?viewPanel=22

    所有存活性检测的持续时间阈值设定为1分钟,对15s的采集周期通常意味着连续4次探活失败。常规的快速重启操作通常不会触发存活性告警。

    集群脑裂分区

    一个数据库集群,应当有且仅有一个主库领导者实例。即集群正常情况下应当只有一个分区。如果集群的分区数量不为1(为0代表群龙无首,大于1代表群雄逐鹿)则代表集群进入了异常状态:不可写入或脑裂,会立即触发P0报警。因为检测阈值为1分钟,所以常规的Failover与Switchover通常不容易触发此告警。

    与复制延迟有关的告警有二个:复制中断,复制延迟高,定级为P1警告。

    • 其中复制中断是一种错误,使用指标:pg_downstream_count{state="streaming"}进行判断,当前streaming状态的从库如果数量发生负向变动,则触发break告警。walsender会决定复制的状态,从库直接断开会产生此现象,缓冲区出现积压时会从streaming进入状态也会触发此告警。此外,采用-Xs手工制作备份结束时也会产生此告警,此告警会在5分钟后自动Resolve。复制中断会导致客户端读到陈旧的数据,具有一定的场外影响,定级为P1。

    • 复制延迟可以使用延迟时间或者延迟字节数判定。以延迟字节数为权威指标。常规状态下,复制延迟时间在百毫秒量级,复制延迟字节在百KB量级均属于正常。根据历史经验数据,目前采用的是1MB与1s的时间告警阈值。

    1. #==============================================================#
    2. # Replication #
    3. #==============================================================#
    4. # replication break for 1m triggers a P1 alert (WARN: heal in 5m)
    5. - alert: PostgresReplicationBreak
    6. expr: changes(pg_downstream_count{state="streaming"}[5m]) > 0
    7. # for: 1m
    8. labels: { level: 1, severity: WARN, category: pgsql }
    9. annotations:
    10. summary: "WARN PostgresReplicationBreak: {{ $labels.ins }}@{{ $labels.instance }}"
    11. description: |
    12. changes(pg_downstream_count{ins={{ $labels.ins }}, instance={{ $labels.instance }}, state="streaming"}[5m]) > 0
    13. # replication lag bytes > 1MiB or lag seconds > 1s
    14. - alert: PostgresReplicationLag
    15. expr: pg:ins:lag_bytes > 1048576 or pg:ins:lag_seconds > 1
    16. for: 1m
    17. labels: { level: 1, severity: WARN, category: pgsql }
    18. annotations:
    19. summary: "WARN PostgresReplicationLag: {{ $labels.ins }}@{{ $labels.instance }}"
    20. description: |
    21. pg:ins:lag_bytes[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value | printf "%.0f" }} > 1048576 or
    22. pg:ins:lag_seconds[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value | printf "%.2f" }} > 1

    此外,查询延迟与磁盘延迟也有相应的报警规则:

    例如,磁盘读写平均响应时间持续一分钟超过32ms,或Pgbouncer中平均查询RT超过16ms均会触发P1告警。

    1. # read latency > 32ms (typical on pci-e ssd: 100µs)
    2. expr: node:dev:disk_read_rt_1m > 0.032 or node:dev:disk_write_rt_1m > 0.032
    3. for: 1m
    4. labels: { level: 1, severity: WARN, category: node }
    5. annotations:
    6. summary: 'WARN NodeReadSlow {{ $labels.ins }}@{{ $labels.instance }} {{ $value | printf "%.6f" }}'
    7. description: |
    8. node:dev:disk_read_rt_1m[ins={{ $labels.ins }}] = {{ $value | printf "%.6f" }} > 32ms
    9. # pgbouncer avg response time > 16ms (database level)
    10. - alert: PgbouncerQuerySlow
    11. expr: pgbouncer:db:query_rt_1m > 0.016
    12. for: 3m
    13. labels: { level: 1, severity: WARN, category: pgsql }
    14. annotations:
    15. summary: "WARN PgbouncerQuerySlow: {{ $labels.ins }}@{{ $labels.instance }} [{{ $labels.datname }}]"
    16. description: |
    17. pgbouncer:db:query_rt_1m[ins={{ $labels.ins }}, instance={{ $labels.instance }}, datname={{ $labels.datname }}] = {{ $value | printf "%.3f" }} > 0.016

    饱和度指标主要资源,包含很多系统级监控的指标。主要包括:CPU,磁盘(这两个属于系统监控但对于DB非常重要所以纳入),连接池排队,数据库后端连接数,年龄(本质是可用事物号的饱和度),SSD寿命等。

    数据库压力是:机器CPU使用率,Pgbouncer时间利用率,Postgres时间利用率(14引入)的综合最大值(百分比,但过载时可以超过100%)。压力是Pigsty中最重要的指标,集中体现了数据库实例与集群的负载水位。

    堆积检测

    堆积主要包含两类指标,一方面是PG本身的后端连接数与活跃连接数,另一方面是连接池的排队情况。

    PGB排队是决定性的指标,它代表用户端可感知的阻塞已经出现,因此出现排队持续1分钟触发P0告警。

    当使用Session Pooling模式时,可适当放宽此报警指标。

    1. # pgbouncer client queue exists
    2. - alert: PgbouncerClientQueue
    3. expr: pgbouncer:db:waiting_clients > 1
    4. for: 1m
    5. labels: { level: 0, severity: CRIT, category: pgsql }
    6. annotations:
    7. summary: "CRIT PgbouncerClientQueue: {{ $labels.ins }}@{{ $labels.instance }} [{{ $labels.datname }}]"
    8. description: |
    9. pgbouncer:db:waiting_clients[ins={{ $labels.ins }}, instance={{ $labels.instance }}, datname={{ $labels.datname }}] = {{ $value | printf "%.0f" }} > 1

    后端连接数是一个重要的告警指标,如果后端连接持续达到最大连接数,往往也意味着雪崩。连接池的排队连接数也能反映这种情况,但不能覆盖应用直连数据库的情况。

    目前,Pigsty使用连接使用率作为告警指标,即数据库可用连接数量已经使用的百分比,超过70%持续3分钟即出发P1告警。

    1. # database connection usage > 70%
    2. - alert: PostgresConnUsageHigh
    3. expr: pg:db:conn_usage > 0.70
    4. for: 3m
    5. labels: { level: 1, severity: WARN, category: pgsql }
    6. annotations:
    7. summary: "WARN PostgresConnUsageHigh: {{ $labels.ins }}@{{ $labels.instance }} [{{ $labels.datname }}]"
    8. description: |
    9. pg:db:conn_usage[ins={{ $labels.ins }}, instance={{ $labels.instance }}, datname={{ $labels.datname }}] = {{ $value | printf "%.3f" }} > 0.70

    空闲事务

    即数据库出现Idle in Transaction状态的连接数量,超过2条持续3分钟即出发P1告警。

    资源告警

    年龄(XID)使用量超过80%出发P0告警,这意味着系统快要消耗完事务号资源,进入XID Wraparound状态

    1. # database age saturation > 80%
    2. - alert: PostgresXidWarpAround
    3. expr: pg:db:age > 0.80
    4. for: 1m
    5. labels: { level: 0, severity: CRIT, category: pgsql }
    6. annotations:
    7. summary: "CRIT PostgresXidWarpAround: {{ $labels.ins }}@{{ $labels.instance }} [{{ $labels.datname }}]"
    8. description: |