1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【AWS】CloudWatchのカスタムウィジェットからリソースを操作する(EC2開始/停止)

Last updated at Posted at 2023-11-05

はじめに

Lambdaで実装できるならCloudWatchのダッシュボード上で色々な操作ができそうなので、
EC2を開始/停止するLambda関数を書いてカスタムウィジェットに設定し、CloudWatchのダッシュボードからEC2の開始/停止をしてみる。
(Lambda書いてまでCloudWatchからEC2を操作する必要性は置いておいて)

Lambda

サーバレスでコードを実行できるサービス。今回はAWS SDK for Python(Boto3)を使う。

CloudWatch

ダッシュボードに追加するウィジェットは折れ線グラフだったり円グラフだったり色々種類がある。その中にカスタムウィジェットというものがあり、Lambdaを実行し、実行結果を表示することができる。

カスタムウィジェット自体には料金は掛からないが、Lambda関数は実行した分従量課金される。

1. Lambda関数を実装

以下2つを実装する。

  • パラメータで指定したインスタンスの状態を表示し、開始/停止ボタンを表示する関数
  • インスタンスを開始/停止する関数

パラメータで指定したインスタンスの状態を表示し、開始/停止ボタンを表示する関数

Lambda関数にEC2 ec2:DescribeInstancesのポリシーが必要。

import json
import boto3

def lambda_handler(event, context):
   
    instance_name = event.get('Instance_Name')
    client = boto3.client('ec2')
    
    startbutton = '''
    <!DOCTYPE html>
    <a class="btn btn-primary">Start EC2</a>
    <cwdb-action 
        display="widget"
        action="call" 
        endpoint="<インスタンスを開始/停止する関数のarn>"
    >    
    </cwdb-action>
    </html>'''
    
    stopbutton = '''
    <!DOCTYPE html>
    <a class="btn btn-primary">Stop EC2</a>
    <cwdb-action 
        display="widget"
        action="call" 
        endpoint="<インスタンスを開始/停止する関数のarn>"
    >    
    </cwdb-action>
    </html>'''
    
    responses = client.describe_instances(
        Filters=[
            {
                'Name': 'tag:Name',
                'Values': [
                    instance_name,
                ]
            },
        ],
    )
    
    
    for instances in responses['Reservations']:
        for instance in instances['Instances']:
            instance_state = instance['State']['Name']

    if instance_state == "running":
        return f"<h2>InstanceName:&nbsp;{instance_name}</h2>, <h2>State:&nbsp;{instance_state}</h2><br>{stopbutton}"
    else:
        return f"<h2>InstanceName:&nbsp;{instance_name}</h2>, <h2>State:&nbsp;{instance_state}</h2><br>{startbutton}"
    

htmlでStartボタン、Stopボタンの定義をしておいて、インスタンスの状態を見て表示するボタンを変えている。
インスタンスの状態の場合分けはrunningとそれ以外にしたけど、もっと丁寧に場合分けした方がベターかなと思う。

インスタンスを開始/停止する関数

関数にec2:StartInstancesとec2:StopInstancesのポリシーが必要

import boto3

def lambda_handler(event, context):    
    instance_name =  event['widgetContext']['params']['Instance_Name']

    client = boto3.client('ec2')

    responses = client.describe_instances(
        Filters=[
            {
                'Name': 'tag:Name',
                'Values': [
                    instance_name,
                ]
            },
        ],
    )

    for response in responses['Reservations']:
        for instance in response['Instances']:
            state =instance['State']['Name']
    
            if  state == "stopped":
                client.start_instances(
                    InstanceIds=[
                        instance['InstanceId'],
                    ],
                )
                return f'<h3>Successfully Started</h3>'
                
            elif state == "running":
                client.stop_instances(
                    InstanceIds=[
                        instance['InstanceId'],
                    ],
                )
                return f'<h3>Successfully Stopped</h3>'            
    
            else:
                return f'<h3>You don\'t have Running/Stopped Instances</h3>'

呼び出したLambda関数でもウィジェットで設定したパラメータを使いたいので、
instance_name = event['widgetContext']['params']['Instance_Name']でインスタンス名を取ってきている。

2. CloudWatchのカスタムウィジェットの設定

CloudWatchのダッシュボードを開き、最初のウィジェットを作成か右上の+ボタンをクリックする。
image.png

カスタムウィジェットを選択し、次へをクリックする。
image.png

プルダウンでは何も選択せず、次へをクリックする。
image.png

プルダウンからLambda関数を選択するかARNを入力。関数のパラメータがあればここで設定する(JSON or YAML)。
image.png

設定するとこんな感じで表示される。Sampleインスタンスは停止しているので、Start EC2ボタンが表示されている。
image.png

3. 動かしてみる

Start EC2ボタンをクリックしてみると…
image.png

インスタンスを起動/停止する関数が実行された
image.png

インスタンスも起動される
インスタンス.png

ダッシュボード側でウィジェットを更新すると、インスタンスの状態もrunningに変わっている。
image.png

再度インスタンスの状態を表示する関数に戻りたいなと思ってSuccessfully Startedの画面にbackボタンを実装してみたけど、ボタンを押してみたら以下エラーが出た。
ウィジェットをリフレッシュすると状態表示をする関数のところに戻れるので、backボタンの実装は今後の課題とする。

The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

4. 参考サイト

  • AWSのカスタムウィジェットサンプルコード

  • ボタン実装の参考
    DevelopersIO「[アップデート]CloudWatch dashboardに任意のLambda関数の結果を表示できるcustom widgetsが使えるようになりました」

  • cwdb-actionの公式ドキュメント

  • 呼び出したLambda関数にパラメータを渡すときの参考
    DevelopersIO「CloudWatch dashboard custom widgetsのcwdb-actionで実行するLambda関数にパラメーターを渡したいときはどうするの?」

おわりに

コードを書ければダッシュボードで色々できそうな感じ

今後の課題

  • 呼び出したLambda関数から呼び出し元のLambda関数を呼び出す方法
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?