amazon-web-servicesamazon-ec2yamlaws-cloudformationelastic-ip

First associate Elastic IP then run command


I am trying to launch an EC2 instance with an Elastic IP attached to it via cloudformation. I have a YAML file that launches the EC2 instance and runs code after launch via UserData property (AWS::EC2::Instance). It then associates an IP via AWS::EC2::EIPAssociation. However, this order does not fit my requirements. I want to first associate and then run the script, because my script actually depends on the IP associated with it.

Does anybody know how to first associate IP and then run script via YAML? Is there an option of defining the Elastic IP within AWS::EC2::Instance?


Solution

  • You can use the option to create a ENI first > Associate the EIP to it > Use this ENI as primary interface of your Instance during launch. This way your EC2 will come up with the EIP associated and thus have internet access to proceed with User-Data. In the example below, I am also doing an EIP allocation. If this is not needed in your case, do make changes to the EC2EIP section.

    Metadata:
      TemplateId: EC2 With EIP
    Parameters:
      EC2AmazonLinuxAMIID:
        Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
        Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
      EC2Subnet:
        Type: AWS::EC2::Subnet::Id
        Description: Subnet to launch EC2
      EC2VPC:
        Type: AWS::EC2::VPC::Id
        Description: VPC to launch EC2
      KeyName:
        Type: AWS::EC2::KeyPair::KeyName
        Description: Key Pair to login
    Resources:
      EC2EIP:
        Type: AWS::EC2::EIP
        Properties:
          PublicIpv4Pool: amazon
          Domain: vpc
          Tags:
            - Key: Name
              Value: EIP EC2
      EC2SecurityGroup:
        Type: AWS::EC2::SecurityGroup
        Properties:
          GroupDescription: EC2 Security Group
          VpcId: !Ref EC2VPC
          SecurityGroupIngress:
            - IpProtocol: tcp
              FromPort: '22'
              ToPort: '22'
              CidrIp: 0.0.0.0/0
            - IpProtocol: tcp
              FromPort: '3389'
              ToPort: '3389'
              CidrIp: 0.0.0.0/0
            - IpProtocol: tcp
              FromPort: '80'
              ToPort: '80'
              CidrIp: 0.0.0.0/0
            - IpProtocol: tcp
              FromPort: '443'
              ToPort: '443'
              CidrIp: 0.0.0.0/0
          SecurityGroupEgress:
            - IpProtocol: '-1'
              CidrIp: 0.0.0.0/0
          Tags:
            - Key: Name
              Value: !Sub "${AWS::StackName}-EC2SecurityGroup"
    
      EC2ENI:
        Type: AWS::EC2::NetworkInterface
        Properties:
            Tags:
            - Key: Name
              Value: !Sub "${AWS::StackName}-EC2ENI"
            Description: EC2 Network Interface
            SourceDestCheck: 'false'
            GroupSet:
            - !Ref EC2SecurityGroup
            SubnetId: !Ref EC2Subnet
    
      EC2ENIAssociation:
        Type: AWS::EC2::EIPAssociation
        Properties:
          NetworkInterfaceId: !Ref EC2ENI
          AllocationId: !GetAtt EC2EIP.AllocationId
      
      EC2Instance:
        Type: AWS::EC2::Instance
        DependsOn:
          - EC2ENI
          - EC2ENIAssociation
        Properties:
          InstanceType: t2.micro
          ImageId: !Ref EC2AmazonLinuxAMIID
          KeyName: !Ref KeyName
          NetworkInterfaces:
            - NetworkInterfaceId: !Ref EC2ENI
              DeviceIndex: 0
          UserData:
            Fn::Base64: !Sub |
              #!/bin/bash
              yum update -y
              yum install -y httpd
              systemctl start httpd
              systemctl enable httpd
              echo "Hello World from EC2 Instance" > /var/www/html/index.html
          Tags:
            - Key: Name
              Value: !Sub "${AWS::StackName}-EC2Instance"
    

    This lets you select a VPC, Subnet as parameters. Then it pulls an EIP from Amazon pool and associate with an ENI. Next, launches an EC2 with this ENI mentioned. In this order, the User-Data will be triggered after EIP is associated.