CloudFormationの「Property DeviceIndex cannot be empty」エラーに対処する(Public IPアドレス割当のおさらい)

2015.05.29

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、虎塚です。

CloudFormationでスタックを作成しようとして、「Property DeviceIndex cannot be empty.」というエラーが出たことはありませんか?

この記事では、上記のエラーメッセージがなぜ出るのか、どのように対処すればよいのかについて書きます。

エラーが発生するユースケース

永続的なIPアドレスが不要な時、Elastic IP Address (EIP) ではなく、Public IPアドレスを自動アサインしてインスタンスを起動することがありますよね。たとえば、ちょっとした検証用に短時間、1個だけEC2を立ち上げたい時などです。

そのようなEC2をCloudFormationで立ち上げようとした時に、このエラーに遭遇することがあると思います。

DeviceIndexがないというエラー

ちなみに、Management Consoleでは、上記のエラーに至るような設定はできないように、バリデーションがかかっています(後述)。

前提知識: パブリックIPアドレス割り当ての設定

パブリックIPアドレス割り当ての設定がどのように反映されるかを、次の図に示します。

Auto-Assign Public IP設定の適用

EC2-Classicでは、起動したインスタンスにPublic IPアドレスが必ず割り当てられます。この挙動は、他の設定によって変更することができません。

しかし、EC2-Classicは、VPCがデフォルトで導入される前に作成された古いAWSアカウントでのみ利用できるので、最近AWSを使いはじめた人は気にしなくてもよいでしょう。というわけで、EC2-Classic何それという方は、2つ目の条件から先をご覧ください。

VPCで起動するEC2インスタンスにパブリックIPアドレスが割り当てられるかどうかは、次の2つの設定によって決まります。

  • 起動するEC2インスタンスのAuto-Assign Public IP設定
  • EC2が起動されるVPCサブネットのAuto-Assign Public IP設定

EC2の設定は、VPCの設定を上書きします。

続いて、Management Consoleを利用したそれぞれの設定方法を確認しておきましょう。

EC2インスタンスのAuto-Assign Public IP設定方法

こちらはおなじみですね。EC2インスタンスを起動する際のナビゲーションに、設定項目があります。ドロップダウンリストで設定できます。

インスタンス起動時のAuto-Assign Public IP設定

ユーザが設定する前には、ドロップダウンリストは上のスクリーンショットのように、「Use subnet setting (Disable)」もしくは「Use subnet setting (Enable)」になっています。これは、次に説明するサブネットの設定が適用されるという意味です。カッコ内の値が、現在のサブネットの設定値です。

VPCサブネットのAuto-Assign Public IP設定方法

VPCダッシュボードで、[Subnets]を選択します。サブネット一覧から設定対象のサブネットをチェックし、[Modify Auto-Assign Public IP]ボタンをクリックします。

VPCサブネット一覧

「Modify Auto-Assign Public IP」モーダルダイアログが表示され、設定を変更できます。

Auto-Assign Public IPの設定モーダルダイアログ

なお、この設定の初期値はサブネットの種類によって異なります。

- デフォルトVPCのサブネットでは、この設定が有効になっています - ユーザが作成したVPCのサブネットでは、この設定が無効になっています

デフォルトVPCとは、AWSアカウントに最初からあるVPCです。

エラー原因: パブリックIPアドレス割り当ての条件に不適合

さて、以上のようにパブリックIPアドレス割り当てを正しく設定していても、冒頭のエラーメッセージが発生することがあります。これは、パブリックIPアドレス割り当ての条件を満たしていない時に起こります。

パブリックIPアドレスは、デバイスインデックスeth0の新規ネットワークインタフェースにだけ割り当てることができます。つまり、次のような場合には、割り当てできません。

  • 割り当て先のデバイスインデックスeth0を指定しない場合
  • eth0以外に割り当てようとした場合(=ネットワークインタフェースが複数ある場合)

CloudFormationテンプレートでの失敗例

次のテンプレートのように、AWS::EC2::InstanceのNetworkInterfacesブロックで単に「AssociatePublicIpAddress」をtrueにしただけで、デバイスインデックスを指定していないと、スタック作成時に「Property DeviceIndex cannot be empty.」というエラーメッセージが表示されます。

※このテンプレートは動作しません。

{
  "Description" : "webServer (this template is failed)",

  "Parameters" : {

    "BasedAmi" : {
      "Description" : "AMI ID to use",
      "Type" : "String"
    }

  },

  "Resources" : {

    "MyInstance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "AvailabilityZone" : "ap-northeast-1c",
        "IamInstanceProfile" : "ima-role-name",
        "ImageId" : { "Ref" : "BasedAmi" },
        "InstanceType" : "t2.micro",
        "KeyName" : "your-key-name",
        "NetworkInterfaces" : [{
          "AssociatePublicIpAddress" : "true",
          "DeleteOnTermination" : "true",
          "GroupSet" : [ { "Ref" : "MySecurityGroup" } ],
          "SubnetId" : "subnet-9999999"
        }]
      }
    },

   "MySecurityGroup" : {
     "Type" : "AWS::EC2::SecurityGroup",
     "Properties" : {
       "GroupDescription" : "Allow http to client host",
       "SecurityGroupIngress" : [{
         "IpProtocol" : "tcp",
         "FromPort" : "80",
         "ToPort" : "80",
         "CidrIp" : "0.0.0.0/0"
       }],
       "VpcId" : "vpc-01234567"
     }
   }

  },

  "Outputs": {
    "MyInstanceIP" : {
      "Description" : "Public IP Address",
      "Value" : { "Fn::GetAtt" : [ "MyInstance", "PublicIp" ] }
    }
  }

}

(参考)Management Consoleから起動する場合

Management Consoleでインスタンスを起動する時には、このようなエラーに至らないように、GUIでバリデーションがかかっています。画面を詳しく見てみましょう。

デフォルトVPC以外のVPCを選択して、[Network Interfaces]メニューを開きます。

ネットワークインタフェースが1個のとき

インデックスが「eth0」の行だけが存在します。Auto-Assign Public IPの設定を有効にした場合、Public IPアドレスはeth0に自動割り当てされます。

ここで、[Add Device]ボタンをクリックすると、画面は次のように変わります。

ネットワークインタフェースが2個のとき

インデックスが「eth1」の行が追加されると同時に、Auto-Assign Public IPの設定値が自動的に「Disable」になりました。この値は変更できません。そして、Public IPアドレスの自動割り当てができない旨のメッセージが表示されます。

このように、Management Consoleでは、デバイスを特定せずにPublic IPアドレスの自動割り当てを有効化することは、できないようになっています。

対処法

というわけで、CloudFormationテンプレートでEC2のAuto-Assign Public IPを有効にしたい場合は、デバイスIDを明記しましょう。具体的には、上の失敗テンプレートを次のように変更します。

[...]
    "MyInstance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
[...]
        "NetworkInterfaces" : [{
          "AssociatePublicIpAddress" : "true",
          "DeleteOnTermination" : "true",
          "DeviceIndex" : "0",
          "GroupSet" : [ { "Ref" : "MySecurityGroup" } ],
          "SubnetId" : "subnet-9999999"
        }]
      }
    },
[...]

"DeviceIndex" : "0"を追加するだけです。これで、自動割り当てするデバイスインデックスを指定したことになり、スタックが作成できるようになります。

参考資料

CloudFormationでAuto-Assign Public IPを有効にしてEC2を起動しようとした時、もしエラーになったら、上記の設定を見直しましょう。

それでは、また。