修正 monitoring.yml 的 check 模式与 Patroni pending 判断
只读探测在 check 模式下照常执行;依赖真实执行结果的等待与验证在 check 模式跳过。 patronictl JSON 会省略空值字段,pending 判断先检查键是否存在。 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -23,27 +23,30 @@
|
|||||||
vars:
|
vars:
|
||||||
pg_patronictl: [/opt/homelab-patroni/bin/patronictl, -c, "{{ pg_config_root }}/prod/patroni.yml"]
|
pg_patronictl: [/opt/homelab-patroni/bin/patronictl, -c, "{{ pg_config_root }}/prod/patroni.yml"]
|
||||||
tasks:
|
tasks:
|
||||||
|
# JSON 输出会省略空值字段:没有 pending 的成员不带 "Pending restart" 键。
|
||||||
- name: 读取集群成员状态
|
- name: 读取集群成员状态
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
argv: "{{ pg_patronictl + ['list', '-e', '-f', 'json'] }}"
|
argv: "{{ pg_patronictl + ['list', '-f', 'json'] }}"
|
||||||
register: pg_members
|
register: pg_members
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
check_mode: false
|
||||||
# Patroni 在原位重启 primary,不触发 failover;写入会短暂中断,客户端需重试。
|
# Patroni 在原位重启 primary,不触发 failover;写入会短暂中断,客户端需重试。
|
||||||
- name: 仅重启 pending restart 的成员
|
- name: 仅重启 pending restart 的成员
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
argv: "{{ pg_patronictl + ['restart', 'pg-prod', '--pending', '--force'] }}"
|
argv: "{{ pg_patronictl + ['restart', 'pg-prod', '--pending', '--force'] }}"
|
||||||
when: pg_members.stdout | from_json | selectattr('Pending restart', 'equalto', '*') | list | length > 0
|
when: pg_members.stdout | from_json | selectattr('Pending restart', 'defined') | selectattr('Pending restart', 'equalto', '*') | list | length > 0
|
||||||
changed_when: true
|
changed_when: true
|
||||||
- name: 等待两个成员恢复且无 pending
|
- name: 等待两个成员恢复且无 pending
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
argv: "{{ pg_patronictl + ['list', '-e', '-f', 'json'] }}"
|
argv: "{{ pg_patronictl + ['list', '-f', 'json'] }}"
|
||||||
register: pg_members_after
|
register: pg_members_after
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
when: not ansible_check_mode
|
||||||
retries: 30
|
retries: 30
|
||||||
delay: 4
|
delay: 4
|
||||||
until: >-
|
until: >-
|
||||||
(pg_members_after.stdout | from_json | length) == 2
|
(pg_members_after.stdout | from_json | length) == 2
|
||||||
and (pg_members_after.stdout | from_json | selectattr('Pending restart', 'equalto', '*') | list | length) == 0
|
and (pg_members_after.stdout | from_json | selectattr('Pending restart', 'defined') | selectattr('Pending restart', 'equalto', '*') | list | length) == 0
|
||||||
and (pg_members_after.stdout | from_json | selectattr('State', 'in', ['running', 'streaming']) | list | length) == 2
|
and (pg_members_after.stdout | from_json | selectattr('State', 'in', ['running', 'streaming']) | list | length) == 2
|
||||||
|
|
||||||
- name: 创建监控角色并安装 exporter
|
- name: 创建监控角色并安装 exporter
|
||||||
@@ -69,6 +72,8 @@
|
|||||||
dest: /opt
|
dest: /opt
|
||||||
remote_src: true
|
remote_src: true
|
||||||
creates: /opt/postgres_exporter-{{ pg_exporter_version }}.linux-amd64/postgres_exporter
|
creates: /opt/postgres_exporter-{{ pg_exporter_version }}.linux-amd64/postgres_exporter
|
||||||
|
# check 模式不下载,首次时没有可解压的文件。
|
||||||
|
when: not (ansible_check_mode and pg_exporter_download is changed)
|
||||||
- name: 逐实例配置
|
- name: 逐实例配置
|
||||||
ansible.builtin.include_tasks: tasks/monitoring-exporter.yml
|
ansible.builtin.include_tasks: tasks/monitoring-exporter.yml
|
||||||
loop: "{{ pg_instances }}"
|
loop: "{{ pg_instances }}"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
argv: [systemctl, is-active, "homelab-postgresql-{{ pg_instance }}.service"]
|
argv: [systemctl, is-active, "homelab-postgresql-{{ pg_instance }}.service"]
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
check_mode: false
|
||||||
# 生产:Patroni 只在自身 reload 时把本地配置写成数据目录里的 postgresql.conf/pg_ident.conf,
|
# 生产:Patroni 只在自身 reload 时把本地配置写成数据目录里的 postgresql.conf/pg_ident.conf,
|
||||||
# 所以文件视图能说明 Patroni 是否已接收新配置;预加载库是否已生效另看 current_setting。
|
# 所以文件视图能说明 Patroni 是否已接收新配置;预加载库是否已生效另看 current_setting。
|
||||||
# dev:ident_file 是 postmaster 级参数,视图读取的是“当前生效”的那个文件,
|
# dev:ident_file 是 postmaster 级参数,视图读取的是“当前生效”的那个文件,
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
become: true
|
become: true
|
||||||
become_user: "{{ pg_profile.user }}"
|
become_user: "{{ pg_profile.user }}"
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
check_mode: false
|
||||||
register: pg_monitor_state
|
register: pg_monitor_state
|
||||||
- name: 让 Patroni 接收新的本地配置(reload,不重启)
|
- name: 让 Patroni 接收新的本地配置(reload,不重启)
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
@@ -45,7 +47,7 @@
|
|||||||
argv: "{{ pg_monitor_state.cmd }}"
|
argv: "{{ pg_monitor_state.cmd }}"
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ pg_profile.user }}"
|
become_user: "{{ pg_profile.user }}"
|
||||||
when: pg_instance == 'prod' and pg_monitor_state.stdout.split('|')[0] != 't'
|
when: pg_instance == 'prod' and pg_monitor_state.stdout.split('|')[0] != 't' and not ansible_check_mode
|
||||||
changed_when: false
|
changed_when: false
|
||||||
register: pg_monitor_reloaded
|
register: pg_monitor_reloaded
|
||||||
retries: 10
|
retries: 10
|
||||||
@@ -62,7 +64,7 @@
|
|||||||
argv: "{{ pg_monitor_state.cmd }}"
|
argv: "{{ pg_monitor_state.cmd }}"
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ pg_profile.user }}"
|
become_user: "{{ pg_profile.user }}"
|
||||||
when: pg_instance == 'dev'
|
when: pg_instance == 'dev' and not ansible_check_mode
|
||||||
changed_when: false
|
changed_when: false
|
||||||
register: pg_monitor_dev
|
register: pg_monitor_dev
|
||||||
retries: 10
|
retries: 10
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
become: true
|
become: true
|
||||||
become_user: "{{ pg_profile.user }}"
|
become_user: "{{ pg_profile.user }}"
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
check_mode: false
|
||||||
register: pg_monitor_role
|
register: pg_monitor_role
|
||||||
- name: 创建或修正监控角色(无密码,仅能经本地 ident 映射登录)
|
- name: 创建或修正监控角色(无密码,仅能经本地 ident 映射登录)
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
@@ -49,6 +50,8 @@
|
|||||||
daemon_reload: "{{ pg_exporter_unit is changed }}"
|
daemon_reload: "{{ pg_exporter_unit is changed }}"
|
||||||
enabled: true
|
enabled: true
|
||||||
state: "{{ 'restarted' if pg_exporter_unit is changed else 'started' }}"
|
state: "{{ 'restarted' if pg_exporter_unit is changed else 'started' }}"
|
||||||
|
# check 模式下 unit 文件尚未写入,systemd 找不到服务。
|
||||||
|
when: not (ansible_check_mode and pg_exporter_unit is changed)
|
||||||
# 同时证明 HBA/ident 已加载、角色可登录、exporter 能查询。
|
# 同时证明 HBA/ident 已加载、角色可登录、exporter 能查询。
|
||||||
- name: 检查 exporter 已连上数据库
|
- name: 检查 exporter 已连上数据库
|
||||||
ansible.builtin.uri:
|
ansible.builtin.uri:
|
||||||
@@ -56,6 +59,7 @@
|
|||||||
return_content: true
|
return_content: true
|
||||||
register: pg_exporter_metrics
|
register: pg_exporter_metrics
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
when: not ansible_check_mode
|
||||||
retries: 10
|
retries: 10
|
||||||
delay: 3
|
delay: 3
|
||||||
until: pg_exporter_metrics.status == 200 and pg_exporter_metrics.content is search('(?m)^pg_up 1$')
|
until: pg_exporter_metrics.status == 200 and pg_exporter_metrics.content is search('(?m)^pg_up 1$')
|
||||||
|
|||||||
Reference in New Issue
Block a user