NRIネットコム Blog

NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

AWS SAM の Tips 集

本記事は  初夏のAWSアワードエンジニア祭り  8日目の記事です。
🍦  7日目  ▶▶ 本記事 ▶▶  9日目  💻

西です。この度 2023 Japan AWS Jr. Champions 及び 2023 Japan AWS All Certifications Engineers に選出頂きました。

大変光栄なことですが "Jr." も "Champion" もあまりに自分とかけ離れた印象の単語なので違和感が拭えません、今後も精進します。

今回は「初夏の AWS アワードエンジニア祭り」とのことで、業務の中での AWS についての気づきなどをお伝えできればと思います。 私は普段の業務では AWS SAM を利用する機会が多く、その分ちょっとした便利ポイントやハマりを目にすることも多いです。

というわけで今回は AWS SAM の便利なポイントや注意すべき点について Tips としてまとめていきます。

AWS SAM とは

https://aws.amazon.com/jp/serverless/sam/

AWS サーバーレスアプリケーションモデル (SAM、Serverless Application Model) は、サーバーレスアプリケーション構築用のオープンソースフレームワークです。

詳細については公式情報を確認頂くのが1番かと思いますが、AWS SAM CLI を使って AWS Lambda をはじめとするサーバレスサービスを使ったアプリケーション開発を手軽に開発できるツールとして有名ですね。

本稿において、以降は各種 AWS サービス/用語は略称で表記 (e.g. AWS SAM → SAM) して進めようと思います。

CI/CD ツールによる sam deploy 時の注意点

早速ですが、SAM での開発を高速に進めるために活用できるのが samconfig.toml という設定ファイルです。

CloudFormation 用の設定や AWS の profile/region 設定も予め記載しておくことでコマンドを簡潔な形で実行できます。 設定群を TOML テーブルに分けて記載もできるので、開発用/本番用 でそれぞれ設定が違う場合も予め記載することでコマンド記載ミスのオペミスを減らせます。

そんな samconfig.toml ですが、このファイルで AWS の profile まで定義した場合には少し注意が必要です。

以下のような記載を考えてみましょう。

 [dev.deploy.parameters]
 stack_name = "my-app-stack-dev"
 s3_bucket = "my-source-bucket-dev"
 s3_prefix = "my-s3-prefix"
 profile = hogehoge-dev
 region = "us-west-2"
 confirm_changeset = true
 capabilities = "CAPABILITY_IAM"
 
 [prod.deploy.parameters]
 stack_name = "my-app-stack-prod"
 s3_bucket = "my-source-bucket-prod"
 s3_prefix = "my-s3-prefix"
 profile = hogehoge-prod
 region = "us-west-2"
 confirm_changeset = true
 capabilities = "CAPABILITY_IAM"
 parameter_overrides=Env=\"prod\"

profile に AWS プロファイルが指定されていると思います。

この状態で CI/CD ツールからデプロイを進めようとした場合、ツール上では指定されたプロファイル名 (dev / prod) が見つからずエラーが発生します。

もちろんツール側にも profile として設定していれば問題ありませんが、多くの場合ツール側には IAM ユーザの認証情報を払い出しているか AssumeRole での操作による場合が多いと思うので、注意が必要なポイントです。

ただデプロイに失敗するだけ & 手元からデプロイする場合には問題ないので重大な影響が起こることはないと思いますが、見落としがちな点なので発生しやすいエラーかと個人的には思います。 profile 指定でローカルからのデプロイは手軽になりますが、ツール利用時は profile 指定項目は削除/コメントアウトするのが安全です。

CI/CD ツールを利用した SAM のデプロイについては以前別の記事にてまとめたことがありますのでそちらもよければご覧下さい。

tech.nri-net.com

Tags の付け方

露骨な誘導が済んだところで次のポイントです。この点は有名な点かもしれません。

開発ルール等でリソースにタグ付けを行わなければならない場合などがあるかと思います。 しかし、SAM 関連のリソース (Type: AWS::Serverless::* のリソース) には通常の CloudFormation と同じような形ではタグを付けられません。というのも CloudFormation とは Tags の型が異なるからです。

