【AWS】SAM-CLIでサーバーレスアプリケーション② - Lambda関数のデプロイ -
SAMアプリケーションのデプロイは
ビルド → テスト(省略可) → パッケージング → デプロイ
の順に行います。
ビルド
アプリケーションをビルドする
sam build
$ sam build Building resource 'HelloWorldFunction' Running NodejsNpmBuilder:NpmPack Running NodejsNpmBuilder:CopyNpmrc Running NodejsNpmBuilder:CopySource Running NodejsNpmBuilder:NpmInstall Running NodejsNpmBuilder:CleanUpNpmrc Build Succeeded Built Artifacts : .aws-sam/build Built Template : .aws-sam/build/template.yaml Commands you can use next ========================= [*] Invoke Function: sam local invoke [*] Package: sam package --s3-bucket [yourbucket]
成功すると .aws-sam/ にビルドされたモジュールが生成されます。
次に必要なコマンドを教えてくれる。(Commands you can use next)
が、Invoke Functionはビルドしたアプリケーションをテスト実行してくださいと言っていますが、これに関してはすでに検証済み(と仮定して)なのでスキップします。
なので最後の行、sam packageでパッケージングを実行します。
パッケージング
sam packageコマンドでパッケージングを実行します。
オプション
options
- --template-file … template.yamlを指定
- --s3-bucket … パッケージのアップロード先(※Lambda関数のデプロイではない)
- --output-template-file … デプロイ用のテンプレートファイル
実行
sam package
$ sam package \ --template-file template.yaml \ --s3-bucket test-bucket \ --output-template-file packaged.yaml Unable to upload artifact hello-world/ referenced by CodeUri parameter of HelloWorldFunction resource. S3 Bucket does not exist. Execute the command to create a new bucket aws s3 mb s3://test-bucket
失敗です。S3にtest-bucketが無いのであらかじめ作っておきます。
$ sam package \ --template-file template.yaml \ --s3-bucket test-bucket \ --output-template-file packaged.yaml Successfully packaged artifacts and wrote output template to file packaged.yaml. Execute the following command to deploy the packaged template aws cloudformation deploy --template-file packaged.yaml --stack-name [YOUR STACK NAME]
成功しました。次にaws cloudformation deployでデプロイしろと言われるが、samでデプロイします。
やってることは同じはずです。
デプロイ
sam deployコマンドでデプロイする。
オプション
options
- --template-file パッケージングにより生成したテンプレートファイル
- --stack-name クラウドフォーメーションに登録するタスク名
※クラウドフォーメーションとはAWSの各サービスのリソース管理を行う。詳細は以下
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/Welcome.html
実行
sam deploy
$ sam deploy \ --template-file packaged.yaml \ --stack-name sam-test deploy command is called You must specify a region. You can also configure your region by running "aws configure".
失敗しました。regionを指定しないとダメらしいです。~/.aws/configにあるのに見てくれないのでしょうか。
$ sam deploy \ --template-file packaged.yaml \ --stack-name sam-test \ --region ap-northeast-1 Waiting for changeset to be created.. Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state Status: FAILED. Reason: Requires capabilities : [CAPABILITY_IAM
これも失敗です。アプリケーションをデプロイするときのIAMロールが必要なので付けろと言われます。
詳細は以下ですが、とりあえず言われた通りに付けてサイド実行します。
$ sam deploy \ --template-file packaged.yaml \ --stack-name sam-test \ --region ap-northeast-1 \ --capabilities CAPABILITY_IAM Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - sam-test
成功すると以下の名前でAWS上にLambda関数が登録されます。
[デプロイ時に指定したスタック名]-[template.yamlのResoucesに作った関数名]-[ハッシュ値(のようなもの)]
例) sam-test-HelloWorldFunction-F0RK3F1ALE8
動作確認
AWS上のLambda関数を叩いてみる
エンドポイントは以下の手順で確認できる。
AWSコンソール→サービス→Lambda→[デプロイしたLambda関数を開く]→APIゲートウェイ
$ curl -i https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello HTTP/2 200 content-type: application/json content-length: 25 x-amzn-requestid: xxxxx-xxxxx {"message":"hello world"}
ResponseヘッダーにあるrequestidはCloudWatchで検索してやると、そのトランザクションをひとまとめに検索できます。
CloudWatch
START RequestId: xxxxx-xxxxx Version: $LATEST END RequestId: xxxxx-xxxxx REPORT RequestId: xxxxx-xxxxx Duration: 89.87 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 75 MB Init Duration: 145.88 ms
トリガーの設定
トリガーを設定しないと意味が無いので任意のトリガーを設定します。
上記のAPIゲートウェイは前の記事にも書きましたが、1回確認したら消しとくと良いです。
もちろんtemplate.yamlから消してしまってもOKです。
トリガーに設定できるサービス
- API Gateway
- AWS IoT
- Alexa Skills Kit
- Alexa Smart Home
- Application Load Balancer
- CloudWatch Events
- CoudWatch Logs
- CodeCommit
- Cognito Sync Trigger
- DynamoDB
- Kinesis
- S3
- SNS
- SQS
※この他にもAmazonEventBridgeを使用して外部サービスと連携できるらしいです。
自分の場合はS3を選択したので、S3の場合の設定例が以下です。
- S3バケット … 任意のバケットを選択
- イベントタイプ … 全てのオブジェクト作成イベント
- プレフィックス … test_
- サフィックス … .txt
→トリガーの有効化にチェックを入れて追加する
これでS3の指定バケットに test_1234.txt などのファイルが作成された時にLambda関数が実行される用になりました。Lambda関数内では以下のコードで作成されたファイル名が取得できます。
var keyfile = event.Records[0].s3.object.key;
console.log('keyfile:' + keyfile);
※Lambda関数にトリガーとなったS3バケットに書き込みを行いたい場合は、Lambdaの実行ロールにその権限が必要になります。
権限がない場合、Lambda関数の中でConnection timedout.が発生します。(これで嵌った)
逆に言うと、アクセス権限がなくてもアップロードされたファイル名はevent変数から取得できます。
temlate.yamlの書き方
少し話が前後しますが、template.yamlの書き方について少し触れます。
前回の記事にも書きましたが、S3のイベントトリガーをtemplate.yamlに設定したかったんですが、うまくいかず断念...
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: menu-import/
Handler: app.lambdaHandler
Runtime: nodejs10.x
Timeout: 600
MemorySize: 512
Role: arn:aws:iam::000000000:role/test-sam-role
Events:
Environment:
Variables:
VAR_TEST: '{{resolve:ssm:/parameter-store/test:1}}'
書き方のポイント
- Properties.Timeout … Lambda関数のタイムアウトを秒で指定する
- Properties.MemorySize … Lambda関数のメモリーサイズをMBで指定する
※この設定がないとデプロイのたびに初期値に戻ってしまうため非常に面倒
- Properties.Role … Lambda関数を実行するのに使用するロールARNを指定する
- Environment.Variables … 環境変数VAR_TESTを宣言する
設定している値はパラメータストアから読み込んだ値が展開される
パラメータストアに環境毎の変数を設定しておけばLambda関数側では以下のコードで環境毎の値が受け取れる
var test = process.env.VAR_TEST; console.log('env:' + test);
コメント
コメントを投稿