AWS LoadBalancer access from EKS worker nodes in provate subnets - amazon-web-services

I have an EKS cluster with worker nodes in private subnet. The worker nodes can access internet via the nat gateway. I have a Route53 hosted zone record routing traffic (alias) to a load balancer.
When I try to access the url (route53 record) from a pod within the EKS cluster, it times out. I tried allowing the worker nodes security group in the inbound rules of the load balancer security group but it does not work. Only thing that works is if I allow the public IP of the nat gateway in the inbound rules of the load balancer security group.
I am sure this setup is very common. My question is, is the solution of allowing the nat gateway public ip in the inbound rules of the LB SG the correct way or is there a better cleaner way to allow the access?

based on what you have described here, it seems like you have a internet facing load balancer and trying to access it from the pod. In this case, the traffic needs to go out to internet(through nat gateway) and come back to the load balancer, that is why it only works when you add the public IP of nat gateway to load balancer's SG.
Now, in terms of the solution, it depends on what you are trying to do here:
if you only need to consume the service inside the cluster, you can use DNS name created for that service inside the cluster. in this case the traffic will stay inside the cluster. you can read more here
if you need to make the service available to other clusters but same VPC, you can use a private load balancer and add the security group of worker nodes to the load balancer SG.
if the service needs to be exposed to internet, then your solution works but you have to open the SG of the public load balancer to all public IPs accessing the service.

Related

AWS EC2 Internet access from behind Load Balancer

Using Terraform to setup a VPC with two EC2s in private subnets. The setup needs to SSH to the EC2s to install package updates from the Internet and install the application software. To do this there is an IGW and a NAT-GW in a public subnet. Both EC2s can access the Internet at this point as both private subnets are routing to the NAT-GW. Terraform and SSH to the private subnets is done via Client VPN.
One of the EC2s is going to host a web service so a Classic mode Load Balancer is added and configured to target the web server EC2. Using Classic mode because I can't find a way to make Terraform build Application mode LBs. The Load Balancer requires the instance to be using a subnet that routes to the IGW, so it is changed from routing to the NAT-GW, to the IGW. At this point, the Load Balancer comes online with the EC2 responding and public Internet can access the web service using the DNS supplied End Point for the LB.
But now the web server EC2 can no longer access the Internet itself. I can't curl google.com or get package updates.
I would like to find a way to let the EC2 access the Internet from behind the LB and not use CloudFront at this time.
I would like to keep the EC2 in a private subnet because a public subnet causes the EC2 to have a public IP address, and I don't want that.
Looking for a way to make LB work without switching subnets, as that would make the EC web service unavailable when doing updates.
Not wanting any iptables or firewalld tricks. I would really like an AWS solution that is disto agnostic.
A few points/clarifications about the problems you're facing:
Instances on a public subnet do not need a NAT Gateway. They can initiate outbound requests to the internet via IGW. NGW is for allowing outbound IPv4 connections from instances in private subnets.
The load balancer itself needs to be on a public subnet. The instances that the LB will route to do not. They can be in the same subnet or different subnets, public or private, as long as traffic is allowed through security groups.
You can create instances without a public IP, on a public subnet. However, they won't be able to receive or send traffic to the internet.
Terraform supports ALBs. The resource is aws_lb with load_balancer_type set to "application" (this is the default option).
That said, the public-private configuration you want is entirely possible.
Your ALB and NAT Gateway need to be on the public subnet, and EC2 instances on the private subnet.
The private subnet's route table needs to have a route to the NGW, to facilitate outbound connections.
EC2 instances' security group needs to allow traffic from the ALB's security group.
It sounds like you got steps 1 and 2 working, so the connection from ALB to EC2 is what you have to work on. See the documentation page here as well - https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Scenario2.html

Can we make EC2 instances in the web tier as Private?

