磁盘空间与 inode 管理:从 df 到 lsof 的生产排障全攻略

概述 凌晨三点,你被告警吵醒——线上数据库写入失败,Nginx 起不来,SSH 登录卡顿。登上服务器一查,df -h 显示根分区 100%。这种事每个运维都遇到过,磁盘满大概是生产环境最高频的故障类型之一,根据实际运维统计,磁盘相关告警占比约 15%-20%。 但磁盘满不是一个简单问题。df -h 看到的 100% 可能并不是全部真相: inode 耗尽:磁盘空间还有剩余,但文件系统inode用完了,照样报 No space left on device。这种问题更隐蔽,排查难度也更大。 已删除文件未释放:rm 删了大文件,df 显示空间没变。因为还有进程持有文件描述符,数据块并没有真正释放。 预留空间:ext4 默认预留 5% 空间给 root,400GB 的数据盘就有 20GB 被"藏"起来了。 这篇文章把磁盘空间和 inode 管理的排查思路、清理策略、预防机制一次说透。所有命令都在 Ubuntu 22.04 和 CentOS 7.9 上实测过,能直接拿去用。 磁盘空间的两个维度:blocks 与 inode 很多人对磁盘空间的理解只停留在"还剩多少 GB"这个层面。但 Linux 文件系统管理的是两个独立资源:数据块(blocks) 和 索引节点(inode)。 打个比方:文件系统像一个停车场。blocks 是停车位,inode 是停车记录。停车场可能还有空车位(blocks 没满),但记录本写满了(inode 耗尽),新来的车也停不进去。 inode 是什么 inode(Index Node,索引节点)是文件系统里描述文件元数据的数据结构。每个文件或目录对应一个 inode,存储了以下信息: 元数据字段 说明 文件类型 普通文件、目录、符号链接等 权限信息 rwx 权限位 所有者 uid 和 gid 文件大小 字节数 时间戳 atime / mtime / ctime 数据块指针 指向实际数据存储位置的索引 硬链接数 指向该 inode 的目录项数量 注意一个关键点:inode 不存储文件名。文件名存在目录项(dentry)中,目录项将文件名映射到 inode 编号。这也是为什么硬链接能存在——多个文件名可以指向同一个 inode。...

July 23, 2026 · 9 分钟 · 1726 字 · 徐保金

系统韧性工程:从被动救火到主动防御的架构演进

