ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

云计算选型与成本优化:IaaS/PaaS/FaaS及稳定上线避坑

云计算选型与成本优化:IaaS/PaaS/FaaS及稳定上线避坑

1. 云到底替你接管了哪几件事:把"虚拟化"这层壳拆开看

1.1 从"买机器"到"买能力"的思维切换

很多人第一次登录云平台控制台的反应都差不多:几十上百个产品名挤在左侧菜单里,每个产品后面挂一张架构图,看上去全都跟自己有关,又全都不敢点。我最初也是这样,在菜单里翻了两个小时,最后还是老老实实回到"买一台服务器"这条最熟悉的路。这条路本身没错,但如果一直停在这里,云对你来说就只是一台"远程租来的电脑",它真正值钱的那部分能力,你一点都没用上。

这个差别可以用一个生活场景说清楚。自己搭机房,类似于自己盖房子:地要自己批,水电要自己接,墙要自己砌,房子盖好之后还得有人常年守着修修补补。用云,类似于住进一栋带物业的公寓:你关心的是住几间、住多久、要不要加个阳台,剩下的承重墙、配电房、消防管道、电梯维保,都由另一套体系在背后运转。你付的钱,一部分是房租(算力、存储),另一部分是物业费(运维、可用性、安全基线)。

把这句话记住,后面所有的选型和省钱动作都能对上号:云卖给你的从来不是"一台机器",而是"一段时间内可用的某种能力"。能力是可以按需伸缩、按秒计费、随时换规格的,机器不行。你一旦用"买机器"的思路去用云,就必然会出现两种典型浪费:买了用不完的规格,以及为了"看起来稳定"而常年开着一堆根本没人访问的实例。

我见过不少团队,账面上一年的云支出不算少,但真正支撑业务的机器只占三成,剩下七成是"当初试了一下忘了关""怕出问题多开了一台备用""测试环境一直没下线"。这些钱不是被云厂商赚走的,是被"买机器"的思维习惯漏掉的。

1.2 三层服务形态的边界:IaaS、PaaS 与函数计算

搞不清 IaaS、PaaS、FaaS 这三个词,是新手选型时最大的绊脚石。它们不是三个产品,而是三种"你管到哪一层"的分工方式。用一栋楼来类比:

  • IaaS(基础设施即服务):你租到的是毛坯房。水电到户、承重墙到位,但地板、墙面、家具、门锁全归你管。对应到技术上,就是你拿到一台裸的虚拟机,操作系统要自己装,运行环境要自己配,中间件要自己维护,扩缩容要自己写脚本。
  • PaaS(平台即服务):你租到的是精装房。地板墙面都做好了,你只负责搬家具进去。对应到技术上,就是托管数据库、托管消息队列、托管容器运行时这一类,你提交代码或者配置,平台负责版本升级、主备切换、故障迁移。
  • FaaS / Serverless(函数计算):你租到的是酒店日租。住一晚付一晚,走的时候什么都不用收拾。对应到技术上,就是把一段处理逻辑丢上去,有请求才算钱,没请求就是零成本,连"实例在不在"这个问题都不存在。

三层之间没有绝对优劣,只有边界匹配。判断标准其实只有三个问题:这件事我是否具备长期维护的能力?它的负载曲线是否可预测?它的故障代价我能不能自己兜住?三个问题里有两个答"否",就该往 PaaS 或 FaaS 挪。

举个具体的判断例子。一个小团队要做图片处理服务,日请求量波动极大,白天高峰是凌晨的二十倍。如果按 IaaS 思路,得按高峰配置机器,夜里那二十小时基本在空转;如果改用函数计算,只在对请求的那几百毫秒计费,成本可能只有前者的十分之一。但如果这个服务需要常驻内存做缓存预热、需要长连接、需要本地磁盘做临时大文件处理,那 FaaS 的冷启动和执行时长限制就会变成新的麻烦,这时候托管容器反而是更稳的选择。

1.3 一个必须纠正的误解:云不是"别人家的服务器"

"云就是把服务器放到别人机房"——这句话在十几年前勉强算对,现在完全不是这么回事。真正的差别不在物理位置,而在故障模型和责任边界。

