云成本优化:停止为你的MVP过度付费
大多数初创公司浪费了40-60%的云预算。这是一份实用的指南,教你如何在不牺牲可靠性的前提下,调整基础设施规模。

上个季度,我审计了一家初创公司的AWS账单,发现他们每月在基础设施上花费2,800美元,而这些基础设施本可以轻松地以900美元运行。他们有一台t3.2xlarge实例运行一个Node.js API,CPU利用率峰值仅为12%。三个未使用的弹性IP地址闲置着,每个每月花费3.65美元。一个用于只有200行数据的数据库的RDS多可用区部署。一个NAT网关路由着本可以通过VPC端点免费传输的流量。所有这些都不是恶意甚至特别粗心造成的——这只是在冲刺发布产品期间,一系列“先搞个能用的”决策累积的结果。
这并非例外,而是常态。大多数早期初创公司浪费了40-60%的云支出,因为当有功能需要发布时,团队中没有人有时间或动力去优化成本。问题会不断加剧:一旦基础设施配置并运行起来,就没人会去动它了。
我经常看到的最大的成本陷阱
在深入探讨解决方案之前,了解资金实际流向何处会有所帮助。这些是我在审查初创公司基础设施时最常遇到的陷阱。
过度配置的计算实例
这是最大的浪费来源。团队在初始设置时选择一个实例大小——通常是基于一篇博客文章或“以防万一”的心态——然后就再也不会重新审视它。我见过m5.xlarge实例运行每小时执行30秒的cron作业。该实例闲置59.5分钟,每小时消耗0.192美元(每月140美元),基本上什么也没做。
根本原因是心理上的:没有人想成为那个配置不足导致服务中断的人。所以每个人都会向上取整。两次。
# Check your EC2 instance CPU utilization over the past 2 weeks
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=i-0abcdef1234567890 \
--start-time $(date -u -d '14 days ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--period 3600 \
--statistics Average Maximum
如果你的平均CPU利用率低于20%,峰值低于50%,那么你几乎可以肯定配置过度了。降低一到两个实例大小,监控一周,然后进行调整。
被遗忘的EBS卷和快照
当你终止一个EC2实例时,除非你在启动时进行了配置,否则附加的EBS卷不会自动删除。这意味着终止的实例会留下孤立的卷,并持续产生费用。我见过一些账户有几十个未附加的gp3卷,每个每月花费0.08美元/GB,总计数百美元用于无人使用的存储。
快照甚至更隐蔽。自动化备份脚本每天创建快照,但没有生命周期策略,因此它们会无限期地累积。一个500GB的卷每天进行快照,一年会生成365个快照,虽然EBS快照是增量的,但成本会累积成一笔可观的费用。
# Find all unattached EBS volumes
aws ec2 describe-volumes \
--filters Name=status,Values=available \
--query 'Volumes[*].{ID:VolumeId,Size:Size,Created:CreateTime}' \
--output table
# Find snapshots older than 90 days
aws ec2 describe-snapshots \
--owner-ids self \
--query 'Snapshots[?StartTime<=`2025-12-01`].{ID:SnapshotId,Size:VolumeSize,Date:StartTime}' \
--output table
NAT网关:无声的预算杀手
NAT网关仅存在就需要花费0.045美元/小时(32.40美元/月),外加每处理1GB数据0.045美元。对于一家从私有子网频繁调用外部API服务的初创公司来说,仅数据处理费用就可能超过每月100美元。我见过NAT网关费用占小型初创公司AWS总账单的15-20%。
解决方案取决于流经NAT的流量类型:
- 流向AWS服务的流量(S3、DynamoDB、SQS): 使用VPC网关端点(S3和DynamoDB免费)或接口端点(每个每月7.20美元,但对于高流量仍比NAT便宜)。
- 来自Lambda函数的互联网流量: 考虑这些函数是否真的需要在VPC中。许多Lambda函数在不访问任何VPC资源的情况下,出于“安全”目的被放置在VPC中。
- 低流量出站流量: t4g.nano上的NAT实例(每月3.02美元)可以以NAT网关成本的一小部分处理适度的流量。
数据传输费用
AWS对离开区域的数据收取0.09美元/GB的费用,跨可用区流量双向收取0.01美元/GB的费用。这些费用在不被注意时是隐形的,一旦被注意就会显现。一个跨三个可用区部署的、服务之间每秒调用数百次的“健谈”微服务架构,可能会产生惊人的数据传输账单。
架构解决方案:对于非关键工作负载,将频繁通信的服务部署在同一个可用区中,或者使用具有可用区亲和性的内部负载均衡器。
合理调整规模:系统化方法
合理调整规模并非一次性工作。你应该每季度重新审视它。以下是我遵循的流程。
步骤1:收集利用率数据
AWS Compute Optimizer是免费的,并为EC2、EBS、Lambda和ECS提供合理调整规模的建议。启用它并让它收集至少14天的数据,然后再根据其建议采取行动。
为了进行更精细的分析,CloudWatch指标是你的主要数据源。需要关注的关键指标有:
- EC2: CPUUtilization、NetworkIn/Out、MemoryUtilization(需要CloudWatch代理)
- RDS: CPUUtilization、DatabaseConnections、FreeableMemory、ReadIOPS、WriteIOPS
- ElastiCache: CPUUtilization、CurrConnections、BytesUsedForCache
步骤2:对工作负载进行分类
并非所有工作负载都应以相同的方式进行规模调整。我将它们分为三类:
稳定工作负载(API服务器、数据库):这些需要一致的容量。通过找到能够处理峰值负载并留有30%余量的最小实例来调整规模。对基线使用预留实例(Reserved Instances)或节省计划(Savings Plans)。
可变工作负载(批处理、构建服务器):这些应该使用具有适当扩展策略的自动扩展组(Auto Scaling Groups),或者对容错批处理作业使用竞价实例(Spot Instances)。
周期性工作负载(cron作业、计划报告):这些根本不应该在专用实例上运行。将它们迁移到Lambda、Fargate Spot或Step Functions。
步骤3:增量行动
切勿一次性调整所有资源的规模。每次只降低一个实例大小,监控一周,然后决定是否进一步调整。短暂的过度配置期所产生的成本远低于因激进缩减规模而导致的生产中断所产生的成本。
预留实例 vs 节省计划 vs 竞价实例
这是真正节省成本的地方——比按需定价节省30-72%——但承诺机制足够复杂,以至于许多初创公司完全避开它们。
预留实例 (RIs)
你承诺在特定区域使用特定实例类型1年或3年。作为交换,你可以获得30-40%(无预付,1年)到60%(全预付,3年)的折扣。问题是:如果你需要更改实例类型,标准RI不灵活。可转换RI提供更大的灵活性,但折扣略低(3年全预付约45%)。
何时使用RI: 数据库和其他实例类型和大小真正稳定的工作负载。RDS预留实例几乎总是值得的——数据库很少改变大小。
节省计划
节省计划是计算型RI的现代替代方案。你承诺在1年或3年内每小时支付一定金额的计算费用(例如,0.10美元/小时)。该承诺自动适用于EC2、Fargate和Lambda的使用,并且在实例系列、大小、操作系统和区域之间都具有灵活性。
何时使用节省计划: 对于计算工作负载,几乎总是优于EC2 RI。计算节省计划提供了最佳的灵活性与折扣比。从覆盖你的最低基线支出的承诺开始。
# Example: Calculating Savings Plan commitment
# Current on-demand spend: $500/month on EC2
# Minimum baseline (never drops below): $350/month
# Recommended Savings Plan commitment: $350/month = ~$0.48/hour
# Expected savings: ~30% on the committed amount = ~$105/month
# Remaining $150/month stays on-demand for flexibility
竞价实例
竞价实例提供60-90%的折扣,但可能会在2分钟通知后中断。它们非常适合:
- CI/CD构建代理(使用具有多种实例类型的Spot Fleet)
- 可以检查点和恢复的批处理作业
- 开发和测试环境
- 负载测试
它们不适用于生产API服务器、数据库或任何无法处理突然终止的服务。
# Example: GitHub Actions self-hosted runner on Spot
# This saves roughly 70% compared to GitHub-hosted runners
# for compute-heavy builds
Resources:
SpotFleet:
Type: AWS::EC2::SpotFleet
Properties:
SpotFleetRequestConfigData:
IamFleetRole: !GetAtt SpotFleetRole.Arn
TargetCapacity: 2
AllocationStrategy: lowestPrice
LaunchSpecifications:
- InstanceType: c5.xlarge
SpotPrice: "0.06"
- InstanceType: c5a.xlarge
SpotPrice: "0.06"
- InstanceType: c6i.xlarge
SpotPrice: "0.06"
无服务器成本模型:并非总是更便宜
有一个普遍的误解,认为无服务器对初创公司来说总是更便宜。在低规模时它通常更便宜,但随着流量增长,经济效益会发生变化。
Lambda定价真相
Lambda按请求(每百万次0.20美元)和每GB-秒计算(0.0000166667美元)收费。对于一个运行200毫秒、使用256MB内存的典型API端点:
- 1,000次请求/天: 约0.03美元/月。基本免费。
- 100,000次请求/天: 约3.00美元/月。仍然非常便宜。
- 1,000,000次请求/天: 约30美元/月。开始与小型EC2实例相当。
- 10,000,000次请求/天: 约300美元/月。一个带有适当缓存的t3.medium实例(30美元/月)可以轻松处理此流量。
盈亏平衡点在很大程度上取决于执行持续时间和内存分配,但对于大多数API工作负载,Lambda在每天1-5百万次请求之间就不再具有成本效益了。低于这个阈值,它几乎总是最便宜的选择。
API Gateway成本累积
人们常常忘记,API Gateway后面的Lambda函数会产生额外费用。API Gateway每百万次请求收费3.50美元(REST API)或1.00美元(HTTP API)。在大规模情况下,API Gateway的成本会超过Lambda的成本。如果你运行的流量大到需要担心Lambda成本,那么你应该使用Application Load Balancer(每LCU-小时0.008美元)而不是API Gateway。
Fargate:中间地带
AWS Fargate在成本和操作复杂性方面介于Lambda和EC2之间。你按秒支付vCPU和内存费用,无需管理实例。对于需要持续运行但你不想管理服务器的工作负载,带有竞价容量提供商的Fargate提供了一个很好的平衡。
一个具有0.25 vCPU和0.5GB内存的Fargate任务持续运行每月大约花费9美元。这与t4g.nano具有竞争力,并且你无需管理底层主机即可获得自动放置、健康检查和扩展功能。
成本监控与警报
你无法优化你没有衡量的事物。以下是我为每个项目设置的监控堆栈。
AWS成本浏览器
启用成本浏览器(Cost Explorer),并设置每月预算,在50%、80%和100%的阈值处设置警报。这是最低限度。成本浏览器的“按服务成本”视图会立即显示资金流向。
# Create a budget with email alerts
aws budgets create-budget \
--account-id 123456789012 \
--budget '{
"BudgetName": "Monthly-Total",
"BudgetLimit": {"Amount": "500", "Unit": "USD"},
"TimeUnit": "MONTHLY",
"BudgetType": "COST"
}' \
--notifications-with-subscribers '[{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 80,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [{
"SubscriptionType": "EMAIL",
"Address": "team@startup.com"
}]
}]'
用于基础设施即代码的Infracost
如果你使用Terraform,Infracost可以集成到你的CI管道中,并在每次基础设施更改应用之前显示成本估算。这是变革性的——它将成本意识从每月的意外转变为拉取请求对话。
# .github/workflows/infracost.yml
name: Infracost
on: pull_request
jobs:
infracost:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Infracost
uses: infracost/actions/setup@v3
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- name: Generate cost estimate
run: |
infracost breakdown --path=. \
--format=json --out-file=/tmp/infracost.json
infracost comment github \
--path=/tmp/infracost.json \
--repo=$GITHUB_REPOSITORY \
--pull-request=${{ github.event.pull_request.number }} \
--github-token=${{ secrets.GITHUB_TOKEN }}
成本异常检测
AWS成本异常检测(Cost Anomaly Detection)使用机器学习来识别异常的支出模式。它是免费的,并在支出偏离历史模式时发送警报。为每个服务启用它,并设置SNS通知到Slack。
省钱的架构模式
除了合理调整单个资源的规模,某些架构决策会从根本上改变你的成本结构。
积极缓存
在你的API前端使用CloudFront分发来缓存可缓存的响应,每10,000次HTTPS请求和每GB传输费用为0.085美元——但这可以避免这些请求到达你的后端。对于读密集型API(大多数都是),90%的缓存命中率意味着你的后端处理的流量减少了10倍。
更简单的方法是:像Redis这样的内存缓存,或者只是应用程序中的本地LRU缓存,都可以消除冗余的数据库查询。我曾见过在5个最常访问的端点上添加15分钟缓存后,数据库成本下降了60%。
智能使用S3
S3有多种存储类别,选择正确的类别很重要:
| 存储类别 | 成本/GB/月 | 用例 |
|---|---|---|
| S3 Standard | $0.023 | 活跃数据,频繁访问 |
| S3 Infrequent Access | $0.0125 | 备份,30天以上的日志 |
| S3 Glacier Instant | $0.004 | 需要即时访问的归档 |
| S3 Glacier Deep Archive | $0.00099 | 长期归档,不常访问 |
设置S3生命周期策略以自动在存储类别之间转换对象:
{
"Rules": [
{
"ID": "TransitionToIA",
"Status": "Enabled",
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER_INSTANT_RETRIEVAL"
}
]
}
]
}
托管服务 vs 自托管
这种权衡是微妙的。托管服务(RDS、ElastiCache、OpenSearch Service)的每单位计算成本高于在EC2上自托管,但它们包含了补丁、备份、故障转移和监控。对于没有专门运维人员的初创公司来说,节省的工程时间几乎总是值得支付额外费用的。
例外情况是:最高级别的托管服务。一个db.r6g.2xlarge的RDS实例比运行PostgreSQL的同等EC2实例成本高得多。一旦你拥有一个具备运维能力的团队,并且每月在单一托管服务上花费超过1,000美元,就值得评估自托管方案了。
尽可能整合
为预发布、QA和开发环境运行单独的RDS实例是昂贵的。可选方案:
- 对非生产环境使用一个带有独立数据库的RDS实例。
- 对开发/预发布环境使用Aurora Serverless v2——它在空闲时可以扩展到零。
- 在单个EC2竞价实例上使用Docker运行开发数据库。
一份真实的成本优化攻略
以下是我在承担成本优化项目时遵循的循序渐进的流程。这通常能在第一个月内实现30-50%的节省。
第1周:审计
- 如果尚未启用,请启用AWS成本浏览器(Cost Explorer)。
- 按服务拉取3个月的成本明细。
- 识别支出最高的5项服务。
- 运行AWS Compute Optimizer和Trusted Advisor。
- 列出所有未附加的EBS卷、未使用的弹性IP和闲置的负载均衡器。
第2周:快速见效
- 删除审计中识别出的未使用资源。
- 合理调整配置最过度的实例(降低一个大小,并监控)。
- 为S3和DynamoDB流量设置VPC端点。
- 在所有存储桶上启用S3生命周期策略。
- 设置预算警报。
第3周:承诺
- 分析稳定工作负载是否符合节省计划的条件。
- 为基线计算支出购买计算节省计划。
- 为生产数据库购买RDS预留实例。
- 将合适的工作负载转换为竞价实例。
第4周:架构
- 在适当的地方添加缓存层。
- 评估适合工作负载的无服务器迁移。
- 整合非生产环境。
- 在CI管道中设置Infracost。
- 记录成本基线以进行持续监控。
不应优化的事项
成本优化有递减效应,有些“节省”带来的问题比解决的问题更多。
不要为了成本牺牲可靠性。 为了节省多可用区费用而将生产数据库部署在单可用区是一种虚假的节约。第一次中断造成的损失将超过多年多可用区溢价的总和。
不要过度优化当前规模。 如果你的初创公司每月增长20%,那么花费一周时间优化每月50美元的服务并不是一个好的时间利用方式。专注于大额开销项目。
不要与云提供商的定价模型作对。 如果你违背AWS的惯例,它就会变得昂贵。按照其设计意图使用托管服务,利用免费套餐,并利用他们提供的承诺折扣。试图通过过于巧妙的架构来规避定价通常会适得其反。
不要为了省钱而移除监控。 CloudWatch会产生费用,但盲目运行会付出更高的代价。你每月花费15美元进行详细监控,将帮你避免详细监控本可以发现的500美元意外开销。
复利效应
早期成本优化的最大理由并非即时节省——而是你建立起来的习惯和基础设施。一家设置了预算警报、在CI中使用Infracost并每月审查成本的初创公司,将在规模扩展时保持高效的基础设施。而一家直到B轮融资才关注成本的初创公司,会发现自己每月面临30,000美元的AWS账单,需要六个月的专门努力才能理清。
从审计开始。数字会告诉你应该关注哪里。