晴耕雨読

working in the fields on fine days and reading books on rainy days

[AWS] Pythonのboto3でタグ付きEC2だけを停止させる

Pythonのboto3で特定のタグが付いているEC2だけを停止させる方法について説明します。

事前準備

AWSコマンド (AWS CLI) と、Pythonから操作するためのboto3をインストールします。 インストール後は、AWSコンソールで生成したアクセスキーをAWS CLIに設定します。

$ pip install awscli boto3
$ aws configure

次に、設定したアクセスキーに紐づくユーザのロールが、EC2の読み取りや停止する権限を持っているか確認します。

$ aws ec2 describe-instances --filters "Name=instance-state-name,Values=running"
$ aws ec2 stop-instances --instance-ids <停止したいインスタンスID>

PythonによるEC2停止スクリプト

以下の条件を全て満たすインスタンス一覧を取得し、停止させます。

  • EC2が稼働中 (running) であること
  • EC2のタグ「AutoStop」の値が「true」であること
import boto3  # pip install boto3

def stop_ec2():
    """
    boto3を使って全てのリージョンで条件を満たすEC2インスタンスを停止する
    """

    # 全リージョンを取得
    client = boto3.client('ec2')
    regions = client.describe_regions()['Regions']

    # リージョン毎にEC2一覧を取得&停止
    for region in regions:
        client = boto3.client('ec2', region_name=region['RegionName'])

        # 以下の条件を全て満たすインスタンス一覧を取得
        response = client.describe_instances(Filters=[
            {   # EC2が稼働中
                'Name': 'instance-state-name',
                'Values': ['running'],
            },
            {   # EC2のタグ「AutoStop」の値が「true」
                'Name': 'tag:AutoStop',
                'Values': ['true'],
            },
        ])

        # 一致なしの場合はスキップ
        if len(response['Reservations']) <= 0:
            continue

        # 一致ありの場合はインスタンスID一覧で停止
        instance_ids = []
        for instance_dic in response['Reservations']:
            instance_ids.append(instance_dic['Instances'][0]['InstanceId'])
        response = client.stop_instances(InstanceIds=instance_ids)

        print('[+] stop ec2 on region "%s"' % region['RegionName'])
        print(response)

stop_ec2()

上記のスクリプトをcronやAWS Lambdaに組みこんで定期的に実行させるなどの利用方法が考えられます。

以上です。

参考文献