コンテンツにスキップ

AWS の SAM をやってみる

S3 にある Excel や CSV を読んで、parquet を出力する Lamda を作りたい。

AWS コンソールへのログイン

久しぶりなので、root アカウントでログインしてみた。

  • コンソールログイン用のアカウント
  • amplify 用のアカウント

があった。

Lamda 関連の権限について

開発者

  • AWSLambda_ReadOnlyAccess: 見るだけ。実行もできない。
  • AWSLambdaRole: 実行権限のみ。
  • AWSLambda_FullAccess: DynamoDB や S3 含めた Lambda 関連のフルアクセス。

Lambda 関数

  • AWSLambdaBasicExecutionRole: CloudWatch Logs への書き込み。
  • AWSLambdaKinesisExecutionRole: Kinesis Streams アクション。
  • AWSLambdaDynamoDBExecutionRole: DynamoDB アクション。
  • AWSLambdaVPCAccessExecutionRole: VPC アクセス。

Lambda 関数用のロールを作成

  • ロールを作成する
  • ロールタイプは AWS サービス、Lambda
  • AWSLambdaBasicExecutionRole をアタッチ

コンソールで Lambda の作成とテスト

Lambda 関数の作成

  • Lambda サービスで作成
  • 関数名は helloFunction
  • ランタイムは Python3.9
  • アーキテクチャは x86
  • 実行ロールは作った example-lambda-role

関数の実装

  • コードを書いて
  • 保存
  • デプロイ

テスト

  • テストイベント作って
  • 引数を JSON 作る
  • テスト

ログ

  • Cloud Watch で確認できる。
  • ログには実行時間と使用メモリが出力されている。
  • Billed Duration: 2 msと課金時間もでている。
  • Init Duration: 93.25 msと準備にかかる時間がでている。連続実行の場合はでてない。

Lambda の設定

  • メモリ: 512MB 以上
  • タイムアウト: 15 分以内
  • 環境変数が Lambda 関数毎に設定できる
  • /tmp が使える

Lambda の再利用

環境は再利用される可能性があるので注意。

Lambda のプロビジョニング

プロビジョニングしておけば、ランタイムの準備を省略できる。 料金かかるけど。

https://dev.classmethod.jp/articles/simulate-provisioned-concurrency-cost/

イベントモデル

  • プッシュ
  • ストリーム

ストリームは DynamoDB、Kinesis、MQ、SQS など限られている。データをポーリングしてデータを取得して Lambda が呼ばれる。

プッシュは同期と非同期があって、同期は呼び出し+戻りまで、非同期は呼び出しのみ。ほとんど非同期。

SAM を使う準備

AWS : Linux への AWS SAM CLI のインストール

ステップ 1: AWS アカウントを作成する

当然できてる。

ステップ 2: IAM 許可と AWS 認証情報を設定する

AWS 認証情報のセットアップが必要。

AWS CLI を使うのはやりすぎなので、「AWS CLI を使用しない場合」を使って設定してみよう。

まずは、AWS のコンソールで、作成済みの IAM アカウントで、「アクセスキーを作成」した。

後は設定ファイルに書き込む。

$ vi ~/.aws/credentials

[default]
aws_access_key_id=your_access_key_id
aws_secret_access_key=your_secret_access_key

default だと面白くないので、[sam-cli]にしてみた。

ステップ 3: Docker をインストールする (オプション)

WSL に docker はインストール済み。

ステップ 4: AWS SAM CLI をインストールする

zip をダウンロードして

$ unzip aws-sam-cli-linux-x86_64.zip -d sam-installation
$ sudo ./sam-installation/install
$ sam --version
SAM CLI, version 1.42.0

# アップグレードする場合
$ sudo ./sam-installation/install --update

# アンインストールする場合
$ which sam
# 場所をしらべて
$ ls -l /usr/local/bin/sam
# シンボリックリンク先のディレクトリしらべて、まずシンボリックリンクを削除
$ sudo rm /usr/local/bin/sam
# ディレクトリを削除
$ sudo rm -rf /usr/local/aws-sam-cli

はじめての SAM

初期化

$ sam init

Which template source would you like to use?
    1 - AWS Quick Start Templates
Choose an AWS Quick Start application template
    1 - Hello World Example
 Use the most popular runtime and package type? (Python and zip) [y/N]: y
Project name [sam-app]: sam-example-cron

Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)

これで、ディレクトリが作られた。

template.yaml の作り方

SAR から探す。 lambda-canary-python3を選ぶ。

テンプレートの中身を見て参考に修正する。

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-example-cron
  Sample SAM Template for sam-example-cron
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      # Handler: app.lambda_handler
      Handler: lambda_function.lambda_handler
      Runtime: python3.9
      Architectures:
        - x86_64
#      Events:
#        HelloWorld:
#          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
#          Properties:
#            Path: /hello
#            Method: get

#Outputs:
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
# Find out more about other implicit resources you can reference within SAM
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
#  HelloWorldApi:
#    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
#    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
#  HelloWorldFunction:
#    Description: "Hello World Lambda Function ARN"
#    Value: !GetAtt HelloWorldFunction.Arn
#  HelloWorldFunctionIamRole:
#    Description: "Implicit IAM Role created for Hello World function"
#    Value: !GetAtt HelloWorldFunctionRole.Arn

ソースの修正

hello_world/lambda_handler.pyを作る。

import json
def lambda_handler(event, context):
    print('Hello')
    print(json.dumps(event))

ビルド

$ sam build -u

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

デプロイ

$ sam deploy -g

Stack Name [sam-app]: stack-sam-example-cron
AWS Region [us-east-1]: ap-northeast-1
Confirm changes before deploy [y/N]: y
Allow SAM CLI IAM role creation [Y/n]: y
Disable rollback [y/N]: y
Save arguments to configuration file [Y/n]: y
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:

エラーになった。

botocore.exceptions.NoCredentialsError: Unable to locate credentials

クレデンシャルが見つからなかったらしい。 profile の指定でできた。 デフォルトにしたほうがよさそう。 常に使うやつをデフォルトにして、切り替えればいんだと思う。

$ sam deploy -g --profile sam-cli

以下のようなログがでた。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                             ResourceType                               LogicalResourceId                          ResourceStatusReason
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS                         AWS::IAM::Role                             HelloWorldFunctionRole                     -
CREATE_IN_PROGRESS                         AWS::IAM::Role                             HelloWorldFunctionRole                     Resource creation Initiated
CREATE_COMPLETE                            AWS::IAM::Role                             HelloWorldFunctionRole                     -
CREATE_IN_PROGRESS                         AWS::Lambda::Function                      HelloWorldFunction                         -
CREATE_IN_PROGRESS                         AWS::Lambda::Function                      HelloWorldFunction                         Resource creation Initiated
CREATE_COMPLETE                            AWS::Lambda::Function                      HelloWorldFunction                         -
CREATE_COMPLETE                            AWS::CloudFormation::Stack                 stack-sam-example-cron                     -
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

以下ができたようだ。確認した。

  • IAM ロール HelloWorldFunctionRole AWSLambdaBasicExecutionRole が割当たっていた。
  • Lambda HelloWorldFunction
  • CloudFormation stack-sam-example-cron

んー、SAM はいまいちだ。


最終更新日: 2022年4月2日