ENGINEER BLOG ENGINEER BLOG
  • 公開日
  • 最終更新日

【Lambda】AWS リソース情報を一括収集する

この記事を共有する

目次

はじめに

皆さんこんにちは!パーソル&サーバーワークスの小泉です。
AWS環境を運用していると、リソースの棚卸や構成管理のために、定期的にAWSリソースの情報を収集したいケースがあります。
本記事では、AWS Lambda関数を使用して様々なAWSリソース情報を収集し、Excelファイルとして出力する方法をまとめました

実現したいこと

以下のようなことを自動化したいと思ったことはありませんか?

  • AWS環境のリソースを定期的に棚卸したい
  • 実環境をもとにしたパラメータシートを作成したい

本記事で紹介するLambda関数を使えば、EC2、VPC、セキュリティグループ、RDS、Route 53など、多岐にわたるAWSリソースの情報を自動的に収集し、整理されたExcelファイルとして出力することができます。

全体の処理フロー

このLambda関数の処理フローは以下の通りです。

  1. 各種AWSリソース情報をAWS SDKを使って収集
  2. 収集した情報をExcelファイルに整理して出力
  3. 生成したExcelファイルをS3バケットにアップロード

実装の詳細

必要なライブラリ

この機能を実現するために、以下のライブラリを使用しています。

import boto3
import openpyxl
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill
from io import BytesIO
from datetime import datetime
  • boto3: AWS SDKでAWSリソースにアクセスするために使用
  • openpyxl: Excelファイルを操作するために使用
  • BytesIO: メモリ上でバイナリデータを扱うために使用
  • datetime: 日時情報を扱うために使用

収集するAWSリソース情報

この関数では、以下のAWSリソース情報などを収集することができます。
※本記事では、EC2インスタンスの処理を抜粋して説明します。

  1. EC2インスタンス
  2. Auto Scaling Group
  3. AMI
  4. VPC
  5. サブネット
  6. ルートテーブル
  7. セキュリティグループ
  8. インターネットゲートウェイ
  9. NATゲートウェイ
  10. ALB(Application Load Balancer)
  11. ターゲットグループ
  12. RDSインスタンス
  13. Route 53ホストゾーンとレコードセット
  14. ACM証明書
  15. IAMロール

主要な関数の解説

リソース情報収集関数

この関数では、boto3のEC2クライアントを使用して、すべてのEC2インスタンス情報を取得しています。
ページネーションにも対応しており、大量のインスタンスがある環境でも全てのデータを取得できます。

def get_ec2_instances():
    ec2 = boto3.client('ec2')
    ec2_data = []
    next_token = None
    while True:
        try:
            response = ec2.describe_instances(NextToken=next_token) if next_token else ec2.describe_instances()
        except Exception as e:
            print(f"EC2インスタンスの取得エラー: {e}")
            break
        for reservation in response['Reservations']:
            for instance in reservation['Instances']:
                security_groups = [sg['GroupName'] for sg in instance['SecurityGroups']]
                tags = {tag['Key']: tag['Value'] for tag in instance.get('Tags', [])}
                launch_time = remove_timezone(instance['LaunchTime']).strftime("%Y-%m-%d %H:%M:%S")
                ec2_info = {
                    'Instance ID': instance['InstanceId'],
                    'Instance Type': instance['InstanceType'],
                    'State': instance['State']['Name'],
                    # 他の属性も収集
                }
                ec2_data.append(ec2_info)
        next_token = response.get('NextToken', None)
        if not next_token:
            break
    return ec2_data

同様に、他のAWSリソースについても専用の関数を用意し、それぞれのリソース情報を収集することが可能です。

Excel出力関数

この関数では、openpyxlを使用して新しいExcelワークブックを作成し、各リソースタイプごとにシートを作成して情報を書き込みを行います。 ヘッダー行は太字と黄色背景で強調表示されるようにスタイル設定されています。

def create_excel_file(
    ec2_data, vpc_data, subnet_data, route_table_data, sg_data, igw_data, 
    nat_data, alb_data, listener_data, target_group_data, rds_data, 
    route_53_data, record_set_data, acm_data, iam_roles_data,
    asg_data, ami_data
):
    workbook = Workbook()
    # EC2情報をシートに書き込む
    ec2_sheet = workbook.active
    ec2_sheet.title = "EC2 Instances"
    ec2_headers = [
        "Instance ID", "Instance Type", "State", "Public IP", "Private IP", "Launch Time", 
        # 他のヘッダー
    ]
    style_headers(ec2_sheet, ec2_headers)
    for instance in ec2_data:
        ec2_sheet.append([
            instance['Instance ID'], instance['Instance Type'], instance['State'], 
            # 他の属性
        ])
    # 他のリソース情報も同様にシートに書き込む
    # ...
    # バイナリストリームに保存
    excel_stream = BytesIO()
    workbook.save(excel_stream)
    excel_stream.seek(0)
    return excel_stream

