AWS Compute Optimizer のレコメンデーションを AWS CLI で CSV 出力してみた
コンバンハ、千葉(幸)です。
AWS Compute Optimizer は、 AWS リソースの設定と使用率のメトリクスを分析し、ワークロードの最適利用を推奨してくれるサービスです。
一定期間 継続稼働している以下リソースに対して、インスタンスタイプやボリュームタイプといったリソースのプロビジョニングが最適かどうかを表示してくれます。
- EC2 インスタンス
- AutoScaling グループ
- EBS ボリューム
- Lambda 関数
分析結果の推奨事項であるレコメンデーションはマネジメントコンソールから確認するのがお手軽ですが、報告用に別の形式にして出力したい・数が多いので必要な情報に絞って出力したい、という場面があるかもしれません。
そんな時はそう……、AWS CLI の出番ですね。
どのコマンドを叩くとどのような結果が返ってくるか、必要な情報だけに絞りたい時にはどう指定したらいいかの使い心地を確認していきます。
AWS Compute Optimizer レコメンデーションのエクスポート
AWS CLI の出番、と言っておきながらいきなり翻すようですが、レコメンデーションはコンソールから csv 形式でエクスポートすることもできます。
ポチッと押せばダウンロードが始まる……わけでなく、出力先の S3 バケットや結果に含める項目を選択する必要があります。
特に S3 バケットは、バケットポリシーで以下のようにサービスプリンシパルcompute-optimizer.amazonaws.com
からのアクセスを許可しておく必要があります。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": {"Service": "compute-optimizer.amazonaws.com"}, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::myBucketName" }, { "Effect": "Allow", "Principal": {"Service": "compute-optimizer.amazonaws.com"}, "Action": "s3:GetBucketPolicyStatus", "Resource": "arn:aws:s3:::myBucketName" }, { "Effect": "Allow", "Principal": {"Service": "compute-optimizer.amazonaws.com"}, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::myBucketName/[optional prefix]/compute-optimizer/myAccountID/*", "Condition": {"StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control", "aws:SourceAccount": "myAccountID", "aws:SourceArn": "arn:aws:compute-optimizer:myRegion:myAccountID:*" } } } ] }
のっぴきならない事情があって、バケットポリシーを修正したり新規の S3 バケットを作成したりが気軽にできない環境もあることでしょう。そんなケースを想定し、別のアプローチを取ることにします。
aws compute-optimizer get-xxx-recommendations を使う
AWS CLI の aws compute-optimizer コマンドでは、 recommendation を Get するためのサブコマンドが各種リソースごとに用意されています。
- compute-optimizer — AWS CLI 2.2.39 Command Reference
- get-auto-scaling-group-recommendations
- get-ebs-volume-recommendations
- get-ec2-instance-recommendations
- get-lambda-function-recommendations
今回は、直近で私が試す機会があった以下の 3 つを取り上げます。
- get-ec2-instance-recommendations
- get-ebs-volume-recommendations
- get-auto-scaling-group-recommendations
(Lambda 関数はいいサンプルがありませんでした、、)
使用している AWS CLI のバージョンは以下です。
$ aws --version aws-cli/2.2.39 Python/3.8.8 Darwin/20.6.0 exe/x86_64 prompt/off
AWS CLI による出力結果を jq で csv 形式に変換してみます。
get-ec2-instance-recommendations
リファレンスはこちら。
アウトプットの例は以下です。
折り畳み
$ aws compute-optimizer get-ec2-instance-recommendations { "instanceRecommendations": [ { "instanceArn": "arn:aws:ec2:ap-northeast-1:012345678910:instance/i-0000000000000000", "accountId": "012345678910", "instanceName": "EXAMPLENAME", "currentInstanceType": "m5.large", "finding": "OVER_PROVISIONED", "findingReasonCodes": [ "CPUOverprovisioned", "EBSIOPSOverprovisioned", "EBSThroughputOverprovisioned", "NetworkBandwidthOverprovisioned", "NetworkPPSOverprovisioned" ], "utilizationMetrics": [ { "name": "CPU", "statistic": "MAXIMUM", "value": 7.399999999999999 }, { "name": "MEMORY", "statistic": "MAXIMUM", "value": 10.202603632391153 }, { "name": "EBS_READ_OPS_PER_SECOND", "statistic": "MAXIMUM", "value": 0.013333333333333334 }, { "name": "EBS_WRITE_OPS_PER_SECOND", "statistic": "MAXIMUM", "value": 4.253333333333333 }, { "name": "EBS_READ_BYTES_PER_SECOND", "statistic": "MAXIMUM", "value": 29.296875 }, { "name": "EBS_WRITE_BYTES_PER_SECOND", "statistic": "MAXIMUM", "value": 827996.4192708334 }, { "name": "NETWORK_IN_BYTES_PER_SECOND", "statistic": "MAXIMUM", "value": 16982.868055555555 }, { "name": "NETWORK_OUT_BYTES_PER_SECOND", "statistic": "MAXIMUM", "value": 96.98083333333334 }, { "name": "NETWORK_PACKETS_IN_PER_SECOND", "statistic": "MAXIMUM", "value": 2.447388888888889 }, { "name": "NETWORK_PACKETS_OUT_PER_SECOND", "statistic": "MAXIMUM", "value": 0.4082777777777778 } ], "lookBackPeriodInDays": 14.0, "recommendationOptions": [ { "instanceType": "t3.micro", "projectedUtilizationMetrics": [ { "name": "CPU", "statistic": "MAXIMUM", "value": 7.399999999999999 }, { "name": "MEMORY", "statistic": "MAXIMUM", "value": 81.62082905912922 } ], "performanceRisk": 3.0, "rank": 1 }, { "instanceType": "t3.small", "projectedUtilizationMetrics": [ { "name": "CPU", "statistic": "MAXIMUM", "value": 7.399999999999999 }, { "name": "MEMORY", "statistic": "MAXIMUM", "value": 40.81041452956461 } ], "performanceRisk": 3.0, "rank": 2 }, { "instanceType": "t3.medium", "projectedUtilizationMetrics": [ { "name": "CPU", "statistic": "MAXIMUM", "value": 7.399999999999999 }, { "name": "MEMORY", "statistic": "MAXIMUM", "value": 20.405207264782305 } ], "performanceRisk": 3.0, "rank": 3 } ], "recommendationSources": [ { "recommendationSourceArn": "arn:aws:ec2:ap-northeast-1:012345678910:instance/i-0000000000000000", "recommendationSourceType": "Ec2Instance" } ], "lastRefreshTimestamp": "2021-08-13T18:26:26.010000+09:00" }, ........ ], "errors": [] }
--filters
で使えるname
とvaluse
の組み合わせは以下の通りです。
name | values |
---|---|
Finding | Underprovisioned , Overprovisioned , Optimized |
RecommendationSourceType | Ec2Instance , AutoScalingGroup |
FindingReasonCodes | 多数(以下参照) |
FindingReasonCodes
の値として指定できるコードは以下です。
CPUOverprovisioned CPUUnderprovisioned MemoryOverprovisioned MemoryUnderprovisioned EBSThroughputOverprovisioned EBSThroughputUnderprovisioned EBSIOPSOverprovisioned EBSIOPSUnderprovisioned NetworkBandwidthOverprovisioned NetworkBandwidthUnderprovisioned NetworkPPSOverprovisioned NetworkPPSUnderprovisioned DiskIOPSOverprovisioned DiskIOPSUnderprovisioned DiskThroughputOverprovisioned DiskThroughputUnderprovisioned
コマンド例
「最適化済み」以外のレコメンデーションを以下項目のみ表示する場合の例です。
- インスタンス ARN
- インスタンス名
- 現在のインスタンスタイプ
- 結果
- 推奨のインスタンスタイプ(オプション1)
$ aws compute-optimizer get-ec2-instance-recommendations\ --filters name=Finding,values=Underprovisioned,Overprovisioned\ | jq -r ' ["インスタンスARN","インスタンス名","現在のインスタンスタイプ","結果","推奨のインスタンスタイプ"], (.instanceRecommendations[] | [.instanceArn,.instanceName,.currentInstanceType,.finding,.recommendationOptions[0].instanceType]) | @csv' > result.csv
CSV ヘッダレコードは 4 行目で任意のものを指定しているため、省略・変更が可能です。
出力結果の例は以下の通りです。
get-ebs-volume-recommendations
リファレンスはこちら。
アウトプットの例は以下です。
折り畳み
$ aws compute-optimizer get-ebs-volume-recommendations { "volumeRecommendations": [ { "volumeArn": "arn:aws:ec2:ap-northeast-1:012345678910:volume/vol-0d0b8ddxxxxxxxxxx", "accountId": "012345678910", "currentConfiguration": { "volumeType": "gp3", "volumeSize": 800, "volumeBaselineIOPS": 3000, "volumeBurstIOPS": 3000, "volumeBaselineThroughput": 250, "volumeBurstThroughput": 250 }, "finding": "NotOptimized", "utilizationMetrics": [ { "name": "VolumeReadOpsPerSecond", "statistic": "Maximum", "value": 2464.34 }, { "name": "VolumeWriteOpsPerSecond", "statistic": "Maximum", "value": 615.7633333333333 }, { "name": "VolumeReadBytesPerSecond", "statistic": "Maximum", "value": 226064433.59375 }, { "name": "VolumeWriteBytesPerSecond", "statistic": "Maximum", "value": 16606290.690104166 } ], "lookBackPeriodInDays": 14.0, "volumeRecommendationOptions": [ { "configuration": { "volumeType": "gp3", "volumeSize": 800, "volumeBaselineIOPS": 3000, "volumeBurstIOPS": 3000, "volumeBaselineThroughput": 145, "volumeBurstThroughput": 145 }, "performanceRisk": 2.0, "rank": 1 }, { "configuration": { "volumeType": "gp3", "volumeSize": 800, "volumeBaselineIOPS": 3000, "volumeBurstIOPS": 3000, "volumeBaselineThroughput": 177, "volumeBurstThroughput": 177 }, "performanceRisk": 1.0, "rank": 2 } ], "lastRefreshTimestamp": "2021-09-18T18:20:52.372000+09:00" }, ...... ], "errors": [ { "identifier": "arn:aws:ec2:ap-northeast-1:012345678910:volume/vol-010xxxxxxxxxx", "code": "UNSUPPORTED_CONFIGURATION", "message": "Unsupported volume type with type sc1." } ] }
--filters
で使えるname
とvaluse
の組み合わせは以下の通りです。
name | values |
---|---|
Finding | Optimized , NotOptimized |
コマンド例
「最適化されていない」レコメンデーションの以下項目を表示する場合のコマンド例は以下です。
- ボリューム ARN
- 現在の設定
- ボリュームタイプ
- ボリュームサイズ
- ボリュームベースライン IOPS
- ボリュームバースト IOPS
- ボリュームベースラインスループット
- ボリュームバーストスループット
- 推奨の設定(オプション1)
- ボリュームタイプ
- ボリュームサイズ
- ボリュームベースライン IOPS
- ボリュームバースト IOPS
- ボリュームベースラインスループット
- ボリュームバーストスループット
$ aws compute-optimizer get-ebs-volume-recommendations\ --filters name=Finding,values=NotOptimized\ | jq -r ' (.volumeRecommendations[] | [.volumeArn,.currentConfiguration[],.finding,.volumeRecommendationOptions[0].configuration[]]) | @csv' | pbcopy
項目数が多いのでヘッダーレコードの指定は省略しました。また、わたしは Mac を使用しているため pbcopy を用いてクリップボードにコピーする、というパターンもよく使用します。
出力結果の例は以下の通りです。
get-auto-scaling-group-recommendations
リファレンスはこちら。
アウトプットの例は以下です。
折り畳み
$ aws compute-optimizer get-auto-scaling-group-recommendations { "autoScalingGroupRecommendations": [ { "accountId": "012345678910", "autoScalingGroupArn": "arn:aws:autoscaling:ap-northeast-1:012345678910:autoScalingGroup:562xxxxx-fxxx-4xxx-9xxx-fbaxxxxxxxx:autoScalingGroupName/EXAMPLENAME", "autoScalingGroupName": "EXAMPLENAME", "finding": "OPTIMIZED", "utilizationMetrics": [ { "name": "CPU", "statistic": "MAXIMUM", "value": 41.825 }, { "name": "EBS_READ_OPS_PER_SECOND", "statistic": "MAXIMUM", "value": 0.04 }, { "name": "EBS_WRITE_OPS_PER_SECOND", "statistic": "MAXIMUM", "value": 5.4 }, { "name": "EBS_READ_BYTES_PER_SECOND", "statistic": "MAXIMUM", "value": 768.2291666666666 }, { "name": "EBS_WRITE_BYTES_PER_SECOND", "statistic": "MAXIMUM", "value": 860442.7083333334 }, { "name": "NETWORK_IN_BYTES_PER_SECOND", "statistic": "MAXIMUM", "value": 23469.210000000003 }, { "name": "NETWORK_OUT_BYTES_PER_SECOND", "statistic": "MAXIMUM", "value": 19396.498055555556 }, { "name": "NETWORK_PACKETS_IN_PER_SECOND", "statistic": "MAXIMUM", "value": 24.26527777777778 }, { "name": "NETWORK_PACKETS_OUT_PER_SECOND", "statistic": "MAXIMUM", "value": 22.950833333333332 } ], "lookBackPeriodInDays": 14.0, "currentConfiguration": { "desiredCapacity": 1, "minSize": 1, "maxSize": 1, "instanceType": "m5.large" }, "recommendationOptions": [ { "configuration": { "desiredCapacity": 1, "minSize": 1, "maxSize": 1, "instanceType": "m5.large" }, "projectedUtilizationMetrics": [ { "name": "CPU", "statistic": "MAXIMUM", "value": 41.825 } ], "performanceRisk": 1.0, "rank": 1 }, { "configuration": { "desiredCapacity": 1, "minSize": 1, "maxSize": 1, "instanceType": "m5n.large" }, "projectedUtilizationMetrics": [ { "name": "CPU", "statistic": "MAXIMUM", "value": 41.825 } ], "performanceRisk": 1.0, "rank": 2 }, { "configuration": { "desiredCapacity": 1, "minSize": 1, "maxSize": 1, "instanceType": "m5zn.large" }, "projectedUtilizationMetrics": [ { "name": "CPU", "statistic": "MAXIMUM", "value": 30.061718749999997 } ], "performanceRisk": 1.0, "rank": 3 } ], "lastRefreshTimestamp": "2021-09-18T18:03:51.563000+09:00" }, ...... ], "errors": [] }
--filters
で使えるname
とvaluse
の組み合わせは以下の通りです。
name | values |
---|---|
Finding | Optimized , NotOptimized |
RecommendationSourceType | Ec2Instance , AutoScalingGroup |
リファレンスではFindingReasonCodes
を使用できるとありますが、AWS CLI の v2.2.39 では以下のようなエラーが発生しました。
$ aws compute-optimizer get-auto-scaling-group-recommendations\ --filters name=FindingReasonCodes,values=CPUOverprovisioned An error occurred (InvalidParameterValueException) when calling the GetAutoScalingGroupRecommendations operation: Invalid filter value.
アウトプットには get-ec2-instance-recommendations と異なりfindingReasonCodes
が含まれていないので、現状のバージョンでは使用できないものと思います。
コマンド例
すべてのレコメンデーションに対して以下項目を出力する場合の例です。
- AutoScaling名
- 結果
- 現状の設定
- 希望の容量
- 最小台数
- 最大台数
- インスタンスタイプ
- 推奨の設定(オプション1)
- 希望の容量
- 最小台数
- 最大台数
- インスタンスタイプ
$ aws compute-optimizer get-auto-scaling-group-recommendations\ | jq -r ".autoScalingGroupRecommendations[] | [.autoScalingGroupName,.finding,.currentConfiguration[],.recommendationOptions[0].configuration[]] | @csv" | pbcopy
出力結果の例は以下です。
余談ですが、Compute Opimizer による分析対象となる AutoScaling グループは 希望の容量/最小台数/最大台数 が同一のものである必要があります。
こういった要件は以下から確認できます。
終わりに
AWS Compute Optimizer レコメンデーションを AWS CLI で出力してみました。jq と組み合わせることで、csv 形式での出力にも対応できます。
単発での実行を考えると、わざわざコマンドを組み立てるよりはマネジメントコンソールからエクスポートした方がお手軽かと思います。
エクスポート先の S3 バケットを準備するのにハードルがある、何度も実行したいため都度エクスポートしたくない、という場合には本エントリのコマンドをご参考ください。
以上、 チバユキ (@batchicchi) がお送りしました。