AWS - List All ELB, NLB and CLB with Target and Target Groups | Python Boto

In this article, we are presenting an AWS  Boto Python script that lists all load balancers and their Target group along with the Instances associated and their health check status

This script helps you in various ways

  • Get the list of load balancers and their target group and instance mapping along with their health
  • Find out the load balancers with no backend target group or listeners which can simply be removed for cost saving
  • Find how many Elastic Load balancer or Target groups, a Specific instance is associated with and receive traffic from
  • Instance to ELB Mapping auditing - helping to remove unwanted instances
  • A Health Check and Monitoring script for your entire Elastic Load Balancers and Target Groups, and Instances.
  • This script helps you to find Unused Elastic Load Balancers ALBs and ELBs.

As you know there are three major types of load balances in AWS ELB. such as

  • Classic Load Balancer
  • Application Load Balancer
  • Network Load Balancer

While Classic Load Balancer and Application Load Balancer are widely used and they differ in the way they are configured/designed.

I had to create two scripts one for each of them.

  • clb-list.py - For Classic Load Balancer
  • alb-list.py - For Application Load Balancer & Network Load Balancer

 

  We have update our scripts with JSON output format. Check it out.

 

AWS ELB Boto

Prerequisites

  • AWS CLI must be installed and configured with API Key and Secret
  • Named Profile (Optional) or use default as profile name in the script
  • Boto3 must be installed

If you are new to AWS CLI refer to our previous article before proceeding

Wondering what is Named Profile in AWS, refer to this article from AWS here

Besides that, you must have proper IAM permissions for you to be able to list these resources and configurations. You can try with Administrator Access IAM role if possible.

You can simply install boto3 by executing pip install boto3 Refer to this article for more details

 

To List Classic Load Balancer Configuration and Instances

This is a named profile based script where I have used prod as my profile name, you can refer to the previous article and use named profiles for managing multiple AWS accounts.

Update the script profile=default instead of PROD, If you are not using Named Profile,

For the Named Profile setup, you have to update this profile variable anyway with your profile name before executing.

Also the region_name must be updated in both cases.

 

clb-list.py

import boto3
import pprint
region_name = "us-east-1"
profile = "prod"
session = boto3.session.Session(profile_name=profile)
elb = session.client('elb')
ec2 = session.client('ec2')


def getinstancename(instanceid):
    instances=ec2.describe_instances(Filters=[
        {
            'Name': 'instance-id',
            'Values': [
                instanceid
            ]
        },
    ],)

    resultset = {}    
    for instance in instances["Reservations"]:
        for inst in instance["Instances"]:
            resultset["State"]=inst["State"]["Name"]    
            for tag in inst["Tags"]:
                if tag['Key'] == 'Name':
                    resultset["Name"]=tag['Value']
    # print (resultset)  
    return resultset
             

def getinstancehealth(lbname,instanceid):
    instancestate=elb.describe_instance_health(
            LoadBalancerName=lbname,
            Instances = [{
                'InstanceId' : instanceid
            }]
            )
    return instancestate['InstanceStates'][0]['State']

lbs = elb.describe_load_balancers(PageSize=400)

for lb in lbs["LoadBalancerDescriptions"]:
    print("\n"*2)
    print ("-"*6)
    print("Name:",lb["LoadBalancerName"])
    print("HealthCheck:",lb["HealthCheck"])
    print("Instance Info:")
    if len(lb["Instances"]) > 0:
        for instance in lb["Instances"]:
            instance.update(getinstancename(instance["InstanceId"]))
            instance['Health']=getinstancehealth(lb["LoadBalancerName"], instance["InstanceId"])
            print (instance)
    else:
        print("Instance List is Empty, Or no Instance is mapped")

Sample Output

------
Name: test-elb
HealthCheck: {'Target': 'HTTP:80/index.html', 'Interval': 30, 'Timeout': 5, 'UnhealthyThreshold': 2, 'HealthyThreshold': 10}
Instance Info:
{'InstanceId': 'i-somestring', 'State': 'running', 'Name': 'test.gritfy.io', 'Health': 'InService'}