自己维护一台物理机,故障模型是相对简单的:硬盘坏了换硬盘,内存报错换内存,电源烧了换电源,你大致知道问题出在哪一层。上了云之后,故障模型变成了分布式的:可能是宿主机异常触发迁移,可能是某个可用区的网络抖动,可能是存储服务的某次后台任务导致 IO 延迟升高,也可能是你自己配置的安全组规则把所有入站流量挡掉了却毫无察觉。这些故障里,有一部分云平台会兜住(比如宿主机宕机自动迁移),有一部分必须你自己兜(比如你没做多可用区部署,那就只能等)。

责任边界这件事,行业里有个通用的说法叫"共享责任模型":云平台负责"云本身的安全与可用",你负责"云里面的安全与可用"。具体拆开是这样的:

层次平台负责你负责
物理设施机房、供电、网络、硬件更换无
虚拟化层宿主机调度、故障迁移选择合适的可用区与冗余策略
操作系统提供镜像补丁、内核参数、账号
运行环境部分托管组件中间件配置、依赖版本
应用与数据无全部
访问控制提供权限体系谁能访问什么、密钥怎么管
备份提供备份工具备份策略、恢复演练

这张表最右边那一列,就是新手最容易漏掉的部分。很多人以为"上了云就自动高可用",结果单可用区部署、没做备份、root 账号密码写在配置文件里,出了一次事故才发现,平台该兜的都兜了,剩下的全是自己的锅。

2. 计费模型比配置参数更值得先看

2.1 四种花钱方式:按量、包周期、预留与竞价

新手看云产品页面,眼睛全在 CPU、内存、带宽这些参数上,很少人第一眼去看计费方式。这是个很贵的习惯。同一台配置的实例,用不同的付费方式,一年下来的差价可能超过百分之六十。

四种主流模式,用租房打个比方就很好理解:

  • 按量付费:像住酒店,按小时甚至按秒结算,随时退房。适合短期项目、临时压测、不确定会不会长期用的场景。贵,但灵活。
  • 包周期(包年包月):像签一年租约,单价明显低,但中途退租通常不退钱。适合负载长期稳定、明确要跑一年以上的核心服务。
  • 预留/节省计划:像承诺"我未来一年至少用这么多",换来一个折扣价,但承诺的部分即使不用也要付。适合有稳定基线负载、且对成本比较敏感的团队。
  • 竞价/抢占式实例:像捡漏房源,价格随供需浮动,便宜很多,但随时可能被收回,通常只给很短的回收通知。只适合无状态、可中断的任务,比如批量计算、离线渲染、CI 构建。

我自己的经验是:先把负载分成"基线"和"波动"两段,再分别匹配付费方式。基线部分(比如常年跑着的数据库、常驻的网关)走包周期或预留,波动部分(比如白天高峰的 Web 层)走按量加自动伸缩。这个组合思路几乎在所有业务里都能省下一笔,而且不影响任何可用性。

有一个坑必须提前说:包周期实例到期前,如果自动续费没开、又没设到期提醒,实例会被释放,数据可能一起没。我见过一次,测试环境的一台实例到期两天,正好赶上有人在那上面放了一份还没入库的样本数据,最后只能重跑。

2.2 容易被忽略的计量表:流量、请求数、快照与读写

账单之所以吓人,往往不是因为主实例贵,而是因为那些"看起来不要钱"的计量项。我列几个最常见、也最容易被忽略的:

  • 公网出流量。这是新手的第一个暴击点。入流量通常免费或极便宜,出流量按 GB 计价,而且跨地域、跨网络类型的价格差别很大。一个没做压缩的图片站,一个月出流量几百 GB 很轻松。
  • 对象存储的请求数与取回费。存储本身单价很低,但每次读写都算请求。小文件多、请求频率高的场景,请求费可能超过存储费本身。低频存储类型还有"取回费",平时不显眼,一旦批量拉数据就冒出来。
  • 快照与镜像。很多人习惯每天给云盘打快照,觉得反正是增量、很便宜。但快照会不断累积,几个月后占用的存储可能比原始数据大好几倍。更麻烦的是,快照不清理,账单上是一行不起眼的小数字,一年下来相当可观。
  • NAT 网关与负载均衡的处理费。这类托管组件的费用通常由"实例费 + 处理流量费"两部分组成,实例费看着便宜,流量费随业务线性增长。
  • 跨可用区、跨地域的数据传输。同一地域内跨可用区通信通常有少量费用,跨地域则是明显更贵的价格。多地域部署如果没有做数据本地化,账单会非常难看。