We have Typical 3 tier architecture having Web, App and DB.
Can we make EC2 instances in the web tier as Private? and allow incoming traffic only through ALB?
AFAIK we can apply an SG only allowing connections from the SG of the ALB. But What if our Private EC2 instance has to return response back to the client? How it'll be routed through ALB as ALB is mostly used for managing incoming traffic.
Also for outgoing traffic can we configure something like Private EC2 instance -> ALB -> Internet? If yes then how? So, is there any way for private EC2 instances to communicate to internet without assigning them public IP?
But What if our Private EC2 instance has to return response back to the client? How it'll be routed through ALB as ALB is mostly used for managing incoming traffic.
You don't have to do anything special, assuming your ALB and instances are correctly set. Any request coming to ALB, will be able to return to the client event if instances are in private subnet without any internet connectivity.
However, your instance won't be able to initiate internet connections by themselves. So if the instances don't need internet to operate, you don't need NAT. Otherwise, it is required.
Keeping your instances in a private subnet is best practice, even for the web layer.
For inbound traffic you would add a load balancer into your public subnets then allow HTTP/HTTPS ingress on the webs security group only from the load balancer. You can either do this through adding the subnet ranges into the web servers security group, or reference the security group the load balancer has assigned to it instead.
For outbound internet traffic in a private subnet you will need to create either a NAT Gateway or NAT instance within a public subnet, and then add a route for 0.0.0.0/0 for the private subnet to route traffic to the NAT. Additionally if you want IPv6 traffic you would create an egress only internet gateway with a route of ::/0.

Adding an additional static IP to elastic beanstalk instances