概述 凌晨两点,你的手机响了。支付服务超时,线程池被占满,上游订单服务开始排队,10 分钟后整个交易链路雪崩。你打开日志一看:下游一个缓存集群抖动了 3 秒,这 3 秒里上游疯狂重试,把连接数打到了上限,然后所有依赖这个连接池的服务一起挂了。 这故事不新鲜。几乎每个干过几年运维的人都经历过类似的连锁故障。问题不在于某个组件会不会挂——分布式系统里,什么都可能挂,网络会抖、磁盘会满、DNS 会抽风、机房会断电。真正的问题是:一个局部故障为什么会演变成全局灾难? 韧性工程(Resilience Engineering)回答的就是这个问题。它不是某个具体工具或某个框架,而是一套从架构设计到运维实践的系统性方法论,核心目标只有一个:让系统在部分组件失效时仍能提供可接受的服务,而不是一路雪崩到全站不可用。 这篇文章把韧性工程拆成三块来讲:一是韧性模式——你的系统到底需要哪些容错机制,每种解决什么问题;二是实践框架——这些模式怎么组合落地,不是东拼西凑几个注解就完事;三是度量与验证——你怎么知道系统真的"韧",而不是你以为它韧。 韧性工程到底在解决什么问题 先说清楚一件事:可靠性(Reliability)和韧性(Resilience)不是一回事。 可靠性回答的是"系统在规定条件下、规定时间内,能不能正常工作"——它关注的是正常状态。你定了 99.9% 的可用性 SLO,这衡量的是可靠性。 韧性回答的是"当条件不满足、甚至出现预期外故障时,系统能不能优雅降级而不是直接崩溃"——它关注的是异常状态。你的服务在数据库挂了 30 秒后还能返回缓存数据,延迟从 50ms 升到 200ms 但没有雪崩,这体现的是韧性。 用一个不太精确但好理解的类比:可靠性是百米短跑你能跑多快,韧性是你摔了一跤后多快能爬起来继续跑。 分布式系统天然比单机系统脆弱,因为引入了网络这个最大的不确定性来源。CAP 定理告诉我们,分区容忍(P)在网络不可靠时是无法回避的。你不可能消灭故障,只能控制故障的影响范围和传播速度。韧性工程本质上就是在做两件事:缩小爆炸半径(一个故障不要扩散到其他组件)和缩短恢复时间(出问题后尽快回到正常状态)。 五大韧性模式 熔断器(Circuit Breaker) 熔断器解决的问题是:当一个下游服务持续故障时,不要继续向它发请求。 道理很直白。如果支付网关已经挂了,你的订单服务每笔请求还在傻等 30 秒超时,100 个并发请求瞬间就把线程池占满了。这时候不光支付不行,连查订单、查库存一起死掉。熔断器的作用就是当失败率达到阈值时,直接切断这条调用链路——后续请求不再访问故障服务,而是立即返回降级响应或报错。 熔断器有三个状态,跟家庭配电箱的空气开关一样: 状态 行为 类比 Closed(闭合) 正常放行请求,记录失败率 开关正常通电 Open(断开) 拒绝所有请求,直接走降级 开关跳闸断电 Half-Open(半开) 放行少量探测请求,试探恢复 试探性恢复供电 状态转换的核心逻辑: Closed → Open: 滑动窗口内失败率超过阈值(如 50%) Open → Half-Open: 经过冷却时间(如 30s)后自动转换 Half-Open → Closed: 探测请求成功率达标 → 恢复正常 Half-Open → Open: 探测请求仍然失败 → 重新断开 实测中有个坑要避:阈值别定太敏感。我见过有人设 10% 失败率就熔断,结果正常的一次 GC 停顿(偶尔 1-2 秒延迟升高)就触发熔断,服务在 Open 和 Closed 之间来回弹跳。建议初始配置失败率阈值 50%、最小调用次数 20、滑动窗口 10 秒,然后根据实际数据调。...

July 23, 2026 · 7 分钟 · 1470 字 · 徐保金

K8s 安全扫描与 CIS Benchmark 合规:从 kube-bench 到生产级加固的完整实战

概述 你管着一个 K8s 集群,API Server 的 --anonymous-auth=true 没关,etcd 的证书权限是 644,kubelet 的 --read-only-port=10255 还开着——这些东西单独看每个都是"小问题",但攻击者拿到其中一个入口,就能一路横向打到整个集群。这不是假设,CNCF 2025 年度调查报告显示,超过 90% 的生产 K8s 集群存在至少一个 CIS Benchmark 级别的配置缺陷。 CIS(Center for Internet Security)Benchmark 是一套业界公认的安全配置基线,K8s 有对应的专门版本。kube-bench 就是用来跑这套基线检查的工具——你把它跑一遍,它告诉你哪些配置不符合安全标准、应该怎么改。 但这只是第一步。光跑出报告不够,你还得知道怎么修、怎么持续监控、怎么把扫描嵌进 CI/CD 流水线里。本文从实际操作出发,覆盖从安装 kube-bench、跑第一次扫描、解读报告、修复常见问题,到配合 Trivy 做镜像漏洞扫描、kube-hunter 做渗透模拟、把安全扫描自动化到 GitOps 流程中的完整路径。 CIS Kubernetes Benchmark 是什么 CIS Benchmark 说白了就是一份"安全配置检查清单"。CIS 这个组织拉了一批安全专家,把某个系统(操作系统、数据库、云平台、K8s 等)应该怎么做才算安全,整理成一份文档,每一条都有明确的检查方法和修复建议。 K8s 的 CIS Benchmark 把检查项分成四个层面: 层面 检查对象 典型检查项 控制平面 API Server、Scheduler、Controller Manager、etcd 是否禁用匿名访问、是否启用 RBAC、etcd 是否启用 TLS 工作节点 kubelet、kube-proxy 是否禁用只读端口、是否启用客户端证书认证 策略 RBAC、PodSecurityPolicy/PSA 是否使用最小权限、是否限制特权容器 托管服务 EKS/GKE/AKS 等 云平台特有的安全配置 每个检查项标注了严重级别:L1 是基本要求,任何环境都该满足;L2 是更严格的要求,适用于安全敏感度高的环境。...

