19.3 操作系统与主机基线
主机调优的最大风险,不是漏掉某个神奇参数,而是不知道当前系统实际是什么, 却批量套用一份来源、版本和目标都不明的模板。
19.3.1 文件系统、挂载、预读与透明大页
文件系统选择是一份兼容与恢复合同
记录:
filesystem type/version
mount source and target
mount options
block/sector size
discard
inode capacity
snapshot/reflink
encryption
quota
repair tooling
backup compatibility选择 XFS、ext4 或其他支持文件系统,要基于目标 OS、存储、运维能力与 PostgreSQL/Pigsty 支持矩阵,不凭论坛结论。
数据、WAL、日志、备份与临时文件的路径
典型职责:
PGDATA
WAL (可能同盘或独立)
tablespaces
PostgreSQL logs
pgBackRest spool/repository
PgBouncer/Patroni logs
temp files (位于 relation tablespace)
monitoring/log storage
package repository分盘不是目的。要问:
- 故障是否独立;
- I/O 是否真正隔离;
- capacity 是否独立;
- backup/restore 是否更复杂;
- mount 缺失时会不会写进 root;
- 监控是否覆盖每个 filesystem;
- 权限和 SELinux/AppArmor 是否一致。
防止“挂载没上,目录还在”
危险场景:
/pg/data intended mount absent
directory exists on root filesystem
PostgreSQL starts and writes root disk
root fills
later mount hides wrong data保护:
systemd RequiresMountsFor
mountpoint validation before service
expected device/filesystem UUID
directory marker
capacity sanity check
monitor filesystem identity, not only path本章 capture 同时记录 target、source、fstype、options 与 free,不只记录
/pg 存在。
mount option 不应照抄
常见选项需要理解:
noatime
discard / periodic fstrim
barrier/durability defaults
inode/allocation
network filesystem sync/cache semantics现代文件系统默认行为会变化。任何影响持久性或恢复的选项,必须有官方 文档、目标版本和故障测试证据。
预读依赖访问形状
OS/block device read-ahead 对顺序扫描可能有益,对随机 OLTP 可能放大无效 I/O。
记录:
lsblk -o NAME,TYPE,ROTA,RA,SIZE,FSTYPE,MOUNTPOINTS
blockdev --getra /dev/...然后用:
OLTP random
analytics sequential
backup/restore stream
replica replay分别测。不要把某 SSD 模板的 KB 值复制到所有设备。
I/O scheduler 也要与设备匹配
物理旋转盘、NVMe、virtio、cloud block 的队列和 scheduler 不同。
采集:
cat /sys/block/<dev>/queue/scheduler
cat /sys/block/<dev>/queue/nr_requests改变前后同时看 workload latency、throughput、queue 和 CPU。
THP 与显式 huge pages
当前值:
grep . /sys/kernel/mm/transparent_hugepage/{enabled,defrag}
grep -i huge /proc/meminfo本章要求 THP never,与 Pigsty node tuning 预期一致。PostgreSQL 官方
Resource Consumption
区分 THP 与显式 huge pages,并指出 THP 对部分 PostgreSQL 环境会造成性能
下降。
显式 huge pages 需要:
shared memory size
page size
nr_hugepages
postgres OS group/lock permissions
startup policy try/on
reboot/fragmentation behavior
monitoring若 huge_pages=on 且数量不足,PostgreSQL 会拒绝启动;这是刻意强约束,
不能未经演练启用。
data directory 权限
PostgreSQL 官方
initdb
要求以最终 server owner 运行,不能 root 运行。目录应由 database OS user
拥有并限制权限。
检查:
namei -l "$PGDATA"
stat -c '%U %G %a %n' "$PGDATA"
findmnt -T "$PGDATA"父目录权限同样重要。不要让普通应用用户读取 data files、WAL 或 backup。
19.3.2 用户、目录、权限、时间同步与日志
OS 身份与数据库身份分开
OS:
admin automation user
postgres service user
backup/repository user
monitoring/log agentsPostgreSQL:
bootstrap superuser
NOLOGIN object owner
runtime roles
monitor/replication/backup/admin roles同名不代表同一身份。Peer authentication 才把 OS user 映射为 database role。
admin user 的前提要验收
Pigsty multi-node 部署需要管理用户可以:
passwordless SSH to targets
passwordless sudo
run Python/Ansible modules
write expected directories
reach package sources/infra这是一项强权限。要用:
dedicated identity
key protection/rotation
source restriction
sudo policy
audit
break-glass
offboarding本章 disposable Vagrant 用 vagrant + nopass sudo,只能在本地 sandbox
接受;production 必须重新设计。
目录清单是接口
记录每个组件:
| 项 | owner/mode | purpose | retention |
|---|---|---|---|
| source/inventory | admin | IaC | versioned/private |
/pg/data | postgres | data | authoritative |
/pg/log | postgres/agents | component logs | policy |
/pg/backup | backup | repository/spool | backup policy |
/etc/patroni | root/postgres | HA config | config |
/etc/pgbouncer | service | pool config | config |
/etc/pgbackrest | controlled | backup config/secret refs | config |
/etc/haproxy | root | routing | config |
不要把目录路径写死进应用;通过 service/config 接口访问。
文件权限要从 threat model 验证
检查:
find ... -maxdepth ... -printf '%m %u %g %p\n'
systemctl cat <service>
systemctl show <service> -p User -p Group -p EnvironmentFiles
getfacl特别关注:
private keys
password/config files
.pgpass / service files
backup cipher pass
Patroni REST credentials
HAProxy stats credentials
MinIO keys
Ansible inventory/vault本章 live inventory 必须 0600,projection 不能含 secret value。
时间同步先于集群判断
chrony/其他 NTP 服务需要:
active
source reachable
synchronized
offset/jitter within policy
boot behavior
monitoring只看 service active 不够;本章读取 timedatectl NTPSynchronized。
时间跳变可能影响日志、lease、TLS、业务 timestamp 与 incident timeline。 数据库业务时间语义仍要用第 16 章的 UTC/event-time 合同。
hostname、machine-id 与 address
基线同时保存:
declared address
live hostname
hashed /etc/machine-id
live interface addresses原因:
- IP 可能被错误复用;
- hostname 可能全部相同;
- SSH config 可能把不同别名指向同一主机;
- VM clone 可能复制 machine-id;
- inventory 拼写可能连错环境。
本章准备部署时就发现,常规 SSH config 把 Vagrant 地址重写为本地转发端口;
只看命令参数不够。正式采集强制 ssh -F /dev/null 直连,并以 machine-id
hash 证明四个目标不同。
hash 不让 evidence 暴露原始 machine-id,但仍能检测重复。
日志要有来源身份
每条集中日志至少关联:
timestamp + timezone
host/machine
service/component
cluster/instance
process/session
severity
request/query correlation where safe不能只按 hostname,如果重装/复用会混淆。
日志容量与敏感性
PostgreSQL 日志可能含:
SQL text
parameters/data
roles/database
client addresses
errors
file paths控制:
log_statement/log_min_duration choice
parameter logging/redaction
access
encryption
retention
export failure buffer
deletion/legal hold“为了排障全量记录 SQL 与参数”可能制造数据泄露。
logrotate 与磁盘故障
要验证:
rotation
compression
retention
copytruncate vs reopen semantics
agent backpressure
local buffer
disk alert
component restart日志不能与 PGDATA 互相填满;集中日志不可达也不应无限占用本地磁盘。
19.3.3 基线检查必须记录事实而非套用调优模板
基线与目标分两列
推荐格式:
| 项 | observed | desired | status | evidence |
|---|---|---|---|---|
| OS | Ubuntu 24.04.4 | Ubuntu 24.04.x | pass | host JSON |
| THP | never | never | pass | sysfs |
| swap | 0 | 0 | pass | meminfo |
| filesystem | ext4 virtual | qualified prod storage | sandbox exception | findmnt |
| NTP | synchronized | synchronized | pass | timedatectl |
事实不符合时:
fail
accepted exception with owner/expiry
planned remediation不能把 desired 覆盖 observed 后再宣布通过。
“最佳实践参数”有上下文
网络文章常给:
vm.swappiness=1
vm.dirty_ratio=...
read_ahead_kb=...
noatime
hugepages=...
max_connections=...每项必须问:
哪个 OS/kernel/filesystem/device?
哪个 PostgreSQL/version?
哪个 workload?
解决什么测量瓶颈?
副作用?
生效范围与重启?
如何回滚?
如何证明改善?答不出就先记录,不变更。
配置层级要可追踪
一个值可能来自:
kernel default
distribution sysctl
cloud image
hypervisor
Pigsty role default
global inventory
cluster vars
host vars
manual change
runtime command审计要保存最终事实和来源。只看 Git inventory 无法发现手工漂移;只看
sysctl -a 又无法知道下次重启会恢复成什么。
一次性探测命令也有风险
基线 collector 应:
read-only
bounded timeout
explicit target
no secret output
stable schema
known command allowlist
stderr/exit preserved避免:
curl | sh
unbounded find /
dump all environment
print full config
copy /etc wholesale
run benchmark on production本章 collector 不读取原始 machine-id 以外的 secret 文件;machine-id 只输出 SHA-256。
自动修复与验收分开
部署 playbook 可以改变主机;acceptance collector 只读。
好处:
- 验收失败不会偷偷修复;
- 能发现 automation 未覆盖的漂移;
- 证据可由不同身份运行;
- 重跑不会增加变更;
- 故障现场可先保留状态。
task.sh all 不会执行 deploy.yml。
运行两次不等于幂等证明
Ansible 第二次 changed=0 是强证据,但不是全部:
- 外部 API 可能有副作用;
- task 可能每次重启但未报告 change;
- 数据初始化可能非幂等;
- template 中动态值可漂移;
- service 行为可能改变;
- secrets/certificates 可能轮换。
需要同时比较:
changed/failed counts
service state
SQL/catalog identity
endpoint behavior
files/config hashes where safepending reboot 也是事实
包安装可能提示:
new kernel installed, running kernel still old不要忽略。记录:
running kernel
installed candidate
reboot required
maintenance plan
post-reboot acceptance是否立即 reboot 取决于授权和维护窗口,不应由 collector 自动作出。
例外要结构化
例外至少:
{
"id": "EX19-VIRTUAL-STORAGE",
"reason": "...",
"production_impact": "...",
"owner": "...",
"expiry_or_scope": "sandbox only",
"compensating_control": "no production claim"
}本章 requirements 先固定 ID/reason/impact;production 使用时还必须补真实 owner、expiry 与 control。
基线漂移比较
每次变更前后比较:
host identities
OS/kernel/package
mount/storage
sysctl/limits
service versions/state
PostgreSQL init identity
topology/endpoints
exceptions某些字段天然变化:
capture time
uptime
LSN
metrics counters
log size比较器要分类,不能要求整个 JSON byte-identical。
本章采集 schema
remote_host_facts.py
输出稳定分类:
identity
kernel/OS/architecture/virtualization
CPU/NUMA
memory/THP/swap/overcommit
root and /pg mount/free
clock
network/firewall/ports
services
packages动态运行指标留给第 25/26 章;本章是配置与环境基线。
最后的判断
主机基线的合格结论不是:
所有参数都等于模板。
而是:
对每个与服务目标有关的主机事实,我们知道 observed 值、来源、期望、 差异、证据和 owner;没有任何未解释差异被伪装成通过。
上一节:计算、内存、存储与网络 · 返回本章目录 · 下一节:版本与数据库初始化契约 · 查看全书目录 · 查看索引中心