云与基础设施
把云成本优化当作一门工程学科
云支出是架构决策与运维决策的产物,而不是每季度处理一次的财务问题。我们像对待延迟一样对待它:按单位工作量度量,由产生成本的团队负责,并在设计阶段就纳入预算。
· 阅读约 5 分钟 · Starone 工程团队
大多数降本行动都遵循同一个套路:账单越过某条线,有人被要求砍成本,删掉几台闲置实例,买一份承诺折扣,然后数字在接下来的几个月里慢慢涨回去。这种做法之所以失败,是因为它把成本当成一张发票,而不是系统本身的一项属性。
我们的立场是,成本应当与延迟、可用性归为同一类指标。它有预算,被持续度量,被归因到产生它的组件,并且在画设计图的时候就被考虑,而不是等系统跑起来之后再说。
从单位经济性入手,而不是看总额
一个月度总额无法告诉你系统是否高效。流量涨到三倍而账单只翻一倍,是好结果;用量下滑而账单持平,是坏结果。真正有用的数字是单位工作量的成本:每千次请求、每个活跃租户、每笔已处理交易、每 GB 摄入数据。
选择哪个单位是一项工程决策,因为它必须跟随真正驱动负载的因素。一旦确定,它的表现就和其他服务等级指标(SLI)没有区别:可以与部署记录叠加绘图,可以出现回退,回退也可以追溯到某一次变更。如果某个功能在每次请求上增加了一次对托管服务的同步调用,那么在上线当天,单次请求成本就会出现一个台阶,而这正是质疑它代价最低的时刻。
先归因,再优化
没有负责人的东西无从优化。我们的默认做法是,每个资源都带有所属团队、服务、环境和成本中心的标签,并且这些标签由基础设施即代码(IaC)模块自动打上,而不是靠约定。流水线中的策略会直接拒绝未打标签的资源,因为依赖记忆的标签纪律撑不过几周。
共享平台光靠标签还不够。一个 Kubernetes 集群或一个共享数据库在账单上只是一行,因此它的成本必须按命名空间的资源请求量、查询耗时或存储占用来分摊。分摊不可能完美。一个大致公平、团队看得见的模型,远比一个精确但来得太晚、已无法据此行动的模型有用。
先调整规格,再做承诺
顺序很重要。如果机群规模是合理值的两倍,却为它承诺一年或三年的容量,等于把浪费锁死。我们根据一段有代表性的周期内观测到的利用率来调整规格,看的是 CPU 和内存的高百分位而不是平均值,并且看的是真正先饱和的那项资源。一个受内存限制的服务,分配再多 CPU 也没有收益。
预留容量、节省计划(savings plans)这类承诺,随后才作为一种财务工具用在稳定基线上,也就是一周当中最安静的那个小时仍然存在的负载。用承诺去覆盖峰值,意味着为闲置的小时买单。可中断容量适合能够容忍被停止的工作:批处理作业、CI runner、队列后面的无状态 worker。它不适合主数据库,也不适合任何恢复时间长于中断通知期的组件。
由架构造成的账单条目
计算资源是账单上最显眼的部分,通常也最容易分析。真正让团队意外的条目来自设计决策,实例调优做得再多也消除不了。
- 数据传输:分散在多个可用区、调用频繁的服务,每一次跨可用区调用都要付费;经由 NAT 网关访问公网端点的流量,则按处理的 GB 数计费。私有端点和可用区感知路由属于设计选择,而不是调优。
- 存储分层:没有生命周期规则的对象存储,会让所有数据永远留在最贵的存储类别里。更冷的层级持有成本更低,但取回要收费,还有最短存储期限,因此适合很少被读取的数据。
- 可观测性:debug 级别的日志、高基数的指标标签和无限期保留,其成本可能超过它们所描述的工作负载本身。采样与保留期限都应当是有负责人的决策。
- 孤儿资源:未挂载的卷、旧快照、闲置的负载均衡器和被遗忘的非生产环境会不断堆积,除非有机制按计划清理它们。
自动伸缩是一个控制回路,需要调校
自动伸缩只有在依据能够反映需求的信号进行伸缩,并且缩容与扩容同样果断时,才能降低成本。对一个等待 I/O 的 worker 来说,CPU 是很差的信号;队列深度或单实例在途请求数通常更接近真实情况。启动慢就不得不留更大的缓冲,所以缩小镜像体积、减少预热工作,本身就是成本工作。
在 Kubernetes 上,调度器按 Pod 的资源请求(requests)而非实际用量来安排位置。虚高的 requests 会让节点看起来已满,实际却大部分闲置。对照实际用量审视 requests,往往比对节点池做任何调整都能回收更多容量。让非生产环境在工作时间之外缩容到零,是最简单的节省手段,前提是它们能够从代码可靠地重建。
什么时候不该优化
成本效率与其他属性相互竞争,有时它应当让步。余量是用来吸收流量尖峰或一个可用区失效的,因此一个以极高利用率运行的系统,其实是用韧性换了一张更小的账单。这种取舍应当是明确的、经过测试的,而不是激进伸缩策略带来的意外结果。
工程时间同样是成本。对于账单不大、市场尚未验证的早期产品,花一周时间抠基础设施开支,通常是把这一周用错了地方;单位成本更高的托管服务反而是正确选择,因为它们省掉了运维工作。我们主张的纪律是从一开始就做好度量与归属,把优化精力投到单位成本表明会有回报的地方。
- 当单位成本的上升速度快于用量,或者某一个账单条目占比过大却说不出明确理由时,应当优化。
- 当账单相对于团队时间而言很小,且架构仍在变化时,应当推迟。
- 当节省下来的恰恰是可用性目标所依赖的冗余或余量时,应当拒绝。