July 22, 2026 · 10 分钟 · 2096 字 · 徐保金

故障复盘改进项跟踪:从清单到闭环的工程化实践

概述 每个做过线上运维的人大概都经历过这个场景:凌晨三点被告警吵醒,一通操作止血恢复,第二天组织复盘,会上列了十几条改进措施,会议纪要发到群里,大家纷纷表示"收到"。然后呢?一个月后你翻出来看,真正落地的大概只有两三条,其余的全躺在某个文档里吃灰。更扎心的是,半年后类似故障又来了一次,复盘会上一翻历史记录,好家伙,上次就提过改进建议,就是没人跟进。 这不叫复盘,这叫走过场。 改进项跟踪(Action Items Tracking)解决的就是这个问题——把复盘会议上产出的改进清单,变成有负责人、有截止日期、有验收标准、能被持续追踪直到闭环的工作项。说白了,复盘的价值不在会议本身,而在会议之后的那三个月里,这些改进项到底执行了没有、执行到位了没有。 Google SRE Book 里有一句话大意是:复盘没有 action items 的故障,等于白复盘。但我觉得这话还差半句——有 action items 但没跟踪,一样白复盘。 这篇文章聊的就是改进项跟踪这件事怎么做。从改进项的分类和生命周期讲起,到跟踪工具选型,再到自动化提醒和度量指标,最后给一套可以直接落地的实践方案。 改进项是什么:从模糊建议到可执行任务 改进项不是建议 很多人把"改进项"和"建议"搞混了。复盘会上有人说"以后上线要多测试一下",这是建议,不是改进项。改进项必须是可执行、可追踪、可验收的具体任务。 一个合格的改进项需要回答五个问题: 要素 说明 反面示例 正面示例 做什么 具体的行动内容 “加强监控” “为订单服务的下游调用增加超时熔断,超时阈值设为 3 秒” 谁来做 明确到具体责任人 “研发团队” “张三(订单服务 owner)” 什么时候完成 有明确的截止日期 “尽快” “2026-08-15 前” 怎么验收 可验证的完成标准 “优化好” “Prometheus 中出现 order_downstream_timeout_total 指标,且在压测环境验证熔断生效” 优先级 P0/P1/P2 分级 不标注 “P1:影响范围是全量用户,需在两周内完成” 缺任何一个要素的"改进项",本质上都是空头支票。你没法跟踪一张空头支票。 改进项的分类 根据改进的对象和执行周期,改进项可以分为四类: 1. 技术修复类(Technical Fix) 直接改代码或配置就能解决的问题。比如修复一个 bug、补一段熔断逻辑、加一个监控指标。这类改进项执行周期短,通常几天到两周搞定。 示例: - 修复 order-service 的 N+1 查询问题(P0,2 天内) - 为 payment-gateway 增加限流中间件(P1,1 周内) - 将 Redis 连接池从 lettuce 换成 jedis 并配置合理超时(P2,2 周内) 2....

July 21, 2026 · 9 分钟 · 1807 字 · 徐保金

容器镜像签名与验证:用 cosign 守住供应链安全的最后一道门

