EC2のIOPSとスループットをNameタグを指定して確認する

2023年10月31日

Amazon EC2

ひとつ前の記事で、EBS の IOPS とスループットを CloudWatch で確認するための Source を作成するスクリプトを書きました。

Amazon EC2
EC2にアタッチされたEBSのIOPSとスループットを確認する

EC2 インスタンスを運用していてトラブルがあったとき、EBS の IOPS とスループットを確認したいことがあります。 ...

上記の記事で紹介したスクリプトは 1 つの特定のインスタンスの IOPS とスループットを確認することができます。AutoScaling Group を使っていくつかの EC2 インスタンスを運用している場合、複数の EC2 インスタンスの IOPS とスループットをまとめてひとつのグラフで確認したいことがあります。そこで、前回のスクリプトを修正して、EC2 インスタンスの Name タグを指定して、EBS の IOPS とスループットをひとつのグラフで確認できるようにしました。

目次

  1. インスタンスのタグ名を指定して IOPS グラフの Source を出力するシェルスクリプト
  2. 使い方
  3. json を CloudWatch Metrics の Source に貼り付ける
  4. スループット版のスクリプト

インスタンスのタグ名を指定して IOPS グラフの Source を出力するシェルスクリプト

CloudWatch Metrics グラフの元となる Source(json) を生成します。

#!/usr/bin/env bash
#/ Usage: cloudwatch-ebs-iops-source-generator-by-name [options] <ec2-instance-tag-name>
#/
#/ You can run following commands:
#/     cloudwatch-ebs-iops-source-generator-by-name my-instance
#/
#/ Options:
#/     -h, --help
#/

set -e

if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
  grep '^#/' < "$0" | cut -c4-
  exit 2
fi

