AWS EC2 RI(预留实例) 付费优化
AWS EC2 预留实例(Reserved Instance, 下文统一简称 RI) 简单来说就是虚拟机包年, 一次性缴纳一年的费用折扣非常诱人, 比按需启动(也就是按小时计费) 便宜非常多, 但如何知道该买多少个 RI 呢? 尤其公司开始增长, 数据开发人员经常会按需启动一些计算集群的情况下, 如何优化购买策略达到节省开支的目的?
找了一圈也没有成熟的方案(有知道的可以随时告诉我, 感激不尽), 利用一些时间自己写了一个 ‘基于使用历史优化 RI 购买’ 的方案, 简单来说就是
让开发
可劲儿造
, 根据一段时间的使用历史, 后续去购买 RI
先说说 AWS 现状
- 每个实例按小时计费, 不足一小时按照一小时计费 (注意是每个实例, 比如 t2.micro 类型实例在一个小时内启动两个(启动一个, terminate 后再启动一个, 再 terminate 要算两个小时)
- 每个启动的 EC2 实例都有唯一的一个ID: instance id
- 虚拟机启动’慢’, 基本上启动一个节点要1分钟+
- 所有的 EC2 信息可以通过 API 很容易拿到
- RI 针对的是对应的 AvailabilityZone 的相应类型, 比如在 cn-north-1a 购买的t2.micro RI 对 cn-north-1b 的 t2.micro 实例没有用
第一种思路: 官方账单
可以在账户中设置导出账单, 指定一个 S3 bucket , 每个月会以 csv 文件的方式导出详细账单. 推荐大家都开启这个功能. 但这个账单没有官方规范, 貌似一个月才出一次, 不能等到 on demand 付费了一个月才想起买RI 很不划算.
第二种思路: 自行记录是否买过 RI
单独写 Excel 也好, 或者在 EC2 上使用 tag 方式标记也好, 但这个终究是靠人力, 忘记标记/标记错误都是事儿. 如果使用tag 的方式, 如果这个 EC2 实例被 terminate 替换了(云计算的优势不就是玩儿坏了重来快么 >;<) 导致 tag 丢失等问题也是麻烦. 靠人力办事, 不推荐
第三种思路: 根据使用历史日志, 优化购买 RI
实现很简单, 跟 把大象放进冰箱
一样, 仅需3步:
- 每隔2分钟 dump 正在运行的 EC2 实例的日志, 扔进数据仓库.
- 每隔几天运行分析脚本, 生成带图的 Excel
- 瞅一眼 Excel, 看哪种类型的 EC2 实例需要买 RI 赶紧买
1. dump 日志
使用 aws ec2 describe-instances
很方便获取所有在运行的 EC2 实例信息, JSON 格式非常容易解析. 重要的字段有如下几个:
- InstanceId, 全局唯一ID
- State, 实例状态, 只有
running
的才会被计费, 需要过滤一下 - AvailabilityZone, az 信息, 包含 aws region 信息.
- LaunchTime, 启动时间
- Tags, 实例上的标签, 后续可以根据 Tag 按部门/系统分析使用状况
- dump_time, 本次 dump 日志的时间. 这个字段 JSON 中没有, 相当于给本次 dump 记录一个时间
解析后直接扔数据仓库. 刚刚不是说过 AWS EC2 启动慢, 所以每隔2分钟dump一次所有运行时的 EC2 日志, 一定不会错过任何启动的 EC2 节点. 其实推荐将整个 JSON 都存储下来, 后续可以有其他用处.
为何采用 dump 日志的方式, 比如 cloudtrail 也可以获取相关数据?
因为简单! 几行代码就搞定, 数据仓库是现成儿的. 扔进去就可以用 SQL 分析.
2. 分析报告
写一个脚本, 根据时间范围分析日志, 获取每小时每个类型的 EC2 实例运行个数, 以及 已经购买的 AWS RI 现状, 计算差值并画图.
比如这个 Query:
SELECT concat(substr(dump_time, 1, 13), ':00:00') AS instance_hour,
az,
instance_type,
count(DISTINCT instance_id) AS cnt
FROM testdb.aws_instance_log
WHERE data_date BETWEEN '2016-02-11' AND '2016-02-15'
AND json_extract_scalar(raw_json, '$.State.Name') = 'running'
GROUP BY concat(substr(dump_time, 1, 13), ':00:00'),
instance_type,
az
ORDER BY az,
instance_type,
instance_hour
是计算 2016-02-11 至 2016-02-15 日之间的实例使用状况. 然后根据结果生成 Excel 并画一个三条线的线图: 一条是运行的实例数量, 一条是已经购买的该类型的实例数量, 还有一条就是需要买的 RI
3. 购买 RI
别搞错 AvailabilityZone 就好了.
一点想法
由于 RI 是针对某个 AvailabilityZone 的某个类型的节点, 因此, 尽量使用少类型的 EC2 节点有时可以节省成本. 比如A系统需要 c3.4xlarge 类型节点10台, B 系统需要20台 c3.2xlarge, 如果有可能, 是不是可以都用一个类型的节点, 购买同样的 RI, 等到系统 resize了还可以空余 RI 给其他系统. 针对 AvailabilityZone, 如果不需要高可用, 尽量在同一个 AvailabilityZone, 比如计算密集型的系统.
总结
云计算这种形式的确带来了很大效率的提升, 但至于如何节省成本, 还是要看如何做容量规划, 省钱还是要靠小算盘.
容易扩容也意味着容易浪费
比如, 之前物理机/租机房时代, 公司上架服务器慢, 做数据开发临时跑大计算想扩容有钱都花不出去, 只能在现有集群上慢慢等, 慢慢优化; 现在用了 AWS, 随随便便加计算资源只要计算集群做得好, 非常容易, 如果不做限制, 大家都想快出结果因此 on demand 启动大量节点计算, 虽说节省了时间, 但由于随机性太大无法购买 RI 节省成本. 总体来说还是有可能浪费.