First associate Elastic IP then run command

34 Views Asked by At

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?

1

There are 1 best solutions below

0
Halod On BEST ANSWER

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.