Network load balancer never becomes healthy - amazon-web-services

I am trying to host a service on Fargate that exposes a TCP port.
Even this simple example that exposes HTTP on port 80 never becomes healthy on Fargate.
var loadBalancedFargateService = NetworkLoadBalancedFargateService.Builder.create(this, "ServiceSample")
.cluster(fargateCluster)
.publicLoadBalancer(true)
.memoryLimitMiB(1024)
.cpu(512)
.listenerPort(80)
.taskImageOptions(NetworkLoadBalancedTaskImageOptions.builder()
.image(ContainerImage.fromRegistry("amazon/amazon-ecs-sample"))
.containerPort(80)
.build())
.build();
The error I get is:
service dev-shopapi-redis-ServiceSampleService16E525F0-ASe7w3oUlGf9 port 80 is unhealthy in target-group dev-sh-Servi-EFOUJ7LG0YPP due to (reason Health checks failed).
My intention is to expose another service with a TCP protocol and this is a simplified version that exposes HTTP.
What I am doing wrong?

Try these troubleshooting steps:
If your container is mapped to port 80, confirm that your container security group allows inbound traffic on port 80 for the
load balancer.
Confirm that the ping port value for your load balancer health is configured correctly. If this port isn't configured correctly, then
your load balancer could de-register the container from itself.
Define a minimum health check grace period.
This instructs the service scheduler to ignore Elastic Load Balancing
health checks for a pre-defined time period after a task has been
instantiated.
Monitor the CPU and memory metrics of the service. For example, high CPU can make your application unresponsive and result in a 502
error.
Check your application logs for application errors.
Check if the ping port and the health check path are configured correctly.
Unlike the ApplicationLoadBalancedFargateService, the NetworkLoadBalancedFargateService does not automatically configure the container port.
So just add the following in the CDK:
loadBalancedEcsService.getService().getConnections().allowFromAnyIpv4( Port.tcp(80) );//80 since the container is listening on port 80
Source: https://aws.amazon.com/premiumsupport/knowledge-center/ecs-fargate-health-check-failures/

Related

ELB health check fail AWS

My ELB health check fails all the time but cannot figure it why (502 bad gateway).
I have a cluster (ECS) with a service that runs at least one task (Fargate) which is a Node API listening on port 3000 & 3001 (3000 for http & 3001 for https since I cannot use port below 1024).
I have an Elastic Load Balancer (application) that is listening on port 80. It forwards the trafic on a target group with protocol port 3000.
This target group has as target type: ip address since I use fargate and not EC2 for my tasks.
So when a task is turning on, I correctly see the private IP of the task registering into the target group.
My health route is server_ip_address/health and it returns a classic 200 status code. This route works well because I tried it directly from the public ip address of the task (quickly before it stopped because of the health check failing) and it returns a 200. I also tried it through the ELB dns name (so my-elb.eu-west-1.elb.amazonaws.com/health) and it worked well as well so I don't understand why the health check fail.
Anyone know what I missed ?
In the screenshot of your targets in the target group it is showing the port as 80, this means that the load balancer (and health check) will be attempting to connect to the Fargate container on port 80.
You mentioned that it should be served from port 3000, therefore you will need to ensure that the target group is listening on port 3000 instead. Once this is in place, assuming that the security group of the host allows inbound access the 502 error should go away.
To be clear the listener port is what port the client connects to, whereas the target port is the port the load balancer connects to your target on.

aws ECS, ECS instance is not registered to ALB target group

I create ECS service and it runs 1 ecs instance and I can see the instance is registered as a target of the load balancer.
Now I trigger a Auto Scaling Group (by just incrementing desired instance count) to launch a new instance.
The instance is launched and added to the ECS cluster. (I can see it on ECS instances tab)
But the instance is not added to the ALB target. (I expect to see 2 instances in the following image, but I only see 1)
I can edit AutoScalingGroup 's target group like the following
Then I see the following .
But the health check fails. It seems the 80 port is not reachable.
Although I have port 80 open for public in the security group for the instance. (Also, instance created from ecs service uses dynamic port mapping but instance created by ALS does not)
So AutoScalingGroup can launch new instance but my load balancer never gives traffic to the new instance.
I did try https://aws.amazon.com/premiumsupport/knowledge-center/troubleshoot-unhealthy-checks-ecs/?nc1=h_ls and it shows I can connect to port 80 from host to the docker container by something like curl -v http://${IPADDR}/health.
So it must be the case that there's something wrong with host port 80 (load balancer can't connect to it).
But it is also the case the security group setting is not wrong, because the working instance and this non working instance is using the same SG.
Edit
Because I used dynamic mapping, my webserver is running on some random port.
As you can see the instance started by ecs service has registered itself to target group with random port.
However instance started by ALB has registered itself to target group with port 80.
The instance will not be added to the target group if it's not healthy. So you need to fix the health check first.
From your first instance, your mapped port is 32769 so I assume if this is the same target group and if it is the same application then the port in new instance should be 32769.
When you curl the IP endpoint curl -I -v http://${IPADDR}/health. is the HTTP status code was 200, if it is 200 then it should be healthy if it's not 200 then update the backend http-status code or you can update health check HTTP status code.
I assume that you are also running ECS in both instances, so ECS create target group against each ECS services, are you running some mix services that you need target group in AS group? if you are running dynamic port then remove the health check path to traffic port.
Now if we look the offical possible causes for 502 bad Gateway
Dynamic port mapping is a feature of container instance in Amazon Elastic Container Service (Amazon ECS)
Dynamic port mapping with an Application Load Balancer makes it easier
to run multiple tasks on the same Amazon ECS service on an Amazon ECS
cluster.
With the Classic Load Balancer, you must statically map port numbers
on a container instance. The Classic Load Balancer does not allow you
to run multiple copies of a task on the same instance because the
ports conflict. An Application Load Balancer uses dynamic port mapping
so that you can run multiple tasks from a single service on the same
container instance.
Your created target group will not work with dynamic port, you have to bind the target group with ECS services.
dynamic-port-mapping-ecs
HTTP 502: Bad Gateway
Possible causes:
The load balancer received a TCP RST from the target when attempting to establish a connection.
The load balancer received an unexpected response from the target, such as "ICMP Destination unreachable (Host unreachable)", when attempting to establish a connection. Check whether traffic is allowed from the load balancer subnets to the targets on the target port.
The target closed the connection with a TCP RST or a TCP FIN while the load balancer had an outstanding request to the target. Check whether the keep-alive duration of the target is shorter than the idle timeout value of the load balancer.
The target response is malformed or contains HTTP headers that are not valid.
The load balancer encountered an SSL handshake error or SSL handshake timeout (10 seconds) when connecting to a target.
The deregistration delay period elapsed for a request being handled by a target that was deregistered. Increase the delay period so that lengthy operations can complete.
http-502-issues
It seems you know the root cause, which is that port 80 is failing the health check and thats why it is never added to ALB. Here is what you can try
First, check that your service is listening on port 80 on the new host. You can use command like netcat
nv -v localhost 80
Once you know that the service is listening, the recommended way to allow your ALB to connect to your host is to add a Security group inbound rule for your instance to allow traffic from your ALB security group on port 80

