Elastic Load Balancing both internal and internet-facing
Asked Answered
W

6

27

We are trying to use Elastic Load Balancing in AWS with auto-scaling so we can scale in and out as needed.

Our application consists of several smaller applications, they are all on the same subnet and the same VPC.

We want to put our ELB between one of our apps and the rest.

Problem is we want the load balancer to be working both internally between different apps using an API and also internet-facing because our application still has some usage that should be done externally and not through the API.

I've read this question but I could not figure out exactly how to do it from there, it does not really specify any steps or maybe I did understand it very well.

Can we have an ELB that is both internal and external?

For the record, I can only access this network through a VPN.

Whichever answered 12/4, 2016 at 21:40 Comment(1)
You can set up a private DNS address to resolve to your internal ELB through Route 53, so if you can use that for your internal API calls then it should work fine. Difficulty may ensue if you have to use a static IP address rather than a DNS endpoint.Elastomer
A
30

It is not possible to for an Elastic Load Balancer to have both a public IP address and a private IP address. It is one or the other, but not both.

If you want your ELB to have a private IP address, then it cannot listen to requests from the internet.

If your ELB is public-facing, you can still call to it from your internal EC2 instances using the public endpoint. However, there are some caveats that goes with this:

  • The traffic will exit your VPC and re-enter it. It will not be direct instance-to-ELB connection that a private IP address will afford you.
  • You also cannot use security groups in your security group rules.

There are 3 alternative scenarios:

  1. Duplicate the ELB and EC2 instances, one dedicated to private traffic, one dedicated to public traffic.
  2. Have 2 ELBs (one public, one private) that share the same back-end EC2 instances.
  3. Don't use an ELB for either private or public traffic, and instead use an Elastic IP address (if public) or a private IP address (if private) on a single EC2 instance.
Acord answered 13/4, 2016 at 0:6 Comment(3)
Thanks, that's what I was looking forWhichever
This is actually not true, as @DaryL already posted in his answer. You can lookup the internal ip addresses using the AWS API and SDK, and then create your own DNS record in Route53 to these addresses. Updating them every 5 minutes should be enough, but it's safe to put something like HAProxy in between, to ensure all IPs are still alive. Or use Route53 healthchecks, but I think those can become pretty expensive.Conformal
@Conformal If you're pulling HAProxy into the picture (which presumably you're self-hosting), what is the advantage of using an ELB/ALB in the first place?Bichloride
E
14

I disagree with @MattHouser answer. Actually, in a VPC, your ELB have all its internal interfaces listed in Network Interfaces with Public IP AND Primary private IP. I've tested the private IP of my public ELB and it's working exactly like the external one.

The problem is : theses IPs are not listed anywhere in a up to date manner like on a private ELB DNS. So you have to do it by yourself.

I've made a little POC script on this, with an internal Route53 hosted zone : https://gist.github.com/darylounet/3c6253c60b7dc52da927b80a0ae8d428

Evie answered 1/5, 2016 at 9:33 Comment(3)
With this solution, specifically, is it not a problem that the IP addresses associated with load balancers are dynamic? See forums.aws.amazon.com/message.jspa?messageID=287183.Liquescent
Be careful, on this AWS forum thread, they are talking about public IPs. The script I provide register private ELB IPs in a private Route53 zone. Both public and private ELB IPs are dynamic, so you have to launch this script regularly, in a crontab for example. I have it in production since 1 year without any problem and I launch this script every 5 minutes in a crontab.Evie
A nodeJS example: github.com/Bramzor/lambda-sync-private-elb-ipsDiaphane
D
4

I made a Lambda function that checks which private IPs are set to the loadbalancer and will update Route53 record when it changes: https://github.com/Bramzor/lambda-sync-private-elb-ips

Using this function, you can easily make use of the ELB for private traffic. I personally use it to connect multiple regions to each other over a VPC inter-region peering without needing an additional ELB.

Diaphane answered 25/7, 2019 at 20:39 Comment(3)
how much it costs comparing to having a private lb?Whizbang
@Whizbang Running a Lambda of this kind will amount to a negligible cost. For example, if the lambda completes in 10 seconds (most likely it'll be under that), it will cost you 2 cents per 1000 invocations in Canada. Add to that even more negligible costs for EventBridge and CloudWatch Logs.Curvaceous
@lanweb compared to paying 10s of $ per month for a dedicated private LB, these Lambda functions cost only a few cent.Diaphane
W
2

I faced the same challenge and I can confirm the best solution so far is to have two different ALBs, one internet-facing and the other internal. You can attach both ALBs to a single AutoScaling Group so you can access the same cluster.

Make sure the networking options (Subnets, security groups) of both ALBs are the same in order for both to access the same cluster instances. Autoscaling and Launch Configuration works seamlessly with both ALBs attached to the same AutoSacling Group. This is also working with ALBs created from ElasticBeanstalk environments.

Wretched answered 10/1, 2019 at 15:56 Comment(0)
V
1

The standard AWS solution would be to have an extra internal ELB for this. Looks like @DaryL has an interesting workaround, but it could fail for 5 minutes if the DNS is not updated. Also there is no way to have a separate security group for the internal IPs since they share the ENI and security of the external IP of the ELB.

Verney answered 24/9, 2017 at 14:23 Comment(0)
A
-2

I understand it might not answer the direct question but still helpful for an alternative (multi-env) design scenario. If you're using multiple environments (like snapshot / staging / prod) with Terraform you could create conditional resources based on an environment variable. E.g. in testing environments you deploy into private subnets and set ALB internal = true but in prod you set it to internet-facing and deploy into subnets with public IP assignment.

resource aws_lb "test" {
  ...
  internal        = (var.env_name == "prod" ? false : true)
  subnets         = (var.env_name == "prod" ? split(",", 
  var.public_subnets) : split(",", var.private_subnets))
  ...

}

Alidus answered 13/7, 2023 at 10:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.