Application Load Balancer Target Groups Health Checks
Hello Everyone
Welcome to CloudAffaire and this is Debjeet.
In the last blog post we have discussed Application Load Balancer Target Groups. https://cloudaffaire.com/application-load-balancer-target-groups/
In this blog post, we will discuss the Application Load Balancer Target Groups health checks.
Application Load Balancer Target Groups Health Checks:
Your Application Load Balancer periodically sends requests to its registered targets to test their status. These tests are called health checks. Each load balancer node routes requests only to the healthy targets in the enabled Availability Zones for the load balancer. Each load balancer node checks the health of each target, using the health check settings for the target groups with which the target is registered. After your target is registered, it must pass one health check to be considered healthy. After each health check is completed, the load balancer node closes the connection that was established for the health check.
Note: If a target group contains only unhealthy registered targets, the load balancer nodes route requests across its unhealthy targets.
Health Check Settings:
You configure health checks for the targets in a target group using the following settings. The load balancer sends a health check request to each registered target every HealthCheckIntervalSeconds seconds, using the specified port, protocol, and ping path. Each health check request is independent and the result lasts for the entire interval. The time that it takes for the target to respond does not affect the interval for the next health check request. If the health checks exceed UnhealthyThresholdCount consecutive failures, the load balancer takes the target out of service. When the health checks exceed HealthyThresholdCount consecutive successes, the load balancer puts the target back in service.
- HealthCheckProtocol: The protocol the load balancer uses when performing health checks on targets. The possible protocols are HTTP and HTTPS. The default is the HTTP protocol.
- HealthCheckPort: The port the load balancer uses when performing health checks on targets. The default is to use the port on which each target receives traffic from the load balancer.
- HealthCheckPath: The ping path that is the destination on the targets for health checks. Specify a valid URI (/path?query). The default is /.
- HealthCheckTimeoutSeconds: The amount of time, in seconds, during which no response from a target means a failed health check. The range is 2–120 seconds. The default is 5 seconds if the target type is instance or ip and 30 seconds if the target type is lambda.
- HealthCheckIntervalSeconds: The approximate amount of time, in seconds, between health checks of an individual target. The range is 5–300 seconds. The default is 30 seconds if the target type is instance or ip and 35 seconds if the target type is lambda.
- HealthyThresholdCount: The number of consecutive successful health checks required before considering an unhealthy target healthy. The range is 2–10. The default is 5.
- UnhealthyThresholdCount: The number of consecutive failed health checks required before considering a target unhealthy. The range is 2–10. The default is 2.
- Matcher: The HTTP codes to use when checking for a successful response from a target. You can specify values or ranges of values between 200 and 499. The default value is 200.
Target Health Status:
Before the load balancer sends a health check request to a target, you must register it with a target group, specify its target group in a listener rule, and ensure that the Availability Zone of the target is enabled for the load balancer. Before a target can receive requests from the load balancer, it must pass the initial health checks. After a target passes the initial health checks, its status is Healthy.
- initial: The load balancer is in the process of registering the target or performing the initial health checks on the target.
- healthy: The target is healthy.
- unhealthy: The target did not respond to a health check or failed the health check.
- unused: The target is not registered with a target group, the target group is not used in a listener rule for the load balancer, or the target is in an Availability Zone that is not enabled for the load balancer.
- draining: The target is deregistering and connection draining is in process.
Application Load Balancer Target Groups Health Checks Demo:
Step 1: Create a custom VPC for your ALB.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
########################################################### ## Application Load Balancer Target Groups Health Checks ## ########################################################### ## Prerequisite: AWS CLI installed and configured with proper access ## https://cloudaffaire.com/category/aws/aws-cli/ ##---------------------------------- ## Create custom vpc for your alb ## ##---------------------------------- ## Create a directory for this demo mkdir alb_health_check_demo && cd alb_health_check_demo ## Create a VPC with DNS hotsname enabled AWS_VPC_ID=$(aws ec2 create-vpc \ --cidr-block 10.0.0.0/16 \ --query 'Vpc.{VpcId:VpcId}' \ --output text) && aws ec2 modify-vpc-attribute \ --vpc-id $AWS_VPC_ID \ --enable-dns-hostnames "{\"Value\":true}" ## Create two public subnets AWS_SUBNET_PUBLIC_ONE_ID=$(aws ec2 create-subnet \ --vpc-id $AWS_VPC_ID --cidr-block 10.0.1.0/24 \ --availability-zone ap-south-1a --query 'Subnet.{SubnetId:SubnetId}' \ --output text) && AWS_SUBNET_PUBLIC_TWO_ID=$(aws ec2 create-subnet \ --vpc-id $AWS_VPC_ID --cidr-block 10.0.2.0/24 \ --availability-zone ap-south-1b --query 'Subnet.{SubnetId:SubnetId}' \ --output text) ## Enable Auto-assign Public IP on Public Subnets aws ec2 modify-subnet-attribute \ --subnet-id $AWS_SUBNET_PUBLIC_ONE_ID \ --map-public-ip-on-launch && aws ec2 modify-subnet-attribute \ --subnet-id $AWS_SUBNET_PUBLIC_TWO_ID \ --map-public-ip-on-launch ## Create an Internet Gateway and attach to the VPC AWS_INTERNET_GATEWAY_ID=$(aws ec2 create-internet-gateway \ --query 'InternetGateway.{InternetGatewayId:InternetGatewayId}' \ --output text) && aws ec2 attach-internet-gateway \ --vpc-id $AWS_VPC_ID \ --internet-gateway-id $AWS_INTERNET_GATEWAY_ID ## Create a route table with route to Internet Gateway AWS_CUSTOM_ROUTE_TABLE_ID=$(aws ec2 create-route-table \ --vpc-id $AWS_VPC_ID \ --query 'RouteTable.{RouteTableId:RouteTableId}' \ --output text ) && aws ec2 create-route \ --route-table-id $AWS_CUSTOM_ROUTE_TABLE_ID \ --destination-cidr-block 0.0.0.0/0 \ --gateway-id $AWS_INTERNET_GATEWAY_ID ## Associate the public subnet with route table AWS_ROUTE_TABLE_ASSOID_ONE=$(aws ec2 associate-route-table \ --subnet-id $AWS_SUBNET_PUBLIC_ONE_ID \ --route-table-id $AWS_CUSTOM_ROUTE_TABLE_ID \ --query 'AssociationId' \ --output text) && AWS_ROUTE_TABLE_ASSOID_TWO=$(aws ec2 associate-route-table \ --subnet-id $AWS_SUBNET_PUBLIC_TWO_ID \ --route-table-id $AWS_CUSTOM_ROUTE_TABLE_ID \ --query 'AssociationId' \ --output text) ## Create a security group aws ec2 create-security-group \ --vpc-id $AWS_VPC_ID \ --group-name myvpc-security-group \ --description 'My VPC non default security group' && AWS_DEFAULT_SECURITY_GROUP_ID=$(aws ec2 describe-security-groups \ --filters "Name=vpc-id,Values=$AWS_VPC_ID" \ --query 'SecurityGroups[?GroupName == `default`].GroupId' \ --output text) && AWS_CUSTOM_SECURITY_GROUP_ID=$(aws ec2 describe-security-groups \ --filters "Name=vpc-id,Values=$AWS_VPC_ID" \ --query 'SecurityGroups[?GroupName == `myvpc-security-group`].GroupId' \ --output text) ## Create security group ingress rules aws ec2 authorize-security-group-ingress \ --group-id $AWS_CUSTOM_SECURITY_GROUP_ID \ --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 22, "ToPort": 22, "IpRanges": [{"CidrIp": "0.0.0.0/0", "Description": "Allow SSH"}]}]' && aws ec2 authorize-security-group-ingress \ --group-id $AWS_CUSTOM_SECURITY_GROUP_ID \ --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "IpRanges": [{"CidrIp": "0.0.0.0/0", "Description": "Allow HTTP"}]}]' |
Step 2: Create two EC2 instances for your ALB target groups.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
##-------------------------------------------------- ## Create two ec2 instances your alb target group ## ##-------------------------------------------------- ## Get Amazon Linux 2 latest AMI ID AWS_AMI_ID=$(aws ec2 describe-images \ --owners 'amazon' \ --filters 'Name=name,Values=amzn2-ami-hvm-2.0.????????-x86_64-gp2' 'Name=state,Values=available' \ --query 'sort_by(Images, &CreationDate)[-1].[ImageId]' \ --output 'text') ## Create a key-pair aws ec2 create-key-pair \ --key-name myvpc-keypair \ --query 'KeyMaterial' \ --output text > myvpc-keypair.pem ## Change access to key pair to make it secure chmod 400 myvpc-keypair.pem ## Create user data to configure LAMP stack vi myuserdataone.txt ----------------------- #!/bin/bash sudo yum install -y httpd sudo systemctl start httpd sudo usermod -a -G apache ec2-user sudo chown -R ec2-user:apache /var/www sudo chmod 2775 /var/www sudo find /var/www -type d -exec chmod 2775 {} \; sudo find /var/www -type f -exec chmod 0664 {} \; sudo echo "hello from instance one" > /var/www/html/index.html ----------------------- :wq vi myuserdatatwo.txt ----------------------- #!/bin/bash sudo yum install -y httpd sudo systemctl start httpd sudo usermod -a -G apache ec2-user sudo chown -R ec2-user:apache /var/www sudo chmod 2775 /var/www sudo find /var/www -type d -exec chmod 2775 {} \; sudo find /var/www -type f -exec chmod 0664 {} \; sudo echo "hello from instance two" > /var/www/html/index.html ----------------------- :wq ## Create two EC2 instance in two public subnet AWS_EC2_INSTANCE_ONE_ID=$(aws ec2 run-instances \ --image-id $AWS_AMI_ID \ --instance-type t2.micro \ --key-name myvpc-keypair \ --monitoring "Enabled=false" \ --security-group-ids $AWS_CUSTOM_SECURITY_GROUP_ID \ --subnet-id $AWS_SUBNET_PUBLIC_ONE_ID \ --user-data file://myuserdataone.txt \ --private-ip-address 10.0.1.10 \ --query 'Instances[0].InstanceId' \ --output text) ## Check if the instance one is running ## It will take some time for the instance to get ready aws ec2 describe-instance-status \ --instance-ids $AWS_EC2_INSTANCE_ONE_ID --output text AWS_EC2_INSTANCE_TWO_ID=$(aws ec2 run-instances \ --image-id $AWS_AMI_ID \ --instance-type t2.micro \ --key-name myvpc-keypair \ --monitoring "Enabled=false" \ --security-group-ids $AWS_CUSTOM_SECURITY_GROUP_ID \ --subnet-id $AWS_SUBNET_PUBLIC_TWO_ID \ --user-data file://myuserdatatwo.txt \ --private-ip-address 10.0.2.10 \ --query 'Instances[0].InstanceId' \ --output text) ## Check if the instance two is running ## It will take some time for the instance to get ready aws ec2 describe-instance-status \ --instance-ids $AWS_EC2_INSTANCE_TWO_ID --output text |
Step 3: Create your application load balancer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
##------------------------------------ ## Create application load balancer ## ##------------------------------------ ## Create the application load balancer AWS_ALB_ARN=$(aws elbv2 create-load-balancer \ --name my-application-load-balancer \ --subnets $AWS_SUBNET_PUBLIC_ONE_ID $AWS_SUBNET_PUBLIC_TWO_ID \ --security-groups $AWS_CUSTOM_SECURITY_GROUP_ID \ --query 'LoadBalancers[0].LoadBalancerArn' \ --output text) ## Check the status of load balancer aws elbv2 describe-load-balancers \ --load-balancer-arns $AWS_ALB_ARN \ --query 'LoadBalancers[0].State.Code' \ --output text ## Once the ALB status is active, get the DNS name for your ALB AWS_ALB_DNS=$(aws elbv2 describe-load-balancers \ --load-balancer-arns $AWS_ALB_ARN \ --query 'LoadBalancers[0].DNSName' \ --output text) && echo $AWS_ALB_DNS ## Create the target group for your ALB AWS_ALB_TARGET_GROUP_ARN=$(aws elbv2 create-target-group \ --name my-alb-targets \ --protocol HTTP --port 80 \ --vpc-id $AWS_VPC_ID \ --query 'TargetGroups[0].TargetGroupArn' \ --output text) ## View details of current health check configuration of target groups aws elbv2 describe-target-groups \ --target-group-arns $AWS_ALB_TARGET_GROUP_ARN |
Step 4: ALB target group health checks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
##------------------------------ ## Target Group Health Checks ## ##------------------------------ ## Register both the instances in the target group aws elbv2 register-targets --target-group-arn $AWS_ALB_TARGET_GROUP_ARN \ --targets Id=$AWS_EC2_INSTANCE_ONE_ID Id=$AWS_EC2_INSTANCE_TWO_ID ## Verify the health of the registered targets for your target group (State = unused) aws elbv2 describe-target-health \ --target-group-arn $AWS_ALB_TARGET_GROUP_ARN \ --query 'TargetHealthDescriptions[*].TargetHealth' \ --output table ## Create a listener for your load balancer with a default rule that forwards requests to your target group AWS_ALB_LISTNER_ARN=$(aws elbv2 create-listener --load-balancer-arn $AWS_ALB_ARN \ --protocol HTTP --port 80 \ --default-actions Type=forward,TargetGroupArn=$AWS_ALB_TARGET_GROUP_ARN \ --query 'Listeners[0].ListenerArn' \ --output text) ## Verify the health of the registered targets for your target group ## Initially its (State = initial) and then (State = healthy) aws elbv2 describe-target-health \ --target-group-arn $AWS_ALB_TARGET_GROUP_ARN \ --query 'TargetHealthDescriptions[*].TargetHealth' \ --output table ## Change the health check interval to 10 seconds aws elbv2 modify-target-group \ --target-group-arn $AWS_ALB_TARGET_GROUP_ARN \ --health-check-timeout-seconds 5 \ --health-check-interval-seconds 10 \ --healthy-threshold-count 2 ## Open the DNS name of your ALB (below output) in your browser and hit refresh several time ## Or curl your ALB DNS name repetedly echo $AWS_ALB_DNS curl $AWS_ALB_DNS ## Responce from both instance one and two ## login to the second instance and stop webserver aws ec2 describe-instances \ --instance-ids $AWS_EC2_INSTANCE_TWO_ID \ --query 'Reservations[0].Instances[0].PublicIpAddress' \ --output text ssh -i myvpc-keypair.pem ec2-user@52.66.136.67 #replace the ip with above output sudo systemctl stop httpd exit ## Verify the health of the registered targets for your target group (State = unhealthy) aws elbv2 describe-target-health \ --target-group-arn $AWS_ALB_TARGET_GROUP_ARN \ --query 'TargetHealthDescriptions[*].TargetHealth' \ --output table ## Open the DNS name of your ALB (below output) in your browser and hit refresh several time ## Or curl your ALB DNS name repetedly echo $AWS_ALB_DNS curl $AWS_ALB_DNS ## Responce from instance one only ## Deregister instance one from target group aws elbv2 deregister-targets --target-group-arn $AWS_ALB_TARGET_GROUP_ARN \ --targets Id=$AWS_EC2_INSTANCE_ONE_ID ## Verify the health of the registered targets for your target group (State = draining) aws elbv2 describe-target-health \ --target-group-arn $AWS_ALB_TARGET_GROUP_ARN \ --query 'TargetHealthDescriptions[*].TargetHealth' \ --output table ## Open the DNS name of your ALB (below output) in your browser and hit refresh several time ## Or curl your ALB DNS name repetedly echo $AWS_ALB_DNS curl $AWS_ALB_DNS #No responce form any of the instances, 502 Bad Gateway |
Step 5: Cleanup.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
##----------- ## Cleanup ## ##----------- ## Delete the listener aws elbv2 delete-listener \ --listener-arn $AWS_ALB_LISTNER_ARN ## Deregister targets aws elbv2 deregister-targets \ --target-group-arn $AWS_ALB_TARGET_GROUP_ARN \ --targets Id=$AWS_EC2_INSTANCE_TWO_ID ## Delete target group aws elbv2 delete-target-group \ --target-group-arn $AWS_ALB_TARGET_GROUP_ARN ## Delete Application Load Balancer aws elbv2 delete-load-balancer \ --load-balancer-arn $AWS_ALB_ARN ## Terminate the ec2 instances aws ec2 terminate-instances \ --instance-ids $AWS_EC2_INSTANCE_ONE_ID && aws ec2 terminate-instances \ --instance-ids $AWS_EC2_INSTANCE_TWO_ID ## Delete key pair aws ec2 delete-key-pair \ --key-name myvpc-keypair ## Delete custom security group (once instances are terminated) aws ec2 delete-security-group \ --group-id $AWS_CUSTOM_SECURITY_GROUP_ID ## Delete internet gateway aws ec2 detach-internet-gateway \ --internet-gateway-id $AWS_INTERNET_GATEWAY_ID \ --vpc-id $AWS_VPC_ID && aws ec2 delete-internet-gateway \ --internet-gateway-id $AWS_INTERNET_GATEWAY_ID ## Disassociate the subnets from custom route table aws ec2 disassociate-route-table \ --association-id $AWS_ROUTE_TABLE_ASSOID_ONE && aws ec2 disassociate-route-table \ --association-id $AWS_ROUTE_TABLE_ASSOID_TWO ## Delete custom route table aws ec2 delete-route-table \ --route-table-id $AWS_CUSTOM_ROUTE_TABLE_ID ## Delete the public subnets aws ec2 delete-subnet \ --subnet-id $AWS_SUBNET_PUBLIC_ONE_ID && aws ec2 delete-subnet \ --subnet-id $AWS_SUBNET_PUBLIC_TWO_ID ## Delete the vpc aws ec2 delete-vpc \ --vpc-id $AWS_VPC_ID ## Delete the directory for this demo cd .. && rm -rf alb_health_check_demo |
Hope you have enjoyed this article, In the next blog post, we will discuss Application Load Balancer monitoring.
All the public cloud providers are changing the console user interface rapidly and due to this some of the screenshots used in our previous AWS blogs are no longer relevant. Hence, we have decided that from now onwards most of the demo will be done programmatically. Let us know your feedback on this in the comment section.
To get more details on AWS ELB, please refer below AWS documentation
https://docs.aws.amazon.com/elasticloadbalancing/index.html