Lambda関数をVPCにアタッチする

作成するイメージ

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

■ネットワークの概要

・Lambdaを単独で作成し、公開するのではなく、VPCにアタッチし、インターネットゲートウェイ経由でLambdaからインターネットにアクセスさせる。

 

※パブリックサブネットとプライベートサブネットの2つの構成にしなくてもよいが

  Lambdaはプライベートサブネットに置かれるケースの方が多いのでこのような構成としている。

 

 
VPCの作成
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
■設定する値            
名前         :任意の値    
IPv4 CIDR   : 10.0.0.0/16    



 

 

サブネットの作成
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
①パブリックサブネットとするサブネットを作成する。
設定する値
VPC ID作成したVPC
サブネット名任意の値
IPv4 サブネットCIDRブロック10.0.1.0/24
 



②プライベートサブネットとするサブネットを作成する。
■設定する値
VPC ID作成したVPC
サブネット名任意の値
IPv4 サブネットCIDRブロック: 10.0.2.0/24
 
 



 
IGWの作成
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
①インターネットゲートウェイを作成する。
 
■設定する値
名前タグ任意の値

 

 
②作成されたインターネットゲートウェイを選択し、「VPCにアタッチ」。

 

③  アタッチするVPCを選択し、「インターネットゲートウェイのアタッチ」をクリックする。

 

 
NGWの作成
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
①NATネットゲートウェイを作成する。
設定する値
名前タグ任意の値
サブネット作成したパブリック用サブネット
 
 

 

ルートテーブルの作成
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
①パブリックサブネット用のルートテーブルを作成する。
設定する値
名前任意の値
VPC ID作成したVPC
 

 
②ルートを編集し、IGWへのルートを追加する。
設定する値
送信先0.0.0.0/0
ターゲット作成したIGW
 

 

③作成したルートテーブルを選び、明示的なサブネットの関連付けを行う。    

 

④作成したパブリックサブネットを選び、ルートテーブルを関連付ける。    

 

 
プライベートサブネット用のルートテーブルを作成する。
設定する値
名前任意の値
VPC ID作成したVPC

 

ルートを編集し、NGWへのルートを追加する。
設定する値
送信先 0.0.0.0/0
ターゲット作成したNGW

 

⑦作成したプライベートサブネットを選び、ルートテーブルを関連付ける。    

 

 

LambdaをVPCにアタッチ・テスト
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

 ①以下のようにLambdaからインターネットにアクセスするコードを記述する。
※requestsを使うためにレイヤーを使用しているがここでは説明を省略する。

 

 

②作成したLambda関数の「設定」⇒「VPC」→「編集」をクリックする。

 

 

③作成したVPC、プライベートサブネットを選び、関連つける。

 


④テストを実行し、正常に結果が返ってくることを確認する。




 

 
 
 

既存の外部ライブラリをLambdaレイヤで利用する

Pythonで外部ライブラリをLambdaのレイヤに登録するために

使用するzipファイルの作り方は以下の通り。

 


なお、環境はdockerに作成したamazon linux:2環境で以下を実行しています。

Windowsや他のLinuxだとそのOS用のライブラリが含まれてしまうこともあり

正常に動かない可能性が高いです。

 


以下の①~③コマンドはdoccker内のLinuxに接続した状態で実行してください。

 


①pipコマンドを実行しpandasをインストールする。 

pip3 install -t /python pandas 

 

②①をpythonという名前のzip形式のファイルに固める。 

zip -r /dist/pandas.zip /python

 

③dokcerから抜ける。 

exit

 

④②のファイルをローカルPCにコピーする。 

docker cp testcont01:/dist/pandas.zip D:\hoge

 

▼パラメタの説明                    
testcont01・・・イメージから起動されるコンテナの名前(任意で設定した値でよい)    
D:\hoge・・・ローカルPCのパス    

パラメータストアを利用する

lambdaで実行する際に利用する値を外部ファイルから取得する方法の1つとして

パラメータストアがあります。(基本無料)

 

利用例は以下の通り。

 

AWS System Manager → パラメータストア →「パラメータストアを作成」を行う

パラメタ名:TEST_PARAM_HOGE

利用枠:標準(無料)

 

 

●パラメータストアから値を取得するLambda関数

import boto3
import os

def lambda_handler(event, context):
    # boto3のクライアントを作成
    ssm = boto3.client('ssm')
   
    # パラメータ名を指定
    parameter_name = 'TEST_PARAM_HOGE'

    # パラメータの値の変数の初期化  
    parameter_value = ""

    try:
        # パラメータを取得
        response = ssm.get_parameter(
            Name=parameter_name,
            WithDecryption=True  # 暗号化されている場合はTrueにする
        )
       
        # パラメータの値を取得
        parameter_value = response['Parameter']['Value']
       
        # パラメータの値をPrint
        print(f"取得したパラメータの値: {parameter_value}")

       
    except ssm.exceptions.ParameterNotFound:
        print(f"パラメータ '{parameter_name}' が見つかりませんでした")
    except Exception as e:
        print(f"エラーが発生しました: {e}")

    return {
        'statusCode': 200,
        'body': 'パラメータ取得完了!!' +  parameter_value
    }

 

 

