Edited at

EC2 のスポット価格の 平均値, 標準偏差, 最大値を AWS-CLI を使って計算して、スポットで起動するかを判断しよう!

More than 3 years have passed since last update.


背景

 最近,東京リージョンのc3.8xlargeのスポット価格の変動が激しいことご存知ですか?下記の画像は2015年4月27日にスクショした、c3.8xlarge の Pricing History ですが、このように大きく価格が変動しています。そのため、スポットを使うべきか、オンデマンドを使うべきか、他のインスタンスを使うべきかなど悩むことが多くなりました。

Kobito.tZHil1.png


課題

 スポットインスタンスが使えそうか、使えなさそうか、一瞬で判断したいのですが、マネージメントコンソール上からだと、スポット価格を見るまでの操作が面倒です。またc3.8xlarge と c4.8xlargeなど異なるインスタンスタイプで比較することができないといった問題がありました。一方、 AWS CLIを使って 'aws ec2 describe-spot-price-history' コマンドをたたいても、JSONが大量にでるで〜るでツライだけでした。


解決策

 パッと一目で、「このインスタンスはスポットで使えねー」など判断したいということで、discribeコマンドで得られるJSONをフィルタリングし、スポット価格の

 

- 平均

- 標準偏差

- 最大値

- 最小値

を計算するスクリプトを作ることにします!


  • 価格のバラツキは標準偏差を見ればよいですね!

  • スポットインスタンスのリクエスト時に設定する Maximum price の値は最大値を見ればよいですね!


シェルスクリプトで実装してみた

 世界中のc4,c3.8xlargeのスポット価格を比較できると面白いかも・・ということで、全体の流れとしては下記のようにしました。

 

1. aws ec2 describe-regions でリージョン取得

2. AWS_DEFAULT_REGIONの設定

3. aws ec2 describe-availability-zones で Availability Zone を取得

4. aws ec2 describe-spot-price-history で Pricing History の JSON データを取得

5. jq で データをフィルタリング後、awkで統計処理

 これで、世界中の Region と Availability Zone を自動で取得し順次出力することができます。尚、Pricing History の期間は、現時点から1週間前までのデータを処理しています。

以下実装したシェルスクリプトです。Macから動作確認しています。ちなみに、GNUのdateコマンドは、オプションが異なりますので、適宜読み替えてください。


script

#!/bin/bash

#
# INITIAL CONDITION
#

INSTANCE="c4.8xlarge c3.8xlarge"
DAYS=7
START=`date -u -v-${DAYS}d +"%Y-%m-%dT%H:%M:%S"`
END=`date -u +"%Y-%m-%dT%H:%M:%S"`

#
# SOLVER
#

MY_SOLVER()
{
MY_INS=$1
MY_AZ=$2
MY_START=$3
MY_END=$4

aws ec2 describe-spot-price-history \
--instance-types ${MY_INS} \
--product-description "Linux/UNIX (Amazon VPC)" \
--start-time ${MY_START} \
--end-time ${MY_END} \
--availability-zone ${MY_AZ} \
| jq -r '.SpotPriceHistory[] | "\(.Timestamp)\t\(.SpotPrice)"' | \
sed s/.000Z//g | CALC ${MY_INS} ${MY_AZ}
}

CALC()
{
awk -v instance=$1 -v az=$2 '
BEGIN{
i = 0;
sum = 0;
}
{
price[i] = $2;
sum += $2;
i++;
}
END{
imax = i;
if (imax != 0) {
ave = sum / imax;
sumdx = 0;
max = ave;
min = ave;

for (i = 0; i < imax; i++) {
val = price[i];
dx = val - ave;
dx2 = dx * dx;
sumdx += dx2;
if (val > max) max = val;
if (val < min) min = val;
}
sigma = sqrt(sumdx / imax);
printf("%16s%20s%10.3f%10.3f%10.3f%10.3f\n",
instance, az, ave, sigma, max, min);
} else {
printf("%16s%20s%40s\n",
instance, az, "--- NO DATA ---");
}
}'
}