S3アップロード関数

この関数では、boto3のS3クライアントを使用して、メモリ上のExcelファイルをS3バケットにアップロードを行います。

def upload_to_s3(excel_stream, bucket_name, file_name):
    s3 = boto3.client('s3')
    try:
        s3.upload_fileobj(excel_stream, bucket_name, file_name)
        print(f"S3バケット '{bucket_name}' にファイル '{file_name}' が正常にアップロードされました。")
    except Exception as e:
        print(f"S3へのアップロードエラー: {e}")

メイン処理(Lambda Handler)

この関数では、各リソース情報を収集し、Excelファイルを生成して、S3バケットにアップロードするという一連の処理を実行します。 ファイル名には現在の日時が含まれるため、実行するたびに一意のファイル名が生成されます。

def lambda_handler(event, context):
    # 各種AWSリソースデータを取得
    (
        ec2_instances, vpc_information, subnet_information, route_table_information,
        security_group_information, internet_gateway_information, nat_gateway_information,
        alb_information, listener_information, target_group_information, rds_information,
        route_53_information, record_set_information, acm_information, iam_roles_information,
        asg_information, ami_information
    ) = gather_aws_resource_data()
    # Excelファイルを生成
    print("Generating Excel file with collected AWS resource data...")
    excel_file = create_excel_file(
        ec2_instances, vpc_information, subnet_information, 
        route_table_information, security_group_information, 
        internet_gateway_information, nat_gateway_information, 
        alb_information, listener_information, target_group_information, 
        rds_information, route_53_information, record_set_information, 
        acm_information, iam_roles_information,
        asg_information, ami_information
    )
    print("Excel file generation completed.")
    # ファイル名に現在の日時を追加
    current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
    file_name = f'aws_resources_{current_time}.xlsx'
    # S3にアップロード
    bucket_name = 'xxxxxxx'
    print(f"Uploading file {file_name} to S3 bucket {bucket_name}...")
    upload_to_s3(excel_file, bucket_name, file_name)
    print(f"File {file_name} successfully uploaded to S3 bucket {bucket_name}.")
    # レスポンスを返却
    return {
        'statusCode': 200,
        'body': f"全てのAWSリソース情報をExcelファイルとしてS3バケット '{bucket_name}' にアップロードしました。ファイル名: {file_name}"
    }

実装のポイント

1. エラーハンドリング

各リソース情報を取得する関数では、try-except文を使用してエラーハンドリングを行っています。これにより、一部のリソース情報の取得に失敗しても、処理全体が中断されることなく続行されます。

try:
    response = ec2.describe_instances(NextToken=next_token) if next_token else ec2.describe_instances()
except Exception as e:
    print(f"EC2インスタンスの取得エラー: {e}")
    break

2. ページネーション対応

AWS APIは多くの場合、結果がページネーションされます。このコードでは、NextTokenを使用して全てのページを取得する処理を実装しています。

while True:
    response = ec2.describe_instances(NextToken=next_token) if next_token else ec2.describe_instances()
    # データ処理
    next_token = response.get('NextToken', None)
    if not next_token:
        break

3. タイムゾーン情報の処理

AWS APIから返される日時情報にはタイムゾーン情報が含まれていますが、Excelに出力する際にはタイムゾーン情報を削除して統一的に扱うようにしています。

def remove_timezone(dt):
    if dt is not None and hasattr(dt, 'replace'):
        return dt.replace(tzinfo=None)
    return dt

4. メモリ効率の良い処理

大量のデータを扱う場合でも効率的に処理できるよう、ファイルをディスクに書き込まずにメモリ上で処理しています。

excel_stream = BytesIO()
workbook.save(excel_stream)
excel_stream.seek(0)

感想

本記事が、どなたかのお役に立てれば幸いです。

この記事は私が書きました

小泉 和貴

記事一覧

全国を旅行することを目標に、仕事を頑張っています。

小泉 和貴

この記事を共有する

クラウドのご相談

CONTACT

クラウド導入や運用でお悩みの方は、お気軽にご相談ください。
専門家がサポートします。

サービス資料ダウンロード

DOWNLOAD

ビジネスをクラウドで加速させる準備はできていますか?
今すぐサービス資料をダウンロードして、詳細をご確認ください。