Pythonでインフラ自動化|boto3とAWS操作の実践入門

AWSインフラの運用効率を10倍向上させたいエンジニアは、Pythonとboto3を組み合わせた自動化を今すぐ始めるべきです。手動操作で発生する人的ミスや時間的コストを劇的に削減できるだけでなく、再現性の高いインフラ構築が可能になります。本記事では、AWS SDKであるboto3の基本から実践的な自動化スクリプトまで、具体的な手順を網羅的に解説します。初心者でも理解できるように、実務で即活用できるサンプルコードを豊富に用意しています。


目次


はじめに:Pythonとboto3でAWS自動化を始める理由

AWSクラウドの運用において、手動操作によるインフラ管理はもはや時代遅れです。特に以下のような課題を抱えているエンジニアにとって、Pythonとboto3を活用した自動化は必須のスキルとなります。

  • 人的ミスの削減:手動でEC2インスタンスを停止し忘れると、翌日には高額なコストが発生する可能性があります。自動化により、このような人的ミスを完全に排除できます。
  • 時間的コストの削減:AWSコンソールでの操作はGUIに依存するため、同じ作業を繰り返すのに膨大な時間がかかります。自動化スクリプトを実行すれば、数分で完了します。
  • 再現性の確保:手動操作では環境の一貫性が保てません。自動化により、同じ設定を何度でも再現できます。
  • スケーラビリティの向上:手動で100台のEC2インスタンスを管理するのは現実的ではありません。自動化により、数千台規模の管理も容易になります。

実際に、AWSの公式ドキュメントによると、クラウドコンピューティングの6つのメリットのうち、「俊敏性(Agility)」と「コスト削減(Cost Savings)」は自動化によって飛躍的に向上します。特に、自動スケーリング(Auto Scaling)サーバーレスアーキテクチャを活用したシステムでは、Pythonとboto3による自動化が欠かせません。

本記事では、これらの課題を解決するための具体的な手法を、実務で即活用できるレベルで解説します。まずは、Pythonとboto3の基本から学んでいきましょう。


boto3の基礎知識:AWS SDKのインストールから認証設定まで

boto3は、AWSが公式に提供するPython用のSDK(Software Development Kit)です。このライブラリを使うことで、Pythonスクリプトから直接AWSの各種サービスを操作できます。まずは、boto3の基本的な使い方から学びましょう。

boto3のインストールとバージョン管理

boto3をインストールするには、以下のコマンドを実行します。

pip install boto3

最新バージョンを使用することを推奨しますが、プロジェクトによっては特定のバージョンを指定する必要があります。バージョンを固定する場合は、以下のように実行します。

pip install boto3==1.26.0

また、boto3と併せてbotocoreもインストールされます。botocoreはAWS APIリクエストの低レベルな処理を担当しており、boto3と密接に連携して動作します。

インストールが完了したら、以下のコマンドでバージョンを確認できます。

python -c "import boto3; print(boto3.__version__)"

なお、boto3のバージョンによってAPIの互換性が異なる場合があるため、公式リリースノートを確認してください。

AWS認証情報の設定方法(IAMユーザー vs IAMロール)

boto3を使ってAWSリソースにアクセスするには、認証情報(AWS Access Key IDとSecret Access Key)が必要です。認証情報の設定方法には主に2つの方法があります。

1. IAMユーザーを使った認証

IAMユーザーを作成し、そのユーザーに対して必要な権限を付与します。以下は、IAMユーザーを作成するための手順です。

  1. AWS Management Consoleにログインし、IAMサービスを開きます。
  2. 「ユーザー」→「ユーザーを追加」をクリックします。
  3. ユーザー名を入力し、「プログラムによるアクセス」を選択します。
  4. 「既存のポリシーを直接アタッチ」を選択し、必要な権限(例:AmazonEC2FullAccess)を付与します。
  5. 「タグの追加(オプション)」はスキップし、ユーザーを作成します。
  6. アクセスキーIDとシークレットアクセスキーが表示されるので、安全な場所に保存します。

次に、これらの認証情報をboto3で使用するために、以下のいずれかの方法で設定します。

方法1:環境変数に設定
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export AWS_DEFAULT_REGION=ap-northeast-1
方法2:~/.aws/credentialsファイルに設定
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
region = ap-northeast-1
方法3:Pythonコード内で直接指定
import boto3