CloudFormation では Tags は List 型ですが、SAM 関連リソースの場合は Map 型で定義されます。そのため以下のような形での定義が必要です。

CloudFormation だと

Tags:
    - Key: hoge
      Value: fuga

SAMだと

Tags:
    hoge: fuga

という形になります。 余談ですが、CloudFormation スタックそのものにタグ付けする場合は samcomfig.toml の tags という項目から実施できます。

 [dev.deploy.parameters]
 stack_name = "my-app-stack-dev"
 s3_bucket = "my-source-bucket-dev"
 s3_prefix = "my-s3-prefix"
 profile = hogehoge-dev
 region = "us-west-2"
 confirm_changeset = true
 capabilities = "CAPABILITY_IAM"
 tags = "hoge=\"fuga\""

parameter_overrides を綺麗に書く

samconfig.toml には parameter_overrides という項目があります。 この項目では template.yaml で定義している 各 Parameters を上書きすることができます。

以下のような形で記載します。

parameter_overrides = "hogeARNSuffix=\"hogehoge\" SecretARNSuffix=\"secret\" Environment=\"dev\" DynamoDBEndpoint=\"\" DynamoDBTableName=\"hogehoge_table\" DomainName=\"hogefuga.hoge.net\" CertificateArn=\"arn:aws:acm:{region}:{account_id}:certificate/*******-****-****-****-************\" HostedZoneId=\"thisishostzoneid\""

この書き方ですが、見ての通り Parameter の項目が増えるほど見づらく複雑になります。 2~3 個の Parameter ならまだ許容できるかもしれませんが、数が増えるほど可視性が下がってコード修正ミスの温床となります。つらいですね。

そんな parameter_overrides ですが、以下のように記載することができます。

parameter_overrides = [
    "hogeARNSuffix=hogehoge",
    "SecretARNSuffix=secret",
    "Environment=dev",
    "DynamoDBEndpoint=",
    "DynamoDBTableName=hogehoge_table",
    "DomainName=hogefuga.hoge.net",
    "CertificateArn=arn:aws:acm:{region}:{account_id}:certificate/*******-****-****-****-************",
    "HostedZoneId=thisishostzoneid"
]

最初の例と比較すると明らかに見やすくなっているのがわかりますね。

エスケープせずに済むため修正ミスも少なくなりますし、何より見栄えが綺麗です。個人的にはこれが一番嬉しいポイントです。

Lambda パッケージサイズのスリム化

アプリケーションで利用している外部ライブラリが増えて、アプリケーションのパッケージサイズが肥大化する場合があります。 こうなるとサイズの都合でマネジメントコンソール上でコードが表示されなくなり「コンソールで少し修正してすぐに動作を見たい」のようなことが一気に難しくなります。 パッケージの依存関係管理を厳密に行なっているときほど遭遇する現象です。

このような場合、外部ライブラリ取得用の layer を定義することで再びコンソールでの操作が可能になります。 例えば Lambda の Runtime に Python を利用している場合は以下のようなファイル/ディレクトリ構造となります。 まずは template.yaml ですが、以下のように定義します。

  Layer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      Description: Lambda layer for Python3.9
      ContentUri: ./src/layer
      CompatibleRuntimes:
        - python3.9
  Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: ./src/function
      Handler: app.lambda_handler
      Runtime: python3.9
      Layers:
        - !Ref Layer

パッケージ依存関係の情報を定義している場合は layer 用のディレクトリを作成しておくことが必要です。 ディレクトリ構造は以下のようになります。

├── samconfig.toml
├── src
│   ├── layer
│   │   └── requirements.txt
│   └── function
│       ├── app.py
│       └── requirements.txt
└── template.yaml

layer 側の requirements.txt にのみ外部ライブラリの情報を出力することで依存関係管理の切り出しが実現可能です。

おわりに

今回は SAM の便利なポイントや注意すべき点についてまとめました。

そのまま使っているだけでも使いやすい SAM ですが、さらに高速かつスムーズに使いこなす一助になればと思います。

執筆者: 西 洋平 クラウドエンジニア AWS をメインに触っています