目次
はじめに
こんにちは、株式会社エーピーコミュニケーションズ クラウド事業部の佐藤です。 私は2025年2月にAPCに中途入社いたしました。前職ではAzureをメインに触っていたのですが、今後AWSを触る機会が多くなりそうなので早速AWSに触れてみて力を身に着けていこうと思います。
AWSを触ってみたい、Lambdaを触ってみたい、PythonでLambda動かしてみたいなど、初心者の方の第一歩の一助になれば幸いです。
この記事のゴール
- AWSのLambdaにPythonで実装したHello World相当のソースコードをデプロイし、HTTPで結果の取得ができることを確認する。
- Lambda上でpandas(外部モジュール)をimportする
- 外部モジュールをどのように使用可能にするのか確認するため
- URLクエリパラメーターで操作内容が分岐できるようにする
?control=hello
のときにHello Worldのメッセージをjsonで返却する?control=calc
のときにpandasを利用して足し算を行い結果をjsonで返却する- 今回の目的はpandasの動作確認のみのため、足し算に使用する数値はユーザーが入力する仕様ではなくハードコーディングをしておく。
- 今回は
10 + 123.456
を処理する
- Lambda上でpandas(外部モジュール)をimportする
作業の流れ
- Pythonのソースコードを実装
- AWS上でLambda関数の作成と設定
- Lambda関数の作成
- レイヤーの設定
- 関数URLの設定
- PythonソースコードをLambdaへデプロイ
- 動作確認
取り上げないこと
- API Managementやロードバランサーの設定など
- 今回は関数URLを使用して動作確認を行いました。
- 関数URLの認証
- 今回は動作確認のみのため認証は無効にして確認しました。
- zipファイルを用いたデプロイ、Pythonのレイヤー作成など
- 下記「ハマったこと」に記載したのですが今回は用意されているレイヤーを追加したので、zipファイルを用いたデプロイやレイヤーの作成は行いませんでした。
- 外部モジュールを手動でインストールする際には、Lambda関数のアーキテクチャとインストールするモジュールのアーキテクチャを合わせることに気を付けたほうがよさそうです。
作業
ハマったこと
作業全体を通じてハマったポイントを先に記載します。
zipファイルのデプロイについて docs.aws.amazon.com
- 閲覧日: 2025年2月18日
- 公式ドキュメントでは依存する外部モジュールをすべてzipファイルにまとめてデプロイする方法が記載されていますが、今回利用するpandasモジュールをこの方法でインストールしてからzipファイルにしてデプロイしようとすると容量が50MBを超えてしまうので失敗します。
- 解決策1. 用意されているレイヤーをLambda関数に追加する (この記事内で採用した方法)
- 今回利用するpandasはAWS上でレイヤーが用意されているので、それを追加するだけでLambda関数内でpandasが利用可能になります。
- 解決策2. レイヤーを自作する
- 今回は解決策1で解決したため使用しませんでしたが自分でレイヤーを作る方法もあるようです。 docs.aws.amazon.com
- AWS上でレイヤーが用意されていない外部モジュールを使いたいときはこちらの方法をとるほうが良さそうに見えます。(要調査)
- 解決策1. 用意されているレイヤーをLambda関数に追加する (この記事内で採用した方法)
- 余談: Azure Functionsだとrequirements.txtを置くだけでよかったので、AWSのほうが一手間かかりますね。。。
50MBを超えるzipファイルをアップロードしようとした際のエラー
AzureのようにVisial Studio Code上で操作が完結しない
- Azureの場合、VScodeの公式拡張機能を入れることでGUI上だけでデプロイできたりログが見れたりと色んな操作ができたのですが、AWSではできないようです(それはそうという話かもですが。。。)
- 以前はまったく気にしてなかったのですが、Azure(Microsoft)のプロダクトの強みを今さら感じているところです。。。
Pythonのソースコードを実装
docs.aws.amazon.com - 閲覧日: 2025年2月18日
- ゴールに到達できるように今回実装したソースコードは以下です。
import pandas as pd from typing import TypedDict class HelloWorldResult(TypedDict): """ ?control=helloの結果表示用 """ message: str class CalcResult(TypedDict): """ ?control=calcの結果表示用 """ value1: int value2: float answer: float def get_hello_world(event, context) -> HelloWorldResult: """ control=helloのときに実行される Hello Worldを返す """ result = HelloWorldResult( message='Hello World!' ) return result def get_calc_result(event, context) -> CalcResult: """ control=calcのときに実行される value1 = 10, value2 = 123.456を定義し、 pandasのDataFrameにしてから足し算した結果を返す """ # value1 と value2 を定義 value1: int = 10 value2: float = 123.456 # DataFrameを作成 data = {'Value1': [value1], 'Value2': [value2]} df = pd.DataFrame(data) # Value1 と Value2 を足し算 calc_result = (df['Value1'] + df['Value2']).iloc[0] result = CalcResult( value1=value1, value2=value2, answer=float(calc_result) ) return result def lambda_handler(event, context): """ Lambda関数のメイン部分 """ # クエリパラメータのチェック、controlが存在するか if not 'queryStringParameters' in event: return 'No query string' if not 'control' in event['queryStringParameters']: return 'No query string' control = event['queryStringParameters']['control'] # helloとcalc以外は何もしないで終了 if control == 'hello': return get_hello_world(event, context) elif control == 'calc': return get_calc_result(event, context) else: return 'Invalid query string' ###EOF
- 実装のポイント
ファイル名は
lambda_function.py
とし、メインとなる関数の名前はlambda_handler
とする。- 公式ドキュメントに記載のとおりこちらが標準設定なのですが、Lambdaのランタイム設定より任意のファイル名や関数名に変更できるようです。
- 公式ドキュメントより引用 (閲覧日: 2025年2月18日)
関数ハンドラーには任意の名前を付けることができますが、Lambda コンソールのデフォルト名は
lambda_function.lambda_handler
です。この関数ハンドラー名には、関数名 (lambda_handler) と、ハンドラコードが保存されているファイル (lambda_function.py) が反映されます。
URLクエリパラメーターはevent変数内の
queryStringParameters
に格納されるので、ここから取得する。 docs.aws.amazon.com- 今回の例では
control
を取得し、hello
のときとcalc
のときで処理を分岐させています。
- 今回の例では
- dict型の変数を返すことで、Lambda上ではjsonで取得が可能。
- ソースコード内ではTypedDictで定義しています。
AWS上でLambda関数の作成と設定
- AWSのコンソールからLambda関数を作成と設定を行います。
- Lambda関数の作成
- ランタイムは
Python 3.13
にする- 2025年2月18日時点の最新バージョンです。
- ランタイムは
- レイヤーの設定
- pandasを利用するために、Lambda関数のコンソールの「コード」タブの画面下部にある「レイヤー」で「レイヤーの追加」を行う。
- 「レイヤーを追加」の画面では「AWSレイヤー」を選択し、
AWSSDKPandas-Python313
を選択し追加する。Lambda関数へのレイヤーの追加画面 AWSSDKPandas-Python313のレイヤーを追加した状態
- 「レイヤーを追加」の画面では「AWSレイヤー」を選択し、
- pandasを利用するために、Lambda関数のコンソールの「コード」タブの画面下部にある「レイヤー」で「レイヤーの追加」を行う。
- 関数URLの設定
- HTTPでアクセスするために「設定」タブの「関数URL」より関数URLを作成する。
- 今回は簡単な動作確認のみのため「認証タイプ」は
NONE
を選択する NONE
にすると認証機能が無効になり、該当のLambda関数が外部に公開された状態になるようなので、セキュリティ上問題がないかちゃんと確認が必要です。- 作成した関数URLは動作確認で利用します。
- 今回は簡単な動作確認のみのため「認証タイプ」は
- HTTPでアクセスするために「設定」タブの「関数URL」より関数URLを作成する。
PythonのソースコードをLambdaへデプロイ
- Lambda関数画面のコードソース内に
lambda_function.py
を作成して、上記のソースコードを貼り付ける。 - Deployボタンを押す。
- デプロイする手段は色々あるようですが、今回はPythonのソースコードのファイルが1個だけなので、一番お手軽なコピペで対応しました。
ソースコードを貼り付けた状態。画面左部にDeployボタン。
- デプロイする手段は色々あるようですが、今回はPythonのソースコードのファイルが1個だけなので、一番お手軽なコピペで対応しました。
動作確認
ブラウザやcurlコマンドなどで関数URLにアクセスして動作確認をします。
- 関数URLのみの場合
https://[生成されたURL]/
No query string
?control=
を指定していないので実装した通りのエラーメッセージが表示される。
- helloの場合
https://[生成されたURL]/?control=hello
{"message":"Hello World!"}
?control=helloの結果
- calcの場合
https://[生成されたURL]/?control=calc
{"value2":123.456,"answer":133.45600000000002,"value1":10}
- 今回は特に対策をしていないのでpandas(numpy)の丸め誤差の影響から,
10 + 123.456
の答えが133.456
とはなっていないです。?control=calcの結果
ゴールに到達できました🎉
感想など
- 何もない状態で作業を始めてからゴールに到達するまで4時間程度かかりました。元々PythonやAzure (Azure Functions)を触っていたこともあり勘所がすぐに掴めたからか比較的スムーズにできたかと思っています。
- Serverlessは思いついてから実際に何かを動かすまでの敷居が低くて本当に素晴らしいですね。
- 今回はHello Worldをゴールとしましたが、AWS SDK for Python (boto3)を利用すると他のAWSリソースと連携してできることの幅が広がりそうなのでチェックしてみようと思います。 aws.amazon.com
- Node.js環境のTypeScript実装版もやってみたいです。