Application Load BalancerのCLI設定取得
Application Load Balancer(以下、ALB)の設定値をAWS CLIコマンドで取得するのに実行するコマンドが多すぎると思ったことはありますか?
ALBの設定パラメーターをCLIで取得するにあたり、ロードバランサーの設定・ターゲットグループの設定・リスナーの設定・リスナールールの設定など、確認したいポイント複数に対してそれぞれのdescribeコマンドを実行する必要があります。
そこで、よく確認する項目だけでも一覧化してALBのデータ確認を効率をするためのpythonコードになります。
また、ターゲット先のEC2やACM(HTTPS証明書)がインスタンスIDやACM ARNで出力されるため、EC2名や証明書名と比べて直感的にわかりにくい箇所をEC2名などの一目見てわかるように変換して出力してくれます。
具体的には以下の項目を一覧化して表示します。
- ALB 設定
— ALB名
— 接続タイプ(内部向け or 外部向け)
— IPアドレスタイプ
— サブネット
— セキュリティグループ
— 属性設定 - リスナー設定
— 接続プロトコル
— 接続ポート
— (使用するデフォルト証明書)(HTTPSのみ)
— 一部のリスナールール - ターゲットグループ設定
— ターゲットグループ名
— ターゲットタイプ
— プロトコル
— 接続ポート
— ヘルスチェック設定
— 属性設定
自分向けに作成しているため「この情報を追加出力したい」などあればアレンジして活用いただければと思います。
前提条件
- Python : ver3.11.4 (細かなバージョン指定はありませんがPythonが実行できる環境が必要)
- boto3 Library : インストール済み
- AWS環境へのReadOnly権限 : データ参照する際に必要になる権限。(名前表示のための EC2をNameタグ/SG Name/ACM 証明書名などELB以外のリソースに対するreadonly権限も必要)
- デフォルトリージョンを指定 : 特定のリージョンを事前指定済みであること
pythonコード
output_alb_status.py などの名前で下記コードを保存。
import sys
import datetime
import boto3
from distutils.util import strtobool
def main():
if len(sys.argv) < 2:
print('invalid argument.'
'(example : python3 output_alb_status.py ALBName)')
sys.exit(1)
alb_name = sys.argv[1]
client = boto3.client('elbv2')
# get alb general status
response = client.describe_load_balancers(
Names=[
alb_name
]
)
print_alb_parameter(response)
print('\n')
print_tg_parameter(response)
def print_alb_parameter(alb_para: dict):
client = boto3.client('elbv2')
response = alb_para['LoadBalancers'][0]
attribute = client.describe_load_balancer_attributes(
LoadBalancerArn=response['LoadBalancerArn']
)
print("###### ALB Parameter ##### ")
print(f' LoadBalancerName : {response["LoadBalancerName"]}')
print(f' Scheme : {response["Scheme"]}')
print(f' IpAddressType : {response["IpAddressType"]}')
print(' Subnet1 ')
print(f' SubnetID : {response["AvailabilityZones"][0]["SubnetId"]}')
print(f' AZ_Name : {response["AvailabilityZones"][0]["ZoneName"]}')
print(' Subnet2 ')
print(f' SubnetID : {response["AvailabilityZones"][1]["SubnetId"]}')
print(f' AZ_Name : {response["AvailabilityZones"][1]["ZoneName"]}')
print(' SecurityGroup ')
for i, SecurityGroups in enumerate(response['SecurityGroups']):
sg_name = return_sg_name(SecurityGroups)
print(f' SG{i} : {sg_name}')
print()
print(' Attribute ')
for Attributes in attribute["Attributes"]:
if 'deletion_protection.enabled' in Attributes.values():
print(f' DeletProtection: {Attributes["Value"]}')
for Attributes in attribute["Attributes"]:
if 'idle_timeout.timeout_seconds' in Attributes.values():
print(f' IdleTimeOut : {Attributes["Value"]}')
for Attributes in attribute["Attributes"]:
if 'routing.http2.enabled' in Attributes.values():
print(f' HTTP2Enable : {Attributes["Value"]}')
print()
print(' AccessLog ')
for Attributes in attribute["Attributes"]:
if 'access_logs.s3.enabled' in Attributes.values():
print(f' LogEnable : {Attributes["Value"]}')
for Attributes in attribute["Attributes"]:
if 'access_logs.s3.bucket' in Attributes.values():
print(f' Backet : {Attributes["Value"]}')
for Attributes in attribute["Attributes"]:
if 'access_logs.s3.prefix' in Attributes.values():
print(f' Prefix : {Attributes["Value"]}')
print()
print(' Listener ')
print_listener_parameter(response['LoadBalancerArn'])
def print_listener_parameter(lb_arn):
client = boto3.client('elbv2')
listener = client.describe_listeners(
LoadBalancerArn=lb_arn
)
for i, Listeners in enumerate(listener['Listeners']):
print(f' Listener{i} ')
print(f' Protocol : {Listeners["Protocol"]}')
print(f' Port : {Listeners["Port"]}')
if 'Certificates' in Listeners:
for Certificates in Listeners['Certificates']:
cert_name = return_acm_name(Certificates["CertificateArn"])
print(f' Cert{i} : {cert_name}')
else:
print(' Cert : None')
if 'SslPolicy' in Listeners:
print(f' SslPolicy : {Listeners["SslPolicy"]}')
print_listener_rule(Listeners["ListenerArn"], i)
print()
def print_listener_rule(listener_arn, i):
client = boto3.client('elbv2')
rules = client.describe_rules(
ListenerArn=listener_arn
)
print()
for j, Rule in enumerate(rules['Rules']):
print(f' ListerRule {i}-{j}')
print(f' Priority : {Rule["Priority"]}')
print(' Conditions ')
for Condition in Rule["Conditions"]:
if 'source-ip' in Condition.values():
print(f' source-ip : {Condition["SourceIpConfig"]}')
elif 'host-header' in Condition.values():
print(f' host-header: {Condition["Values"]}')
elif 'path-pattern' in Condition.values():
print(f' path-patter: {Condition["Values"]}')
elif 'http-header' in Condition.values():
print(f' http-header: {Condition["HttpHeaderConfig"]}')
else:
print(' Condition Setting: None')
print(' Actions ')
for Actions in Rule["Actions"]:
if 'forward' in Actions.values():
for k, targetgroup in enumerate(Actions['ForwardConfig']['TargetGroups']):
tg_response = client.describe_target_groups(
TargetGroupArns=[
targetgroup['TargetGroupArn']
]
)
print(f' forward : {tg_response["TargetGroups"][0]["TargetGroupName"]}')
print(f' Weight : {targetgroup["Weight"]}')
print(f' Stikiness : {Actions["ForwardConfig"]["TargetGroupStickinessConfig"]["Enabled"]}')
elif 'redirect' in Actions.values():
print(f' Redirect : {Actions["RedirectConfig"]}')
elif 'fixed-response' in Actions.values():
print(f' FixResponse: {Actions["FixedResponseConfig"]}')
print()
def print_tg_parameter(alb_para):
client = boto3.client('elbv2')
lb_arn = alb_para['LoadBalancers'][0]['LoadBalancerArn']
tg_para = client.describe_target_groups(
LoadBalancerArn=lb_arn
)
for i, TargetGroups in enumerate(tg_para["TargetGroups"]):
print(f"###### TG Parameter {i} ##### ")
print(f' TargetGroupName : {TargetGroups["TargetGroupName"]}')
print(f' TargetType : {TargetGroups["TargetType"]}')
print(f' Protocol : {TargetGroups["Protocol"]}')
print(f' Port : {TargetGroups["Port"]}')
print()
print(' HealthCheck ')
print(f' Protocol : {TargetGroups["HealthCheckProtocol"]}')
print(f' Path : {TargetGroups["HealthCheckPath"]}')
print(f' Port : {TargetGroups["HealthCheckPort"]}')
print(f' Threshold : {TargetGroups["HealthyThresholdCount"]}')
print(f' UnHhealtyTH : {TargetGroups["UnhealthyThresholdCount"]}')
print(f' Timeout : {TargetGroups["HealthCheckTimeoutSeconds"]}')
print(f' Interval : {TargetGroups["HealthCheckIntervalSeconds"]}')
print(f' SuccessCode : {TargetGroups["Matcher"]["HttpCode"]}')
print()
print(' HealthCheckTarget ')
tg_instance = client.describe_target_health(
TargetGroupArn=TargetGroups["TargetGroupArn"]
)
for i, HealthDescriptions in enumerate(tg_instance["TargetHealthDescriptions"]):
instance_name = return_instance_name(HealthDescriptions["Target"]["Id"])
print(f' Target {i} : {instance_name}')
print(f' Target {i} Health: {HealthDescriptions["TargetHealth"]["State"]}')
print()
print(' Attribute ')
tg_attribute = client.describe_target_group_attributes(
TargetGroupArn=TargetGroups["TargetGroupArn"]
)
for tg_Attributes in tg_attribute["Attributes"]:
if 'deregistration_delay.timeout_seconds' in tg_Attributes.values():
print(f' DerectionDelay : {tg_Attributes["Value"]}')
for tg_Attributes in tg_attribute["Attributes"]:
if 'slow_start.duration_seconds' in tg_Attributes.values():
print(f' SlowStart : {tg_Attributes["Value"]}')
for tg_Attributes in tg_attribute["Attributes"]:
if 'load_balancing.algorithm.type' in tg_Attributes.values():
print(f' LbAlgorithm : {tg_Attributes["Value"]}')
for tg_Attributes in tg_attribute["Attributes"]:
if 'stickiness.enabled' in tg_Attributes.values():
print(f' Stickiness : {tg_Attributes["Value"]}')
if strtobool(tg_Attributes["Value"]):
for stickinessAttri in tg_attribute["Attributes"]:
if 'stickiness.type' in stickinessAttri.values():
print(f' StickinessType : {stickinessAttri["Value"]}')
if stickinessAttri["Value"] == "lb_cookie":
for stickinessAttri in tg_attribute["Attributes"]:
if 'stickiness.lb_cookie.duration_seconds' in stickinessAttri.values():
td = datetime.timedelta(seconds=int(stickinessAttri["Value"]))
print(f' StickinessDuration: {td}')
elif stickinessAttri["Value"] == "app_cookie":
for stickinessAttri in tg_attribute["Attributes"]:
if 'stickiness.app_cookie.duration_seconds' in stickinessAttri.values():
td = datetime.timedelta(seconds=int(stickinessAttri["Value"]))
print(f' StickinessDuration: {td}')
for stickinessAttri in tg_attribute["Attributes"]:
if 'stickiness.app_cookie.cookie_name' in stickinessAttri.values():
print(f' StickinessAppName: {stickinessAttri["Value"]}')
print()
def return_sg_name(sg_id: str):
client = boto3.client('ec2')
response = client.describe_security_groups(
GroupIds=[
sg_id
]
)
return (response['SecurityGroups'][0]['GroupName'])
def return_acm_name(acm_id: str):
client = boto3.client('acm')
acm_list = client.list_certificates(
CertificateStatuses=[
'ISSUED'
]
)
for CertificateSummaryList in acm_list['CertificateSummaryList']:
if acm_id in CertificateSummaryList['CertificateArn']:
return (CertificateSummaryList['DomainName'])
else:
continue
return ("None")
def return_instance_name(instance_id: str):
client = boto3.client('ec2')
response = client.describe_instances(
InstanceIds=[
instance_id
]
)
for Ec2Name in response["Reservations"][0]["Instances"][0]["Tags"]:
if 'Name' in Ec2Name.values():
return (Ec2Name["Value"])
else:
continue
return (instance_id)
if __name__ == '__main__':
main()
出力イメージ
python3 output_alb_status.py ubukata-albでコマンドを実行することで、以下のような設定を取得できます。
※ 出力イメージ用の設定パラメーターは適当です。あくまで出力イメージように設定しているため、パラメーターが適切でない場合があります。
###### ALB Parameter #####
LoadBalancerName : ubukata-alb
Scheme : internet-facing
IpAddressType : ipv4
Subnet1
SubnetID : subnet-XXXXXXXXXXXXXXXX
AZ_Name : ap-northeast-1a
Subnet2
SubnetID : subnet-XXXXXXXXXXXXXXXX
AZ_Name : ap-northeast-1c
SecurityGroup
SG0 : ubukata-sg-pub
Attribute
DeletProtection: false
IdleTimeOut : 60
HTTP2Enable : true
AccessLog
LogEnable : false
Backet :
Prefix :
Listener
Listener0
Protocol : HTTPS
Port : 443
Cert0 : ubukata.xxxx.xxxx.hoge.jp
SslPolicy : ELBSecurityPolicy-TLS13-1-2-2021-06
ListerRule 0-0
Priority : 1
Conditions
host-header: ['hoge.example.com']
source-ip : {'Values': ['172.16.0.0/24']}
Actions
forward : ubukata-tg-1
Weight : 1
Stikiness : False
forward : ubukata-tg-2
Weight : 2
Stikiness : False
ListerRule 0-1
Priority : 2
Conditions
source-ip : {'Values': ['192.168.0.2/32']}
Actions
FixResponse: {'MessageBody': 'not found', 'StatusCode': '404', 'ContentType': 'text/plain'}
ListerRule 0-2
Priority : 3
Conditions
path-patter: ['/hoge/test/*']
Actions
FixResponse: {'MessageBody': 'sorry', 'StatusCode': '503', 'ContentType': 'text/plain'}
ListerRule 0-3
Priority : 4
Conditions
http-header: {'HttpHeaderName': 'aa', 'Values': ['hoge']}
Actions
Redirect : {'Protocol': 'HTTPS', 'Port': '10050', 'Host': '#{host}', 'Path': '/#{path}', 'Query': '#{query}', 'StatusCode': 'HTTP_301'}
ListerRule 0-4
Priority : default
Conditions
Actions
forward : ubukata-tg-1
Weight : 1
Stikiness : False
Listener1
Protocol : HTTP
Port : 80
Cert : None
ListerRule 1-0
Priority : default
Conditions
Actions
forward : ubukata-tg-1
Weight : 1
Stikiness : False
###### TG Parameter 0 #####
TargetGroupName : ubukata-tg-1
TargetType : instance
Protocol : HTTP
Port : 80
HealthCheck
Protocol : HTTP
Path : /
Port : traffic-port
Threshold : 5
UnHhealtyTH : 2
Timeout : 5
Interval : 30
SuccessCode : 200
HealthCheckTarget
Target 0 : ubukata-windows
Target 0 Health: unhealthy
Attribute
DerectionDelay : 300
SlowStart : 0
LbAlgorithm : round_robin
Stickiness : false
###### TG Parameter 1 #####
TargetGroupName : ubukata-tg-2
TargetType : instance
Protocol : HTTP
Port : 80
HealthCheck
Protocol : HTTP
Path : /index.html
Port : traffic-port
Threshold : 5
UnHhealtyTH : 2
Timeout : 5
Interval : 30
SuccessCode : 200
HealthCheckTarget
Target 0 : ubukata-ec2-rhel
Target 0 Health: healthy
Attribute
DerectionDelay : 300
SlowStart : 0
LbAlgorithm : round_robin
Stickiness : false