LambdaでEC2インスタンス内のプログラムを実行してみた

この記事は「スパムFAXを画像解析+機械学習でブロックしてみた」の全6回のシリーズ記事の第2回です。

はじめに

こんにちは、hacknoteのr.katoです。

前回の記事【第1回】Fax着信通知をAWSのSESメールで受け取りLambdaを起動してみたではSESメール受信時にLambdaを実行する方法を紹介しました。

今回はheadless chromeを利用してWebサイトからFaxデータをダウンロードしていきたいと思います。

最初、headless chromeの制御はpythonで行えるため、FaxデータをLambda単体でダウンロードし、S3に保存していこうかと考えました。
しかし、headless chromeそのものを動かすことはLambdaのみで出来ましたが、FaxデータのダウンロードはLambda関数のデータサイズの関係から出来ませんでした。

そこで次の手段として、今回はSystems Manager(ssm)を使って、EC2インスタンス内の特定のプログラムの実行をlambdaから指示することにしましたので紹介していきます。

以下の図のように構築すればssmを利用してEC2インスタンス内のプログラムを叩けるようになります。

用意したもの

  1. AmazonLinux2 インスタンス -python3導入済み(東京リージョン)
  2. Lambdaから指示して実行したいインスタンス内のheadless chrome制御プログラム(今回はpython)
  3. Lambda関数(北米リージョン)
  4. EC2用のAmazonEC2RoleforSSMがアタッチされたロール
  5. Lambda用のAmazonSSMFullAccessがアタッチされたロール

Lambda関数(XXXの部分を任意の文字へ変更)

import boto3

instance_id = "XXXXXXXXXXXXXXXXX"
aws_id='XXXXXXXXXXXXXX'
aws_key='XXXXXXXXXXXXXXXXXXX'

def command(ssm,instance, commands):

    r = ssm.send_command(
        InstanceIds = [instance],
        DocumentName = "AWS-RunShellScript",
        Parameters = {
          "commands": commands
        }
    )
    command_id = r['Command']['CommandId']

    while True:
        time.sleep(0.2)
        res = ssm.list_command_invocations(CommandId=command_id)

        invocations = res['CommandInvocations']
        if len(invocations) <= 0: continue

        status = invocations[0]['Status']
        if status == 'Success': return True
        if status == 'Failed': return False

def lambda_handler(event, context):

    client = boto3.client('ssm', region_name='ap-northeast-1',aws_access_key_id=aws_id,aws_secret_access_key=aws_key)

    res=command(client,instance_id,["cd /home/ec2-user/XXXXXXXXX","python3 XXXXX.py"])
headless chromeの記事はこちらを参照してください

注意!!!

以下のようになっているため、EC2インスタンスのpythonはsudoが頭に付いている状態でも実行できるように環境構築しておく必要があります。

Session Manager をサポートする SSM エージェント のバージョンがインスタンス上で起動すると、ssm-user という名前のルートまたは管理者権限を持つユーザーアカウントが作成されます。AWSドキュメント

おわりに

これでLambdaからEC2インスタンス内のプログラムを実行指示を出せるようになります。

ちなみに、LambdaとEC2インスタンスでリージョンが異なっているのは
第1回で紹介したSESメール受信をトリガーにしてLambdaを実行するのにSESのリージョンが北米リージョンなためです。

次回は「【第3回】Fax画像でスパム分類したかった話」 をしていきたいと思います。 

▼Faxのスパム分類シリーズ記事(全6回)