When managing web applications across multiple cloud providers (AWS, DigitalOcean, Vultr), you might need to distribute traffic to external endpoints while maintaining a single entry point. AWS Load Balancers can handle this through specific configurations.
Client → DNS → AWS ALB/NLB → Target Groups →
- AWS EC2 Instances (Internal IPs)
- DigitalOcean Droplets (External IPs)
- Vultr Instances (External IPs)
1. Creating Target Groups for External IPs
For Application Load Balancer (ALB):
aws elbv2 create-target-group \
--name external-backends \
--protocol HTTP \
--port 80 \
--vpc-id vpc-123456 \
--health-check-protocol HTTP \
--health-check-path /health
2. Registering External IP Targets
Using AWS CLI to register non-AWS instances:
aws elbv2 register-targets \
--target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/external-backends/1234567890123456 \
--targets Id=203.0.113.10,Port=8080 Id=198.51.100.20,Port=8081
3. Network Load Balancer (NLB) Alternative
For TCP/UDP traffic forwarding:
aws elbv2 create-load-balancer \
--name external-nlb \
--type network \
--scheme internet-facing \
--subnets subnet-123456 subnet-789012
- Security Groups must allow traffic from the ALB/NLB to external IPs
- Health checks must be properly configured for external targets
- Consider using PrivateLink for better security with external endpoints
- For HTTPS, ensure proper certificate management across providers
resource "aws_lb_target_group" "external" {
name = "multi-cloud-tg"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
path = "/health"
}
}
resource "aws_lb_target_group_attachment" "do" {
target_group_arn = aws_lb_target_group.external.arn
target_id = "203.0.113.10"
port = 8080
}
When routing to external endpoints:
- Add latency between 5-15ms per hop between cloud providers
- Monitor TCP connection times with CloudWatch metrics
- Consider geographic distribution of your external targets
- Implement connection draining for better failover handling
In a distributed architecture, you might have web applications running across multiple cloud providers (AWS, Digital Ocean, Vultr) with instances listening on different ports. A common requirement is to use AWS Load Balancer as a single entry point to route traffic to these external endpoints.
AWS offers two main types of load balancers that can potentially solve this:
- Application Load Balancer (ALB): Operates at layer 7 (HTTP/HTTPS)
- Network Load Balancer (NLB): Operates at layer 4 (TCP/UDP)
Network Load Balancer is better suited for this scenario as it supports IP addresses as targets:
# AWS CLI command to register external IPs as targets
aws elbv2 register-targets \
--target-group-arn your-target-group-arn \
--targets Id=203.0.113.5,Port=8080 Id=198.51.100.10,Port=8081
Here's how to set up an NLB to forward to external IPs:
- Create a Network Load Balancer
- Create a target group with target type as 'IP addresses'
- Register your external IP addresses and ports
- Configure health checks for your external endpoints
- Create listeners and rules
When routing to external IPs, keep in mind:
# Sample CloudFormation template snippet
Resources:
ExternalTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: external-ips-target-group
Port: 80
Protocol: TCP
TargetType: ip
Targets:
- Id: 203.0.113.5
Port: 8080
- Id: 198.51.100.10
Port: 8081
If traffic isn't flowing correctly:
- Verify security groups and network ACLs allow traffic from NLB to your external IPs
- Check that health checks are passing
- Ensure your external instances can handle the additional hop
While ALB doesn't natively support IP targets, you can use a Lambda function as a target to proxy requests:
// Sample Lambda code to route to external endpoints
exports.handler = async (event) => {
const http = require('http');
const options = {
hostname: 'external.example.com',
port: 8080,
path: event.path,
method: event.httpMethod
};
return new Promise((resolve) => {
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => resolve({
statusCode: res.statusCode,
body: data
}));
});
req.end();
});
};