AWS Elastic Load Balancing Connecting Internet-Facing Load Balancer to Private IP Address Targets
External
- https://aws.amazon.com/premiumsupport/knowledge-center/public-load-balancer-private-ec2/
- https://aws.amazon.com/blogs/networking-and-content-delivery/how-to-securely-publish-internet-applications-at-scale-using-application-load-balancer-and-aws-privatelink/
Internal
Overview
The essential configuration pieces that puts an Application Load Balancer in the position to take publicly issued requests and forward them to targets running in private subnets is to:
- Declare the application load balancer as internet-facing
- Associate the application balancer with two public subnets. We need two, deployed in different availability zones, for high availability purposes:
Resources:
...
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub ${Color}-public-alb
Scheme: internet-facing
Type: application
IpAddressType: ipv4
Subnets:
- !Ref PublicSubnet1
- !Ref PublicSubnet2
SecurityGroups:
- !Ref ApplicationLoadBalancerSecurityGroup
LoadBalancerAttributes:
- Key: access_logs.s3.enabled
Value: false
After being declared as such, the Application Load Balancer gets a dynamically generated publicly routable IP address, and the packets sent to the load balancer are routed to it by the virtue of the fact it is associated with public subnets.
The association between the Application Load Balancer and its target processes is done via a Target Group:
Resources:
...
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
#
# the "DependsOn" is important, I've seen race conditions
#
DependsOn: ApplicationLoadBalancer
Properties:
Name: !Sub ${Color}-themyscira-tg
VpcId: !Ref VPC
Protocol: HTTP
Port: !Ref ApplicationPort
TargetType: ip
HealthCheckProtocol: HTTP
HealthCheckIntervalSeconds: 60
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 3
UnhealthyThresholdCount: 3
HealthCheckPath: '/actuator/health'
The Target Group is referred by the Service definition, which is the configuration element that specifies the fact that the target tasks will be deployed in private subnets, in its Network Configuration section.
Resources:
...
ServiceDefinition:
Type: AWS::ECS::Service
Properties:
ServiceName: !Sub ${Color}-themyscira
LaunchType: FARGATE
Cluster: !Ref Cluster
TaskDefinition: !Ref TaskDefinition
DesiredCount: 1
HealthCheckGracePeriodSeconds: 60
LoadBalancers:
- ContainerName: !Sub themyscira-container
ContainerPort: !Ref ApplicationPort
TargetGroupArn: !Ref TargetGroup
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: DISABLED
SecurityGroups:
- !Ref ServiceSecurityGroup
Subnets:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
The full CloudFormation stack that can be used to experiment with this is available here:
Note that if the application load balancer is "internal" and not "internet-facing", the "Subnets" configuration element can be used to specify the private subnets, directly.