概述 先说一个让我后怕的事。 去年我们一个内部镜像仓库的权限配置出了问题,松了几天。事后复盘虽然没发现被人动过手脚,但那几天我心里一直打鼓——万一有人往仓库里推了个同名 tag 的镜像,把 app:latest 换成他自己的版本,我们的部署流水线照样拉、照样跑,谁能发现? digest 确实会变。但那时候我们的部署根本没人去核对 digest。镜像这东西,默认的逻辑是"谁能推就信谁"。仓库里躺着一个 app:v1.2.3,你怎么知道它是你的 CI 构建推上去的,而不是别人冒名顶替推的? 答案很扎心:光看,你不知道。得有签名。 这篇文章讲的是怎么用 cosign(Sigstore 生态的核心工具)给容器镜像签名和验证,把"镜像从构建到运行"这条链条上的信任问题解决掉。核心思路是:CI 构建完镜像后签名,部署前验证签名,验不过的镜像根本不让进生产环境。 镜像供应链的安全威胁 在讲方案之前,得先搞清楚我们在防什么。 攻击路径 容器镜像供应链攻击的核心特点是:攻击者不需要直接入侵你的生产服务器,他只需要在镜像到达生产之前的任何一个环节动手脚。 典型的攻击路径: 攻击者 │ ├─ 路径1:上传恶意基础镜像到 Docker Hub │ → 开发者基于该镜像构建应用 │ → 恶意代码进入 CI/CD 流水线 │ → 部署到生产环境 │ ├─ 路径2:入侵 CI 系统,篡改构建产物 │ → 推送同名 tag 的篡改镜像 │ → 部署系统拉取"最新"镜像 │ → 后门进入生产 │ ├─ 路径3:中间人攻击,篡改镜像传输 │ → 拦截 docker pull 请求 │ → 返回篡改后的镜像层 │ └─ 路径4:内部人员误操作或恶意操作 → 直接推送未经验证的镜像到生产仓库 路径 1 和路径 2 是最常见的。2024 年安全研究人员在 Docker Hub 上发现了超过 10000 个镜像泄露了生产系统的敏感凭证。Sysdig 的容器安全报告显示,超过 65% 的容器镜像包含已知高危漏洞——这些漏洞往往来自基础镜像。...

July 20, 2026 · 6 分钟 · 1187 字 · 徐保金

前端性能监控实战:从 Core Web Vitals 到 RUM 的全链路方案

概述 后端监控做得再花,用户打开页面白屏 5 秒,你的 SLO 全绿也是白搭。 这话不是我故意唱反调。很多团队的监控大盘里全是 CPU、内存、QPS、P99 延迟,看着一片祥和。可真实用户的投诉邮件已经在客服那边堆成山了——“页面打开慢”、“点不动”、“图片一直闪”。问题出在哪?你监控的是服务器视角,用户看到的是浏览器视角,中间隔着 CDN 缓存、DNS 解析、第三方脚本阻塞、渲染管线,任何一环拉胯,用户的体验就崩了。 这篇文章要解决的问题是:怎么把"用户实际感受到的性能"量化成指标,采集起来,配上告警,最后形成优化闭环。核心是两件事——Core Web Vitals 指标体系和真实用户监控(RUM,Real User Monitoring)。 前端性能监控和后端监控有一个本质区别:后端监控的是"我的服务处理得快不快",前端监控的是"用户等得久不久"。同一个接口,后端 P99 是 50ms,但用户在 4G 网络下等了 3 秒才看到内容——中间差的那 2.95 秒,只有前端监控能看到。 Core Web Vitals:用户感受的"体温计" 三大核心指标 Google 定义的 Core Web Vitals 是目前业界最主流的前端体验量化标准,聚焦三个维度: 指标 全称 衡量什么 良好阈值 需改进 差 LCP Largest Contentful Paint 最大内容绘制时间 ≤ 2.5s 2.5-4.0s > 4.0s INP Interaction to Next Paint 交互到下一帧绘制延迟 ≤ 200ms 200-500ms > 500ms CLS Cumulative Layout Shift 累计布局偏移 ≤ 0....

July 20, 2026 · 8 分钟 · 1636 字 · 徐保金

Linux 时间同步与 NTP:chrony 配置、排障与生产实践

