EC2 インスタンス (EBS) の AMI (Snapshot) 作成に関する制限について

# ０．はじめに

Python スクリプトから CreateImage で AMI を作成し、EC2 インスタンスのバックアップを日時で取っていたんですが、AMI の作成に失敗することがあったので、サポートに確認したところ、ご回答を頂いたのでシェア。

# １．経緯

Python スクリプトは、EC2 インスタンス上で定期実行していたんですが、CloudWatchEvent → Lambda に移行しようかと思い、色々やっていたところ、両方のスクリプトを同じ時間に実行すると、一つの EC2 インスタンスについて２つの AMI が作成されるかと思いきや、一つしか作成されない事象が…。

それも、
どちらかのスクリプトで作成されたものだけ、というわけではなく、インスタンスによってバラバラだったので、CreateImage に何か制限事項でもあるのかと思い、サポートに確認しました。

# ２．原因

結論からいうと、

EC2 インスタンスの AMI 作成の制限ではなく、
EBS のスナップショット作成の制限がある。

とのことでした。

<br>
で、
EBS のスナップショット作成に関する制限が、以下とのこと。

### ２−１．同時並行のスナップショット作成数の制限
* 単一のボリュームで許可される同時並行のスナップショット作成数は、
    * io1、gp2、magnetic の場合 : 5
    * st1、sc1 の場合 : 1
    * [AWS サービス制限 \- アマゾン ウェブ サービス](https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws_service_limits.html#limits_ebs)

### ２−２．同時並行スナップショット作成レートの制限
* 単一のボリュームで許可される同時並行のスナップショット作成では、15 秒以上間を開ける必要がある。
    * [Error Codes \- Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/errors-overview.html)
        * SnapshotCreationPerVolumeRateExceeded: The rate limit for creating concurrent snapshots of an EBS volume has been exceeded. Wait at least 15 seconds between concurrent volume snapshots. 

<br>
ということで、

今回、スクリプトを同じ時間に実行した為に、一つの EC2 インスタンスに対する AMI 作成に伴う EBS のスナップショット作成が、「２−２．同時並行スナップショット作成レートの制限」に引っかかり、後に実行された AMI 作成の処理が失敗となっていたみたいです。

### ※ 参考

* [Amazon EBS\-Backed Linux AMI の作成 \- Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/creating-an-ami-ebs.html#process-creating-an-ami-ebs)
    * AMI 作成プロセスの間、Amazon EC2 はインスタンスのルートボリュームとインスタンスにアタッチされているその他の EBS ボリュームのスナップショットを作成します。
<br><br>
* [Amazon EBS スナップショットの作成 \- Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-creating-snapshot.html)
    * ボリュームの前のスナップショットが pending 状態の間でもボリュームのスナップショットを作成できますが、1 つのボリュームで複数の pending スナップショットを作成すると、スナップショットが完了するまでボリュームのパフォーマンスが低下する場合があります。
    * スナップショットの数は、gp2、io1、または マグネティック のボリュームごとに 5 つ pending、st1 または sc1 のボリュームごとに 1 つ pending に制限されています。
    * 同一のボリュームで複数のスナップショットを同時に作成する際に ConcurrentSnapshotLimitExceeded エラーが発生した場合は、pending スナップショットが 1 つ以上完了するまで待ってから、そのボリュームの次のスナップショットを作成します。

### ※ 補足

補足として、以下のご説明も頂きました。

* AWS では EBS スナップショット取得に関わらず、API が短い間隔で多数リクエストされた場合、API リクエストそのものがスロットリングされる場合があり、
* この制限に該当するような数のリクエストを同時に実施された場合にも、AMI 作成に失敗する可能性がある。
* なお、当該制限に該当した場合、「RequestLimitExceeded」が発生する。
* [Error Codes \- Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/errors-overview.html)
    * There are a number of reasons that you might encounter an error while performing a request. Some errors can be prevented or easily solved by following these guidelines:
    * Use a sleep interval between request rates: Amazon EC2 API requests are throttled to help maintain the performance of the service. If your requests have been throttled, you get the following error: Client.RequestLimitExceeded. For more information, see Query API Request Rate.

# ３．解決策

基本的に、

* 一つの AWS リソースに対して、同じリクエストを同時並行で実行するのは避けた方がいいのかなと。

逆にいうと、

* 前のリクエストがちゃんと終わったことを確認してから次の処理を実行する。
* もしくは、前のリクエストの処理が残っている場合は実行しない。

のがいいみたいです。

<br>
また、
今回 CloudWatch Logs にエラーと思わしき記録が確認できなかったんですが、
それについても、

* エラーが AMI 作成そのものではなく、AMI 作成に伴う EBS スナップショット作成によるものであり、AMI 作成リクエストには問題がなかったためで、
* AWS の API の多くは非同期処理であり、API 実行時の応答はリクエストそのものが正常に受け付けられたかどうかを返すものとなっておりますため、API によってはこのような動作をする場合がある。

<br>
とのこと。

当スクリプトにおいては、CreateImage 後に DescribeImages で作成した AMI の状態をウォッチしないと、エラーハンドリングが出来ないみたいです。

* [DescribeImages \- Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/API_DescribeImages.html)
* [DescribeImages \- Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/API_DescribeImages.html)
* [Image \- Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/API_Image.html)

# ＸＸ．まとめ

やはり何事もやってみないとわからないことが多いですね。
AWS もとにかくどんどん試してみることが大切かと。