1. 课程导入与运维自动化全景

PostgreSQL 在生产环境中往往不是“装好就完事”的数据库。随着实例数量增长、业务表持续膨胀、备份窗口被压缩、慢查询和锁等待频繁出现,DBA 与运维工程师每天面对的是大量重复、可预期、但又必须准确执行的任务:备份与恢复演练、VACUUM 与膨胀治理、索引重建、统计信息更新、连接数巡检、复制延迟监控、参数变更与回滚。自动化运维的核心目标,就是把这些任务从“依赖个人记忆和手工敲命令”转变为“可描述、可执行、可观测、可回滚”的工程化流程。

需要先明确一个边界:自动化不等于无人值守,也不等于把所有操作都写成脚本。任务治理关注的是“哪些任务值得自动化、以什么频率执行、失败后如何处置、变更如何审计”。一个典型的判断标准是:如果一个任务每周重复三次以上、步骤固定、结果可验证、失败影响可评估,它就适合进入自动化清单;反之,涉及大版本升级、存储引擎级变更、跨机房切换等高风险操作,更适合做成“半自动化 + 人工确认”的流程。

自动化运维的三层目标:
第一层,可重复——同一任务在任何时间、任何实例上执行结果一致;
第二层,可观测——每次执行都有日志、指标和退出状态;
第三层,可治理——任务有负责人、有审批、有回滚方案、有历史记录。

本课程使用的工具链围绕 PostgreSQL 生态展开,不追求“大而全”,而是选择能直接落地、便于验证的组合。数据库侧以 PostgreSQL 15/16 为主,配合 pg_stat_statements、pg_stat_activity、pg_stat_user_tables 等内置视图;操作系统侧使用 Linux(Ubuntu 22.04 或 Rocky Linux 9 均可),依赖 systemd 管理服务、cron 与 systemd timer 调度任务;脚本层以 Bash 和 Python 为主,Python 使用 psycopg2 或 psycopg 连接数据库;配置管理与编排可选用 Ansible;监控与告警使用 Prometheus + postgres_exporter + Grafana;备份工具使用 pg_basebackup、pg_dump 与 pgBackRest 中的一种或多种组合。

实验环境建议采用“单机多实例 + 容器辅助”的方式搭建,既节省资源,又能模拟真实的多实例管理场景。下面给出一个可复现的初始化示例,假设使用 Ubuntu 22.04,安装 PostgreSQL 16 并创建两个独立实例:

# 安装 PostgreSQL 16(示例,实际以官方源为准)
sudo apt update
sudo apt install -y postgresql-16 postgresql-client-16

# 创建第二个实例的数据目录
sudo mkdir -p /var/lib/postgresql/16/secondary
sudo chown -R postgres:postgres /var/lib/postgresql/16/secondary

# 初始化第二个实例
sudo -u postgres /usr/lib/postgresql/16/bin/initdb \
  -D /var/lib/postgresql/16/secondary \
  --encoding=UTF8 --locale=C

# 修改端口,避免与主实例冲突
sudo -u postgres sed -i "s/^#port = 5432/port = 5433/" \
  /var/lib/postgresql/16/secondary/postgresql.conf

# 启动第二个实例
sudo -u postgres /usr/lib/postgresql/16/bin/pg_ctl \
  -D /var/lib/postgresql/16/secondary -l /tmp/pg2.log start

启动后,用 psql -p 5433 -c "select version();" 验证实例可用。此时环境中已有两个独立实例,后续章节中的巡检、备份、参数变更等任务都可以在两个实例上分别执行,便于观察自动化脚本在多目标场景下的行为差异。

为了让后续的自动化任务有统一的观察入口,建议在实验库中预先创建一张任务执行记录表,用于记录每次自动化任务的名称、目标实例、开始时间、结束时间、退出码和简要结果。这张表不是课程要求,但它能让“可观测”这一目标变得具体:

CREATE TABLE ops_task_log (
  id          bigserial PRIMARY KEY,
  task_name   text        NOT NULL,
  target_db   text        NOT NULL,
  started_at  timestamptz NOT NULL DEFAULT now(),
  finished_at timestamptz,
  exit_code   int,
  message     text
);

下面这张图展示了本课程所讨论的自动化运维全景:从任务来源、治理判断、工具链执行,到结果观测与反馈。它不描述某一条具体命令,而是帮助建立“任务—治理—执行—观测”的整体关系,后续章节会分别深入其中的各个环节。

任务来源 日常巡检 连接数 / 膨胀 / 慢查询 备份与恢复 全量 / 增量 / 演练 空间与膨胀治理 VACUUM / 索引重建 参数与变更 配置下发 / 回滚 告警响应 复制延迟 / 锁等待 任务治理判断 是否重复且固定? 频率 ≥ 3 次/周 结果是否可验证? 退出码 / 指标 / 日志 失败影响是否可控? 可回滚 / 可重试 是否有负责人? 审批 / 审计 / 记录 是否高风险? 半自动 + 人工确认 工具链执行 Bash / Python 脚本 psycopg2 / psql cron / systemd timer 定时调度 Ansible 批量配置与编排 pg_basebackup / pgBackRest 备份与恢复 postgres_exporter 指标暴露 观测与反馈 Prometheus 指标采集 Grafana 可视化面板 ops_task_log 执行记录表 告警通道 邮件 / Webhook 复盘与调优 频率 / 阈值调整 反馈:根据观测结果调整任务频率、阈值与自动化范围 PostgreSQL 自动化运维全景

从图中可以看到,任务来源、治理判断、工具链执行和观测反馈构成一个闭环。左侧的任务来源是“输入”,中间的治理判断决定“做不做、怎么做”,右侧的工具链负责“执行”,最右侧的观测与反馈则把执行结果重新送回治理环节。这个闭环的意义在于:自动化不是一次性写完脚本就结束,而是需要根据实际运行数据不断调整任务范围、执行频率和告警阈值。

在实验环境搭建完成后,建议先做一次最小验证:手动执行一条巡检命令,把结果写入 ops_task_log,再用 psql 查询这张表,确认“执行—记录—查询”这条链路是通的。例如:

-- 记录一次巡检任务
INSERT INTO ops_task_log (task_name, target_db, exit_code, message)
VALUES ('daily_check', 'primary:5432', 0, '连接数 42,膨胀率 3.1%');

-- 查看最近任务
SELECT task_name, target_db, started_at, exit_code, message
FROM ops_task_log
ORDER BY started_at DESC
LIMIT 5;

如果这条链路可以稳定运行,后续章节中更复杂的备份、VACUUM、索引重建、参数变更等任务,都可以沿用同样的“执行 + 记录 + 观测”模式。课程后续会逐步展开:如何编写可复用的巡检脚本、如何用 systemd timer 替代 cron 获得更好的日志与依赖管理、如何用 Ansible 批量下发配置、如何用 pgBackRest 做增量备份与恢复演练、如何用 Prometheus 与 Grafana 建立数据库关键指标面板,以及如何在出现复制延迟、锁等待、连接数暴涨时快速定位并处置。

本节的重点不是记住所有工具名称,而是建立三个判断:
1. 这个任务是否值得自动化?
2. 自动化之后,失败了我能不能第一时间知道?
3. 如果执行结果不符合预期,我能不能回滚或重试?
把这三个问题回答清楚,自动化运维就有了可靠的起点。