------
Name: service-elb
HealthCheck: {'Target': 'HTTP:80/index.html', 'Interval': 30, 'Timeout': 5, 'UnhealthyThreshold': 2, 'HealthyThreshold': 5}
Instance Info:
{'InstanceId': 'i-somestring', 'Health': 'OutOfService'}
{'InstanceId': 'i-somestring', 'State': 'running', 'Name': 'service.gritfy.io', 'Health': 'InService'}



------
Name: beta-elb
HealthCheck: {'Target': 'HTTP:80/beta/health/', 'Interval': 10, 'Timeout': 5, 'UnhealthyThreshold': 2, 'HealthyThreshold': 2}
Instance Info:
Instance List is Empty, Or not Instance is mapped

 

 

To List Application Load Balancer Configuration and Instances

import boto3
import pprint
region_name = "us-east-1"
profile = "prod"
session = boto3.session.Session(profile_name=profile)
elb = session.client('elbv2')
ec2 = session.client('ec2')


def gettargetgroups(arn):
    tgs=elb.describe_target_groups(LoadBalancerArn=arn)
    tgstring=[]
    for tg in tgs["TargetGroups"]:
        tgstring.append(tg["TargetGroupName"])
    return tgstring

def gettargetgrouparns(arn):
    tgs=elb.describe_target_groups(LoadBalancerArn=arn)
    tgarns=[]
    for tg in tgs["TargetGroups"]:
        tgarns.append(tg["TargetGroupArn"])
    return tgarns

def getinstancename(instanceid):
    instances=ec2.describe_instances(Filters=[
        {
            'Name': 'instance-id',
            'Values': [
                instanceid
            ]
        },
    ],)
    for instance in instances["Reservations"]:
        for inst in instance["Instances"]:
            for tag in inst["Tags"]:
                if tag['Key'] == 'Name':
                    return (tag['Value'])

    
def gettargethealth(arn):
    inss=elb.describe_target_health(TargetGroupArn=arn)
    instanceids=[]
    for ins in inss["TargetHealthDescriptions"]:
        ins["Name"]=getinstancename(ins['Target']['Id'])
        instanceids.append(ins['Target']['Id'])
        print (ins)


lbs = elb.describe_load_balancers(PageSize=400)


for lb in lbs["LoadBalancers"]:
    print("\n"*2)
    print ("-"*6)
    print("Name:",lb["LoadBalancerName"])
    print("Type:",lb["Type"])
    print("TargetGroups:",str(gettargetgroups(lb["LoadBalancerArn"])))

    for tgs in gettargetgrouparns(lb["LoadBalancerArn"]):
        gettargethealth(tgs)
    

 

Sample output

------
Name: iaas-elb
Type: application
TargetGroups: ['iaas-tg']
{'Target': {'Id': 'i-somestring', 'Port': 80}, 'HealthCheckPort': '80', 'TargetHealth': {'State': 'healthy'}, 'Name': 'iaas01.gritfy.io'}
{'Target': {'Id': 'i-somestring', 'Port': 80}, 'HealthCheckPort': '80', 'TargetHealth': {'State': 'healthy'}, 'Name': 'iaas02.gritfy.io'}



------
Name: saas-elb
Type: application
TargetGroups: ['saas-tg']
{'Target': {'Id': 'i-somestring', 'Port': 80}, 'HealthCheckPort': '80', 'TargetHealth': {'State': 'healthy'}, 'Name': 'saas.gritfy.io'}



------
Name: app-saas
Type: application
TargetGroups: ['app-saas-TG']
{'Target': {'Id': 'i-somestring', 'Port': 80}, 'HealthCheckPort': '80', 'TargetHealth': {'State': 'unused', 'Reason': 'Target.InvalidState', 'Description': 'Target is in the stopped state'}, 'Name': None}



------
Name: service-elb
Type: application
TargetGroups: []

 