session = boto3.Session(
    aws_access_key_id='AKIAIOSFODNN7EXAMPLE',
    aws_secret_access_key='wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
    region_name='ap-northeast-1'
)

ec2 = session.client('ec2')

注意事項:認証情報は厳重に管理してください。GitHubなどの公開リポジトリにアップロードしないように注意しましょう。万が一漏洩した場合は、AWS IAMコンソールから即座にアクセスキーを無効化してください。

2. IAMロールを使った認証(推奨)

AWSリソース(例:EC2インスタンス、Lambda関数)にIAMロールをアタッチすることで、認証情報を明示的に管理することなくAWSサービスにアクセスできます。これは、特にクラウド環境で動作する自動化スクリプトに適した方法です。

IAMロールの作成手順は以下の通りです。

  1. IAMコンソールを開き、「ロール」→「ロールを作成」をクリックします。
  2. 「信頼されたエンティティタイプ」として「AWSサービス」を選択します。
  3. 「使用例」として「EC2」を選択します。
  4. 必要な権限(例:AmazonEC2ReadOnlyAccess)をアタッチします。
  5. ロール名を入力し、ロールを作成します。
  6. EC2インスタンスにロールをアタッチします。

IAMロールを使用する場合、boto3では特別な設定は不要です。EC2インスタンス上で動作するPythonスクリプトは、自動的にロールに関連付けられた認証情報を使用します。

基本的な構文とリソース操作の流れ

boto3を使ったAWSリソースの操作は、以下の基本的な流れで行われます。

  1. クライアントまたはリソースオブジェクトの作成:`boto3.client()`または`boto3.resource()`を使って、操作対象のサービスを指定します。
  2. API呼び出し:作成したオブジェクトを使って、AWS APIを呼び出します。
  3. レスポンスの処理:API呼び出しの結果を受け取り、必要な処理を行います。

以下に、EC2インスタンスの一覧を取得するサンプルコードを示します。

import boto3

クライアントオブジェクトの作成

ec2 = boto3.client('ec2')

EC2インスタンスの一覧を取得

response = ec2.describe_instances()

レスポンスの処理

for reservation in response['Reservations']: for instance in reservation['Instances']: print(f"Instance ID: {instance['InstanceId']}") print(f"Instance Type: {instance['InstanceType']}") print(f"State: {instance['State']['Name']}") print("---")

このコードでは、`boto3.client(‘ec2’)`を使ってEC2サービスのクライアントオブジェクトを作成しています。次に、`describe_instances()`メソッドを呼び出すことで、EC2インスタンスの一覧を取得しています。レスポンスはJSON形式で返されるため、必要な情報を抽出して処理します。

また、`boto3.resource()`を使うことで、より高レベルなAPIを利用できます。例えば、EC2インスタンスを起動する場合は以下のように記述できます。

import boto3

リソースオブジェクトの作成

ec2 = boto3.resource('ec2')

EC2インスタンスの起動

