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?
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.