[アップデート]AWS SAMのデプロイが簡単になりました

こんにちは、大阪オフィスのかずえです。今回は、AWS SAMのデプロイ方法が簡単になったことをお伝えします。

これまで

$ aws s3 mb s3://(バケット名)
$ sam package --s3-bucket (バケット名) --output-template-file out.yaml
$ sam deploy --template-file out.yaml --capabilities CAPABILITY_IAM --stack-name (CFnスタック名)

これから

$ sam deploy

コマンド数が少なくなっている上に、パラメーターも無くなってますね!

やってみた

新しくなったdeployコマンドを使って、チュートリアル Deploying a Hello World Application をやってみました。

SAMのバージョンアップデート

※ SAM未インストールの場合は、以下ページを参考にインストールを行なってください。

現在のバージョン

$ sam --version
SAM CLI, version 0.17.0

アップデート

$ brew upgrade aws-sam-cli
(出力内容省略)

アップデートされたことを確認

$ sam --version
SAM CLI, version 0.34.0

Step 1: Download a Sample AWS SAM Application

まずは sam init でアプリケーションの初期化を行ないます。python3.7を使います。

$ sam init
Which template source would you like to use?
    1 - AWS Quick Start Templates
    2 - Custom Template Location
Choice: 1

Which runtime would you like to use?
    1 - nodejs12.x
    2 - python3.8
    3 - ruby2.5
    4 - go1.x
    5 - java11
    6 - dotnetcore2.1
    7 - nodejs10.x
    8 - nodejs8.10
    9 - nodejs6.10
    10 - python3.7
    11 - python3.6
    12 - python2.7
    13 - java8
    14 - dotnetcore2.0
    15 - dotnetcore1.0
Runtime: 10

Project name [sam-app]:

Quick start templates may have been updated. Do you want to re-download the latest [Y/n]: Y

-----------------------
Generating application:
-----------------------
Name: sam-app
Runtime: python3.7
Dependency Manager: pip
Application Template: hello-world
Output Directory: .

Next steps can be found in the README file at ./sam-app/README.md

Step 2: Build Your Application

次に sam build を実行します。

$ cd sam-app/
$ sam build
Building resource 'HelloWorldFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

コンソールの出力結果に記載されていますが、カレントディレクトリ下の .aws-sam/build 以下に色々とファイルが作成されます。大きく分けて二種類あります。

$ ls .aws-sam/build/
HelloWorldFunction  template.yaml

HelloWorldFunctionディレクトリ以下 = Built Artifacts

hello_world 以下のpythonファイルと、そこで使われるパッケージのファイル群がダウンロードされています。

template.yaml = Built Template

カレントディレクトリ(アプリケーションルートディレクトリ)に存在した template.yaml が変換されたものです。どう変わってるのかなと差分を見てみましたが、大して変わっていないような、、内容次第では大きく変換されるのでしょうか。

左がもとの template.yaml、右が変換後のファイルです。

Step 3: Deploy Your Application to the AWS Cloud

ここが今回アップデートされた部分ですね。

チュートリアルには --guided オプションつけてねとあるのですが一旦ナシで実行してみましょう。

$ sam deploy
Usage: sam deploy [OPTIONS]
Try "sam deploy --help" for help.

Error: Missing option '--stack-name', 'sam deploy --guided' can be used to provide and save needed parameters for future deploys.

「どういうこと? sam deploy だけでデプロイできるんじゃなかったの?」

はい。実は sam deploy だけでデプロイできるのは 2回目から です。

これまでは sam deploy の前に sam package が必要でした。sam package でソースコード(+依存パッケージ)群のZIP化、そのZIPのS3バケットへのアップデートを行ない、そのS3上のソースを参照するようにSAMテンプレートファイルも変換されていました。また sam deploy 時には、使用するテンプレートファイルや、CFnのスタック名をパラメーターによって指定する必要もありました。

今後は、 sam deploy 時にこういった設定がない場合は、samconfig.toml という ファイルが無いか探して、そこに記載されている設定に従ってデプロイが行われる、という仕様になりました。で、前述の--guided (もしくは -g)オプションを添えてsam deployすると、質問に答えていくだけで samconfig.tomlを作ってくれるので、次回以降は sam deployだけで済むというわけです。

※ これまでの sam package と sam deployを使う方法も引き続き使用できます。

では、--guidedを付けて再実行

$ sam deploy --guided

Configuring SAM deploy
======================

    Looking for samconfig.toml :  Not found

    Setting default arguments for 'sam deploy'
    =========================================
    Stack Name [sam-app]:
    AWS Region [us-east-1]: 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]:
    Save arguments to samconfig.toml [Y/n]:

    Looking for resources needed for deployment: Not found.
    Creating the required resources...
    Successfully created!

        Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-5vaat5cyd7x4
        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

    Deploying with following values
    ===============================
    Stack name                 : sam-app
    Region                     : ap-northeast-1
    Confirm changeset          : True
    Deployment s3 bucket       : aws-sam-cli-managed-default-samclisourcebucket-5vaat5cyd7x4
    Capabilities               : ["CAPABILITY_IAM"]
    Parameter overrides        : {}

