CloudFormation で EC2 が全然作成されない…!

記事タイトルとURLをコピーする

こんにちは、やまぐちです。

CloudFormation で EC2 を構築しようとして、ステータスを確認するも「CREATE_IN_PROGRESS」から全然進まない!
といったご経験はございませんでしょうか。

エラーなら早く「CREATE_FAILED」を出して…!とエラー結果を早く欲しがってしまいます。

実はしばらく待ったらエラーがでます。
今回は以下のエラーが出た時の対処方法を考えたいと思います。

Value (ec2-test-role) for parameter iamInstanceProfile.name is invalid. Invalid IAM Instance Profile name (Service: AmazonEC2; Status Code: 400; Error Code: InvalidParameterValue; Request ID: リクエストID ; Proxy: null)

やってみる

パターン 1

まず以下のテンプレートから EC2 を構築します。

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  ImageId:
    Type: AWS::EC2::Image::Id
    Description: AMI to use for the EC2 instance
  Subnet:
    Type: AWS::EC2::Subnet::Id
    Description: Subnet to deploy the EC2 instance in
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup::Id
    Description: Security group to assign to the EC2 instance

Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeSize: 8
            VolumeType: gp3
      IamInstanceProfile: !Ref IamRole
      ImageId: !Ref ImageId
      InstanceType: t3.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: false
          DeleteOnTermination: true
          DeviceIndex: 0
          GroupSet: 
            - !Ref SecurityGroup
          SubnetId: !Ref Subnet

  IamRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      RoleName: ec2-test-role

IAMロールは作成されますが、EC2 が「CREATE_IN_PROGRESS」から進みません!

挙句の果てにタイムアウトされてしまいました。
エラー内容は以下です

Value (ec2-test-role) for parameter iamInstanceProfile.name is invalid. Invalid IAM Instance Profile name (Service: AmazonEC2; Status Code: 400; Error Code: InvalidParameterValue; Request ID: リクエストID ; Proxy: null)

原因

エラーの内容からインスタンスプロファイルが怪しいなとわかります。
テンプレートの中では、IAMロールの作成をし、その IAMロールを EC2 へアタッチするような流れとなっています。
以下のようにEC2Instance 内のIamInstanceProfileで IAM Role を参照しています。

      IamInstanceProfile: !Ref IamRole

しかし、これだと EC2 に IAM ロールがアタッチされません。
EC2 の場合、インスタンスプロファイルを使用して IAM ロールを EC2 インスタンスに渡します。
なので、インスタンスプロファイルではなく IAM ロールを直接指定していたため EC2 が作成ができなかったという感じです。

以下、ドキュメントの引用です。

Amazon EC2 は、IAM ロールのコンテナとしてインスタンスプロファイルを使用します。IAM コンソールを使用して IAM ロールを作成すると、コンソールによりインスタンスプロファイルが自動的に作成され、対応するロールと同じ名前が付けられます。Amazon EC2 コンソールを使用して IAM ロールを持つインスタンスを起動する場合、またはインスタンスに IAM ロールをアタッチする場合は、インスタンスプロファイル名のリストに基づいてロールを選択します。

AWS CLI、API、または AWS SDK を使用してロールを作成する場合、ロールとインスタンスプロファイルを別個のアクションとして作成します。名前は異なる可能性があります。次に AWS CLI、API、または AWS SDK を使用して IAM ロールを持つインスタンスを起動する場合、またはインスタンスに IAM ロールをアタッチする場合は、インスタンスプロファイル名を指定します。

インスタンスプロファイルに含めることができる IAM ロールの数は 1 つのみです。この制限を増やすことはできません。

docs.aws.amazon.com

解決法

テンプレートを以下のようにします

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  ImageId:
    Type: AWS::EC2::Image::Id
    Description: AMI to use for the EC2 instance
  Subnet:
    Type: AWS::EC2::Subnet::Id
    Description: Subnet to deploy the EC2 instance in
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup::Id
    Description: Security group to assign to the EC2 instance

Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeSize: 8
            VolumeType: gp3
      IamInstanceProfile: !Ref IamInstanceProfile
      ImageId: !Ref ImageId
      InstanceType: t3.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: false
          DeleteOnTermination: true
          DeviceIndex: 0
          GroupSet: 
            - !Ref SecurityGroup
          SubnetId: !Ref Subnet

  IamInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref IamRole

  IamRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      RoleName: ec2-test-role

修正点 1

以下を追記し、インスタンスプロファイルを作成するようにしました。

  IamInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref IamRole

