📝

EC2 StartInstances API で一部のインスタンスの開始に失敗した場合の挙動を確認してみた

に公開

結論

API が失敗扱いになり指定したすべてのインスタンスが開始しませんでした。

1. EC2 インスタンスの作成

2 つの EC2 インスタンスを作成しました。

2. Lambda 関数の作成

Lambda 関数から以下のコードで 2 つのインスタンスを開始する処理を定義します。

import boto3
import json

def lambda_handler(event, context):
    ec2 = boto3.client('ec2')
    
    instance_ids = [
        'i-002d4c2d813220cce',
        'i-0ed298fff1f7fd475'
    ]
    
    try:
        response = ec2.start_instances(InstanceIds=instance_ids)
        print(f"成功レスポンス: {json.dumps(response, default=str)}")
        
        return {
            'statusCode': 200,
            'body': json.dumps('インスタンス起動成功')
        }
    except Exception as e:
        print(f"エラー発生: {str(e)}")
        return {
            'statusCode': 500,
            'body': json.dumps(f'エラー: {str(e)}')
        }

3. Lambda の実行ロールを編集

以下のポリシーをアタッチしました。

  • AdministratorAccess
  • 片方の EC2 インスタンスの開始のみ拒否するカスタムポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Deny",
            "Action": "ec2:StartInstances",
            "Resource": "arn:aws:ec2:ap-northeast-1:012345678901:instance/i-002d4c2d813220cce"
        }
    ]
}

4. Lambda を実行してみる

以下のエラーにより 2 つの EC2 インスタンスのいずれも開始されませんでした。

エラー発生: An error occurred (UnauthorizedOperation) when calling the StartInstances operation: You are not authorized to perform this operation. User: arn:aws:sts::012345678901:assumed-role/LambdaBasicExecutionRole/StartEC2InstancesTest is not authorized to perform: ec2:StartInstances on resource: arn:aws:ec2:ap-northeast-1:012345678901:instance/i-002d4c2d813220cce with an explicit deny in an identity-based policy.

5. EC2 インスタンスを 1 つずつ起動してみる

StartInstances API では 1 つの EC2 インスタンスの起動に失敗した場合には API が失敗扱いになり指定したすべてのインスタンスが開始されないことを確認できました。
そのため、回避策として instance_ids に定義したインスタンスをループで 1 つずつ指定する処理に変更してみました。

import boto3
import json

def lambda_handler(event, context):
    ec2 = boto3.client('ec2')
    
    instance_ids = [
        'i-002d4c2d813220cce',
        'i-0ed298fff1f7fd475'
    ]
    
    results = {
        'success': [],
        'failed': []
    }
    
    for instance_id in instance_ids:
        try:
            response = ec2.start_instances(InstanceIds=[instance_id])
            print(f"成功: {instance_id}")
            results['success'].append(instance_id)
        except Exception as e:
            print(f"失敗: {instance_id}, エラー: {str(e)}")
            results['failed'].append({
                'instance_id': instance_id,
                'error': str(e)
            })
    
    return {
        'statusCode': 200,
        'body': json.dumps(results, indent=2)
    }

エラーが発生した EC2 インスタンスは開始しませんでしたが、他方の EC2 インスタンスは起動しました。

失敗: i-002d4c2d813220cce,
エラー: An error occurred (UnauthorizedOperation) when calling the StartInstances operation: You are not authorized to perform this operation. User: arn:aws:sts::012345678901:assumed-role/LambdaBasicExecutionRole/StartEC2InstancesTest is not authorized to perform: ec2:StartInstances on resource: arn:aws:ec2:ap-northeast-1:012345678901:instance/i-002d4c2d813220cce with an explicit deny in an identity-based policy.

成功: i-0ed298fff1f7fd475

まとめ

今回は EC2 StartInstances API で一部のインスタンスの開始に失敗した場合の挙動を確認してみました。
どなたかの参考になれば幸いです。

参考資料

Discussion