Initiating deployment
=====================
Uploading to sam-app/84978d376aaae3a733b4ac10f9c7af26  532293 / 532293.0  (100.00%)
Uploading to sam-app/76145a8c10a8178f06e48cafba84e2f0.template  1089 / 1089.0  (100.00%)

Waiting for changeset to be created..

CloudFormation stack changeset
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation                                                  LogicalResourceId                                          ResourceType
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add                                                      HelloWorldFunctionHelloWorldPermissionProd                 AWS::Lambda::Permission
+ Add                                                      HelloWorldFunctionRole                                     AWS::IAM::Role
+ Add                                                      HelloWorldFunction                                         AWS::Lambda::Function
+ Add                                                      ServerlessRestApiDeployment47fc2d5f9d                      AWS::ApiGateway::Deployment
+ Add                                                      ServerlessRestApiProdStage                                 AWS::ApiGateway::Stage
+ Add                                                      ServerlessRestApi                                          AWS::ApiGateway::RestApi
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:047429787746:changeSet/samcli-deploy1575102149/dbcc7649-e72a-4079-a187-95b66803aa95


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

2019-11-30 17:22:46 - Waiting for stack create/update to complete

CloudFormation events from changeset
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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_IN_PROGRESS                          AWS::ApiGateway::RestApi                    ServerlessRestApi                           -
CREATE_IN_PROGRESS                          AWS::ApiGateway::RestApi                    ServerlessRestApi                           Resource creation Initiated
CREATE_COMPLETE                             AWS::ApiGateway::RestApi                    ServerlessRestApi                           -
CREATE_IN_PROGRESS                          AWS::Lambda::Permission                     HelloWorldFunctionHelloWorldPermissionPro   Resource creation Initiated
                                                                                        d
CREATE_IN_PROGRESS                          AWS::ApiGateway::Deployment                 ServerlessRestApiDeployment47fc2d5f9d       -
CREATE_IN_PROGRESS                          AWS::Lambda::Permission                     HelloWorldFunctionHelloWorldPermissionPro   -
                                                                                        d
CREATE_IN_PROGRESS                          AWS::ApiGateway::Deployment                 ServerlessRestApiDeployment47fc2d5f9d       Resource creation Initiated
CREATE_COMPLETE                             AWS::ApiGateway::Deployment                 ServerlessRestApiDeployment47fc2d5f9d       -
CREATE_IN_PROGRESS                          AWS::ApiGateway::Stage                      ServerlessRestApiProdStage                  -
CREATE_IN_PROGRESS                          AWS::ApiGateway::Stage                      ServerlessRestApiProdStage                  Resource creation Initiated
CREATE_COMPLETE                             AWS::ApiGateway::Stage                      ServerlessRestApiProdStage                  -
CREATE_COMPLETE                             AWS::Lambda::Permission                     HelloWorldFunctionHelloWorldPermissionPro   -
                                                                                        d
CREATE_COMPLETE                             AWS::CloudFormation::Stack                  sam-app                                     -
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Stack sam-app outputs:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OutputKey-Description                                                                   OutputValue
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HelloWorldFunctionIamRole - Implicit IAM Role created for Hello World function          arn:aws:iam::047429787746:role/sam-app-HelloWorldFunctionRole-1OCESGCMVCZLY
HelloWorldApi - API Gateway endpoint URL for Prod stage for Hello World function        https://zyk8do4vz4.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
HelloWorldFunction - Hello World Lambda Function ARN                                    arn:aws:lambda:ap-northeast-1:047429787746:function:sam-app-HelloWorldFunction-
                                                                                        RUO13GDC6QR6
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - sam-app in ap-northeast-1

アクセス確認

OutputValue欄に出力されたAPI Gateway のエンドポイント URLにアクセスしています。

$ curl https://zyk8do4vz4.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}

生成された samconfig.toml の中身

version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "sam-app"
s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-5vaat5cyd7x4"
s3_prefix = "sam-app"
region = "ap-northeast-1"
confirm_changeset = true
capabilities = "CAPABILITY_IAM"

S3バケットを作成するCFnスタックも自動で作成される

