API 网关监控实战:从 Kong 到 APISIX 的指标采集与告警设计
概述 凌晨两点,支付系统告警炸了。看了半天日志发现不是下游服务挂了,而是 API 网关的连接池打满了——请求堆在网关这一层根本没转发出去。但你的监控大盘上只有 CPU 和内存曲线,压根看不到网关层的延迟、连接数和错误率。 这不是个例。我见过太多团队把 API 网关当"高级 Nginx"用,监控只看 nginx_active_connections,出事了才去翻日志。问题是网关是所有流量的咽喉,一旦这层出问题,影响面是全局的。 这篇文章讲清楚三件事:Kong、APISIX、Envoy 各自暴露哪些指标、怎么用 Prometheus 采集、告警规则怎么设计才能在故障扩散前收到通知。不是泛泛而谈的"最佳实践",是我在生产环境踩过坑后整理出来的方案。 为什么 API 网关需要专门的监控 你可能会想:网关后面已经有服务监控了,为什么还要单独监控网关? 因为网关和后端服务看到的世界不一样。举个例子: 维度 网关视角 后端服务视角 请求延迟 包含路由匹配、插件执行、上游转发全链路 只看到自己处理那段 错误来源 可能是路由不存在、插件拦截、上游超时、连接池满 只知道返回了 500 连接状态 能看到与上游的连接池使用率 只知道自己收了多少请求 限流触发 网关层限流命中了哪些规则 服务端可能根本不知道被限了 简单说,网关是流量高速公路的收费站。收费站堵了,后面所有车都堵。你不在收费站装监控,等问题传导到后端服务再排查,黄花菜都凉了。 三大主流网关的指标体系对比 Kong 的指标暴露 Kong 通过 prometheus 插件暴露指标,启用方式很简单: # 启用 Prometheus 插件(全局级别) curl -X POST http://kong-admin:8001/plugins \ --data "name=prometheus" \ --data "config.per_consumer=true" \ --data "config.status_code_metrics=true" \ --data "config.latency_metrics=true" \ --data "config.upstream_health_metrics=true" 启用后访问 http://kong-proxy:8001/metrics 就能拿到 Prometheus 格式的指标。Kong 的核心指标分四类:...
别等炸了才看监控:Linux 性能基线建立与异常识别的实战方法论
概述 你大概率经历过这种场景:凌晨三点被告警吵醒,爬起来看 Grafana,发现 CPU 使用率飙到 85%。你紧张了半天,查了一圈,最后发现——这台数据库服务器每天凌晨 2:50 到 3:10 都会跑定时备份任务,CPU 本来就该到这个数。 问题出在哪?你不知道这台机器"正常"是什么样子。没有基线,85% 是高还是低,你根本判断不了。 性能基线(Performance Baseline)解决的就是这个问题:在系统健康的时候,把关键指标记录下来,形成一份"体检报告"。以后出了异常,拿当前数据跟基线一对比,是真故障还是正常波动,一眼就能看出来。 这篇文章讲的是怎么从零建立一套可落地的 Linux 性能基线体系。不是泛泛而谈"监控很重要",而是从方法论选择、指标采集、基线建模、异常识别到自动化落地,每一步都给你能直接用的配置和代码。 为什么静态阈值不靠谱 大多数团队的告警配置是这样的:CPU > 80% 告警,内存 > 90% 告警,磁盘 > 85% 告警。这就是静态阈值——一个拍脑袋定的数字,挂在所有机器上。 静态阈值有三个致命问题: 第一,不同业务、不同时段的正常值不一样。 一台跑批处理任务的服务器,CPU 峰值在工作时间冲到 95% 是正常的;一台 API 网关,CPU 持续 70% 就得警惕了。用同一个 80% 阈值套上去,前者天天误报,后者出了事还不报。 第二,绝对值掩盖趋势。 某台机器 CPU 从 30% 缓慢爬到 60%,持续两周。静态阈值看不到——没到 80% 嘛。但这种缓慢上升往往是内存泄漏或连接堆积的前兆,等真到 80% 的时候已经炸了。 第三,无法识别"不正常的好"。 某个核心服务的 QPS 突然从 5000 掉到 200,CPU 使用率跟着降到 10%。静态阈值觉得一切正常——CPU 低着呢。但实际上上游可能挂了,流量根本没进来。 基线解决这些问题的思路很简单:不设固定阈值,而是让系统自己学什么算正常。当实际表现偏离了历史学到的"正常模式",才触发告警。 USE 方法论:基线采集的骨架 建立基线之前,先得知道采什么指标。乱采一通,采了 200 个指标,80% 没人看,纯属浪费。...
从“群里 @ 运维”到自助执行:20+ 运维操作平台化的 6 层架构与 4 个落地阶段
概述 周五下午四点半,业务群开始刷屏: “@运维 帮我重启一下订单服务” “@运维 线上这个接口报错了,帮我捞下日志” “@运维 机器是不是又满了?帮我清下磁盘” 三个请求,三个 @,运维同学放下手里正在写的巡检脚本,SSH 登录、敲命令、回群里贴截图、再被追问一句“好了吗”。一个下午就这么碎了。这不是个例,是大多数团队运维工作的常态——高频、低难度、高度依赖人肉。 我在自研运维平台项目里做过一次统计:把 20 多个运维操作(服务重启、缓存清理、配置下发、证书续期、日志捞取、磁盘扩容……)从“群里 @ 人”搬进自助平台之后,单次操作的平均耗时从 15 分钟降到 90 秒左右,运维团队花在“响应请求”上的人力降了约 40%。这两个数字后面没有魔法,就是一件事:把操作变成平台上的标准动作。 这篇文章把我做这件事的完整思路摊开讲:为什么要平台化(不是“提效”这种空话,而是四个具体的结构性问题)、6 层架构怎么设计、操作目录怎么标准化、审批流怎么做才不会被绕过,以及四个真实踩过的坑。代码和配置都是可以直接抄走的。 先说清楚一点:运维操作平台化不是“写个 Web 界面跑脚本”。如果你只是在 Web 页面上开了个终端让开发自己敲命令,那不叫平台化,叫换个地方人肉。平台化的核心是:操作本身被定义成结构化的资产——有参数、有权限、有审批、有回滚、有审计。Web 界面只是这个体系的门面。 手工运维的四个结构性问题 在讲架构之前,先把问题说透。很多团队知道手工运维“慢”,但慢只是表象。真正让运维团队疲于奔命的是四个结构性问题: 问题一:请求链路太长,人的时间被切碎 一次“帮我重启服务”的完整链路是这样的: 业务在群里 @ 运维(等待响应:5 分钟) → 运维确认影响范围(翻 CMDB / 问业务:5 分钟) → 运维 SSH 登录执行(1 分钟) → 运维回群确认 + 贴执行结果(2 分钟) → 业务追问验证(3 分钟) 单次 15 分钟,其中真正“执行操作”只有 1 分钟,剩下 14 分钟都是沟通成本。Red Hat 在一篇 AIOps 实践文章里给过一个真实数据:一家英国金融公司用 Ansible Automation Platform 每周跑 600 多个任务(装机、补丁、合规扫描、配置漂移修复),每周产生约 40 张失败工单——如果没有平台,这 40 张工单每一张都是一次“群里 @ 人”。任务量到这个级别,人肉响应模式必然崩掉。...
凌晨三点的电话又响了:On-Call 排班设计与疲劳治理的 7 个工程决策
概述 凌晨三点,手机震了。你看了一眼——P1 告警,订单服务 5xx 错误率飙升。爬起来,开电脑,拉日志,查 Grafana,定位到是上游数据库连接池打满。重启、扩容、恢复,一看表四点半了。第二天早上你顶着黑眼圈开会,会上有人说"昨晚那个告警其实是误报"。 这种感觉,干过运维的人都懂。 On-Call(值班响应)是 SRE 工作中绕不开的一环。但很多团队的 On-Call 做成了"谁被叫醒谁处理",没有轮值,没有备份,没有交接,更没有疲劳管理。结果是:核心工程师离职,告警群形同虚设,故障响应越来越慢。 这篇文章聊聊 On-Call 排班设计中的 7 个工程决策。不是理论框架,是我这些年从 0 到 1 搭建 SRE 值班体系时踩过的坑、做过的取舍。在之前的事件管理与 On-Call 机制设计中讲过事件响应流程,本文聚焦在"排班本身怎么设计"——轮值周期、主备机制、告警分级、疲劳量化、交接班、新人上岗、补偿与度量。 如果你是刚接手 SRE 团队的技术负责人,或者正在被无序的值班制度折磨,这篇文章应该能帮你少走半年弯路。 一、On-Call 到底在解决什么问题 先说清楚 On-Call 是干嘛的,再说怎么设计。 On-Call 的本质是:在非工作时间,系统出问题时,有人能第一时间响应并恢复。 打个比方:医院急诊科不能晚上关门。医生白天上班,晚上也得有人值班。但值班的医生不是同一个人连值一周不睡觉——那第二天手术手抖就出医疗事故了。所以医院有轮班制度:白班、夜班、备班,轮着来,保证每个班次的医生都是清醒的。 On-Call 的逻辑一样。你的系统 7x24 小时跑着,但工程师不能 7x24 小时盯着。On-Call 排班就是让"正确的人在正确的时间收到告警",而不是"所有人都收到告警"或者"没人收到告警"。 Google SRE 的 On-Call 原则 Google SRE 在《Google 运维解密》里用三个章节讲 On-Call,核心原则就一条:琐事不能超过工作时间的 50%。 什么是"琐事"(Toil)?Google 的定义是:重复的、可自动化的、战术性的、没有持久价值的工作。比如手动重启服务、手动扩容、手动查日志定位问题——这些都是琐事。On-Call 是琐事最大的来源之一。 一个 SRE 至少要花一半时间做工程项目(写代码、做工具、改架构),否则就是在用人力填系统的坑,越填越深。要保证这个比例,团队至少需要 6-8 人轮值——人少了轮不过来,工程时间被值班吃光。 Google SRE 的 on-call 方法和工具 这篇文章里有一个很清晰的分析:Google 通过 Outalator 工具管理告警的全生命周期,包括聚合、标签、分析、交接报告,让 On-Call 不只是"被叫醒",而是"被管理"。Outalator 的核心功能包括:...
别被免运维忽悠了:Serverless 冷启动、成本失控与可观测性盲区的 5 个生产级治理决策
概述 凌晨两点,我被电话叫醒。 某出行项目的用户反馈,凌晨时段打开 App 查看行程历史,页面要白屏 3-5 秒才出内容。排查了一圈,发现这组 API 用了 Serverless 函数计算,白天流量正常,凌晨流量低谷后函数实例被回收,第一个请求触发的冷启动直接让 P99 延迟飙到 4.8 秒。 这不是个例。我在多个项目中见过 Serverless 从 POC 到生产翻车的场景:冷启动让接口超时、月账单比传统服务器贵 3 倍、线上故障找不到日志、安全策略越配越乱最后谁也不敢改。 Serverless 的宣传话术很诱人——按需付费、自动扩缩容、无需运维。但真正在生产环境跑过的人都知道,“免运维"是个伪命题。Serverless 不是删掉了运维,而是把运维的战场从服务器管理转移到了冷启动治理、成本控制、可观测性建设和安全策略管理上。而且这些新战场的复杂度,一点也不比传统运维低。 这篇文章不讲 Serverless 的概念和入门,直接上 5 个生产级踩坑和治理决策。每个坑都来自真实项目,每个决策都有数据支撑。 1. 冷启动治理:从 5 秒到 200ms 的四层优化 1.1 冷启动到底卡在哪 很多人只知道"冷启动慢”,但说不清楚慢在哪。先拆解一次完整的冷启动过程: 阶段 耗时占比 具体动作 可优化空间 资源分配 15-20% 平台分配 CPU/内存、挂载文件系统 平台侧,用户不可控 运行时初始化 20-30% 加载语言 Runtime(Java 最慢,Node.js 最快) 选运行时 代码加载 15-25% 下载部署包、解压、加载依赖 精简包体积 初始化逻辑 30-40% 执行全局代码:连接 DB、初始化 SDK、加载配置 用户可控,优化空间最大 关键发现:初始化逻辑阶段占比最大(30-40%),而且这是用户唯一能深度优化的部分。很多团队的冷启动慢,不是因为平台不行,而是在全局初始化里塞了太多东西——建数据库连接池、初始化 Redis 客户端、加载配置文件、注册服务发现——这些操作在传统服务器上只执行一次,但在 Serverless 里每次冷启动都要重来。...
砍掉 80% 年停机时间:可用性从 99.5% 到 99.9% 的 6 个工程决策与踩坑实录
概述 99.5% 的可用性听起来不错——直到你算一笔账。 一年 8760 小时,99.5% 意味着允许停机 43.8 小时。换算到每个月,差不多 3.65 小时的服务中断。如果是核心交易系统,这 3.65 小时可能就是几十万的订单损失。如果赶在大促期间,损失会翻几十倍。 99.9% 呢?年停机 8.77 小时,月均不到 44 分钟。停机时间砍掉 80%。 0.4 个百分点的提升,背后不是加几台服务器那么简单。我在某出行平台推动过一次这样的改造,从立项到稳定运行在 99.9% 以上,花了整整 14 个月。这期间踩的坑、做的权衡、推翻重来的方案,比写代码本身多得多。 这篇文章不讲理论框架,只拆解我们做过的 6 个关键工程决策,以及 3 个让我后背发凉的踩坑时刻。每个决策都附上我们当时的选型对比和最终方案,你拿去就能对照自己的系统查漏补缺。 可用性的数学本质:为什么 0.4% 这么难 先搞清楚一件事:可用性不是加法,是乘法。 假设你的系统由 3 个服务串联组成,每个服务可用性 99.5%。整个链路的可用性是多少? 0.995 × 0.995 × 0.995 = 0.9851 ≈ 98.51% 三个"还不错"的服务串联起来,整体可用性直接跌破 99%。年停机从单服务的 43.8 小时暴涨到 128 小时——超过 5 天。 反过来想:如果链路有 10 个服务,每个要达到整体 99.9% 的可用性,单个服务的可用性得是多少? 0.999^(1/10) ≈ 0.99990 → 99.99% 十个服务每个都得做到四个九。这就是为什么微服务架构下可用性提升的难度呈指数级增长。 关键认知:提升可用性不是给单个服务加机器,而是同时做三件事——减少串联依赖数量、提高单个服务可用性、在关键路径上做冗余和降级。 Google SRE 团队在 The Calculus of Service Availability 中提到一个观点:大多数服务的内部目标应该定在 99....
70% 误报率降到 5%:CI/CD 安全门禁的四层防御与误报治理实录
概述 把一个 SAST 工具装进 Jenkins pipeline,扫描跑完显示 0 告警,然后你跟老板说"我们上了 DevSecOps"——这件事我见过太多次了。 在某出行项目的等保 2.0 审计期间,甲方安全团队要求我们在 CI/CD 流水线中集成安全扫描。第一版方案很"标准":SonarQube 扫代码 + Trivy 扫镜像,门禁设成"Critical 阻断"。上线第一周,流水线红了 47 次。开发团队跑了 47 次"修复",其中 41 次是误报。第二周开始,有人偷偷在 CI 配置里加了 || true 把扫描结果吞掉。 这就是典型的"装了工具但没解决问题"。安全扫描不是把工具塞进 pipeline 就完事的——它是一个系统工程,涉及工具选型、规则调优、误报治理、门禁策略、开发协作五个层面。这篇文章记录了我们从 70% 误报率降到 5% 的完整改造过程,包括四层安全防御体系的设计、6 个生产级踩坑细节,以及一套可以直接拿去用的 GitLab CI 配置。 如果你正在做安全合规或者想提升团队的安全左移能力,这篇内容能帮你少走几个月弯路。 安全扫描的四层防御体系 很多团队的安全扫描只做一层——要么只跑 SAST,要么只跑 SCA。这就像出门只锁了大门,窗户全开着。真正能拦住漏洞的,是多层防御。我把这套体系分成四层,每层解决不同维度的问题。 第一层:SAST(静态应用安全测试) SAST 扫的是源代码本身。它在代码不运行的情况下,通过词法分析、语法分析和数据流追踪,找出 SQL 注入、XSS、硬编码密码等代码级缺陷。 大白话解释:SAST 就像一个英语老师拿着红笔逐行改你的作文,看到语法错误就圈出来。它不看内容合不合理,只看写法对不对。 主流 SAST 工具对比: 工具 语言覆盖 误报控制 规则定制 CI 集成方式 适用场景 SonarQube 40+ 语言 中等(靠规则集裁剪) Java 插件,重 Scanner + Server 全语言团队,需要质量+安全一体化 Semgrep 30+ 语言 高(AST 模式匹配) YAML 规则,轻量 CLI 直接跑 快速增量扫描,自定义规则多 CodeQL 有限(主要 C/C++/Java/Python/JS) 高(数据流分析) CodeQL 查询语言 GitHub Actions GitHub 生态团队,需要深度漏洞挖掘 我推荐的选择策略:...
别把 Terraform 模块写成黑盒:IaC 分层设计决策与 6 个生产级反模式拆解
概述 去年给一家做电商的客户搭 IaC 体系,接手时他们的 Terraform 代码库大概长这样:三个环境(dev/staging/prod)各自一套配置,加起来 3000 多行,90% 是复制粘贴。改一个 VPC CIDR 要同步改三个文件,漏改一个就是环境漂移。最离谱的是有个安全组规则在 prod 里少了一条,三个月没人发现。 这种痛每个用过 Terraform 的团队都经历过。模块化是公认的解法——但很多人做完模块化后发现:代码确实短了,可维护性反而更差了。一个模块塞了 40 个变量、3 层嵌套,改一个参数要翻三个文件才能理解影响面。这就是"把模块写成黑盒"的典型症状。 这篇文章拆解我在多个企业客户项目中验证过的一套 Terraform 模块分层架构,以及 6 个在生产环境中真实踩过的反模式。不是泛泛的"最佳实践"罗列,而是每个决策点都附上"为什么这么做"和"什么场景下不推荐这么做"。 为什么需要模块化 先说清楚模块化解决什么问题。不是"代码复用"这么笼统的话,而是三个具体痛点: 痛点一:环境漂移。 三个环境的配置本应一致,但人工复制必然出错。在某出行项目中,我们统计过:复制粘贴的配置平均每个环境有 3-5 处细微差异(CIDR 偏移、可用区数量不一致、安全组规则遗漏),这些差异在平时不爆发,一出故障就是定位地狱。 痛点二:变更同步成本。 改一个 AMI ID 要在 3 套环境里各改一次。如果团队有 5 个人同时改不同模块,合并冲突频繁到让人怀疑人生。 痛点三:知识传递断裂。 新人来了看一个 800 行的 main.tf,完全不知道哪些资源是有关联的、改哪个会影响哪个。没有模块边界,就没有认知锚点。 模块化的本质不是"把代码拆短",而是建立明确的抽象边界——让每个模块成为一个可以独立理解、独立测试、独立变更的单元。 模块分层架构设计 三层模型 我推荐的三层架构如下: 层级 职责 示例 变量数量 资源数量 基础模块 封装单一云资源 modules/vpc、modules/rds 5-15 3-8 组合模块 组合多个基础模块 modules/eks-platform 15-30 调用 3-5 个基础模块 环境层 定义环境差异化配置 envs/prod/ 不限 调用 2-4 个组合模块 这三层不是什么新概念,但很多人在实际落地时会把层级搞混——最常见的是基础模块里塞了组合逻辑,或者环境层直接调用基础模块跳过了组合层。下面逐层拆解。...
从 Docker Machine 退役说起:GitLab CI Runner 弹性架构与缓存治理的 7 个生产决策
概述 凌晨 1 点,你收到告警:GitLab CI 流水线队列堆积了 47 个 pending job。开发群炸了——“代码推了 40 分钟还没跑起来"“是不是 Runner 挂了"“赶紧加机器啊”。你登录控制台一看,3 个 Runner 全部满载,每个并发 10 个 job,30 个 slot 全占满了。加机器?Docker Machine 执行器拉起新 EC2 要 3 分钟,等机器 Ready 又要 2 分钟。5 分钟过去了,队列又涨了 20 个。 这不是假设。2025 年我在某出行项目做 CI/CD 平台重构时,就遇到过这个场景。当时的 Runner 架构是经典的 Docker Machine + AWS EC2 自动伸缩,高峰期排队 30-40 分钟是常态。后来我们迁移到 Kubernetes Executor + HPA 弹性伸缩,排队时间降到 30 秒以内。这中间踩了不少坑,也做了不少架构决策。 本文不讲 .gitlab-ci.yml 基础语法(那些 CSDN 上够多了),只聊 7 个真正影响生产效率的工程决策:执行器选型、资源规划、弹性伸缩、缓存设计、流水线编排、节点隔离、监控告警。每个决策都附实测数据和踩坑细节。 如果你在评估 CI/CD 平台选型,可以参考我之前的文章 相关文章:别让 Jenkins 决定你的发布节奏:用 Go 自研 DAG 调度引擎的架构决策与踩坑实录,里面对比了 Jenkins、GitLab CI 和自研调度引擎的差异。...
别把容灾做成备份:跨机房 RPO<5min、RTO<30min 的架构决策与踩坑实录
概述 凌晨 2 点 17 分,手机弹出告警:核心机房 A 区网络设备故障,数据库主从同步中断。值班 SRE 切到灾备机房 B 区,发现应用连上新主库后,部分订单数据查不到——异步复制窗口期丢了 47 秒数据。业务恢复用了 38 分钟,超出 RTO 目标 8 分钟。 这是一次真实的容灾切换事故。事后复盘发现,系统设计了容灾架构,配置了数据同步,也写了切换脚本,但真正切换时还是出了问题。问题不在于"有没有灾备",而在于容灾架构的每个环节是否真正经得起生产级考验。 本文拆解跨机房容灾的核心架构决策,覆盖同城双活、异地灾备、两地三中心三种模式的选型权衡,同步复制的性能代价与脑裂防护,异步复制的窗口期补偿机制,以及故障切换从决策到执行的完整流程。每个环节都附有真实踩坑记录和性能数据。 在我经手过的跨机房容灾方案中,最终达成 RPO<5min、RTO<30min 的指标。这个数字看起来不算极致,但它是成本、稳定性和业务需求三方博弈后的工程最优解——不是理论上的 RPO=0,而是生产环境能跑通、能验证、能回滚的方案。 RPO 和 RTO 的工程真相 不是技术指标,是业务指标 RPO(Recovery Point Objective)和 RTO(Recovery Time Objective)这两个词被技术圈用烂了,但很多人理解反了——它们首先是业务指标,然后才是技术指标。 RPO 回答的是"能容忍丢多少数据"。比如一个电商系统,订单数据的 RPO 必须是 0(不能丢订单),但用户行为日志的 RPO 可以是 1 小时(丢了不影响核心交易)。RTO 回答的是"能容忍停多久"——核心交易系统 RTO 要 <5 分钟,而报表系统的 RTO 可以是 4 小时。 关键认知:不要一刀切。 我见过太多团队把所有系统都按 RPO=0、RTO<1min 设计,结果容灾建设成本翻了好几倍,非核心系统根本不需要这么高的规格。 按业务重要性分级设计容灾目标: 级别 系统类型 RPO 目标 RTO 目标 同步方式 P0 核心交易、支付 0 <5min 同步复制 P1 用户中心、订单查询 <1min <15min 半同步复制 P2 内容管理、报表 <30min <2h 异步复制 P3 日志分析、离线计算 <1h <4h 定时备份 RPO=0 的代价不是线性的 很多人觉得"RPO 越小越好",但 RPO 从 1 分钟到 0 的成本跳跃是指数级的:...