#
# AWS CLI DESCRIBE REGIONS AND AVAILABILITY-ZONE
#

MY_REGION()
{
aws ec2 describe-regions | jq -r ".Regions[] | .RegionName"
}

MY_AVAILABILITY_ZONE()
{
aws ec2 describe-availability-zones --region $1 \
| jq -r ".AvailabilityZones[] | .ZoneName"
}

#
# MAIN
#

printf "%16s%20s%10s%10s%10s%10s\n" "InstanceType" "AZ" "average" "stdev" "max" "min"
for TMP_INS in `echo "${INSTANCE}"`
do
for
REGION in `MY_REGION`
do
export AWS_DEFAULT_REGION=${REGION}
for TMP_AZ in `MY_AVAILABILITY_ZONE ${REGION}`
do
MY_SOLVER ${TMP_INS} ${TMP_AZ} ${START} ${END}
done
done
done



世界の c4.8xlarge, c3.8xlarge スポット価格を比較してみた

先ほどのスクリプトを実際に動かしてみました!


動作確認を実施した環境

 今回、動作確認したバージョンです。オイラの環境だと最新の1.7.24においてdescribe-spot-price-history は動作しませんでした。


command

aws --version



result

aws-cli/1.7.1 Python/2.7.6 Darwin/14.1.0



実行結果

 2015年4月27日の実行結果を以下に示します。データは左から、インスタンスタイプ、 AZ(Availability Zone), Pricing Historyの平均、標準偏差、最大、最小値となっています。データを取得期間は4月27日から7日前までの 1 Week です。

 東京リージョンの c3.8xlarge の Pricing History は冒頭で紹介しましたが、データからも ap-northeast-1c の価格変動の大きさが読み取れます。 平均 : 0.879, 標準偏差 : 1.668, 最大値 : 10.000 と なっており、同じ AZ の c4.8xlarge と比較すると、標準偏差は16倍大きく、最大値に限ってはおよそ30倍です。これではスポットで使えない(泣)

 

 なぜか世界中で、c4のほうがc3より空いており、スポットで使うならc4のほうがオススメということもわかりました。c4のほうがオンデマンド価格が高いからですかね?c4.8xlargeはhaswellアーキテクチャでメモリはDDR4採用で帯域幅広くなっているし、c3.8xlargeとの価格差以上の性能でると思うんですけど・・・なぜだ!


result

    InstanceType                  AZ   average     stdev       max       min