aws-sam-cli-managed-defaultという名前で、以下テンプレートを使ったCFnスタックが作成されていました。ソースコードのzipファイルと、それを見に行くように変換されたSAM templateファイルが配置されます。

    AWSTemplateFormatVersion : '2010-09-09'
    Transform: AWS::Serverless-2016-10-31
    Description: Managed Stack for AWS SAM CLI

    Metadata:
        SamCliInfo: {"version": "0.34.0", "installationId": "3445debb-03f9-440c-ab96-fc24662a1c5f"}

    Resources:
      SamCliSourceBucket:
        Type: AWS::S3::Bucket
        Properties:
          VersioningConfiguration:
            Status: Enabled
          Tags:
            - Key: ManagedStackSource
              Value: AwsSamCli

      SamCliSourceBucketBucketPolicy:
        Type: AWS::S3::BucketPolicy
        Properties:
          Bucket: !Ref SamCliSourceBucket
          PolicyDocument:
            Statement:
              -
                Action:
                  - "s3:GetObject"
                Effect: "Allow"
                Resource:
                  Fn::Join:
                    - ""
                    -
                      - "arn:aws:s3:::"
                      -
                        !Ref SamCliSourceBucket
                      - "/*"
                Principal:
                  Service: serverlessrepo.amazonaws.com

    Outputs:
      SourceBucket:
        Value: !Ref SamCliSourceBucket

ソースを修正して今度は --guided なしでdeployしてみる

pythonコード修正

ショボイですが出力内容 「hello world」を「hello world2」にしてみました。

ビルド

最初このステップを忘れていて混乱してしまいました。。

$ sam build
Building resource 'HelloWorldFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

デプロイ

$ sam deploy

    Deploying with following values
    ===============================
    Stack name                 : sam-app
    Region                     : ap-northeast-1
    Confirm changeset          : True
    Deployment s3 bucket       : aws-sam-cli-managed-default-samclisourcebucket-5vaat5cyd7x4
    Capabilities               : ["CAPABILITY_IAM"]
    Parameter overrides        : {}

Initiating deployment
=====================

Waiting for changeset to be created..
Error: No changes to deploy. Stack sam-app is up to date
HL00367:sam-app kazue.masaki$ sam build
Building resource 'HelloWorldFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

HL00367:sam-app kazue.masaki$ sam build
Building resource 'HelloWorldFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

HL00367:sam-app kazue.masaki$ sam deploy

    Deploying with following values
    ===============================
    Stack name                 : sam-app
    Region                     : ap-northeast-1
    Confirm changeset          : True
    Deployment s3 bucket       : aws-sam-cli-managed-default-samclisourcebucket-5vaat5cyd7x4
    Capabilities               : ["CAPABILITY_IAM"]
    Parameter overrides        : {}

Initiating deployment
=====================
Uploading to sam-app/62b5328d77b28db25651302d2667dcb8  532286 / 532286.0  (100.00%)
Uploading to sam-app/805fb24556397f5abb3f5a0b1a19d04f.template  1089 / 1089.0  (100.00%)

Waiting for changeset to be created..

CloudFormation stack changeset
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation                                                  LogicalResourceId                                          ResourceType
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Modify                                                   HelloWorldFunction                                         AWS::Lambda::Function
* Modify                                                   ServerlessRestApi                                          AWS::ApiGateway::RestApi
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:047429787746:changeSet/samcli-deploy1575103528/244d9da2-84e6-4aac-abb3-f6524fba4495


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

2019-11-30 17:46:13 - Waiting for stack create/update to complete

CloudFormation events from changeset
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                              ResourceType                                LogicalResourceId                           ResourceStatusReason
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_IN_PROGRESS                          AWS::Lambda::Function                       HelloWorldFunction                          -
UPDATE_COMPLETE                             AWS::Lambda::Function                       HelloWorldFunction                          -
UPDATE_COMPLETE_CLEANUP_IN_PROGRESS         AWS::CloudFormation::Stack                  sam-app                                     -
UPDATE_COMPLETE                             AWS::CloudFormation::Stack                  sam-app                                     -
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Stack sam-app outputs:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OutputKey-Description                                                                   OutputValue
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HelloWorldFunctionIamRole - Implicit IAM Role created for Hello World function          arn:aws:iam::047429787746:role/sam-app-HelloWorldFunctionRole-1OCESGCMVCZLY
HelloWorldApi - API Gateway endpoint URL for Prod stage for Hello World function        https://zyk8do4vz4.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
HelloWorldFunction - Hello World Lambda Function ARN                                    arn:aws:lambda:ap-northeast-1:047429787746:function:sam-app-HelloWorldFunction-
                                                                                        RUO13GDC6QR6
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - sam-app in ap-northeast-1

結果確認

curl https://zyk8do4vz4.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world2"}

無事デプロイできました!

まとめ

SAMのデプロイ方法が簡単になったことをお伝えしました。半年ぶりくらいにSAMを触ったのですが、半年前は毎回 sam packagesam deploy コマンドのパラメーターなんだったけ?となっていたのを思い出しました笑 ですのでこのアップデータはとても使いやすくなった良いアップデートかなと思います。ぜひ一度お試しくださいませ。

参考資料