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 {}