if [ $# -ne 1 ]; then
    echo "Invalid arguments. Please specify <ec2-instance-tag-name>."
    echo ""
    grep '^#/' < "$0" | cut -c4-
    exit 1
fi

TAG_NAME="$1"
REGION="ap-northeast-1"

declare -a VOLUME_IDS

# get instance ids
INSTANCE_IDS=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=$TAG_NAME" "Name=instance-state-name,Values=running" --query "Reservations[].Instances[].[InstanceId]" --region $REGION --output text)

# get volume ids for each instance
for id in $INSTANCE_IDS
do
    VOLUME_ID=$(aws ec2 describe-volumes --filters "Name=attachment.instance-id,Values=$id" --query "Volumes[0].[VolumeId]" --region $REGION --output text)
    VOLUME_IDS+=($VOLUME_ID)
done

# create metrics part in json
metrics=""
for i in "${!VOLUME_IDS[@]}"
do
    id=m${i}
    volumeId=${VOLUME_IDS[$i]}
    metrics="${metrics},\
        [{\"expression\":\"${id}_0 / PERIOD(${id}_0)\",\"label\":\"Read ${volumeId}\",\"period\":60}],
        [\"AWS/EBS\",\"VolumeReadOps\",\"VolumeId\",\"${volumeId}\",{\"label\":\"${volumeId}\",\"id\":\"${id}_0\",\"visible\":false}],
        [{\"expression\":\"${id}_1 / PERIOD(${id}_1)\",\"label\":\"Write ${volumeId}\",\"period\":60}],
        [\"AWS/EBS\",\"VolumeWriteOps\",\"VolumeId\",\"${volumeId}\",{\"label\":\"${volumeId}\",\"id\":\"${id}_1\",\"visible\":false}]
"
done

# create entire json
cat <<-EOF
{
    "metrics": [
${metrics#,*}
    ],
    "view": "timeSeries",
    "stat": "Sum",
    "period": 60,
    "stacked": false,
    "yAxis": {"left": {"min": 0}},
    "title": "Read and Write IOPS",
    "region": "${REGION}"
}
EOF

使い方

上記のスクリプトをファイルに保存し実行権限を与え、以下のように、引数で EC2 インスタンスの Name タグを指定して実行します。実行するには aws-cli v2 がインストールされ、権限の設定を済ませておく必要があります。

cloudwatch-ebs-iops-source-generator-by-name my-instance

実行結果です。

{
    "metrics": [
        [{"expression":"m0_0 / PERIOD(m0_0)","label":"Read vol-05f6b8962ead73a8b","period":60}],
        ["AWS/EBS","VolumeReadOps","VolumeId","vol-05f6b8962ead73a8b",{"label":"vol-05f6b8962ead73a8b","id":"m0_0","visible":false}],
        [{"expression":"m0_1 / PERIOD(m0_1)","label":"Write vol-05f6b8962ead73a8b","period":60}],
        ["AWS/EBS","VolumeWriteOps","VolumeId","vol-05f6b8962ead73a8b",{"label":"vol-05f6b8962ead73a8b","id":"m0_1","visible":false}]
,        [{"expression":"m1_0 / PERIOD(m1_0)","label":"Read vol-0e3895f262a65b813","period":60}],
        ["AWS/EBS","VolumeReadOps","VolumeId","vol-0e3895f262a65b813",{"label":"vol-0e3895f262a65b813","id":"m1_0","visible":false}],
        [{"expression":"m1_1 / PERIOD(m1_1)","label":"Write vol-0e3895f262a65b813","period":60}],
        ["AWS/EBS","VolumeWriteOps","VolumeId","vol-0e3895f262a65b813",{"label":"vol-0e3895f262a65b813","id":"m1_1","visible":false}]
,        [{"expression":"m2_0 / PERIOD(m2_0)","label":"Read vol-0874ef1987e162924","period":60}],
        ["AWS/EBS","VolumeReadOps","VolumeId","vol-0874ef1987e162924",{"label":"vol-0874ef1987e162924","id":"m2_0","visible":false}],
        [{"expression":"m2_1 / PERIOD(m2_1)","label":"Write vol-0874ef1987e162924","period":60}],
        ["AWS/EBS","VolumeWriteOps","VolumeId","vol-0874ef1987e162924",{"label":"vol-0874ef1987e162924","id":"m2_1","visible":false}]

    ],
    "view": "timeSeries",
    "stat": "Sum",
    "period": 60,
    "stacked": false,
    "yAxis": {"left": {"min": 0}},
    "title": "Read and Write IOPS",
    "region": "ap-northeast-1"
}

json を CloudWatch Metrics の Source に貼り付ける

出力された json を CloudWatch の Source に貼り付けるとグラフが表示されます。やり方は前回の記事の記事を参照してください。

スループット版のスクリプト

スループット版です。使い方は同じです。

#!/usr/bin/env bash
#/ Usage: cloudwatch-ebs-throughput-source-generator-by-name [options] <ec2-instance-tag-name>
#/
#/ You can run following commands:
#/     cloudwatch-ebs-throughput-source-generator-by-name my-instance
#/
#/ Options:
#/     -h, --help
#/

set -e

if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
  grep '^#/' < "$0" | cut -c4-
  exit 2
fi

if [ $# -ne 1 ]; then
    echo "Invalid arguments. Please specify <ec2-instance-tag-name>."
    echo ""
    grep '^#/' < "$0" | cut -c4-
    exit 1
fi

TAG_NAME="$1"
REGION="ap-northeast-1"

declare -a VOLUME_IDS

# get instance ids
INSTANCE_IDS=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=$TAG_NAME" "Name=instance-state-name,Values=running" --query "Reservations[].Instances[].[InstanceId]" --region $REGION --output text)

# get volume ids for each instance
for id in $INSTANCE_IDS
do
    VOLUME_ID=$(aws ec2 describe-volumes --filters "Name=attachment.instance-id,Values=$id" --query "Volumes[0].[VolumeId]" --region $REGION --output text)
    VOLUME_IDS+=($VOLUME_ID)
done

# create metrics part in json
metrics=""
for i in "${!VOLUME_IDS[@]}"
do
    id=m${i}
    volumeId=${VOLUME_IDS[$i]}
    metrics="${metrics},\
        [{\"expression\":\"${id}_0 / PERIOD(${id}_0) / 1024\",\"label\":\"Read ${volumeId}\",\"period\":60}],
        [\"AWS/EBS\",\"VolumeReadBytes\",\"VolumeId\",\"${volumeId}\",{\"label\":\"${volumeId}\",\"id\":\"${id}_0\",\"visible\":false}],
        [{\"expression\":\"${id}_1 / PERIOD(${id}_1) / 1024\",\"label\":\"Write ${volumeId}\",\"period\":60}],
        [\"AWS/EBS\",\"VolumeWriteBytes\",\"VolumeId\",\"${volumeId}\",{\"label\":\"${volumeId}\",\"id\":\"${id}_1\",\"visible\":false}]
"
done

# create entire json
cat <<-EOF
{
    "metrics": [
${metrics#,*}
    ],
    "view": "timeSeries",
    "stat": "Sum",
    "period": 60,
    "stacked": false,
    "yAxis": {"left": {"min": 0}},
    "title": "Read and Write throughput (KiB/s)",
    "region": "${REGION}"
}
EOF

-技術ブログ
-