Lambdaを使ってS3にアップロードされたファイルを自動的にEC2(Windows)内にダウンロード(同期)してみる

91件のシェア(ちょっぴり話題の記事)

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも!大阪オフィスの西村祐二です。

S3にアップロードされたファイルをEC2内に自動的にダウンロードしたいと思うことはよくあると思います。
自動化する方法はいろいろあると思いますが、
今回はLambdaとSSM、AWS CLIを使って自動化してみたいと思います。

さっそくやってみましょう。

構成図

今回、想定する構成が下記の図になります。
S3にファイルがアップロードされたら、LambdaからSSMを実行し、
EC2(Windows)にてAWSCLIのS3 Syncコマンドを実行します。

この構成の利点

私が思うこの構成の利点としては、
・EC2側はAWS CLI設定とSSM Agentのインストールだけで済み、今後の運用不可が軽減されそう
・Lambdaの実装がSSMを実行する部分のみになる

はじめはEC2にFTPサーバをたてて、LambdaでS3からファイルを取得し、EC2にコピーしようと思いましたが、
FTPサーバを立ててしまうと、FTPサーバの設定や、ポート、FTPログなど
新たに管理しなければいけない項目が増えてしまいそうだと思い、
また、コピーする際にLambdaの制限を考慮したり、EC2へのログイン処理など
すこし大袈裟な処理になりそうでしたので、今回はシンプルにLambdaはSSMを実行するだけとし
S3にアップロードされたファイルはEC2から取得する構成としてみました。

環境

■Windows:
Windows Server 2016

■セキュリティグループ:

インバウンドは作業用にマイIPのみ許可しています。

■Lambda:

・ランタイム:python3.6

作業概要

■EC2(Windows):

・AWS CLI環境を構築する
・SSM Agentをインストールし、設定する

■Lambda:

・S3へのアップロードをトリガーとするLambdaからSSMを実行する関数を作成する

EC2(Windows)の作業:AWS CLI環境を構築する

同期用のIAMユーザを作成する

今回、EC2からS3のファイルをダウンロードするため、
まず、S3への権限を付与したIAMユーザを作っておきましょう。
既存のユーザがあるなら、そちらでも大丈夫です。

▼マネージメントコンソールからIAMのサービス画面に移動し、「ユーザを追加」をクリックします

▼ユーザ名を「test-s3-sync」として、「プログラムによるアクセス」にチェックします

▼アクセス権限はS3へのアクセスを許可するポリシーをアタッチしておきます

▼権限等確認して、ユーザを作成します

▼CSVをダウンロードしておき、アクセスキーIDとシークレットアクセスキーをメモしておきます

EC2(Windows)にてAWS CLIを設定する

▼下記ドキュメントを参考にAWS CLIをインストールします。

Microsoft Windows で AWS Command Line Interface をインストールする

インストールが完了したらpowershellなどで下記コマンドを実行し、AWS CLIの情報が出力されるか確認します。

> aws --version
aws-cli/1.11.189 Python/2.7.9 Windows/2012Server botocore/1.7.47

▼プロファイルの設定をします。

powershellから aws configure --profile s3-sync-userと入力して設定していきます。
今回はプロファイル名「s3-sync-user」として設定しています。
AWS Access Key IDAWS Secret Access Key には、ダウンロードしたCSVに記載されていた値を入力します。

▼動作確認を行います。

設定がうまくいっていれば、aws s3 ls s3://<バケット名> --profile s3-sync-user
S3のバケットの中身が確認できます。

EC2(Windows)の作業:SSM Agentをインストールし、設定する

下記ドキュメントを参考にSSM Agentをインストールします。

Windows インスタンスで SSM エージェント をインストールし設定する

EC2用のIAMロールを設定する

▼EC2とSSMがアクセスするために、EC2にIAMロールを設定します。

▼今回は新しくIAMロールを作成します。

▼ロール名を「test-ssm」としてロールを作成します。

▼作成した「test-ssm」を選択し、EC2にIAMロールを設定します。

▼SSMのAgentやIAMの設定が完了したら、きちんと認識されているか確認します。

▼認識されていたら、画像のようにインスタンスIDがみえます。

Lambda関数を作成します

下記がサンプルプログラムになります。
対象のインスタンスIDと、EC2で実行してほしいコマンドを設定します。

今回はAWS-RunPowerShellScriptを使って
EC2内のデスクトップにある、「s3-sync」というフォルダに S3のバケット内のファイルをダウンロードします。

EC2内で実行されるコマンド

aws s3 sync s3://<your target bucket> C:\Users\Administrator\Desktop\s3-sync\

また、対象のバケットをトリガーとする設定と、IAMにはEC2とSSMの権限を付与しておいてください。

"""This is a test program."""

import logging
import boto3

LOGGER = logging.getLogger()
LOGGER.setLevel(logging.INFO)
EC2 = boto3.client('ec2')
SSM = boto3.client('ssm')
INSTANCE_ID = 'i-0XXXXXXXXXXXXX'

def lambda_handler(event, context):
    """
    Run 'S3 sync command'in Windows from Lambda
    """
    try:
        # Get EC2 State
        ec2_resp = EC2.describe_instances(InstanceIds=[INSTANCE_ID])
        ec2_state = ec2_resp['Reservations'][0]['Instances'][0]['State']['Name']
        if not ec2_state == "running":
            LOGGER.info('No EC2 is running')
            return "END"
         # RunPowerShellScript
        command = r'aws s3 sync s3://<your target bucket> C:\Users\Administrator\Desktop\s3-sync\ '
        SSM.send_command(
            InstanceIds=[INSTANCE_ID],
            DocumentName="AWS-RunPowerShellScript",
            Parameters={
                "commands":[command],
                "executionTimeout":["3600"]
            },
        )

    except Exception as error:
        LOGGER.error(error)
        raise error

動作確認

トリガーとなるバケットにファイルをアップロードし、EC2へ同期されるか確認してみます。

想定通り、バケットへファイルを追加すると、右側のEC2のフォルダでもファイルがふえていることがわかります。

さいごに

いかがだったでしょうか。

Lambdaを使ってS3にアップロードされたファイルを自動的にEC2(Windows)内にダウンロード(同期)してみました。
EC2にてAWS CLIの設定と、SSM Agentのインストールを行えば、簡単に実現することができます。
要件次第ではありますが、FTPサーバを利用するより運用コストも軽微で済むのではないでしょうか。

誰かの参考になれば幸いです。