Lambdaで何かをするときチマチマAWSコンソールを触らないといけないとなると面倒すぎる。
ローカルでデバッグ・デプロイできるとかなり楽になる。AWS SAMを使ってみる。
AWS SAM(Serverless Application Model)。広くAWSのServerlessサービスがまとめられている。
AWS SAM CLIのGAは2020年8月。それから何回かアップデートされている。
AWS SAMの実体はCloudFormation。CloudFormationを使ってリソースの構築が走る。
普段CloudFormationを使っていないとSAMのコマンドがコケた時に意味不明なエラーで悩むことになる。
で、悩みながらHelloWorldしてみた。
Permissions
CloudFormationで各種リソースを作る仕組みであるため、同等のPermission設定が必要。
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-permissions.html
AWS SAM は、AWS リソースへのアクセスを制御するために、AWS CloudFormation と同じメカニズムを使用します。詳細については、AWS CloudFormation ユーザーガイドの「Controlling access with AWS Identity and Access Management」を参照してください。
サーバーレスアプリケーションを管理するためのユーザー権限の付与には、3 つの主なオプションがあります。各オプションは、ユーザーに異なるレベルのアクセスコントロールを提供します。
– 管理者権限を付与する。
– 必要な AWS 管理ポリシーをアタッチする。
– 特定の AWS Identity and Access Management (IAM) 許可を付与する。
必要な管理ポリシーは以下。
- AWSCloudFormationFullAccess
- IAMFullAccess
- AWSLambda_FullAccess
- AmazonAPIGatewayAdministrator
- AmazonS3FullAccess
- AmazonEC2ContainerRegistryFullAccess
触るユーザーにロールを割り当て、上記の管理ポリシーをアタッチしておくこと。
aws configureでprofileを設定しておいて、samコマンドのオプションにprofileを渡せる。
インストール
homebrewでインストール。
1 2 3 4 |
$ brew tap aws/tap $ brew install aws-sam-cli $ sam --version SAM CLI, version 1.37.0 |
初期化
sam initでプロジェクトディレクトリを作成できる。
対話的に雛形を作るか、またはテンプレートを読み込む。
Lambdaで使える言語は割と多いが、NodejsとPythonがほとんどとのこと。
NodejsがMost popular runtimeとして扱われてるんだな。
Python書きたくないなというか。all right
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
$ mkdir samtest && cd samtest $ sam init Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Cloning from https://github.com/aws/aws-sam-cli-app-templates Choose an AWS Quick Start application template 1 - Hello World Example 2 - Multi-step workflow 3 - Serverless API 4 - Scheduled task 5 - Standalone function 6 - Data processing 7 - Infrastructure event management 8 - Machine Learning Template: 1 Use the most popular runtime and package type? (Nodejs and zip) [y/N]: y Project name [sam-app]: ----------------------- Generating application: ----------------------- Name: sam-app Runtime: nodejs14.x Architectures: x86_64 Dependency Manager: npm Application Template: hello-world Output Directory: . Next steps can be found in the README file at ./sam-app/README.md |
プロジェクト内は以下のような構成となった。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
sam-app/ │ .gitignore │ README.md │ template.yaml ├─events │ event.json └─hello-world │ .npmignore │ app.js │ package.json └─tests └─unit test-handler.js |
app.jsがコード本体. Hello World.が書かれている。
eventを受け取るlambdaHandlerというアロー関数があって200を返してる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// const axios = require('axios') // const url = 'http://checkip.amazonaws.com/'; let response; /** * * Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format * @param {Object} event - API Gateway Lambda Proxy Input Format * * Context doc: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html * @param {Object} context * * Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html * @returns {Object} object - API Gateway Lambda Proxy Output Format * */ exports.lambdaHandler = async (event, context) => { try { // const ret = await axios(url); response = { 'statusCode': 200, 'body': JSON.stringify({ message: 'hello world', // location: ret.data.trim() }) } } catch (err) { console.log(err); return err; } return response }; |
ビルド
そもそもどういう仕組みなのかというと、Lambdaの実行環境をエミュレートしたコンテナが背後にあり、
その中でコードを実行する、ということになっている。それがゴニョゴニョと隠蔽されている。
Lambda関数のコードをビルドしてデプロイ用の「アーティファクト」を作る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ sam build Building codeuri: /Users/ikuty/ikuty/samtest/sam-app/hello-world runtime: nodejs14.x metadata: {} architecture: x86_64 functions: ['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 [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch [*] Deploy: sam deploy --guided |
ローカルで実行
そしてローカルで実行。
Lambdaをエミュレートするコンテナが動いてapp.jsにあるアロー関数が評価される。
1発目は重いが2発目以降は結構速い。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ sam local invoke Invoking app.lambdaHandler (nodejs14.x) Image was not found. Removing rapid images for repo public.ecr.aws/sam/emulation-nodejs14.x Building image..................................................................................................................................................................................................................................................................................................................................................................................................................... Skip pulling image and use local one: public.ecr.aws/sam/emulation-nodejs14.x:rapid-1.37.0-x86_64. Mounting /Users/ikuty/ikuty/samtest/sam-app/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container START RequestId: e0bbec88-dafd-4e3c-8b5e-5fcb0f38f1fa Version: $LATEST END RequestId: e0bbec88-dafd-4e3c-8b5e-5fcb0f38f1fa REPORT RequestId: e0bbec88-dafd-4e3c-8b5e-5fcb0f38f1fa Init Duration: 0.47 ms Duration: 195.40 ms Billed Duration: 196 ms Memory Size: 128 MB Max Memory Used: 128 MB {"statusCode":200,"body":"{\"message\":\"hello world\"}"}⏎ |
デプロイ
以前はもっと面倒だったらしい。新しいSAMではコマンド1発でデプロイできる。
ただし、1回目と2回目以降でフローが異なる。
1回目ではsamconfig.tomlという設定ファイルを作成する。
2回目以降、作成済みのsamconfig.tomlを使ってデプロイが行われる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
$ sam deploy -g Configuring SAM deploy ====================== Looking for config file [samconfig.toml] : Not found Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app]: AWS Region [ap-northeast-1]: #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: y #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: y #Preserves the state of previously provisioned resources when an operation fails Disable rollback [y/N]: y HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y Save arguments to configuration file [Y/n]: y SAM configuration file [samconfig.toml]: SAM configuration environment [default]: Looking for resources needed for deployment: Creating the required resources... Successfully created! Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-h0aw0pxx8pxv A different default S3 bucket can be set in samconfig.toml Saved arguments to config file Running 'sam deploy' for future deployments will use the parameters saved above. The above parameters can be changed by modifying samconfig.toml Learn more about samconfig.toml syntax at https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html ... (省略) |
最後の文節にあるように、samconfig.tomlを変更することで構成を変更できる。
この後、実際にCloudFormationスタックのアップロード/実行が走りリソースが組み上がる。
2回目以降、-gオプション抜きでsam deployを実行すると以下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ sam deploy File with same data already exists at sam-app/e32dcdf231268fbcad9915436e787001, skipping upload Deploying with following values =============================== Stack name : sam-app Region : ap-northeast-1 Confirm changeset : True Disable rollback : True Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-h0aw0pxx8pxv Capabilities : ["CAPABILITY_IAM"] Parameter overrides : {} Signing Profiles : {} Initiating deployment ===================== File with same data already exists at sam-app/9a813032a850e5b7fb214dffc5ac5783.template, skipping upload Waiting for changeset to be created.. Error: No changes to deploy. Stack sam-app is up to date |