2017-01-24 29 views
5

S3バケットに受け取ったときにcsvをMySQLテーブルに読み込む作業を自動化しようとしています。S3からcsvを読み込み、AWS Lambdaを使用してMySQLテーブルに挿入

私の戦略は、指定されたバケットにファイルを受け取ったときにS3がイベントを起動することです(バケツファイルと呼ぶ)。このイベントは、各行をMySqlテーブルに挿入してファイルをダウンロードして処理するAWSラムダ関数(「target_table」と呼ぶ)に通知されます。

RDSがVPCにあることを考慮する必要があります。

バケットの現在のアクセス許可の設定は次のとおりです。

{ 
    "Version": "2008-10-17", 
    "Statement": [ 
     { 
      "Sid": "PublicReadForGetBucketObjects", 
      "Effect": "Allow", 
      "Principal": { 
       "AWS": "*" 
      }, 
      "Action": "s3:GetObject", 
      "Resource": "arn:aws:s3:::bucket-file/*" 
     } 
    ] 
} 

私は次のポリシーを持つロールを作成し、AmazonS3FullAccessとAWSLambdaVPCAccessExecutionRoleは、AWSラムダ関数に取り付けられています。

ラムダコードは次のとおりです。私は、機能をテストしてきたとS3は、ファイルがアップロードされたイベントを送信

from __future__ import print_function 
import boto3 
import logging 
import os 
import sys 
import uuid 
import pymysql 
import csv 
import rds_config 


rds_host = rds_config.rds_host 
name = rds_config.db_username 
password = rds_config.db_password 
db_name = rds_config.db_name 


logger = logging.getLogger() 
logger.setLevel(logging.INFO) 

try: 
    conn = pymysql.connect(rds_host, user=name, passwd=password, db=db_name, connect_timeout=5) 
except Exception as e: 
    logger.error("ERROR: Unexpected error: Could not connect to MySql instance.") 
    logger.error(e) 
    sys.exit() 

logger.info("SUCCESS: Connection to RDS mysql instance succeeded") 

s3_client = boto3.client('s3') 

def handler(event, context): 

    bucket = event['Records'][0]['s3']['bucket']['name'] 
    key = event['Records'][0]['s3']['object']['key'] 
    download_path = '/tmp/{}{}'.format(uuid.uuid4(), key) 

    s3_client.download_file(bucket, key,download_path) 

    csv_data = csv.reader(file(download_path)) 

    with conn.cursor() as cur: 
     for idx, row in enumerate(csv_data): 

      logger.info(row) 
      try: 
       cur.execute('INSERT INTO target_table(column1, column2, column3)' \ 
           'VALUES("%s", "%s", "%s")' 
           , row) 
      except Exception as e: 
       logger.error(e) 

      if idx % 100 == 0: 
       conn.commit() 

     conn.commit() 

    return 'File loaded into RDS:' + str(download_path) 

、ラムダは、RDSインスタンスに接続し、通知を得ます。私は、バケツ名が「バケツファイル」であり、ファイル名も正しいことを確認しました。問題は、関数がlamdbaの有効期限に達するまでスタックされたs3_client.download_file(bucket, key,download_path)行に達したときです。それが言うのログ見

[INFO] 2017-01-24T14:36:52.102Z SUCCESS: Connection to RDS mysql instance succeeded 
[INFO] 2017-01-24T14:36:53.282Z Starting new HTTPS connection (1): bucket-files.s3.amazonaws.com 
[INFO] 2017-01-24T14:37:23.223Z Starting new HTTPS connection (2): bucket-files.s3.amazonaws.com 
2017-01-24T14:37:48.684Z Task timed out after 60.00 seconds 

は、私はあなたがVPC内で作業している場合は、S3バケットにアクセスするためにあなたがS3へのアクセスを許可するVPCエンドポイントを作成する必要があることも読みましたこのサブネット。私もこのソリューションを試しましたが、結果は同じです。

私はいくつかのアイデアを感謝します。

ありがとうございます!

答えて

2

私はついにそれを手に入れました。

問題はVPCの問題でした。私が言ったように、私はVPCエンドポイントを作成して、S3サービスをVPCからアクセスできるようにしましたが、ルートテーブルを誤って設定しました。

結論として、lambdaのVPCで作業していて、S3にアクセスしたい場合は、VPCエンドポイントを作成する必要があります。また、VPC外の他のインターネットサービスにアクセスする場合は、NATゲートウェイを設定する必要があります。

関連する問題