2.3 我选型时实际用的那张对照表

选型时我不会只看参数,而是把几个维度摆在一起对比,逼自己做取舍。下面这张表是我常用的框架,可以按自己的业务改写权重:

维度需要问自己的问题影响的是
负载曲线峰值是均值的几倍?每天有几个高峰?付费方式、是否自动伸缩
状态性服务是否持有本地状态?重启会不会丢数据?能否用竞价实例、能否弹性
延迟要求端到端能容忍多少毫秒?是否要多可用区、是否要 CDN
数据规模现在多大?一年后大概多大?存储类型、是否分片
合规与留存数据要留多久?能不能放境外?存储地域、归档策略
团队能力出故障时谁能处理?几点能到?IaaS 还是 PaaS
成本敏感度预算是硬约束还是软约束?付费方式、规格选择

这张表最有用的一列其实是"团队能力"。我见过太多团队选了一套架构上很漂亮、但没人能维护的方案,最后出事的时候只能干等。你能兜住的复杂度,才是你真正的技术选型上限。

3. 第一次把服务跑起来:一条最小可用的上线链路

3.1 先搭网络骨架:私有网络、子网与安全组

很多人部署上线是反着来的:先开一台机器,装好环境,能访问了,再想起来要配网络。这个顺序在小规模下能跑通,但只要涉及多台机器、涉及数据库、涉及对外暴露,就一定会返工。

正确的顺序是先画网络。一个最小可用的骨架包含三样东西:

  • 私有网络(VPC):给你的资源划一块独立的地址空间,比如10.0.0.0/16。这一层决定了你能放多少台机器、怎么划子网。
  • 子网划分:至少分两类,一类是"对外"子网,放负载均衡、网关这类需要公网入口的组件;一类是"对内"子网,放数据库、缓存、内部服务。对内外网隔离是最便宜的安全措施。
  • 安全组 / 防火墙规则:这是真正决定"谁能连进来"的东西。原则只有一条——默认全拒,按需放行,源地址尽量写具体网段,不要写0.0.0.0/0。

我踩过的一个典型坑:把数据库端口开在公网可达的安全组里,只靠密码保护。上线第三天就出现了大量异常登录尝试,日志里全是陌生地址在试常见用户名。那次之后我给自己定了个规矩:数据库实例永远不分配公网地址,需要连接就通过跳板机或专线通道。

子网划分还有一个细节值得提前想:同一子网内的机器默认互通,跨子网走路由。如果你的业务里有"前端不该直接访问数据库"这种隔离需求,用子网 + 安全组两道墙来做,比在应用层做判断可靠得多。

3.2 计算与存储:镜像、实例、云盘与初始化脚本

网络搭好之后,才是开机器。这一步的核心是用镜像固化环境,而不是登录上去手工装。

手工装环境的后果我深有体会:半年后需要扩容,你根本记不清当时装的是哪个版本的运行环境、改了哪些内核参数、有没有手动加过一条 iptables 规则。扩容出来的机器和线上机器"看起来一样",但行为不一样,排查起来极其痛苦。

正确做法是三步:

  1. 从一个干净的基础镜像出发,只装最小依赖。
  2. 把安装过程写成脚本,脚本放在代码仓库里,跟应用代码一起做版本管理。
  3. 把脚本挂到实例初始化环节,让机器一启动就自动完成环境配置。

这里说的脚本,哪怕是几十行的 shell 也远胜于手工。我通常写的初始化脚本包含这些内容:

#!/usr/bin/env bash set -euo pipefail # 1. 基础环境 apt-get update -y && apt-get install -y curl jq ca-certificates # 2. 时区与时间同步(很多诡异问题源于此) timedatectl set-timezone Asia/Shanghai # 3. 创建运行用户,禁止直接用 root 跑业务 id -u appuser &>/dev/null || useradd -m -s /bin/bash appuser # 4. 目录规划:数据盘挂到固定路径 mkdir -p /data/app /data/logs chown -R appuser:appuser /data # 5. 拉取应用包并启动(真实项目这里换成自己的制品地址) curl -fsSL "https://internal.example.invalid/pkg/app.tar.gz" -o /tmp/app.tar.gz tar -xzf /tmp/app.tar.gz -C /data/app chown -R appuser:appuser /data/app # 6. 健康检查占位 systemctl enable app.service systemctl start app.service

