2
2

More than 1 year has passed since last update.

CloudWatch から S3 のストレージ使用量推移を取得する(シェルスクリプト版 + Python版)

Last updated at Posted at 2022-02-09

はじめに

S3 の容量推移を取得する方法は色々あります

  • Cost Explorer で取得する

    Web コンソールの請求ダッシュボードから Cost Explorer を表示し、フィルタを以下のように指定すれば
    S3 の全バケットの使用量と、それによるコストの推移が表示されます

    • サービス=S3
    • 使用タイプグループ=Storage - Standard

    cost-explorer.png

  • CloudWatch で取得する

    Web コンソールの CloudWatch から「すべてのメトリクス」を表示し、
    S3 のバケット、 StandardStorage を選択すればバケット毎の使用量推移が表示されます

    cloudwatch.png

  • S3 Storage Lens で取得する

    S3 の統計情報を手軽に取得できる S3 Lens を使用すれば、より詳細なデータを取得できます
    バケット毎のストレージ容量などは無料分に含まれており、デフォルトで収集されています
    プレフィックスなどで集計する場合は有償で個別の設定を行います(設定後、48時間経過すると参照できるようになる)

    Web コンソールの S3 から「Storage Lens」の「ダッシュボード」を選択します
    デフォルトで「default-account-dashboard」が作られているので、これを選択します
    ※ただし、ルートユーザーでは参照できないようになっているので、IAMユーザーでサインインしてください

    s3-lens.png

ただし、これらは Web コンソールから表示する方法であり、
Web コンソール用の認証情報を持っていない場合や、
プログラムからアクセスしたい場合には使用できません

というわけで、コマンドラインから使用できる S3 使用量推移取得ツールを実装しました

実行すると、以下のような CSV を出力します

Date,Bytes
"2022/01/30",4878460855189
"2022/01/31",4851200439116
"2022/02/01",4925325370518
"2022/02/02",5060814016833
"2022/02/03",5079663776337

AWS CLI と jq を利用したシェルスクリプト版と、
boto3 と pandas を利用した Python 版の2種類を作っています

コードの全量は以下のリポジトリを参照してください

仕組み

CloudWatch の API からデータを取得します

CloudWatch には S3 のストレージ容量を監視するためのメトリクスが自動的に作られており、
ここにバケット毎にストレージ容量、オブジェクト数のリクエスト量などが格納されています

シェルスクリプト版

以下のコマンドでバケット毎の指定期間のストレージ容量が1日毎に取得できます

$ aws cloudwatch get-metric-statistics \
    --namespace AWS/S3 \
    --metric-name BucketSizeBytes \
    --dimensions \
        Name=StorageType,Value=StandardStorage \
        Name=BucketName,Value="$backet_name" \
    --statistics Maximum \
    --start-time "$start_date"T00:00:00Z \
    --end-time "$end_date"T00:00:00Z \
    --period 86400 \
    --unit Bytes
  • backet_name: バケット名
  • start_date: 開始日( YYYY-MM-DD )
  • end_date: 終了日( YYYY-MM-DD )

period の 86400 は 60 * 60 * 24 秒 = 1日で集計の単位を表しています

結果は以下のような JSON になります

{
    "Label": "BucketSizeBytes",
    "Datapoints": [
        {
            "Timestamp": "2022-01-31T00:00:00Z",
            "Maximum": 889248651.0,
            "Unit": "Bytes"
        },
        {
            "Timestamp": "2022-01-30T00:00:00Z",
            "Maximum": 889248651.0,
            "Unit": "Bytes"
        }
    ]
}

あとはこれを整形すれば OK です

jq を使えばコマンドラインから JSON データの操作ができます

今回は CSV にしたかったので、以下のように指定しました

jq -r '
    .Datapoints
    | sort_by(.Timestamp)
    | .[]
    | [(.Timestamp|strptime("%Y-%m-%dT%H:%M:%SZ")|strftime("%Y/%m/%d")), .Maximum]
    | @csv
'
  • .Datapoints: Datapoints の値を取得する

  • sort_by(.Timestamp): Timestamp の昇順で並べ替える

  • .[]: 配列の各要素を取り出す

  • [(.Timestamp|strptime("%Y-%m-%dT%H:%M:%SZ")|strftime("%Y/%m/%d")), .Maximum]:

    Timestamp の形式を変換したものと、 Maximum の値を取り出す

    • .Timestamp: Timestamp の値を取り出す
    • strptime("%Y-%m-%dT%H:%M:%SZ"): %Y-%m-%dT%H:%M:%SZ 形式の文字列を日付型に変換する
    • strftime("%Y/%m/%d"): 日付を %Y/%m/%d 形式の文字列に変換する
    • .Maximum: Maximum の値を取り出す
  • @csv: CSV 形式に整形する

最終的にこれを CSV ファイルに書き出すため、コマンドをくっつけると以下のようになります

echo "Date,Bytes" | tee "s3_storage.csv"

aws cloudwatch get-metric-statistics \
    --namespace AWS/S3 \
    --metric-name BucketSizeBytes \
    --dimensions \
        Name=StorageType,Value=StandardStorage \
        Name=BucketName,Value="$backet_name" \
    --statistics Maximum \
    --start-time "$start_date"T00:00:00Z \
    --end-time "$end_date"T00:00:00Z \
    --period 86400 \
    --unit Bytes \
    | jq -r '
        .Datapoints
        | sort_by(.Timestamp)
        | .[]
        | [(.Timestamp|strptime("%Y-%m-%dT%H:%M:%SZ")|strftime("%Y/%m/%d")), .Maximum]
        | @csv
    ' \
    | tee -a "s3_storage.csv"

tee を使っているのは、画面に表示しつつファイルにも書き出すため

Python 版

boto3 では、以下のようにして CLoudWatch からデータを取得します

client = boto3.client("cloudwatch")

dimensions = [
    {"Name": "StorageType", "Value": "StandardStorage"},
    {"Name": "BucketName", "Value": bucket_name},
]

statistics = client.get_metric_statistics(
    Namespace="AWS/S3",
    MetricName="BucketSizeBytes",
    Dimensions=dimensions,
    StartTime=start_time,
    EndTime=end_time,
    Period=86400,
    Statistics=["Maximum"],
)

シェルスクリプトのときと同じ形でデータが返ってくるので、これを加工します

pandas を使用するとデータの集計や加工が簡単に実装できます

pandas で DataFrame に変換してから加工し、 CSV に出力します

df = pd.DataFrame(statistics["Datapoints"])

# 並べ替え
df = df.sort_values("Timestamp").reset_index()
# 日付形式変更
df["Timestamp"] = df["Timestamp"].dt.strftime("%Y/%m/%d")
df["Maximum"] = df["Maximum"].astype(int)
# 不要な項目を消してヘッダの修正
df = df[["Timestamp", "Maximum"]]
df.columns = ["Date", "Bytes"]

print(df)

df.to_csv("s3_storage.csv", index=False)

おわりに

シェルスクリプトなら jq 、 Python なら pandas がものすごく強力なので、
これらを使えばあらゆるデータ加工が可能そうです

CloudWatch には他にも多くのメトリクスがあるため、
同じ方法で色々な AWS データの集計ができそうですね

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2