こんにちは。morizoです。
もともとwebアプリケーションエンジニアとして入社しましたが、ココ一年くらいはAWSを利用したサーバ運用やセキュリティ面の強化に取り組んでいます。
さて、チーム内で共有してる手順書をもとに日頃の運用業務を進めていると
作成日の古い手順書がUIの変更に追いついておらず、混乱することが多々あります。
近頃はメンバー内でも「AWS CLIつかっていこう」という機運が高まっておりますが、
あまり気楽に試せる環境がないことが悩みのタネになっています。
そこで、今回はLocalStackを利用してローカル環境でAWSサービスを動かしてみようと思います。
無料版だとCLIの操作のみに制限されているため、CLI操作の練習にもなりますね。
※執筆中にちょうど正式版がリリースされました
LocalStack導入とその動作検証
LocalStackのインストールと起動
githubで公開されていますのでこちらからcloneしてきます。
今回はお試しということもあり、Docker経由で起動します。
また、clone後にdocker-compose.ymlを一部編集しました。(編集箇所にコメントを追加しています)
環境変数についてはこちらにまとまっています。
version: "3.8" services: 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 - "127.0.0.1:53:53" # DNS config (only required for Pro) - "127.0.0.1:53:53/udp" # DNS config (only required for Pro) - "127.0.0.1:443:443" # LocalStack HTTPS Gateway (only required for Pro) environment: - DEBUG=${DEBUG-} - PERSISTENCE=${PERSISTENCE-} # Lambda関数実行のたびに同じコンテナを再利用する - LAMBDA_EXECUTOR=docker-reuse - LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY-} # only required for Pro - DOCKER_HOST=unix:///var/run/docker.sock # Lambda関数をコンテナにマウントすることで処理が早くなる場合がある(ローカル環境向け) - LAMBDA_REMOTE_DOCKER=0 volumes: - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" - "/var/run/docker.sock:/var/run/docker.sock"
どのようなことができる?
ここから実際にコンテナに入って作業をしてみます。
コンテナ内ではawslocalコマンドが使用できるので簡単のために使用しています。
まずはs3バケットを作成してみました。
※以後コマンドの行頭に実行環境を補足しています
(host) docker exec -it localstack_main bash (container) awslocal s3api create-bucket --bucket morizo-s3 { "Location": "/morizo-s3" } (container) awslocal s3api list-buckets { "Buckets": [ { "Name": "morizo-s3", "CreationDate": "2022-07-ddThh:00:00.000Z" } ], "Owner": { "DisplayName": "webfile", "ID": "XXXXXXXXXXXXXXXXXXXXXXXXXXX" } }
できていますね。
続いてLambdaを実行してみます。
以下ファイルをローカルで用意してコンテナ内にコピーしました。
def handler(event, context): print(event) return 'localstackはじめました'
作成したファイルをzip形式に圧縮して、Lambda関数を作成します。
※roleに指定する値は任意で問題ありません。
(container) zip localstack.zip localstack.py (container) awslocal lambda create-function --function-name localstack --runtime python3.8 --role morizo --handler localstack.handler --zip-file fileb://localstack.zip { "FunctionName": "localstack", "FunctionArn": "arn:aws:lambda:us-east-1:000000000000:localstack", "Runtime": "python3.8", "Role": "morizo", "Handler": "handler.handler", ~ "LastUpdateStatus": "Successful", "PackageType": "Zip", "Architectures": [ "x86_64" ] }
Successfulとあるのでどうやらうまくいったようです。
それでは実行してみます。
(container) awslocal lambda invoke --function-name localstack output.log { "StatusCode": 200, "LogResult": "", "ExecutedVersion": "$LATEST" }
200で返ってきました。
中身をみてみましょう。
(container) cat output.log "localstack\u306f\u3058\u3081\u307e\u3057\u305f" (container) echo -e `cat output.log` "localstackはじめました"
unicode表示になっていたのでcatだけではうまく表示できませんでしたが、
コード内でreturnした文字列がファイルに出力されていることを確認できました。
簡単な関数なら充分やっていけそうです。
ほかのサービスとも組み合わせてみたい
固定の文字列を返すだけでは少し味気ないので、
ほかのサービスを組み合わせた処理を書いてみます。
「cloudwatch logsに保管したログをs3にエクスポート」してみましょう。
まずはlogsにlog groupとlog streamを追加します。
(container) awslocal logs create-log-group --log-group-name morizo-logs (container) awslocal logs create-log-stream --log-group-name morizo-logs --log-stream-name morizo-logs-stream
logsに追加するログはこちらです。
{ "logEvents":[ { "timestamp": 1658746080711, "message": "Example Event 1" }, { "timestamp": 1658746081711, "message": "Example Event 2" }, { "timestamp": 1658746082711, "message": "Example Event 3" } ] }
こちらのログをlogsに作成したlogstreamに追加します。
(container) awslocal logs put-log-events --log-group-name morizo-logs --log-stream-name morizo-logs-stream --cli-input-json file://logs.json (container) awslocal logs get-log-events --log-group-name morizo-logs --log-stream-name morizo-logs-stream { "events": [ { "timestamp": 1658746080711, "message": "Example Event 1", "ingestionTime": 1658758594869 }, { "timestamp": 1658746081711, "message": "Example Event 2", "ingestionTime": 1658758594869 }, { "timestamp": 1658746082711, "message": "Example Event 3", "ingestionTime": 1658758594869 } ], "nextForwardToken": "f/00000000000000000000000000000000000000000000000000000001", "nextBackwardToken": "b/00000000000000000000000000000000000000000000000000000000" }
こちらも無事に追加できました。
ではこのログをs3にエクスポートするLambda関数を実行してみましょう。
以下pythonコードを用意しました。
import boto3 def handler(event, context): client = boto3.client('logs', endpoint_url='http://host.docker.internal:4566', region_name = "us-east-1", aws_access_key_id='dummy', aws_secret_access_key='dummy') return client.create_export_task( logGroupName = 'morizo-logs', fromTime = 1658746080000, to = 1658750400000, destination = 'morizo-s3', destinationPrefix = 'localstack' )
挙動確認用に使用したLambda関数と同様にzipファイルを作成して登録・実行します
(container) awslocal lambda create-function --function-name create_export_task --runtime python3.8 --role morizo --handler create_export_task.handler --zip-file fileb://create_export_task.zip (container) awslocal lambda invoke --function-name create_export_task output.log (container) cat output.log | jq { "ResponseMetadata": { "HTTPHeaders": { "access-control-allow-headers": "authorization,cache-control,content-length,content-md5,content-type,etag,location,x-amz-acl,x-amz-content-sha256,x-amz-date,x-amz-request-id,x-amz-security-token,x-amz-tagging,x-amz-target,x-amz-user-agent,x-amz-version-id,x-amzn-requestid,x-localstack-target,amz-sdk-invocation-id,amz-sdk-request", "access-control-allow-methods": "HEAD,GET,PUT,POST,DELETE,OPTIONS,PATCH", "access-control-allow-origin": "*", "access-control-expose-headers": "etag,x-amz-version-id", "content-length": "50", "content-type": "application/x-amz-json-1.1", "date": "aaa, dd Jul 2022 00:00:00 GMT", "server": "amazon.com, hypercorn-h11" }, "HTTPStatusCode": 200, "RetryAttempts": 0 }, "taskId": "XXXXXXXXXXXXXXXXXXXXXXXXX" }
ステータスコード200とtaskidが返ってきました!
確認のためにs3バケットをみてみます。
(container) awslocal s3 ls s3://morizo-s3 --recursive # 表示なし
おや、ステータスは200にはなっているけどオブジェクトがありません。
作成していないロググループやバケット名を指定するとエラーになるため、
コマンド自体は成功していますがログファイルがS3にエクスポートされていないようです。
こちらについては次回以降改めて挑戦してみます。
まとめ
さらなる調査は必要ですが、LocalStackを使ってDockerコンテナ上でLambda関数を実行するところまでできました。
無料版でも利用できるAWSサービスが数多くありますし、
業務で実際に活用できるLambda関数の動作確認をローカル環境でも一通りできるのではないでしょうか?
正式版リリースによって今後更に勢いづいてくるかと思いますので
更新情報を追っていきつつ、よりよいローカルでの開発・検証環境構築も進めていきたいです。
おわりに
☆スタイル・エッジ・グループでは、一緒に働く仲間を募集しています☆
もし興味を持っていただけましたら、採用サイト↓も覗いてみてください!
recruit.styleedge-labo.co.jp