EC2 instance attached to a load balancer is showing Unhealthy status

I created a load balancer and assigned it one of the running EC2 instance. After creation, I navigated to Target Group section in the AWS Console under Load Balancing and when I selected the target group that was assigned to the load balancer, it shows registered instance status as "Unhealthy" and there was a message above registered instance pane that says "None of these Availability Zones contains a healthy target. Requests are being routed to all targets". While creating the load balancer, I selected all the subnets (availability zones).
settings I used for health check are mentioned below,
Protocol: HTTP
Path: /healthcheck.html
Port: traffic port
Healthy threshold: 3
Unhealthy threshold: 2
Timeout: 5
Interval: 10
Success codes: 200
So why does my registered instance status as "Unhealthy" and how can I rectify/resolve that to change the status to "In-service"?
Unhealthy indicates that the health check is failing for the instance.
Things to check:
Check that the instance is running a web server
Check that the web page at healthcheck.html responds with a valid 200 response
Check that instance has a security group that permits access on Port 80 (HTTP)
In my case health check configuration on ALB is / with https.
I resolved with below steps.
Check the security groups - whether we have opened the required ports from ALB SG to EC2 SG.
Login to server and check does IIS server's default site has 443 port opened if your health-check is on 443. (whatever port you are using for health checks).
Use the curl command to troubleshoot the issue.
If you would like to check on HTTPS use the below command to check the response. Use -k or --insecure to ignore the SSL issue.
curl https://[serverIP] -k
For HTTP test use the below command.
curl http://[serverIP]
If you are sharing the load balancer among several EC2 instances that run similar services, make sure each of your services run in a different port otherwise your service won't be reachable and therefore your health check won't pass

Load balancing in GCE to cluster

I'm trying to set up Load balancing to my cluster that I created via container engine but I keep getting 502 Server Error.
Here is what I do.
I make sure that my service really runs taking this ip in kubernetes dashboard
I have only one instance group. So this belongs cluster
80 port is open for every instance in Firewall rules
I created a load balancer with this configuration. As you can see I set the only instance group I got, also I set up health check. The health check is http endoint /api/ping/ that returns HTTP 200 with body "pong". But I keep getting 502 ERROR. I understand it happens because health check doesn't pass. Apperently it's because when load balancer is sending request it's sending directly to instances, instead of to docker containers. If I go by ip of vm isntance where I host my cluster I will get nothing as well.
I want to do it so I could switch traffic between different clusters If I decide to create a new one, also I would be able to balance https traffic.
Maybe it will help someone so I will post the answer.
I created my pods via UI kubernetes using their consructor-form. When I used this form ports were not exposed to the host machine(Even I marked them as External ports). I wrote an yaml config and exposed ports there to host machine. After this balancer started working.
I used this block to expose 80 port to host machine
ports:
- containerPort: 80
hostPort: 80
protocol: TCP

Logstash ping (or similar) to report its health to Amazon ELB

I have an Amazon Elastic Load Balancer which has a health checker. It attempts to connect to my Logstash instance running on some_ec2_instance:5000.
The ELB health check attempts to open a tcp connection at some_ec2_instance:5000. However, it never passes this health test. I can manually connect to the the ec2 instance and check that Logstash is running and it is indeed operational. I can also telnet localhost 5000 into it without any problems.
In addition my security group allows input/outputs on port 5000 so I don't think that is a problem.
Does anyone have suggestions for how to enable the ELB to pass the health check? is there a /ping path or a plugin which will enable access to such path?
Assuming you are running elasticsearch and logstash on the same hosts, open port 9200 to your ELB and use a http health check on that port.
Running ELB health checks against port 5000 (logstash itself) overwhelms the port.