存储这块,我一般会把云盘分成两类用:系统盘只放操作系统,数据盘单独挂载到/data。理由很实际:系统盘出问题时可以直接换盘重装,数据盘不受影响;做快照的时候也能分开做,系统盘不需要那么高的频率。

3.3 入口层:域名、证书与反向代理

服务在内部跑起来之后,才轮到入口层。这一层看着简单,其实是最容易配置出错的地方。

顺序是这样的:域名解析指向入口地址,入口层做 TLS 终止,再把请求转发给后端。中间隔一个反向代理而不是让应用直接监听公网端口,好处至少有四个:证书只在一处维护、可以做统一的访问日志、可以在应用重启时返回友好错误页、可以按路径做灰度分流。

TLS 证书这块我建议直接上自动化。手工申请、手工上传、手工续期,一定会出现"某天早上打开网站报证书过期"这种事故。用自动续期的方案,一次性配置好,之后基本不用管。配置完成之后一定要做一次验证:

# 查看证书到期时间与颁发者 echo | openssl s_client -connect your.domain.invalid:443 -servername your.domain.invalid 2>/dev/null \ | openssl x509 -noout -subject -issuer -dates

反向代理的配置里,有三个参数我几乎每次都会调:

  • 连接超时:默认值往往偏短,后端稍微慢一点就报 502。设成后端最长正常耗时的一点五倍左右。
  • 请求体大小限制:默认通常很小,上传稍大的文件就 413。按业务需要调整。
  • 真实客户端 IP 透传:把来源 IP 通过标准头部传给后端,否则后端日志里全是代理的地址,排查问题时毫无价值。

3.4 尽量用脚本而不是点鼠标

这一条是我这些年最想安利给新人的经验:凡是能在控制台点出来的东西,尽量用代码来定义。

原因不复杂。控制台点击产生的结果是"一个已经存在的状态",它没有历史、没有 diff、没有评审。三个月后有人想问"这个安全组规则为什么这么配",你只能靠记忆。而用代码定义的基础设施,每一次变更都是一次提交,谁改的、改了什么、为什么改,全在记录里。

入门不需要一上来就搞复杂工具。从最朴素的开始就行:把创建资源的过程写成一个脚本,参数抽成变量,环境分开管理。下面是个示意:

#!/usr/bin/env bash set -euo pipefail ENV="${1:?usage: ./provision.sh <dev|prod>}" REGION="your-region" INSTANCE_TYPE="small" case "$ENV" in dev) COUNT=1; DISK=40 ;; prod) COUNT=3; DISK=100 ;; *) echo "unknown env: $ENV"; exit 1 ;; esac echo "provisioning $COUNT instance(s) for $ENV in $REGION ..." # 具体的创建命令按所用平台的 CLI 补齐

这段脚本真正的价值不在那几行命令,而在case分支里那个 COUNT。它把"开发环境一台、生产环境三台"这个约定固化下来了,任何人执行./provision.sh prod都会得到一致的结果,不会出现"上次是谁手动开了两台,这次忘了解"的情况。

再往前走一步,就是把整个环境(网络、实例、存储、权限)都写进声明式配置文件,用工具做"期望状态"和"实际状态"的比对。这条路一开始学习成本不低,但只要你的资源超过二十个,收益就会明显超过成本。

3.5 上线前我会过一遍的验收清单

服务能访问不等于上线完成。我每次上线前会走一遍这个清单,几次事故之后养成的习惯:

检查项具体做法不做的后果
健康检查入口层配独立探针,不依赖首页应用假死但端口还在,流量持续打进来
优雅停机收到终止信号先摘流量再退出重启瞬间出现一批 502
日志落盘应用日志、访问日志分开,带轮转磁盘被日志写满,服务整体挂掉
时区一致所有机器统一时区与时间同步跨机器日志对不上,排查靠猜
配置外置数据库地址、密钥走环境变量换环境要改代码,容易泄露
最低权限运行账号不是 root,密钥不落盘一旦被利用就是整台机器
回滚路径上一版本制品可随时重新部署出问题时只能往前修,越修越乱

这份清单看起来啰嗦,但它挡住的问题都是"上线当天看不出来、三天后集中爆发"的那种。尤其是优雅停机这一条,很多服务重启时丢掉的那部分请求,监控上看不到,只能从用户反馈里知道。