Updated script with JSON Output format

The previous scripts you have seen return the response in simple Text format.

It served the purpose. but now for further customisations and advancement, we have updated the script output to JSON format.

Now as a new version, I have updated the code to return the response in JSON format

here are the updated scripts

 

List Application Load Balancer and Network Load Balancer with Target Group

This python script is designed to accept the region and the profile name as a startup argument

Copy the following code and save it as clb-list-json.py

Here is the command example you can use. make sure to update the profile name and the region_name.

If you do not have any named profile on AWS CLI. just type default.

python3 alb-list-json.py us-east-1 default

here is the source code

 

alb-list-json.py

import boto3
import pprint
import sys
import json

def gettargetgroups(arn):
    tgs=elb.describe_target_groups(LoadBalancerArn=arn)
    tgstring=[]
    for tg in tgs["TargetGroups"]:
        tgstring.append(tg["TargetGroupName"])
    return tgstring

def gettargetgrouparns(arn):
    tgs=elb.describe_target_groups(LoadBalancerArn=arn)
    tgarns=[]
    for tg in tgs["TargetGroups"]:
        tgarns.append(tg["TargetGroupArn"])
    return tgarns

def getinstancename(instanceid):
    instances=ec2.describe_instances(Filters=[
        {
            'Name': 'instance-id',
            'Values': [
                instanceid
            ]
        },
    ],)
    for instance in instances["Reservations"]:
        for inst in instance["Instances"]:
            for tag in inst["Tags"]:
                if tag['Key'] == 'Name':
                    return (tag['Value'])

    
def gettargethealth(arn):
    # print("arn",arn)
    inss=elb.describe_target_health(TargetGroupArn=arn)
    instanceids=[]
    result=[]
    for ins in inss["TargetHealthDescriptions"]:
        ins["Name"]=getinstancename(ins['Target']['Id'])
        instanceids.append(ins['Target']['Id'])
        result.append(ins)
    return result

def describelbs():
    lbs = elb.describe_load_balancers(PageSize=400)
    for lb in lbs["LoadBalancers"]:
        lbjson={}
        lbjson['Name']=lb["LoadBalancerName"]
        lbjson['Type']=lb["Type"]
        lbjson['TG']=gettargetgrouparns(lb["LoadBalancerArn"])
        lbjson['TGData']=[]

        TGLIST=[]
        if len(lbjson["TG"]) > 0:
            for tgs in lbjson['TG']:
                TGD={}
                TGD['Name']=tgs.split("/")[1]
                tgh=gettargethealth(tgs)
                if len(tgh) > 0:
                    TGD['Instances']=tgh
                else:
                    TGD['Instances']=""
                TGLIST.append(TGD)
                
            lbjson['TGData'] = TGLIST
        
        print("\n",json.dumps(lbjson, indent=4, sort_keys=True))        

        

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print(" – Region Name and the Profile name is mandatory – ")
        print(" Syntax: python3 clb-list-json.py us-east-1 default")
        exit()
    region_name = sys.argv[1]
    profile = sys.argv[2]
    session = boto3.session.Session(profile_name=profile)
    elb = session.client('elbv2')
    ec2 = session.client('ec2')
    describelbs()

 

 

List Classic Load Balancer with Target instances

This python script is designed to accept the region and the profile name as a startup argument

Copy the following code and save it as clb-list-json.py

Here is the command example you can use. make sure to update the profile name and the region_name

python3 clb-list-json.py us-east-1 default

 

clb-list-json.py

import boto3
import pprint
import json
import sys


def getinstancename(instanceid):
    instances=ec2.describe_instances(Filters=[
        {
            'Name': 'instance-id',
            'Values': [
                instanceid
            ]
        },
    ],)

    resultset = {}    
    for instance in instances["Reservations"]:
        for inst in instance["Instances"]:
            resultset["State"]=inst["State"]["Name"]    
            for tag in inst["Tags"]:
                if tag['Key'] == 'Name':
                    resultset["Name"]=tag['Value']
    # print (resultset)  
    return resultset
             

