なにこれ
CLBからALBの移行をしてて、結構な数のALBが作成されたのだけどアクセスログやConnection Drainingのタイムアウトを1台づつ設定するのはめんどくさい。そこでALBとTargetGroupが作成されたときCloudWatch Eventsで発火して、Lambda関数で自動設定できる仕組みを作ってみた。今回は以下項目を自動設定してくれるように作成した。
- 削除保護: 有効化
- アクセスログ
- 登録解除の遅延(Connection Draining) : 60秒
- システムによるだろうけどデフォルト300秒って長くない?
Lambda関数
コード
import boto3 import os import logging # constant timeout = os.environ.get('CONNECTION_DRAINING_TIMEOUT') bucket = os.environ.get('TARGET_S3_BUCKET_NAME') is_prod_env = os.environ.get('IS_PRODUCTION_ENV') # Set "True" if production env # initialize client = boto3.client('elbv2') logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): event_name = event['detail']['eventName'] if event_name == 'CreateLoadBalancer': if is_prod_env == "True": setup_alb_attributes(event) elif event_name == 'CreateTargetGroup': setup_tg_attributes(event) else: logger.error("unexpected event: {}".format(event_name)) return False return True def setup_alb_attributes(event): elb_count = len(event['detail']['responseElements']['loadBalancers']) for n in range(0, elb_count): elb_arn = event['detail']['responseElements']['loadBalancers'][n]['loadBalancerArn'] elb_name = event['detail']['responseElements']['loadBalancers'][n]['loadBalancerName'] try: client.modify_load_balancer_attributes( LoadBalancerArn = elb_arn , Attributes=[ { 'Key' : 'deletion_protection.enabled', 'Value': 'true' }, { 'Key' : 'access_logs.s3.enabled', 'Value': 'true' }, { 'Key' : 'access_logs.s3.prefix', 'Value': elb_name }, { 'Key' : 'access_logs.s3.bucket', 'Value': bucket } ] ) except Exception as e: logger.error("Error: {}".format(e.args)) return False return True def setup_tg_attributes(event): tg_count = len(event['detail']['responseElements']['targetGroups']) for n in range(0, tg_count): tg_arn = event['detail']['responseElements']['targetGroups'][n]['targetGroupArn'] try: client.modify_target_group_attributes( TargetGroupArn = tg_arn , Attributes = [ { 'Key' : 'deregistration_delay.timeout_seconds', 'Value': timeout } ] ) except Exception as e: logger.error("Error: {}".format(e.args)) return False return True
環境変数
補足
- 削除保護/アクセスログはALB、Connection DrainingはTargetGroupで設定が別れているのでイベント毎で処理も別れてる
- アクセスログは本番環境以外だったら設定しねーわとかありそうなので環境変数で設定有無を変更できる
- CloudTrailからイベントの中身をみていると
event['detail']['responseElements']['loadBalancers']
は配列できてるので一応forで回してる - ALBって書いてるけど多分NLBでも設定できるはず。試してないけど
- エラー処理は手抜き
CloudWatch Events
感想
CloudWatch EventsでAPIコールでLambda起動のパターンを覚えるとあんなことやこんなことができそうで夢が膨らみます。時間さえあれば。
この規模であればAWSコンソールで直接作れるけど外部モジュール含めて作ろうとするとやっぱり大変そう。Lambdaでゴリゴリ開発するにはAWS SAM or Serverless Frameworkは必須な気がします。本番環境で導入しようとすると権限管理が非常にめんどくさそうだけど。