195
161

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

NRI OpenStandiaAdvent Calendar 2021

Day 13

LocalStackを使ってローカル環境でS3を立ち上げ、Lambdaでファイルをアップロードしてみた

Last updated at Posted at 2021-10-18

この記事について

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

構築環境のイメージ

環境構成.png

以下を参考にWSL2、Ubuntu、Dockerの環境を構築した。

構成図

LocalStack上でS3、Lambdaを立ち上げ、S3に接続し、日時.txtファイルを作成する。

Localstack構成図.png

事前準備

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.ymlLAMBDA_DOCKER_NETWORK=hostLAMBDA_EXECUTOR=docker-reuseを追記

docker-compose.yml
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でポートを指定することも可能
  • 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であれば起動済み)
health.png

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関数作成

lambda.py
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-nametest 関数名
  • runtimePython3.8 使用するプログラミング言語
  • handlerlambda.lambda_handler 関数のハンドラー名<モジュール名>.<エントリー関数>
  • zip-filelambda.zip zip圧縮したプログラムファイルのパス
  • roler1 任意に設定可能で、ロールの作成は必須ではない
  • profilelocalstack 事前準備で作成したプロファイル名

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ファイルの確認

成功した場合の出力例

result.log
$ cat result.log
"create file 2021-09-21-05-14-50.txt"

エラーが出た場合の出力例

result.log
{"errorMessage":"Lambda process returned with error. Result: {\"errorType\":\"EndpointConnectionError\",\"errorMessage\":\"Could not connect to the endpoint URL: ...(省略)

解決策
docker-compose.ymlLAMBDA_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

  1. https://localstack.cloud/pricing/ より引用

  2. https://localstack.cloud/features/ より引用

195
161
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
195
161

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?