3

I have a simple CloudFormation stack which gets created with a template. A server which hosts one Docker container.

This is part of the template that creates the host and the container:

  ContainerHostInstances:
    Type: "AWS::AutoScaling::LaunchConfiguration"
    DependsOn: "AttachGateway"
    Properties:
      AssociatePublicIpAddress: true
      ImageId: "ami-0302f3ec240b9d23c"
      SecurityGroups:
        - Ref: "NginxSecurityGroup"
      InstanceType: "t3.nano"
      IamInstanceProfile: !Ref "ECSHostEC2InstanceProfile"
      KeyName: "test-key-pair"
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          echo ECS_CLUSTER=${MyCluster} >> /etc/ecs/ecs.config
          yum install -y aws-cfn-bootstrap
          /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}

...

  MyTask:
    Type: "AWS::ECS::TaskDefinition"
    Properties:
      Family: "my-task-family"
      ContainerDefinitions:
        - Name: "nginx"
          Essential: true
          Image: "image_url/nginx:latest"
          MemoryReservation: 300
          LogConfiguration:
            LogDriver: "awslogs"
            Options:
              awslogs-group: "nginx"
              awslogs-region: !Ref "AWS::Region"
              awslogs-stream-prefix: "prefix"
              awslogs-datetime-format: "%Y-%m-%d %H:%M:%S.%L"
          PortMappings:
            - ContainerPort: 80
              HostPort: 80

My problem is that I can't associate an elastic IP address within the template. I can do it using the console but I want to have it inside the template if possible.

I tried this way:

  ElasticIPAssoc:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: "some_id"
      InstanceId: "HOW CAN I GET THIS VALUE"
      NetworkInterfaceId: "OR THAT VALUE"

I don't see a way to get the instanceId or its corresponding NetworkInterfaceId.

2 Answers 2

2

Typically you don’t give Elastic IPs to hosts in Auto Scaling Groups.

Some of the reasons are that ASG can expand and contract and you would need to keep track of the assigned / free EIPs, re-assign them when new instances are created, keep updating DNS to list only the assigned ones, etc. That’s not practical.

The standard approach is to have a Load Balancer in front of the Auto Scaling Group. Preferably Application Load Balancer (ALB) unless you’ve got a special requirement to use Classic / Elastic Load Balancer (ELB) or Network Load Balancer (NLB).

Instances in ASG can automatically register to ALB, in DNS you’ll have CNAME to the ALB hostname, etc. That’s the standard approach with Auto Scaling Groups.

Another option for your CFN template is to simply create a single instance (Type: AWS::EC2::Instance) rather than Launch configuration and Auto scaling group. It won't give you as much resiliency as the ASG but will let you assign EIP in the template and get away without ALB.

Hope that helps :)

0

As MLu wrote it could be better to switch to a single EC2 instance without any AutoScaling group/ASG.

If you use ASG to recover the instance when its status check fails, and that's the default ASG health-check behaviour, you can try EC2 auto-recovery feature. You can create an Amazon CloudWatch alarm that monitors the instance and automatically recovers it if it becomes impaired due to an underlying hardware failure or a problem that requires AWS involvement to repair. In other words, when its status-check fails. This can be easily declared in CloudFormation template.

If you really need to assign EIP to your instance in ASG, assuming this the only instance in the ASG, then, you can try to:

  • create an IAM role with policy allowing associate the EIP with an instance
  • pass the role to the instance by setting its instance profile
  • associate the EIP with the instance by calling corresponding API from its user-data (aka with AWS CLI etc.)

This is sufficient in a VPC in an EC2-VPC-only account where EIP reassociation is allowed by default. Otherwise you would have to explicitly allow it in 'legacy' EC2-classic account.

If you would like to make this more mature you could try using AutoScaling lifecycle hooks. With them, you can say 'associate the EIP with a new instance' when it is launched/ASG scales out but it is not in-service yet. And 'disassociate the EIP from the instance' when it is going to be terminated/ASG scales in before it is terminated. This would require additional permission in the IAM role to allow disassociate EIP address API action.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.