修正点 2

EC2Instance内のIamInstanceProfileで作成したインスタンスプロファイルを参照するようにしました。

      IamInstanceProfile: !Ref IamInstanceProfile

結果

ということで見事「CREATE_COMPLETE」で EC2 インスタンスが作成完了しました!

パターン 2

次のパターンとして、すでに作成済みの IAM ロールを指定して EC2 を作成してみましょう!
テンプレートを以下です。

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  ImageId:
    Type: AWS::EC2::Image::Id
    Description: AMI to use for the EC2 instance
  Subnet:
    Type: AWS::EC2::Subnet::Id
    Description: Subnet to deploy the EC2 instance in
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup::Id
    Description: Security group to assign to the EC2 instance

Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeSize: 8
            VolumeType: gp3
      IamInstanceProfile: ec2-test-role
      ImageId: !Ref ImageId
      InstanceType: t3.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: false
          DeleteOnTermination: true
          DeviceIndex: 0
          GroupSet: 
            - !Ref SecurityGroup
          SubnetId: !Ref Subnet

先ほどのテンプレートと違う点は、IAM ロール「ec2-test-role」はパターン1ですでに作成済みのためそのまま直接指定しています。
IAMロールはすでに作成済みのため、当然 IAMロールやインスタンスプロファイルの作成は行っていません。

      IamInstanceProfile: ec2-test-role

このテンプレートをアップロードして作成を試みるも
「CREATE_IN_PROGRESS」から進まない…!

しばらくすると、パターン1と同じエラーが出ました。

原因

原因はパターン1と同じです。インスタンスプロファイルです。
「でも、今回は既に IAMロールがあるわけだし…」
だから、IAMロールではなくインスタンスプロファイルなんです。

パターン1で作成した IAM ロール「ec2-test-role」をマネコンから確認します。
あれ、ARN インスタンスプロファイルの ARN !?

パターン1で引用したドキュメントの内容をもう一度出します。

AWS CLI、API、または AWS SDK を使用してロールを作成する場合、ロールとインスタンスプロファイルを別個のアクションとして作成します。名前は異なる可能性があります。次に AWS CLI、API、または AWS SDK を使用して IAM ロールを持つインスタンスを起動する場合、またはインスタンスに IAM ロールをアタッチする場合は、インスタンスプロファイル名を指定します。

AWS CLI、API、または AWS SDK で IAMロールを使用する場合は、IAMロール名とインスタンスプロファイル名が異なるものになると記載されています。
ということで、インスタンスプロファイル名が必ずしもIAMロール名と同じになっているとは限らないのです。
今回の場合は以下のように IAMロール名とインスタンスプロファイル名が異なります。
IAMロール名:ec2-test-role
インスタンスプロファイル名:ec2-test2-IamInstanceProfile-IUGySFIUWGfq

解決法

ということで、IamInstanceProfile:にインスタンスプロファイル名を指定します。

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  ImageId:
    Type: AWS::EC2::Image::Id
    Description: AMI to use for the EC2 instance
  Subnet:
    Type: AWS::EC2::Subnet::Id
    Description: Subnet to deploy the EC2 instance in
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup::Id
    Description: Security group to assign to the EC2 instance

Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeSize: 8
            VolumeType: gp3
      IamInstanceProfile: ec2-test2-IamInstanceProfile-IUGySFIUWGfq
      ImageId: !Ref ImageId
      InstanceType: t3.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: false
          DeleteOnTermination: true
          DeviceIndex: 0
          GroupSet: 
            - !Ref SecurityGroup
          SubnetId: !Ref Subnet

変更点

インスタンスプロファイルを IAMロール名からインスタンスプロファイル名に変更しました。

      IamInstanceProfile: ec2-test2-IamInstanceProfile-IUGySFIUWGfq

結果

EC2 が作成されました。

余談

AWS CLI、API、または AWS SDK を使用してロールを作成する場合とことなのでマネコンから作成した場合はどうなるのでしょうか?
マネコンから IAMロールを作成した結果、IAMロール名とインスタンスプロファイル名は同じになりました。

まとめ

  1. CloudFormation で IAMロールと EC2 を作成する時は、インスタンスプロファイルも作成し、参照させること
  2. 既存の IAMロールを指定して EC2 を構築する時はインスタンスプロファイル名が IAMロール名と一致しているかを確認すること

やまぐち まさる (記事一覧)

CS部・CS2課

AWS の構築・運用をやってます

3度の飯より野球が好き

2023 Japan AWS All Certifications Engineers