4. 账单为什么会失控:成本结构的拆解与优化手法

4.1 把账单拆开:成本归因从打标签开始

想省钱,第一步不是砍资源,是搞清楚钱花在哪。而绝大多数团队在第一周根本回答不了这个问题,因为资源没有打标签。

标签是什么?就是给每个资源挂几个键值对,比如project=order-service、env=prod、owner=team-a。看起来很小的一件事,作用是让账单能按项目、按环境、按团队切开。没有标签,你面对的就是一个总数;有了标签,你能看到"测试环境居然占了总支出的一半"这种以前完全想不到的事实。

我建议的标签体系控制在三到四个维度,维度太多反而没人认真填:

  • 项目/业务线:这笔钱是谁的
  • 环境:生产、预发、开发、测试
  • 归属人/团队:出问题找谁,超预算找谁
  • 可选的生命周期:临时、长期

标签还有一个隐性收益:它会逼着团队在创建资源时就思考"这东西要活多久"。我见过太多"临时"资源活了两年,就是因为创建时没人问这一句。

落地方式上,最有效的是强制。把标签设为创建资源的必填项,缺标签直接拒绝创建。一开始会有人抱怨麻烦,两周之后就习惯了,而且账单的可读性提升非常明显。

4.2 计算侧:闲置、超配与规格错配

计算资源的浪费几乎全部来自三种情况,我按出现频率从高到低排:

第一种,闲置。机器开着,CPU 长期在百分之三以下,网络进出流量接近于零。这类资源通常来自"试了一下忘了关""离职同事留下的""没人敢删的旧环境"。处理方式不是一刀切关掉,而是先统计连续三十天的 CPU、内存、连接数,把明显无负载的列出来,通知归属人确认。我给自己的规则是:连续三十天 CPU 峰值低于百分之五、且无任何外部连接的实例,先停机保留两周,无人认领再释放。

第二种,超配。这个更常见,也更容易被忽略。当初为了"保险起见"选了八核十六 G,实际跑下来 CPU 峰值百分之十五、内存用了三成。这种做法在小团队里特别普遍,因为"怕不够用"的心理成本远低于"出问题"的成本。

判断是否超配,不能只看平均 CPU。我一般看三个数:CPU 的 P95(百分之九十五分位)、内存的实际使用峰值、以及磁盘 IO 的等待时间。如果 P95 长期低于百分之三十、内存峰值低于百分之五十,那就基本可以降一档规格。降配之前记得先压测一轮,尤其是内存敏感型应用(比如跑 JVM 的),堆大小和实例内存的配比要重新算。

第三种,规格错配。这个最隐蔽。比如把内存密集型的缓存服务放在计算优化型实例上,把 IO 密集型的数据库放在通用型实例上。表面上看配置够用,实际跑起来 CPU 一直闲着、磁盘队列一直排着,性能上不去,你却以为是代码有问题。

现象可能原因处理方向
CPU 低、磁盘队列长存储性能不足换更高 IOPS 的盘型
CPU 高、内存充足计算型负载放在通用型换计算优化规格
内存频繁回收、CPU 抖动内存不足升内存或调堆参数
网络吞吐打不满实例网络带宽上限低换网络增强型规格

4.3 存储与流量:最容易被放过的两块钱

存储和流量的特点是:单价低、总量大、增长无声。等你注意到的时候,往往已经积累了一年。

存储这块,我做的第一件事永远是盘点。把所有的云盘、对象存储桶、快照、镜像列出来,标注三件事:谁在用、数据多久没被访问、有没有备份价值。盘点完通常会看到三类可以立刻处理的东西:

  • 孤儿盘:实例已经释放,云盘还挂着计费。数量往往比想象中多。
  • 过期快照:半年前的一次性快照,早就没有保留意义。
  • 冷数据放热存储:一年没人读的日志、归档的原始文件,仍然放在标准存储类型里。

冷数据的分层是最容易见效的一招。主流平台一般都提供从"标准"到"低频"到"归档"的多档存储,价格能差好几倍。判断依据就是访问频率:九十天内没被读过的数据,基本可以降到低频;一年没读过的,可以进归档。唯一要小心的是归档类型的取回延迟和取回费用,别把需要随时读的数据放进去了。

