この記事について
AWSのサービスをローカルで実行できるLocalStackについて紹介したいと思います。今回、AWS CLIの練習も兼ねてLocalStackを使用し、ローカルでAWS LambdaとS3を立ち上げ、Lambda関数を使用し、S3に日時.txtファイルをアップロードしてみました。
記事の対象者
- LocalStackに興味のある方
- AWS・AWS CLIに触れてみたい方
LocalStackとは
開発環境において無料でAWSのアカウント登録なしでAWSのサービスを擬似的に使用できるモックフレームワークでpipやdockerを用いて簡単に環境構築が可能。
ローカルにAWS環境を作ってくれて、料金などを気にすることなくテストや動作確認が可能である。
LocalStackは無料版と有料版がある。1 有料版は無料版に加え、高度なサービスをサポート。以下にLocalStackのサービスを示す。2(2021年10月時点)
無料 | 有料 |
---|---|
ACM API Gateway CloudFormation CloudWatch CloudWatchLogs DynamoDB DynamoDB Streams EC2 Elasticsearch Service EventBridge Firehose IAM Kinesis KMS Lambda Redshift Route53 S3 SecretsManager SES StepFunctions STS |
Amplify AppConfig Application AutoScaling AppSync Athena Backup Batch CloudFront CloudTrail CodeCommit Cognito Identity ECR ECS EKS ElastiCache EMR Glue IoT (including IoT Analytics, IoT Data) Managed Streaming for Kafka (MSK) Neptune DB QLDB RDS / Aurora Serverless SageMaker Timestream Transfer XRay |
構築環境
Windows10上でWSL2をインストールし、WSL2上でUbuntuを動かした。
Ubuntu 20.04 LTS
docker 20.10.8
localstack 0.11.0
aws cli 1.18.69
構築環境のイメージ
以下を参考にWSL2、Ubuntu、Dockerの環境を構築した。
構成図
LocalStack上でS3、Lambdaを立ち上げ、S3に接続し、日時.txtファイルを作成する。
事前準備
AWS CLIの設定
AWS CLIとは
AWS Command Line Interface(AWS CLI)は、AWSをコマンド入力で操作できるようにするインターフェースである。
AWS CLIのメリットは、GUIで行っていた操作を自動化できる点である。自動化することで、業務効率化ができヒューマンエラーを減らすことが可能。
LocalStackでも様々な用途でAWS-CLIを利用可能。
AWS CLIのインストール
sudo apt install awscli
AWS CLIがインストールできたか確認
$ aws --version
aws-cli/1.18.69 Python/3.8.10 Linux/5.10.16.3-microsoft-standard-WSL2 botocore/1.16.19
LocalStack用のプロファイルを作成
ローカルで使うだけなのでダミーの設定
$ aws configure --profile localstack
AWS Access Key ID [None]: dummy
AWS Secret Access Key [None]: dummy
Default region name [None]: us-east-1
Default output format [None]: json
# id,keyの確認
$ cat ~/.aws/credentials
[localstack]
aws_access_key_id = dummy
aws_secret_access_key = dummy
# region,outputの確認確認
$ cat ~/.aws/config
[profile localstack]
region = us-east-1
output = json
LocalStackの設定
githubからLocalStackをクローン
GitHubからLocalStack環境一式をダウンロード。
git clone https://github.com/localstack/localstack.git
cd localstack
docker-compose.ymlを編集
クローンしてきたdocker-compose.yml
にLAMBDA_DOCKER_NETWORK=host
とLAMBDA_EXECUTOR=docker-reuse
を追記
version: "3"
services:
localstack:
image: localstack/localstack:latest
ports:
- "4566:4566"
environment:
- SERVICES=${SERVICES- }
- DEBUG=${DEBUG- }
- DATA_DIR=${DATA_DIR- }
- PORT_WEB_UI=${PORT_WEB_UI- }
- KINESIS_ERROR_PROBABILITY=${KINESIS_ERROR_PROBABILITY- }
- DOCKER_HOST=unix:///var/run/docker.sock
- LAMBDA_DOCKER_NETWORK=host
- LAMBDA_EXECUTOR=docker-reuse
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
-
ports
- サービスごとにポートが指定されていたが、LocalStackのバージョン
v0.11.00
以降は4566
番ポートのみを介して提供(有料版のWebUIのみ8080
番が利用可能) - ポート番号は
EDGE_PORT
で指定することで変更可能 - サービスごとには
<SERVICE名>_PORT_EXTERNAL
でポートを指定することも可能
- サービスごとにポートが指定されていたが、LocalStackのバージョン
-
SERVICES
- LocalStackで起動するサービスはSERVICESで指定
-
DATA_DIR
- 永続化データを保存するディレクトリを指定
- 本記事の執筆時点では、下記のサービスが永続化対象
- Kinesis
- DynamoDB
- Elasticssearch
- S3
- Secretmanager
- SSM
- SQS
- SNS
-
KINESIS_ERROR_PROBABILITY
:-
ProvisionedThroughputExceededException
エラーをKinesis APIの応答にランダムに挿入する
-
-
LAMBDA_EXECUTOR
- デフォルトは
docker
で、Dockerが利用できない場合はlocal
-
local
:ローカルマシン上でLambda関数を実行する -
docker
:各Lambda関数呼び出しを別のdockerコンテナで呼び出し実行する -
docker-reuse
:Lambda関数ごとに1つのdockerコンテナを作成し、再利用し実行する。
LocalStack上では、Lambda関数ごとにdockerコンテナが作成され、同じLambda関数を実行するたびにコンテナが作成されるのを防ぐために、
docker-reuse
を指定 - デフォルトは
-
LAMBDA_DOCKER_NETWORK
- Lambda関数を実行するコンテナのネットワークを指定
- LocalStack上のコンテナで実行するようにするために
LAMBDA_DOCKER_NETWORK=host
とした。 - これの設定をしないとLambda関数を実行した際に、後述のエラーが出た。
LocalStackの起動
$ docker-compose up -d
Creating network "localstack_default" with the default driver
Creating localstack_localstack_1 ... done
http://localhost:4566/health
にアクセスするとサービスが立ち上がったかどうか確認可能(runningであれば起動済み)
S3の設定
S3とは
S3とはAWSのサービスのひとつで、「Amazon Simple Storage Service」の略称。
オブジェクトのファイル単位での出し入れが可能なので、その場に応じて自由な使い道が想定され、より柔軟なデータ保存が実行できるのが特徴となっている。
以下のようなS3のメリットが挙げられる。
- 柔軟に対応可能なストレージ機能
- 耐久性と可用性
- AWSのS3ではすべてのオブジェクトに対して99.999999999% (9 x 11)の耐久性を実現
- 低コストによる運用が可能
S3バケットの作成
以下のコマンドでLocalstack内にバケットを作成
オプションで--endpoint-url=http://localhost:4566
とすることでLocalStack上で作成できる。
$ aws --endpoint-url=http://localhost:4566 --profile localstack s3api create-bucket --bucket test-bucket
{
"Location": "/test-bucket"
}
S3バケットの確認
以下のコマンドでバケット一覧を確認できる。先程作成したtest-bucket
が表示されればOK
$ aws s3 ls --endpoint-url=http://localhost:4566 --profile localstack
2021-09-17 11:02:26 test-bucket
Lambda関数の設定
Lambdaとは
Lambdaはサーバレスコンピューティングサービスである。
サーバレスという言葉となっているが、稼働するサーバが無いというわけではなく、
AWS側で実行するサーバが管理されていることから、ユーザが意識して管理するサーバが無いという意味である。
OSなどのインフラストラクチャの管理が不要で、利用者はプログラムコードを準備し、Lambdaにアップロードするだけで実行可能。
現時点でLambdaは次の言語をサポートしている。
- Node.js
- Python
- Ruby
- GO
- java
- PowerShell
- C#
Lambda関数作成
import boto3
from boto3.session import Session
from datetime import datetime
session = Session(aws_access_key_id='dummy',
aws_secret_access_key='dummy',
region_name='us-east-1'
)
s3 = session.resource(
service_name='s3',
endpoint_url='http://localhost:4566'
)
def lambda_handler(event, context):
bucket = 'test-bucket' # バケット名を指定
key = datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.txt'
file_contents = 'Lambda Save File'
s3.Bucket(bucket).put_object(Key=key, Body=file_contents)
return 'create file'+ key
lambda.pyをzipファイルに圧縮
$ zip lambda.zip lambda.py
adding: lambda.py (deflated 42%)
LocalStack上でLambda関数作成
aws --endpoint-url=http://localhost:4566 lambda create-function --function-name test --runtime python3.8 --handler lambda.lambda_handler --role r1 --zip-file fileb://lambda.zip --region us-east-1 --profile localstack
{
"FunctionName": "test",
"FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:f1",
"Runtime": "python3.8",
"Role": "r1",
"Handler": "lambda.lambda_handler",
"CodeSize": 285,
"Description": "",
"Timeout": 3,
"LastModified": "2021-09-17T05:26:23.710+0000",
"CodeSha256": "XfGpeloNrfmdJSseF9lbxrIgTI68G1hSmEpotNGZi0g=",
"Version": "$LATEST",
"VpcConfig": {},
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "90c9bd95-e63e-4bec-adfa-c8aed74c3499",
"State": "Active",
"LastUpdateStatus": "Successful"
}
今回は以下のように設定
-
function-name
:test
関数名 -
runtime
:Python3.8
使用するプログラミング言語 -
handler
:lambda.lambda_handler
関数のハンドラー名<モジュール名>.<エントリー関数> -
zip-file
:lambda.zip
zip圧縮したプログラムファイルのパス -
role
:r1
任意に設定可能で、ロールの作成は必須ではない -
profile
:localstack
事前準備で作成したプロファイル名
Lambda関数の実行
$ aws lambda --endpoint-url=http://localhost:4566 invoke --function-name test --profile localstack result.log
{
"StatusCode": 200,
"LogResult": "",
"ExecutedVersion": "$LATEST"
}
Lambda関数の実行自体が成功した場合、ステータスコードが200となる。
関数がエラーを返した場合もステータスコードは200を返すため、result.log
の確認が必要
Lambda関数を実行するたびにコンテナが起動し作成されていることがわかる。
Ubuntu上での確認
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1eb4639961f4 lambci/lambda:python3.8 "/bin/bash" 7 seconds ago Up 6 seconds localstack_lambda_arn_aws_lambda_us-east-1_000000000000_function_test
ecb128220fd6 localstack/localstack:latest "docker-entrypoint.sh" 3 days ago Up 2 hours 4571/tcp, 0.0.0.0:4566->4566/tcp, :::4566->4566/tcp, 5678/tcp localstack_localstack_1
result.logファイルの確認
成功した場合の出力例
$ cat result.log
"create file 2021-09-21-05-14-50.txt"
エラーが出た場合の出力例
{"errorMessage":"Lambda process returned with error. Result: {\"errorType\":\"EndpointConnectionError\",\"errorMessage\":\"Could not connect to the endpoint URL: ...(省略)
解決策
docker-compose.yml
に LAMBDA_DOCKER_NETWORK=host
を追記
S3にアップロードできているか確認
$ aws s3 ls --endpoint-url=http://localhost:4566 test-bucket --profile localstack
2021-09-21 14:02:11 16 2021-09-21-14-02-11.txt
S3に2021-09-21-14-02-11.txt
がアップロードされていることがわかる。
おわりに
今回は、一部となりますが、LocalStackの簡単な使い方を紹介しました。
実際に触ってみて、AWSサービスをAWSのアカウント登録なしで、触ることができるので、テストや動作確認の際に便利だと感じました。
これからAWSを触りたい方やAWS CLIの勉強をしたい方の練習環境としても手軽に利用することができます。
個人的には、AWSの資格試験があるので、勉強も兼ねて色々触ってみようと思いました!
LocalStackには、今回紹介したS3やLambda以外にもAWSのサービスが利用できるので
ぜひLocalStackで構築してみてください!
参考
https://bsblog.casareal.co.jp/archives/5571
https://aimstogeek.hatenablog.com/entry/2020/08/03/080000
https://arailly.hatenablog.com/entry/2020/04/29/153822
https://tech.unifa-e.com/entry/2020/12/16/080000