instance = ec2.create_instances( ImageId='ami-0c55b159cbfafe1f0', # Amazon Linux 2 AMI (ap-northeast-1) MinCount=1, MaxCount=1, InstanceType='t2.micro', KeyName='my-key-pair', SecurityGroupIds=['sg-12345678'] ) print(f"Created Instance ID: {instance[0].id}")

このコードでは、`boto3.resource(‘ec2’)`を使ってEC2リソースオブジェクトを作成し、`create_instances()`メソッドを呼び出すことでEC2インスタンスを起動しています。リソースオブジェクトを使うことで、より直感的なインターフェースでAWSリソースを操作できます。

補足:`boto3.client()`と`boto3.resource()`の違いについては、公式ドキュメントを参照してください。一般的には、低レベルな操作には`client`、高レベルな操作には`resource`を使用します。


EC2インスタンスの自動起動・停止・監視スクリプト

EC2インスタンスは、AWSの主要なコンピューティングサービスであり、多くのシステムで利用されています。手動でEC2インスタンスを管理するのは非効率的なため、Pythonとboto3を使った自動化が有効です。以下では、EC2インスタンスの自動起動・停止・監視を実現するスクリプトを解説します。

EC2インスタンスの起動・停止・再起動

EC2インスタンスの起動・停止・再起動を自動化するスクリプトを作成します。以下の機能を実装します。

  • 特定のEC2インスタンスを起動する
  • 特定のEC2インスタンスを停止する
  • 特定のEC2インスタンスを再起動する

まず、EC2インスタンスを操作するための基本的なスクリプトを以下に示します。

import boto3

def start_ec2_instance(instance_id):
    ec2 = boto3.client('ec2')
    response = ec2.start_instances(InstanceIds=[instance_id])
    print(f"Starting EC2 instance {instance_id}")
    return response

def stop_ec2_instance(instance_id):
    ec2 = boto3.client('ec2')
    response = ec2.stop_instances(InstanceIds=[instance_id])
    print(f"Stopping EC2 instance {instance_id}")
    return response

def reboot_ec2_instance(instance_id):
    ec2 = boto3.client('ec2')
    response = ec2.reboot_instances(InstanceIds=[instance_id])
    print(f"Rebooting EC2 instance {instance_id}")
    return response

使用例

if __name__ == "__main__": instance_id = "i-1234567890abcdef0" # インスタンスを起動 start_ec2_instance(instance_id) # 30秒待機(起動完了まで) import time time.sleep(30) # インスタンスを再起動 reboot_ec2_instance(instance_id) # 30秒待機(再起動完了まで) time.sleep(30) # インスタンスを停止 stop_ec2_instance(instance_id)

このスクリプトでは、`start_instances()`、`stop_instances()`、`reboot_instances()`メソッドを使ってEC2インスタンスを操作しています。各メソッドは、指定したインスタンスIDのリストを受け取り、対応する操作を実行します。

また、EC2インスタンスのステータスを確認するための関数も追加します。

def get_ec2_instance_status(instance_id):
    ec2 = boto3.client('ec2')
    response = ec2.describe_instances(InstanceIds=[instance_id])
    status = response['Reservations'][0]['Instances'][0]['State']['Name']
    print(f"EC2 instance {instance_id} status: {status}")
    return status

使用例

if __name__ == "__main__": instance_id = "i-1234567890abcdef0" status = get_ec2_instance_status(instance_id)

この関数では、`describe_instances()`メソッドを使ってEC2インスタンスのステータスを取得しています。ステータスは、`pending`、`running`、`stopping`、`stopped`、`shutting-down`、`terminated`のいずれかです。

CloudWatchメトリクスを活用した監視自動化

EC2インスタンスの監視を自動化するために、CloudWatchメトリクスを活用します。CloudWatchを使うことで、CPU使用率やメモリ使用率などのメトリクスを収集し、異常が発生した場合にアラートを発報できます。

以下に、CloudWatchメトリクスを取得し、CPU使用率が一定以上になった場合にアラートを発報するスクリプトを示します。

import boto3

def get_cpu_utilization(instance_id):
    cloudwatch = boto3.client('cloudwatch')

    response = cloudwatch.get_metric_statistics(
        Namespace='AWS/EC2',
        MetricName='CPUUtilization',
        Dimensions=[{'Name': 'InstanceId', 'Value': instance_id}],
        StartTime=datetime.utcnow() - timedelta(minutes=5),
        EndTime=datetime.utcnow(),
        Period=300,
        Statistics=['Average']
    )

    datapoints = response['Datapoints']
    if datapoints:
        latest_cpu = max(datapoints, key=lambda x: x['Timestamp'])['Average']
        print(f"Latest CPU Utilization for {instance_id}: {latest_cpu}%")
        return latest_cpu
    else:
        print(f"No CPU Utilization data for {instance_id}")
        return None

def check_cpu_threshold(instance_id, threshold=80):
    cpu_utilization = get_cpu_utilization(instance_id)
    if cpu_utilization and cpu_utilization > threshold:
        print(f"ALERT: CPU Utilization for {instance_id} exceeded threshold ({threshold}%)")
        # ここでアラートを発報する(例:SNSトピックに通知)
        sns = boto3.client('sns')
        sns.publish(
            TopicArn='arn:aws:sns:ap-northeast-1:123456789012:MyTopic',
            Message=f"High CPU Utilization Alert for {instance_id}: {cpu_utilization}%"
        )
    else:
        print(f"CPU Utilization for {instance_id} is within threshold")

使用例

if __name__ == "__main__": instance_id = "i-1234567890abcdef0" check_cpu_threshold(instance_id, threshold=80)

このスクリプトでは、`get_metric_statistics()`メソッドを使ってCloudWatchからCPU使用率のメトリクスを取得しています。取得したメトリクスが設定したしきい値(デフォルトは80%)を超えた場合、SNSトピックにアラートを発報しています。

また、AWS公式のベストプラクティスによると、EC2インスタンスの監視にはCloudWatchを活用することが推奨されています。特に、以下のメトリクスは重要です。

  • CPUUtilization:CPU使用率
  • MemoryUtilization:メモリ使用率(カスタムメトリクスとして設定する必要あり)
  • DiskReadOps / DiskWriteOps:ディスク読み書き操作数
  • NetworkIn / NetworkOut:ネットワークトラフィック

AMIからの自動インスタンス起動(テンプレート活用)

EC2インスタンスを自動で起動する際に、AMI(Amazon Machine Image)を活用することで、同じ設定のインスタンスを簡単に複製できます。以下に、AMIからEC2インスタンスを起動するスクリプトを示します。

import boto3

def launch_ec2_instance_from_ami(
    ami_id,
    instance_type='t2.micro',
    key_name=None,
    security_group_ids=None,
    subnet_id=None,
    min_count=1,
    max_count=1
):
    ec2 = boto3.client('ec2')

    kwargs = {
        'ImageId': ami_id,
        'InstanceType': instance_type,
        'MinCount': min_count,
        'MaxCount': max_count,
    }

    if key_name:
        kwargs['KeyName'] = key_name
    if security_group_ids:
        kwargs['SecurityGroupIds'] = security_group_ids
    if subnet_id:
        kwargs['SubnetId'] = subnet_id

    response = ec2.run_instances(**kwargs)
    instance_id = response['Instances'][0]['InstanceId']
    print(f"Launched EC2 instance {instance_id} from AMI {ami_id}")
    return instance_id

使用例

if __name__ == "__main__": ami_id = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 AMI (ap-northeast-1) instance_id = launch_ec2_instance_from_ami( ami_id=ami_id, instance_type='t2.micro', key_name='my-key-pair', security_group_ids=['sg-12345678'], subnet_id='subnet-12345678' )

このスクリプトでは、`run_instances()`メソッドを使ってEC2インスタンスを起動しています。AMI IDを指定することで、指定したAMIからインスタンスを起動できます。また、インスタンスタイプ、キーペア、セキュリティグループ、サブネットなどのパラメータを柔軟に設定できます。

AMIを活用することで、以下のようなメリットがあります。

  • 再現性の確保:同じ設定のインスタンスを簡単に複製できます。
  • 迅速なデプロイ:AMIを使うことで、インスタンスの起動が迅速に行えます。
  • バージョン管理:AMIをバージョン管理することで、特定の時点の設定を再現できます。

AMIの作成方法については、公式ドキュメントを参照してください。


S3バケットの自動管理:ファイル操作とライフサイクル設定

Amazon S3は、オブジェクトストレージサービスであり、データの保存やバックアップに広く利用されています。S3バケットの管理を自動化することで、ファイルのアップロード・ダウンロード・削除、ライフサイクルルールの設定、暗号化設定などを効率的に行えます。以下では、S3バケットの自動管理を実現するスクリプトを解説します。

ファイルのアップロード・ダウンロード・削除

S3バケットに対してファイルをアップロード・ダウンロード・削除するスクリプトを作成します。以下の機能を実装します。

  • ローカルファイルをS3バケットにアップロードする
  • S3バケットからローカルにファイルをダウンロードする
  • S3バケットからファイルを削除する

まず、S3バケットにファイルをアップロードするスクリプトを以下に示します。

import boto3
import os

def upload_file_to_s3(bucket_name, file_path, object_name=None):
    s3 = boto3.client('s3')

    if object_name is None:
        object_name = os.path.basename(file_path)

    s3.upload_file(file_path, bucket_name, object_name)
    print(f"File {file_path} uploaded to s3://{bucket_name}/{object_name}")
    return True

使用例

if __name__ == "__main__": bucket_name = "my-bucket" file_path = "/path/to/local/file.txt" upload_file_to_s3(bucket_name, file_path)

このスクリプトでは、`upload_file()`メソッドを使ってローカルファイルをS3バケットにアップロードしています。`object_name`を指定しない場合は、ローカルファイルのベース名がS3オブジェクト名として使用されます。

次に、S3バケットからファイルをダウンロードするスクリプトを以下に示します。

import boto3
import os

def download_file_from_s3(bucket_name, object_name, file_path=None):
    s3 = boto3.client('s3')

    if file_path is None:
        file_path = os.path.basename(object_name)

    s3.download_file(bucket_name, object_name, file_path)
    print(f"File s3://{bucket_name}/{object_name} downloaded to {file_path}")
    return True

使用例

if __name__ == "__main__": bucket_name = "my-bucket" object_name = "file.txt" download_file_from_s3(bucket_name, object_name)

このスクリプトでは、`download_file()`メソッドを使ってS3バケットからファイルをダウンロードしています。`file_path`を指定しない場合は、オブジェクト名と同じ名前でカレントディレクトリにファイルが保存されます。

最後に、S3バケットからファイルを削除するスクリプトを以下に示します。

import boto3

def delete_file_from_s3(bucket_name, object_name):
    s3 = boto3.client('s3')

    s3.delete_object(Bucket=bucket_name, Key=object_name)
    print(f"File s3://{bucket_name}/{object_name} deleted")
    return True

使用例

if __name__ == "__main__": bucket_name = "my-bucket" object_name = "file.txt" delete_file_from_s3(bucket_name, object_name)

このスクリプトでは、`delete_object()`メソッドを使ってS3バケットからファイルを削除しています。

また、S3バケット内のファイル一覧を取得するスクリプトも作成します。

import boto3

def list_files_in_s3(bucket_name, prefix=''):
    s3 = boto3.client('s3')

    response = s3.list_objects_v2(Bucket=bucket_name, Prefix=prefix)
    if 'Contents' in response:
        for obj in response['Contents']:
            print(f"s3://{bucket_name}/{obj['Key']} (Size: {obj['Size']} bytes)")
    else:
        print(f"No files found in s3://{bucket_name}/{prefix}")
    return response

使用例

if __name__ == "__main__": bucket_name = "my-bucket" list_files_in_s3(bucket_name)

このスクリプトでは、`list_objects_v2()`メソッドを使ってS3バケット内のファイル一覧を取得しています。`Prefix`パラメータを使うことで、特定のプレフィックスを持つファイルのみを取得できます。

ライフサイクルルールの自動設定

S3バケットのライフサイクルルールを自動で設定することで、古いファイルを自動的に削除したり、ストレージクラスを移行したりできます。以下に、ライフサイクルルールを設定するスクリプトを示します。

import boto3
from datetime import datetime, timedelta  def set_s3_lifecycle_policy(bucket_name):
 s3 = boto3.client('s3')  lifecycle_policy = {
 'Rules': [
 {
 'ID': 'DeleteOldFiles',
 'Status': 'Enabled',
 'Filter': {'Prefix': ''},
 'Expiration': {'Days': 30},
 'NoncurrentVersionExpiration': {'NoncurrentDays': 7}
 },
 {
 'ID': 'TransitionToIA',
 'Status': 'Enabled',
 'Filter': {'Prefix': 'logs/'},
 'Transitions': [
 {
 'Days': 30,
 'StorageClass': 'STANDARD_IA'
 }
 ]
 }
 ]
 }  s3.put_bucket_lifecycle_configuration(
 Bucket=bucket_name,
 LifecycleConfiguration=lifecycle_policy
 )
 print(f"Lifecycle policy set for bucket {bucket_name}")
 return True

使用例

if __
【編集・制作ポリシー】
本記事はRoute Bloom編集部が各ベンダー公式ドキュメント・エンジニア監修をもとに作成しています。インフラ・クラウド構築は環境により異なります。本番環境への適用前に必ずテストを実施してください。情報の正確性には万全を期していますが、最新情報は各公式ドキュメントをご確認ください。
ABOUT ME
たから
サラリーマンをしながら開業して経営やってます。 今年、本業で独立・別事業を起業予定です。 ◆経験:IT講師/インフラエンジニア/PM/マネジメント/採用/運用・保守・構築・設計 ◆取得資格:CCNA/CCNP/LPIC-1/AZ-900/FE/サーティファイC言語 ◆サイドビジネス:アパレル事業/複数のWEBメディアを運営