流量这块,手段主要是三个:

  1. 静态资源走 CDN。图片、脚本、样式这类内容,命中率通常很高,回源流量能压下来一大截。
  2. 开压缩。文本类响应开 gzip 或 br,体积能减到原来的三分之一甚至更少。这一步几乎零成本,收益直接。
  3. 减少跨地域传输。把计算放在离用户和数据最近的地域,跨地域调用只保留必要的控制面通信。

有一点要提醒:CDN 不是万能的。如果内容更新极频繁、命中率很低,回源流量可能比不走 CDN 还多,因为多了一跳。上之前先看看缓存命中率的预估。

4.4 让省钱自动发生:定时、弹性与生命周期策略

手动省钱有个致命问题:省一次就忘了。真正有效的成本控制,是把规则写成自动化策略,让它在没人管的时候也持续生效。

我这几年积累下来、几乎每个项目都会配的几条:

  • 非生产环境定时开关。开发、测试环境的机器,工作时段开、非工作时段关。一天省十几个小时,一个月就是接近一半。风险是要提前确认没人跑夜间的定时任务。
  • 自动伸缩。Web 层按 CPU 或请求数做伸缩,设好最小和最大实例数。最小实例数不要设成零(除非能接受冷启动),最大实例数一定要设,这是防止异常流量把账单打爆的最后一道闸。
  • 存储生命周期规则。对象存储里按前缀设规则,比如"日志目录下的对象,三十天后转低频,一百八十天后删除"。配置一次,之后全自动。
  • 快照保留策略。只保留最近 N 天的自动快照,更早的自动清理。同时保留每月一次的长周期快照,用于灾难恢复。
  • 预算告警。设一个日预算和一个月预算,超过阈值就通知。这个不是省钱手段,是止血手段,作用是在账单变成四位数之前把你叫醒。

关于自动伸缩,有个参数特别值得说:冷却时间。缩容太快会导致刚扩出来的实例立刻被回收,流量一来又要重新扩,来回抖动;缩容太慢则省不下钱。我的经验值是扩容冷却短一些(几十秒),缩容冷却长一些(几分钟),给流量一点回落的缓冲。

4.5 省钱的边界:别把可用性省没了

这条必须单独说,因为我见过太多"省出事"的案例。

成本优化的红线有三条,我认为不能碰:

第一,不能省掉冗余。把三副本改成单副本、把多可用区改成单可用区,账单是降了,但一次硬件故障就是全站不可用。省下的钱可能还不够一小时的业务损失。

第二,不能省掉备份。备份的存储费用在总账单里通常占比很小,但它的价值是"出事时能救命"。我见过为了省几百块把备份关掉的团队,后来因为一次误删付出了几十倍的代价。

第三,不能省掉监控和告警。监控系统的成本主要是存储指标数据和日志,可以通过降采样、缩短保留期来优化,但不能不采。没有监控的系统,等于闭着眼睛开车。

一个实用的判断方法:把每一项成本优化都换算成"如果出问题,损失是多少"。省下的钱远大于潜在损失,就做;两者接近,就别碰。这个换算不精确没关系,它至少能帮你把"为了省钱而省钱"的冲动按住。

5. 上线只是开始:稳定性底线与新手最常踩的坑

5.1 监控要盯的五个指标

监控最容易走两个极端:要么什么都不配,出事全靠用户投诉;要么把能采的全采了,看板上几百个图表,真出事时没人知道该看哪个。

我建议从五个指标起步,覆盖大部分常见故障:

  • 可用性:入口层返回非 5xx 的比例。这是最贴近用户体验的指标,也是告警的第一优先级。
  • 延迟:P50 和 P95 分开看。只看平均值会被长尾掩盖,一次百分之五的慢请求就足以让部分用户放弃。
  • 错误率:应用层抛出的异常数量,按错误类型分组。分组是为了区分"业务校验失败"和"系统异常"。
  • 资源水位:CPU、内存、磁盘使用率、连接数。重点看趋势而不是瞬时值。
  • 依赖健康:数据库连接池占用、下游接口的成功率和耗时。很多故障不是自己挂了,是下游挂了。

告警配置上有个原则我一直在用:每条告警都必须对应一个明确的动作。如果收到告警之后你不知道该干什么,那这条告警就是噪音,要么删掉,要么补上处理手册。噪音告警最大的危害不是打扰人,是让人对告警麻木。

5.2 备份这件事,"开了"和"能用"差很远