c4.8xlarge eu-central-1a 0.340 0.007 0.362 0.326
c4.8xlarge eu-central-1b 0.324 0.005 0.350 0.321
c4.8xlarge sa-east-1a --- NO DATA ---
c4.8xlarge sa-east-1b --- NO DATA ---
c4.8xlarge sa-east-1c --- NO DATA ---
c4.8xlarge ap-northeast-1a 0.324 0.002 0.337 0.320
c4.8xlarge ap-northeast-1c 0.323 0.001 0.333 0.321
c4.8xlarge eu-west-1a 0.363 0.159 2.112 0.324
c4.8xlarge eu-west-1b 0.368 0.219 2.112 0.325
c4.8xlarge eu-west-1c 0.742 0.729 3.000 0.340
c4.8xlarge us-east-1a 0.424 0.840 7.424 0.258
c4.8xlarge us-east-1b 0.311 0.350 7.424 0.258
c4.8xlarge us-east-1d 0.262 0.004 0.350 0.259
c4.8xlarge us-east-1e 0.336 0.048 1.000 0.280
c4.8xlarge us-west-1a 0.306 0.218 2.208 0.257
c4.8xlarge us-west-1c 0.329 0.229 3.000 0.265
c4.8xlarge us-west-2a 0.352 0.306 1.856 0.257
c4.8xlarge us-west-2b 0.480 0.485 3.100 0.258
c4.8xlarge us-west-2c 0.563 0.492 2.100 0.263
c4.8xlarge ap-southeast-2a 0.336 0.017 0.400 0.320
c4.8xlarge ap-southeast-2b 0.537 0.474 2.432 0.320
c4.8xlarge ap-southeast-1a 0.388 0.162 2.432 0.327
c4.8xlarge ap-southeast-1b 0.426 0.214 2.432 0.343
c3.8xlarge eu-central-1a 0.640 0.605 2.732 0.335
c3.8xlarge eu-central-1b 2.732 0.000 2.732 2.732
c3.8xlarge sa-east-1a 0.323 0.004 0.346 0.320
c3.8xlarge sa-east-1b 0.320 0.000 0.320 0.320
c3.8xlarge sa-east-1c 0.340 0.019 0.399 0.321
c3.8xlarge ap-northeast-1a 0.677 0.891 9.600 0.344
c3.8xlarge ap-northeast-1c 0.879 1.668 10.000 0.327
c3.8xlarge eu-west-1a 0.354 0.491 8.000 0.320
c3.8xlarge eu-west-1b 0.333 0.210 4.000 0.320
c3.8xlarge eu-west-1c 0.332 0.239 9.600 0.320
c3.8xlarge us-east-1a 0.277 0.354 9.600 0.256
c3.8xlarge us-east-1b 0.358 0.562 5.500 0.256
c3.8xlarge us-east-1d 0.273 0.149 3.000 0.256
c3.8xlarge us-east-1e 0.343 0.405 9.600 0.257
c3.8xlarge us-west-1a 0.751 0.773 2.732 0.411
c3.8xlarge us-west-1c 9.600 0.000 9.600 9.600
c3.8xlarge us-west-2a 0.576 1.151 15.000 0.359
c3.8xlarge us-west-2b 1.256 2.313 9.600 0.346
c3.8xlarge us-west-2c 1.403 2.817 10.000 0.272
c3.8xlarge ap-southeast-2a 0.421 0.354 4.000 0.324
c3.8xlarge ap-southeast-2b 0.506 0.898 9.600 0.321
c3.8xlarge ap-southeast-1a 0.362 0.032 0.504 0.322
c3.8xlarge ap-southeast-1b 0.436 0.198 3.024 0.328


半端ない us-west-1a の c3.8xlarge Pricing History

 あまりにも目立つ"us-west-1a"のc3.8xlarge、平均 : 9.6, 標準偏差 : 0.0, 最大値 : 9.6 ... つまり、$9.6 で一定ということでハンパないっす。マネージメントコンソールからチェックしてみても予想通りっ!この感じだと当分スポットでは使えそうにありません(泣)

Kobito.UC1eLD.png


スクリプトのカスタマイズ


確認したいインスタンスタイプの変更するとき

確認したいインスタンスタイプにcc2.8xlargeを追加する場合は下記のように変更してください。


before

INSTANCE="c4.8xlarge c3.8xlarge"



after

INSTANCE="c4.8xlarge c3.8xlarge cc2.8xlarge"



確認したいリージョンを限定するとき

Regionを us-east-1 と ap-northeast の2つに限定したい場合は下記のようにしてください


before

MY_REGION()

{
aws ec2 describe-regions | jq -r ".Regions[] | .RegionName"
}


after

MY_REGION()

{
echo "us-east-1 ap-northeast-1"
}


今後やりたいこと

下記、時間があればやるかも・・


  • ここ1週間で、設定した閾値を何回超えるかみたいなアルゴリズムもいれたいです。これはポアソン分布なのかな?こちらのほうが、もっと定量的な予測ができて、まわりを説得する材料なんかになると思います

  • AMLに突っ込んで、スポット価格を予測はやってみたいですね。これ誰かやってくれないかなぁ〜