跳至内容
19.3 操作系统与主机基线

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 agents

PostgreSQL:

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/modepurposeretention
source/inventoryadminIaCversioned/private
/pg/datapostgresdataauthoritative
/pg/logpostgres/agentscomponent logspolicy
/pg/backupbackuprepository/spoolbackup policy
/etc/patroniroot/postgresHA configconfig
/etc/pgbouncerservicepool configconfig
/etc/pgbackrestcontrolledbackup config/secret refsconfig
/etc/haproxyrootroutingconfig

不要把目录路径写死进应用;通过 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 基线检查必须记录事实而非套用调优模板

基线与目标分两列

推荐格式:

observeddesiredstatusevidence
OSUbuntu 24.04.4Ubuntu 24.04.xpasshost JSON
THPneverneverpasssysfs
swap00passmeminfo
filesystemext4 virtualqualified prod storagesandbox exceptionfindmnt
NTPsynchronizedsynchronizedpasstimedatectl

事实不符合时:

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 safe

pending 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;没有任何未解释差异被伪装成通过。


上一节:计算、内存、存储与网络 · 返回本章目录 · 下一节:版本与数据库初始化契约 · 查看全书目录 · 查看索引中心

最后更新于