def getinstancehealth(lbname,instanceid):
    instancestate=elb.describe_instance_health(
            LoadBalancerName=lbname,
            Instances = [{
                'InstanceId' : instanceid
            }]
            )
    
    return instancestate['InstanceStates'][0]['State']

def describelbs():
    
    lbs = elb.describe_load_balancers(PageSize=400)

    for lb in lbs["LoadBalancerDescriptions"]:
        lbjson={}
        lbjson['Name']=lb["LoadBalancerName"]
        lbjson['HealthCheck']=lb["HealthCheck"]
        lbjson['Instances']=[]

        if len(lb["Instances"]) > 0:
            InstanceList=[]
            for instance in lb["Instances"]:
                instance.update(getinstancename(instance["InstanceId"]))
                instance['Health']=getinstancehealth(lb["LoadBalancerName"], instance["InstanceId"])
                InstanceList.append(instance)
            
            lbjson['Instances']=InstanceList

        print("\n",json.dumps(lbjson, indent=4, sort_keys=True))        
    
if __name__ == "__main__":
    if len(sys.argv) < 3:
        print(" – Region Name and the Profile name is mandatory – ")
        print(" Syntax: python3 clb-list-json.py us-east-1 default")
        exit()
    region_name = sys.argv[1]
    profile = sys.argv[2]
    print("profilename selected:",profile)
    print("regionname selected: ",region_name)
    session = boto3.session.Session(profile_name=profile)
    elb = session.client('elb')
    ec2 = session.client('ec2')
    describelbs()

 

Here is the output as JSON while I have run the script on my end

⚡ ⇒ python3 clb-list-json.py us-east-1 prod
{
  "HealthCheck": {
    "HealthyThreshold": 10,
    "Interval": 30,
    "Target": "HTTP:80/index.html",
    "Timeout": 5,
    "UnhealthyThreshold": 2
  },
  "Instances": [
    {
      "Health": "InService",
      "InstanceId": "i-06e3361ac9fe29d5a",
      "Name": "test-01.gritfy.io-UB20",
      "State": "running"
    },
    {
        "Health": "InService",
        "InstanceId": "i-06e3361ac9fe29d5a",
        "Name": "push-01.gritfy.io-UB20",
        "State": "running"
    }
  ],
  "Name": "gritfy-elb"
}

 

 

Github repo

That's the Github link you can Star and follow for further updates.

https://github.com/AKSarav/BotoScripts

 

List ALB and Target Groups as a Diagram 

I have upgraded this script to the next level and now you can list your Application and Classic Load Balancers and their associated targets and target groups as a Diagram

Yes. I have added the python Diagram module to this existing code and made it possible.

you can create diagrams of all your Load Balancer in AWS using this

Here is the a glimpse of what it can do.

AWS ELB flowchart

I have written an exclusive article on the same with the source code attached. Hope you might like it.

AWS ELB Diagram generator with Python Boto & Diagrams | Devops Junction

 

Find Unused Load Balancers based on Traffic - CloudWatch & Boto

I have created this new script which connects to CloudWatch API and collects the Load Balancer usage metrics of load balancers such as

  • Request Count - ( ALB and CLB)
  • ActiveFlowCount  - ( NLB)

The report is generated and stored as a CSV - It is written with Threaded model for super fast data collection.

Check it out.

How to find Unused Load Balancers - Based on Traffic | AWS FinOps

 

Conclusion

Hope this AWS Boto script helps you with your Administration and AWS Management.  you can feel free to contribute and upgrade this script

You can contribute to DevopsJunction by submitting an Article or the creative Devops work that you would like to share with the world.

 

Cheers
Sarav AK

Follow me on Linkedin My Profile
Follow DevopsJunction onFacebook orTwitter
For more practical videos and tutorials. Subscribe to our channel

Buy Me a Coffee at ko-fi.com

Signup for Exclusive "Subscriber-only" Content

Loading