备份是最典型的"配置了就以为万事大吉"的功能。实际情况是,大量团队在真正需要恢复的时候,才发现备份有问题。

常见的失效场景有这么几种:备份任务因为权限变更静默失败,几个月没有新备份;备份文件存在同一块存储上,存储本身出问题时一起没了;备份是有的,但从来没验证过能不能恢复,真恢复时发现缺少必要的配置或密钥;只备份了数据库,没备份对象存储里的用户上传文件。

我的做法是加一道"恢复演练":每个季度挑一个非核心环境,从备份完整恢复一次,记录耗时和遇到的问题。演练的价值不在于那次恢复本身,而在于它会暴露出一堆平时想不到的问题,比如恢复脚本依赖的某个工具版本已经变了、恢复后需要手工改的连接串没人记得。

演练记录我会留一份文档,写清楚:备份在哪、怎么恢复、大概多久、需要谁配合。这份文档在真出事的时候,价值远超任何架构图。

5.3 权限与密钥:最容易被忽略的高危项

权限这块,新人最容易犯的错是"图省事全给管理员"。短期看没成本,长期看是把所有鸡蛋放在一个篮子里。

最小权限的落地,我的建议是按角色划分,而不是按人划分:

  • 只读角色:能看监控、能看日志,不能改任何配置。给值班和排查用。
  • 运维角色:能重启、能扩缩容、能改配置,不能删数据、不能改权限。
  • 管理角色:能改权限、能删资源。日常不用,需要时临时申请,用完收回。

密钥管理上,有几条是硬规矩:密钥不写进代码、不提交到仓库、不放在镜像里;用平台提供的密钥托管服务,或者至少用环境变量注入;密钥定期轮换,并且轮换流程要能在线完成,不需要停服务。

还有一个经常被忽略的点:离职和转岗时的权限回收。这件事必须流程化,不能靠记忆。我见过一个账号在人员离开半年后仍然有效,而它挂着的是一组相当宽的权限。

5.4 六个高频踩坑点与处理办法

最后把这些年重复见到的问题集中列一下,都是新手阶段大概率会遇到的:

坑一:磁盘被日志写满。表现是服务突然全部异常,登录上去发现磁盘百分百。原因通常是没配日志轮转。处理办法是配置按大小和按天双重轮转,同时加一条磁盘使用率超过百分之八十的告警。

坑二:安全组改错把自己关在门外。表现是 SSH 突然连不上,控制台也进不去。预防办法是改安全组之前先确认有另一条可用的访问路径(比如带外管理或者另一台跳板机),并且改完立刻验证,别一次改一堆。

坑三:数据库连接池耗尽。表现是应用大量超时,数据库本身却看起来正常。原因往往是连接没有正确释放,或者最大连接数配置得比数据库允许的还高。排查时先看连接数的实时曲线,再看慢查询。

坑四:时区不一致导致数据错乱。表现是统计数据对不上、定时任务在错误的时间触发。根源是部分机器用 UTC、部分用本地时区。统一时区、统一用 UTC 存储时间戳,是成本最低的解决方案。

坑五:单点依赖。表现是某个不起眼的内部服务挂掉,导致整条链路不可用。这类问题在架构图上看不出来,只有做故障演练才会暴露。定期做一次"随机干掉一个组件"的演练,能找出很多隐藏的单点。

坑六:镜像里的配置和线上不一致。表现是扩容出来的新机器行为异常。根源是手工改过线上机器但没回写镜像或脚本。解决办法只有一个:禁止手工改线上,所有变更走脚本或配置管理,临时改动也要在二十四小时内固化回代码。

这六个坑有个共同特点:都不是技术难题,都是流程缺失。所以真正的解决办法不是记住这六条,而是建立一套"改动有记录、配置有版本、异常有告警、恢复有演练"的习惯。

我个人在实际操作中的体会是,云这个东西入门门槛其实不高,开一台机器、跑一个服务,一两个小时就能搞定。真正拉开差距的是后面的三件事:知不知道自己用了什么、知不知道自己花了多少、知不知道自己挂的时候怎么办。这三件事都不需要多深的技术,需要的是把资源当成有主人的东西来管,把账单当成需要解释的东西来看,把故障当成一定会发生的事情来准备。我见过太多项目在功能上做得飞快,却在第一次流量高峰或者第一次硬件故障时手忙脚乱,回头补的课远比当初多花的那些时间要贵。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进