概述 一次线上故障让我彻底重视起时间同步这件事。某天凌晨,业务反馈 HTTPS 请求大面积失败,报错 SSL_ERROR_BAD_CERTIFICATE。排查了两个小时,翻遍网络拓扑、防火墙规则、证书配置,都没问题。最后有人无意间看了眼系统时间——比真实时间快了 12 秒。就这 12 秒,让服务器在验证客户端证书的 notBefore 时间时判定"证书尚未生效",拒绝了所有握手。 这不是孤例。时间不同步在分布式系统里是一颗隐形地雷:Kerberos 认证对时间偏差容忍只有 5 分钟,超了直接拒登;Kubernetes 节点时间偏差过大,kubelet 心跳过期,Pod 被驱逐;MySQL 主从复制依赖时间戳,偏差大会导致 binlog 顺序错乱;分布式事务的二阶段提交,节点间时钟不同步会让超时判断失效。 时间同步听起来简单——装个 NTP 客户端,指向时间服务器就完事了。但生产环境的坑远不止于此:虚拟机时钟漂移、容器里没有 NTP 守护进程、多机房时钟源选型、chrony 和 ntpd 冲突、证书续期任务因时间跳变失败。这篇文章把这些问题一次性讲清楚,给出生产可用的配置和排障思路。 从 ntpd 到 chrony:为什么换了 ntpd 是老牌的时间同步服务,跑了二十多年。但从 RHEL 8、CentOS 8、Ubuntu 20.04 开始,主流发行版默认都换成了 chrony。原因不是 ntpd 不好,而是 chrony 在几个关键场景下表现更好: 对比维度 ntpd chrony 首次同步速度 慢,需要逐步逼近 快,iburst 几秒内拉到毫秒级 网络中断后恢复 慢,重新同步耗时长 快,历史漂移率记录加速收敛 虚拟机时钟漂移 处理差,容易抖动 处理好,driftfile 自动补偿 资源占用 较高 更低 离线保持 漂移大 driftfile 让离线也能维持 是否支持时间服务器功能 是 是(allow 指令) 关键区别在首次同步速度。ntpd 出于"不能让时间跳变"的设计哲学,启动后是缓慢逼近目标时间,可能要十几分钟才稳定。chrony 的 iburst(initial burst)选项,启动时一次性发 4 个探测包,几秒内就能完成首次同步。这对虚拟机、容器这种频繁启停的场景至关重要——你不可能等 10 分钟才让一个容器的时间正确。...

July 19, 2026 · 7 分钟 · 1467 字 · 徐保金

消息队列监控实战:Kafka Lag、RabbitMQ 积压与消费延迟告警

概述 凌晨三点,手机被告警轰炸。Kafka 某个消费者组的 Lag 从 200 飙到 50 万,下游实时报表全部卡住,数据团队在群里疯狂 at 你。你爬起来连上跳板机,敲 kafka-consumer-groups.sh --describe,看到 Lag 列一串刺眼的数字。接下来半小时,你要回答三个问题:积压在哪个分区?消费者是死了还是慢了?加机器能救吗? 消息队列是分布式系统的"下水道"——平时没人关注,一旦堵了整栋楼都得停工。Consumer Lag(消费者延迟)就是下水道的流量计,它告诉你生产者往里灌水的速度和消费者抽水的速度差了多少。这个差值持续增大,说明系统出了问题;差值突然归零,也可能出问题(消费者挂了,offset 不再提交,Lag 反而看起来正常)。 这篇文章覆盖 Kafka、RabbitMQ、Redis 三种主流消息队列的监控方案,从指标采集、Prometheus 规则、告警阈值到排障思路,都是我在生产环境踩过坑的实战经验。不讲理论,直接上配置。 为什么 Consumer Lag 是最核心的指标 先说清楚 Lag 到底是什么。Kafka 里每个分区有一个 LogEndOffset(LEO,最新消息位置),消费者组有一个 CurrentOffset(已提交位置)。两者的差值就是 Lag: Lag = LogEndOffset - CurrentOffset Lag 为 0 说明消费者完全跟上。但生产环境小幅波动很正常,单分区 Lag < 100 基本不用管。真正要警惕的是三种模式: Lag 模式 典型原因 危险程度 持续线性增长 消费速度 < 生产速度,处理能力不足 高,不处理会雪崩 突然跳变 消费者重启/崩溃后 offset 回退,或生产者批量灌数据 中,需确认是否预期 突然归零 消费者挂了或跳过提交,offset 停滞但 LEO 也没涨 低但不正常,常被误判为"健康" 第三种最坑人。我见过一个案例:消费者线程死锁,但 auto.commit.enable=true 还在自动提交 offset,导致消息被标记为"已消费"但实际没处理。Lag 显示 0,业务方以为一切正常,直到下游发现数据丢了三天。...

