localstackを用いてlambdaとrdsを作成してみる
対戦よろしくお願いします
$ brew install localstack/tap/localstack-cli
$ localstack --version
3.3.0
localstack start
これだけで立ち上がった。便利。
次にawscli-localを入れる。これを使えばいちいちパラメータを指定しなくてもlocalstackを見に行ってくれるみたい。
awscli-local --version
とやらないように注意(2敗)
$ brew install awscli-local
$ awslocal --version
aws-cli/2.9.12 Python/3.9.11 Darwin/23.2.0 exe/x86_64 prompt/off
動作確認
あとは基本的にawsコマンドと一緒。下記ドキュメントとにらめっこする
試しにs3周りを作ってみる
$ awslocal s3 mb s3://sample
make_bucket: sample
$ awslocal s3 cp ./tmp/hoge s3://sample/
upload: tmp/hoge to s3://sample/main.go
http://localhost:4566/sample/hoge
にアクセスすると取得できた。
lambda
注意点
- zip-fileに渡すのはただのパスではなく、fileb://{file_to_path}の形
-
fileb://
形式で渡すことでバイナリデータであることを明示する - https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-usage-parameters-file.html#cli-usage-parameters-file-binary
-
- roleに渡すのは適当な値でokだが、
arn:(aws[a-zA-Z-]*)?:iam::\d{12}:role/?[a-zA-Z_0-9+=,.@\-_/]+
の形じゃないと怒られる
$ awslocal lambda create-function --function-name auto_webscraping --zip-file fileb://my_deployment_package.zip --handler lambda_function.lambda_handler --runtime python3.9 --role arn:aws:iam::000000000000:role/sample
$ awslocal lambda list-functions
{
"Functions": [
{
"FunctionName": "auto_webscraping",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:000000000000:function:auto_webscraping",
"Runtime": "python3.9",
"Role": "arn:aws:iam::000000000000:role/sample",
"Handler": "lambda_function.lambda_handler",
"CodeSize": 21047848,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2024-04-04T10:31:34.442756+0000",
"CodeSha256": "cxvt7LM6DLhvHZgF2pG47yC5hm9fi2GQg4K2/dk5Tow=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "ae9e975c-44ba-4853-88f8-9ac30b6a6b4b",
"PackageType": "Zip",
"Architectures": [
"x86_64"
],
"EphemeralStorage": {
"Size": 512
},
"SnapStart": {
"ApplyOn": "None",
"OptimizationStatus": "Off"
}
}
]
}
思ったより簡単にできた。localstackすごい。
次に実行環境を作成する
involeで実行できる:
$ awslocal lambda invoke --function-name arn:aws:lambda:ap-northeast-1:000000000000:function:auto_webscraping ./result.txt
{
"StatusCode": 200,
"FunctionError": "Unhandled",
"ExecutedVersion": "$LATEST"
}
200で帰ってきているため、実行はできてそうだが Unhandled
エラーが発生している。
outfile で指定したresult.txt を確認する。
$ cat result.txt
{"errorMessage": "'bucket'", "errorType": "KeyError", "requestId": "efd78967-e1ad-4142-9283-298ad3f886d6", "stackTrace": [" File \"/var/task/lambda_function.py\", line 93, in lambda_handler\n bucket = event[\"bucket\"]\n"]}
lambda内にinputを渡せていないのが原因。
$ awslocal lambda invoke --function-name arn:aws:lambda:ap-northeast-1:000000000000:function:auto_webscraping --payload '{"bucket":"nii-local"}' ./result.txt
Invalid base64: "{"bucket":"nii-local"}"
base64形式で渡せとのこと。
$ awslocal lambda invoke --function-name arn:aws:lambda:ap-northeast-1:000000000000:function:auto_webscraping --payload $(echo '{"bucket":"nii-local"}' | base64 ) ./result.txt
ついでに環境変数もやる
$ awslocal lambda update-function-configuration --function-name auto_webscraping --environment '{"Variables":{"hoge":"piyo"}}'
{
"FunctionName": "auto_webscraping",
...(略)
"Environment": {
"Variables": {
"hoge": "piyo"
}
},
...(略)
}
これで動いた。
次はつなぎ込みを行うRDSを立ち上げる。
memo: lambda更新したらどうやってuploadするのん
こいつでいけそう
RDS
ここみるよ
$ awslocal rds create-db-cluster --db-cluster-identifier rds-local --engine mysql --engine-version 8.0 --database-name english_frequency --master-username hoge --master-user-password hoge
An error occurred (InternalFailure) when calling the CreateDBCluster operation: API for service 'rds' not yet implemented or pro feature - please check https://docs.localstack.cloud/references/coverage/ for further information
pro買えってさ。解散。終わり。終了。完。
API for service 'rds' not yet implemented or pro feature
というわけにもいかないので、localstack EC2にMySQL入れるか、local環境のmysqlに接続するようにしたい。今回は後者で。
別のmysqlコンテナを立ち上げてみる
docker-compose.ymlに追記した方が早かった
version: '3'
services:
mysql:
image: mysql:8.2.0
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: xxxx
MYSQL_PASSWORD: xxxx
MYSQL_ROOT_PASSWORD: xxxx
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME:-localstack-main}"
image: localstack/localstack
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
- "127.0.0.1:4510-4559:4510-4559" # external services port range
environment:
# LocalStack configuration: https://docs.localstack.cloud/references/configuration/
- DEBUG=${DEBUG:-0}
volumes:
- "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
あとはlambda batchに渡すhostをmysql
にすればOK!
私のlambdaソースは環境変数から取得するようにしているので、下記のようにlambdaを修正。ついでにタイムアウトも伸ばしまくり
awslocal lambda update-function-configuration --function-name auto_webscraping --environment '{"Variables":{"host":"mysql"}}' --timeout 300