パラメータの取得には「SSM:GetParameters」権限が必要です。

Lambda関数の実行ロールに「AmazonSSMReadOnlyAccess」など上記を含んだ権限を付与してください。

 

lambda レイヤーのサンプル

自作のlambda関数を作成して呼び出すまでの手順は以下の通り。

 

 

 

①Layerのファイルを作成する

 

①-1.ライブラリ化したい関数を作成する

 

①-2.Python」の名前のフォルダを作成し、作成したファイルを格納する

Python     
   |------hogelayertest.py

 

①-3.2のフォルダをZIP形式にしてPython.zipを作成する

Windowsの機能の右クリック→圧縮先→ZIP形式・・でOK。

 

 

 

②Layerを登録する

 

②-1.レイヤーの作成をクリックする。

 

②-2.作成したzipファイルをアップロードする。

名前は作成したzip内のソースや呼び出し時には無関係なので任意で決めてしまってよい。

 

 

 

③Layerの関数を呼び出す

 

③-1.lambdaを作成し、Layersをクリックする。

 

③-2.レイヤーの追加をクリックする

 

③-3.カスタムレイヤーを選択し、②で登録したレイヤーを選ぶ

 

③-4.レイヤーを呼び出す際のlambdaのコードは以下の通り。

import json
from hogelayertest import myconcat  # レイヤーからインポート

def lambda_handler(event, context):

    # レイヤーの関数を使用
    result = myconcat('love is ','over')


    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda! result=' + str(result))
    }
 
 
●メモ
Unable to import module 'lambda_function' ・・・のエラーが出た場合は
参照設定や作成したZipのフォルダ構成に間違いがないか確認すること。
 

 

lambdaからS3にファイルを書き込み

lambdaからS3にファイルを書き込みするPythonコードは以下の通り。

 

import boto3

# S3に接続するためのクライアントを作成
s3 = boto3.client('s3')

bucket_name = 'hogetest01'  # 使用するS3バケット名を指定

# 作成するファイル名と内容
file_name = 'test.txt'
file_content = 'hello world!!'

def lambda_handler(event, context):
    # S3バケットにファイルをアップロード
    s3.put_object(
        Bucket=bucket_name,
        Key=file_name,
        Body=file_content
    )
    return {
        'statusCode': 200,
        'body': 'File uploaded successfully!'
    }
 
●悩んだところとかのメモ
・lambdaから実行する場合はS3にアクセスするためのアクセスキーIDや
シークレットアクセスキーは設定不要でよい
 
・関数名はlambda_handlerから変更してはいけない
 
・lambda関数にはS3にアクセスする権限をつけなければならない。
 デフォルトでロールを作成するよりかあらかじめロールを作成しておき、
 既存のロールを使用したほうがよい。
 

 ※既存のロールには以下のポリシーをつけて実行した。
  本来はもう少しポリシーを細かく設定すべきかもしれない。
 
  AWSLambdaBasicExecutionRole
  AmazonS3FullAccess
 
 
 
 
 
 
 

GASでJson形式のパラメタを受け取るAPI

Json形式でパラメタを受け取り、Json形式で返すスクリプトは以下の通り。

受け取ったJsonの中にあるkey3の値をmessageの値にセットして返しています。

 

 

//HTTP Postをハンドリングする
function doPost(e) {

    // 値を設定する   
    numval = "123456789"

   // JSONパラメタを受け取る(key3というパラメタ名)
    var params = JSON.parse(e.postData.getDataAsString()); 
    var value = params.key3;  

    // 結果セットを作る
    var result = {
     message: value,
     num: numval,
     val: "test-20240912"
    }


    var out = ContentService.createTextOutput();

    //Mime TypeをJSONに設定
    out.setMimeType(ContentService.MimeType.JSON);

    //JSONテキストをセットする
    out.setContent(JSON.stringify(result));

    return out;
}

 

 

上記のAPIを実行するPythonコード

 
import requests
import json

# Web APIのURL

# 送信するJSONデータ
data = {
    'key1': 'hoge',
    'key2': 'hoge2',
    'key3': 'Hello World!!'
}

# JSONデータをリクエストボディに含めてPOSTリクエストを送信
response = requests.post(url, json=data)

# レスポンスのステータスコードと内容を表示
print('Status Code:', response.status_code)
print('Response JSON:', response.json())

 

 

 

 

GASでパラメタを受け取る

e.parameterでパラメタを受け取ることができる。

 

以下は「inval」という名前のパラメタを受け取っている。

パラメタ名は任意の値をつけてよい。

 

//HTTP GETをハンドリングする
function doGet(e) {

    // 値を設定する   
    value = "hoge ???"
    numval = "123456789"

   // パラメタを受け取る(invalというパラメタ名)
    var text = e.parameter.inval;

    // 結果セットを作る
    var result = {
     message: value,
     num: numval,
     val: text
    }


    var out = ContentService.createTextOutput();

    //Mime TypeをJSONに設定
    out.setMimeType(ContentService.MimeType.JSON);

    //JSONテキストをセットする
    out.setContent(JSON.stringify(result));

    return out;
}

 

 

 

呼び出すときは以下のように?パラメタ名=値を記述する

url ='https://script.google.com/macros/XXXXXX/exec?inval=9998'