I have a few elastic beanstalk applications on the same VPC (which can also be reduced to one application), and I'd like them to be accessible both via one IP address (both inbound and outbound traffic), and via their own URL. I've seen that this can be done via NAT, but I haven't found documentation on whether this is all traffic (in both directions) and if it can be done alongside the original endpoints. Another question is whether there is a better way to do this.
NAT is used to provide access to internet for instances in private subnets. In this case all instances in the subnet will have the same external IP. But you won't be able to access your private instances using that IP, it's only for outbound traffic.
In your case I'd go with a ELB. Following the best practices, keep your instances with running applications in private subnets and:
Have an external facing ELB in public subnets (you'll need at least 2 public subnets in different AZs).
Create a Target Group and add your instances with running apps to it.
Assign the Target Group to the listener on your ELB.
Configure the security groups on ELB and app instances to allow the traffic on the port the applications are serving (usually it's 8080).
As a result you'll have your instances accessible by the ELB URL. If you want to have a pretty URL, you can configure it in Route 53 and resolve it to the ELB URL.
Its not possible by using aws provided NAT cluster but can be achieved by hosting a box with both Load balancer and NAT running in the same instance with EIP, map your domain with that IP for incoming traffic, for outgoing traffic in the route table of private app subnet you configure the NAT as target for all the 0.0.0.0/0 route, But it is not the recommended approach since the front facing instance becomes SPOF.
The recommended way is using ELB as a front facing and NAT cluster as outgoing for high HA.

AWS NLB in public subnets with EC2 in private subnets

Has someone configured a NLB in the public subnets of your VPC to route traffic to EC2 instances that are in the private subnets?
When using an ELB, a good solution is to create a Security Group for the ELB and then create another SecurityGroup for the private EC2 Instances, allowing incoming traffic from that ELB Security Group, as explained here:
https://aws.amazon.com/premiumsupport/knowledge-center/public-load-balancer-private-ec2/
"You can also add a rule on the instance’s security group to allow traffic from the security group assigned to the load balancer. For example, if the security group on the load balancer is sg-1234567a, make the following changes on the security group associated with the private instances"
Since you cannot associate a Security Group to a NLB, how could you accomplish this with the same type of security?
Thanks!
Since you cannot associate a Security Group to a NLB, how could you
accomplish this with the same type of security?
The security aspect does not change.
NLB is a different beast, it not the same as classic Load Balancers. For Classic Load Balancers, from the point of view of your instances, traffic does appear to come from inside the VPC. From outside, traffic goes to a (random and mutating) list of IP addresses, resolved by the DNS record that AWS provides to you.
Network Load Balancers are completely different. From the point of view of your instances, they are completely invisible. If it is an external network load balancer, traffic appears to be coming from instances on the internet directly (even though this is an illusion). Therefore, if you want to talk to everyone on the internet, 0.0.0.0/0 is what you open it to.
This is, in fact, what the documentation says:
https://docs.aws.amazon.com/elasticloadbalancing/latest/network/target-group-register-targets.html#target-security-groups
Recommended Rules
Inbound Source Port Range Comment
Client IP addresses instance listener Allow traffic from clients on the instance listener port
VPC CIDR health check Allow traffic from the load balancer on the health check port
Client IP addresses is whatever your client IPs are. If they are on the open internet, 0.0.0.0/0 it is. Adding the NLB private IP address, as I saw in other responses, accomplishes nothing. Traffic is not coming from there, as far as the instances are concerned.
On the security angle, nothing changes. Since your instances are in private subnets, traffic cannot flow directly to them, as there is a NAT gateway in the middle. It can only flow from them to the internet (through NAT gateway, then internet gateway). Even if you specify all traffic is allowed from everywhere, traffic still won't come. It will have to come through another way. In your case, that way is the NLB, which has a fixed number of ports it listens to, and only sends traffic to the destination ports on the instances you specify.
If you are moving from classic Load Balancers to NLBs, move the security group rules from the Load Balancer to your instances. Or better yet, since you can have multiple security groups, just add the SG you currently have for the classic LB to the instances(and update any ASGs as needed). Your security posture will be exactly the same. With the added benefit that now your applications won't need things like proxy protocol to figure out where traffic is coming from, it is no longer obfuscated by the load balancer.
That is indeed true as per AWS Documentation :
Network Load Balancers do not have associated security groups.
Therefore, the security groups for your targets must use IP addresses
to allow traffic from the load balancer.
So If you do not want to grant access to the entire VPC CIDR, you can grant access to the private IP addresses used by the load balancer nodes. There is one IP address per load balancer subnet.
On NLB Tab of there is one Network Interface per Load Balancer from there :
On the Details tab for each network interface, copy the address from
Primary private IPv4 IP.
You can use this private IP Address at add it SG of EC2 Instances.
Please Refer to AWS Documentation
Tail your http access logs and you will see there is no changing of source IP address from the network load balancer which means you need to allow 0.0.0.0/0 on the endpoints security group if the internet needs access to your endpoint.
This is only ok if you use a private subnet so be careful if you have this server on a public subnet as this solution would not be advisable. In this case just use an application load balancer. You can still setup the same listener and configure a target group by instance as well. The application load balancer will update the source IP address to it's own private address if you tail the access logs. The advantage of this is you only need to allow https traffic to the app load balancer and then you can accept http for the target group if you like from the load balancer.

Any way to configure AWS security group to allow private instances to access a public-facing Load Balancer?

I have a web application with two different sites. Each can be accessed via HTTP. When you access Site #1, it will serve that site directly. When you access site #2, it will actually connect to site #1 behind the scenes via REST API calls. This architecture is shown in the diagram below.
All instances shown (in blue) have ONLY private IP addresses. Both Load Balancers are internet-facing because people from outside the VPC need to access the application. Each autoscale group has an associated security group which is applied to each of its' instances.
How can I configure LoadBalancer #1 to accept HTTP calls from Auto-Scale Group #2 given that those instances don't have public IP addresses? Do I need to have one private-facing Load Balancer and one internet-facing load balancer?
I want all this configuration to be done automatically in my Cloudformation file.
The AWS Elastic Load Balancing service provides a DNS Name for the load balancer. This name should be used when accessing the load balancer.
The DNS name resolves to one of several public IP addresses. Therefore, instances in Auto Scaling Group #2 require access to the Internet.
If all instances are in a Public subnet, then they should be able to access the Internet and, therefore, Load Balancer #1.
If the instances are in a Private subnet, they will require some means of accessing the Internet. This is typically done by launching a NAT instance in a Public subnet and configuring Route Tables on the Private subnet to route Internet traffic to the NAT server.
The traffic won't actually traverse the Internet. Rather, they will traverse AWS's edge of the Internet by popping out of the VPC and then back in again.
There is no configuration required on Load Balancer #1, since it is already accepting incoming traffic.