How to Deploy Elastic Beanstalk Instances Without Elastic IP (AWS SDK Implementation for Docker Demos)


2 views

When building rapid demo environments using Elastic Beanstalk, hitting AWS's 5 Elastic IP limit is frustratingly common. Our development team needed a solution for temporary Docker deployments that wouldn't consume precious Elastic IP resources.

By default, Elastic Beanstalk associates an Elastic IP with single-instance environments. This becomes problematic when:

  • Creating multiple demo environments
  • Running CI/CD pipelines with temporary instances
  • Maintaining developer sandboxes

Add this to your .ebextensions config file:

Resources:
  AWSEBAutoScalingGroup:
    Type: "AWS::AutoScaling::AutoScalingGroup"
    Properties:
      LaunchConfigurationName:
        Ref: "AWSEBAutoScalingLaunchConfiguration"
      VPCZoneIdentifier:
        Fn::GetOptionSetting:
          OptionName: "Subnets"
          DefaultValue: ""
      AssociatePublicIpAddress: false

For existing instances, use the AWS SDK:

const AWS = require('aws-sdk');
const ec2 = new AWS.EC2();

async function removeElasticIP(instanceId) {
  const addresses = await ec2.describeAddresses().promise();
  
  for (const address of addresses.Addresses) {
    if (address.InstanceId === instanceId) {
      await ec2.disassociateAddress({
        AssociationId: address.AssociationId
      }).promise();
      
      await ec2.releaseAddress({
        AllocationId: address.AllocationId
      }).promise();
    }
  }
}

For VPC environments, configure:

option_settings:
  - namespace: aws:ec2:vpc
    option_name: ELBScheme
    value: internal
  - namespace: aws:ec2:vpc
    option_name: AssociatePublicIpAddress
    value: false
  • Instance reboot time after IP change
  • DNS propagation delays
  • Security group implications
  • Load balancer configuration for multi-instance setups

Implement CloudWatch alarms to detect when approaching Elastic IP limits:

aws cloudwatch put-metric-alarm \
  --alarm-name "ElasticIPLimit" \
  --metric-name "ElasticIPAddressCount" \
  --namespace "AWS/EC2" \
  --statistic "Maximum" \
  --period 300 \
  --threshold 4 \
  --comparison-operator "GreaterThanOrEqualToThreshold" \
  --evaluation-periods 1

When rapidly deploying temporary Docker demo environments through Elastic Beanstalk, the default Elastic IP assignment becomes problematic. The 5-Elastic-IP-per-account limit (soft limit that can be increased via support ticket) creates deployment failures when exceeded.

The most efficient approach is preventing Elastic IP assignment during environment creation. This can be achieved through Elastic Beanstalk's configuration files:

# .ebextensions/disable-eip.config
Resources:
  AWSEBAutoScalingGroup:
    Type: "AWS::AutoScaling::AutoScalingGroup"
    Properties:
      LaunchConfigurationName: 
        Ref: "AWSEBAutoScalingLaunchConfiguration"
      VPCZoneIdentifier: 
        Fn::GetOptionSetting:
          OptionName: "Subnets"
          DefaultValue: ""
      AssociatePublicIpAddress: false  # This is the key setting

If instances are already launched with Elastic IPs, here's a Node.js cleanup script using the AWS SDK:

const AWS = require('aws-sdk');
const ec2 = new AWS.EC2();

async function releaseEIPs(environmentName) {
  const beanstalk = new AWS.ElasticBeanstalk();
  const { Environments } = await beanstalk.describeEnvironments({
    EnvironmentNames: [environmentName]
  }).promise();

  const instanceIds = Environments[0].Instances.map(i => i.Id);
  
  const { Addresses } = await ec2.describeAddresses({
    Filters: [{ Name: 'instance-id', Values: instanceIds }]
  }).promise();

  await Promise.all(
    Addresses.map(addr => 
      ec2.disassociateAddress({
        AssociationId: addr.AssociationId
      }).promise()
      .then(() => ec2.releaseAddress({
        AllocationId: addr.AllocationId
      }).promise())
    )
  );
}

For demo environments that don't need persistent IPs:

  • Use Application Load Balancers instead of single instance deployments
  • Consider Route 53 weighted routing for blue/green deployments
  • Implement automatic environment termination after inactivity periods

For quick operations from CI/CD pipelines:

aws ec2 describe-addresses --query 'Addresses[?AssociationId].AssociationId' \
  --output text | xargs -I {} aws ec2 disassociate-address --association-id {}