- 数据库主机上按实例运行 prometheus-community/postgres_exporter 0.20.1, 以实例 OS 用户走本地 socket,经 peer + ident 映射到仅有 pg_monitor 的 homelab_monitor 角色;无密码、不经 Bao。版本与官方 sha256sums.txt 同源。 - prod/dev 启用 pg_stat_statements;monitoring.yml 仅在未生效时 reload/重启 (prod 走 Patroni pending restart),重复执行 changed=0。 - 告警以上游 postgres_mixin 为底改写为 PrometheusRule,阈值对齐 Patroni failover lag 与 max_slot_wal_keep_size;抓取目标带 env 标签。 - Alertmanager 新增 env="dev" 路由到独立 dev 频道,dev SQL 检查告警补 env。 Co-Authored-By: Claude Opus 5.5 <[email protected]>
62 lines
2.8 KiB
YAML
62 lines
2.8 KiB
YAML
---
|
|
- name: 设置现有实例路径
|
|
ansible.builtin.set_fact:
|
|
pg_profile: "{{ pg_profiles[pg_instance] }}"
|
|
pg_config_dir: "{{ pg_config_root }}/{{ pg_instance }}"
|
|
pg_parent_dir: "{{ pg_data_root }}/{{ pg_instance }}"
|
|
pg_socket_dir: "/run/homelab-postgresql-{{ pg_instance }}"
|
|
pg_psql: ["{{ pg_bin_dir }}/psql", -X, -At, -v, ON_ERROR_STOP=1, -h, "/run/homelab-postgresql-{{ pg_instance }}",
|
|
-p, "{{ pg_profiles[pg_instance].port | string }}", -d, postgres]
|
|
# 角色与扩展只在可写实例上创建,standby 经复制获得。
|
|
- name: 检查监控角色与扩展是否符合声明
|
|
ansible.builtin.command:
|
|
argv: "{{ pg_psql + ['-c', pg_monitor_check] }}"
|
|
vars:
|
|
pg_monitor_check: >-
|
|
SELECT pg_is_in_recovery(),
|
|
COALESCE((SELECT rolcanlogin AND NOT rolsuper AND NOT rolcreaterole AND NOT rolcreatedb
|
|
AND NOT rolreplication AND NOT rolbypassrls AND rolconnlimit = 3 AND rolpassword IS NULL
|
|
AND pg_has_role(oid, 'pg_monitor', 'MEMBER')
|
|
FROM pg_authid WHERE rolname = '{{ pg_monitor_user }}'), false)
|
|
AND EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'pg_stat_statements')
|
|
become: true
|
|
become_user: "{{ pg_profile.user }}"
|
|
changed_when: false
|
|
register: pg_monitor_role
|
|
- name: 创建或修正监控角色(无密码,仅能经本地 ident 映射登录)
|
|
ansible.builtin.command:
|
|
argv: "{{ pg_psql }}"
|
|
stdin: |
|
|
SELECT 'CREATE ROLE {{ pg_monitor_user }}'
|
|
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '{{ pg_monitor_user }}') \gexec
|
|
ALTER ROLE {{ pg_monitor_user }} LOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS
|
|
CONNECTION LIMIT 3 PASSWORD NULL;
|
|
GRANT pg_monitor TO {{ pg_monitor_user }};
|
|
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
|
|
become: true
|
|
become_user: "{{ pg_profile.user }}"
|
|
when: pg_monitor_role.stdout == 'f|f'
|
|
changed_when: true
|
|
- name: 安装实例 exporter 服务
|
|
ansible.builtin.template:
|
|
src: postgres-exporter.service.j2
|
|
dest: "/etc/systemd/system/homelab-postgresql-{{ pg_instance }}-exporter.service"
|
|
mode: '0644'
|
|
register: pg_exporter_unit
|
|
- name: 启用 exporter
|
|
ansible.builtin.systemd_service:
|
|
name: "homelab-postgresql-{{ pg_instance }}-exporter.service"
|
|
daemon_reload: "{{ pg_exporter_unit is changed }}"
|
|
enabled: true
|
|
state: "{{ 'restarted' if pg_exporter_unit is changed else 'started' }}"
|
|
# 同时证明 HBA/ident 已加载、角色可登录、exporter 能查询。
|
|
- name: 检查 exporter 已连上数据库
|
|
ansible.builtin.uri:
|
|
url: "http://{{ pg_address }}:{{ pg_profile.exporter_port }}/metrics"
|
|
return_content: true
|
|
register: pg_exporter_metrics
|
|
changed_when: false
|
|
retries: 10
|
|
delay: 3
|
|
until: pg_exporter_metrics.status == 200 and pg_exporter_metrics.content is search('(?m)^pg_up 1$')
|