July 19, 2026 · 7 分钟 · 1369 字 · 徐保金

K8s 日志采集方案:DaemonSet、Sidecar 与 Agentless 模式的选型与实战

概述 线上炸了,你打开 Kibana 搜日志,发现关键 Pod 3 分钟前被 OOM Kill 重启了,旧日志跟着容器一起灰飞烟灭。这种事在 K8s 环境里太常见了——Pod 是短命的,日志不能跟着 Pod 一起消失。 K8s 的日志采集和传统虚拟机完全不是一回事。传统环境日志躺在 /var/log/ 下,SSH 上去就能看。K8s 里 Pod 随时可能被调度到任何节点,随时可能被销毁重建,日志分散在整个集群。如果不做集中采集,故障排查时你根本找不到日志在哪。 这篇文章把 K8s 日志采集的几种方案拆开讲清楚:DaemonSet 模式、Sidecar 模式、以及基于节点 Agent 的方案。每种方案什么场景用、怎么配置、踩什么坑,全部覆盖。最后给出一套生产可用的选型决策框架。 K8s 日志的三种类型 在讲采集方案之前,先搞清楚 K8s 里有哪些日志。不同类型的日志采集策略完全不同。 1. 容器标准输出日志 这是最常见的一类。应用把日志写到 stdout/stderr,容器运行时(containerd 或 Docker)负责把这些日志落盘到节点的 /var/log/containers/ 目录。 # 查看某节点的容器日志文件 ls /var/log/containers/ # 输出示例 # nginx-xxx_default_app-abc123.log # redis-yyy_default_app-def456.log # 这些文件实际是指向 /var/log/pods/ 下的符号链接 ls -l /var/log/containers/nginx-xxx_default_app-abc123.log # lrwxrwxrwx 1 root root 99 ... nginx-xxx_default_app-abc123.log -> /var/log/pods/default_nginx-xxx_abc123/app/0.log 这类日志的好处是采集简单——DaemonSet 模式直接读 /var/log/containers/*....

July 18, 2026 · 11 分钟 · 2247 字 · 徐保金

DNS 解析与排查:从 resolv.conf 到 systemd-resolved 的实战排障指南

概述 凌晨两点,告警炸了。服务连不上数据库,curl 超时,但 ping IP 通。你说这到底是网络问题还是应用问题?十有八九是 DNS 解析出了岔子。 DNS 解析是 Linux 系统最基础也是最容易被忽视的基础设施。平时没人关注它,一旦出问题,整个系统像突然失忆了一样——所有域名都认不出来。更恶心的是,DNS 问题表现千奇百怪:有的直接报 Temporary failure in name resolution,有的莫名其妙卡 5 秒,有的间歇性失败。如果不清楚解析链路,排查起来就是一通乱试。 这篇文章把 Linux DNS 解析的完整链路拆开讲:从 /etc/hosts 到 nsswitch,从 resolv.conf 到 systemd-resolved,从 dig 到 tcpdump。每个环节配实战案例,看完能在生产环境独立排查 DNS 问题。 Linux DNS 解析的完整链路 先搞清楚一个问题:当你在终端敲下 curl http://example.com 的时候,系统到底干了什么? DNS 解析不是一步完成的,它经过多个层级。理解这条链路是排查问题的前提。打个比方:DNS 解析就像寄快递。你写的收件地址是"北京市朝阳区",快递员不会直接知道具体在哪——先查邮编分区,再查街道,最后查门牌号。DNS 也一样,一层一层往下找。 解析优先级 Linux 系统解析一个域名时,默认按以下顺序查找: 本地 hosts 文件(/etc/hosts)——优先级最高,匹配到就直接返回 DNS 缓存——如果系统装了 nscd 或 systemd-resolved,会先查缓存 配置的 DNS 服务器(/etc/resolv.conf 中的 nameserver)——最后才走网络查询 但这个顺序不是写死的。真正控制解析顺序的是 /etc/nsswitch.conf 文件中的 hosts 行: # 查看 nsswitch 配置 cat /etc/nsswitch....

July 18, 2026 · 9 分钟 · 1851 字 · 徐保金