19
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MetapsAdvent Calendar 2023

Day 6

AWS SAM環境で複数環境にデプロイ + Secrets Managerで環境変数管理

Last updated at Posted at 2023-12-05

はじめに

サーバーレス環境のAWS Lambdaをローカルで開発できるよう、AWS SAMを使っています。
https://aws.amazon.com/jp/serverless/sam/

ソースコードもgit管理できるため便利ですし、ローカルで開発している間は課金される恐怖からも逃れることができます。
しかし、ローカルとそれ以外の環境は全く同じわけではありません。特に環境変数回りでハマることがあったので、記録しておきます。

やりたいこと

  • デプロイする環境に応じて環境変数を分けたい
  • セキュアな情報はSecrets Managerで管理したい

結論

  • 環境変数はtemplate.yamlに書く
  • 環境変数の指定はsamconfig.tomlと実行時コマンドで行う
  • Secrets Managerで保管した値を環境変数に指定し、template.yamlで読み込むことができる

前提

Windows 11 + WSL2でPython3環境のスクリプトを開発します。
WSLにはdocker, sam, python3を入れてあります。

また、AWS SAM自体の説明は省略します。

AWS SAMでLambdaを開発する

ローカル環境はDockerで開発する

ローカル環境は sam local invokeコマンドで実行します。

$ sudo sam build --use-container
$ sudo sam local invoke

各環境はデプロイする

検証環境・本番環境にデプロイする際には、 sam deploy コマンドを使います。

$ sudo sam build --use-container
$ sam deploy --config-env staging

環境変数管理

前述のように、SAMを使うとローカルで開発できる代わりに、ローカル環境はDocker、それ以外の環境ではAWS環境になります。
ローカル環境は直書きでも問題ないですが、本番環境の環境変数をソースコード内に残したくないので、AWS Secrets Managerに記載します。

環境に応じて設定を分ける

環境変数定義

SAMが使用するtemplate.yamlに、環境変数一式を定義します。

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
  Function:
    Environment:
      Variables:
        DatabaseHost: !FindInMap [ Variables, !Ref Env, DatabaseHost ]
        DatabasePort: !FindInMap [ Variables, !Ref Env, DatabasePort ]
        DatabaseUser: !FindInMap [ Variables, !Ref Env, DatabaseUser ]
        DatabasePassword: !FindInMap [ Variables, !Ref Env, DatabasePassword ]
        DatabaseName: !FindInMap [ Variables, !Ref Env, DatabaseName ]
...
Mappings:
  Variables:
    local:
      DatabaseHost: 'db'
      DatabasePort: '3306'
      DatabaseUser: 'hogehoge'
      DatabasePassword: 'example'
      DatabaseName: 'test'
    staging:
      DatabaseHost: '{{resolve:secretsmanager:staging-secret-id:SecretString:DatabaseHost}}'
      DatabasePort: '{{resolve:secretsmanager:staging-secret-id:SecretString:DatabasePort}}'
      DatabaseUser: '{{resolve:secretsmanager:staging-secret-id:SecretString:DatabaseUser}}'
      DatabasePassword: '{{resolve:secretsmanager:staging-secret-id:SecretString:DatabasePassword}}'
      DatabaseName: '{{resolve:secretsmanager:staging-secret-id:SecretString:DatabaseName}}'
  ...
Parameters:
  Env:
    Type: String
    Default: staging
    AllowedValues: [local, staging, production]

環境変数をSecrets Manager内に書く

スクリーンショット 2023-11-24 151153.png

コマンドと環境変数をマッピングする

定義した環境変数を呼ぶには、コマンド内でEnv指定を渡してあげる必要があります。
samconfig.toml各環境のparameter_overrides で、template.yaml の環境を指定します。
[default][staging] は、コマンドの --config-env 属性に対応します。

# samconfig.tomlの[staging]呼び出し
$ sam deploy --config-env staging

samconfig.toml
version = 0.1

[default]
[default.global.parameters]
[default.build.parameters]
cached = true
parallel = true
[default.validate.parameters]
lint = true
[default.deploy.parameters]
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
[default.package.parameters]
[default.sync.parameters]
watch = true
[default.local_start_api.parameters]
warm_containers = "EAGER"
[default.local_start_lambda.parameters]
warm_containers = "EAGER"
[default.local_invoke.parameters]
stack_name = "gate"
parameter_overrides = [
    "Env=local"
]

[staging]
[staging.deploy]
[staging.deploy.parameters]
stack_name = "gate-staging"
s3_bucket = "gate-staging-source"
s3_prefix = "staging"
region = "ap-northeast-1"
confirm_changeset = true
capabilities = "CAPABILITY_IAM"
image_repositories = []
parameter_overrides = [
    "Env=staging",
]

ソースコード内で参照する

Pythonだとこんな感じになります。

app.py
import os
import mysql.connector
def lambda_handler(event, context):
  conn = mysql.connector.connect(
    host = os.environ['DatabaseHost'],
    port = os.environ['DatabasePort'],
    user = os.environ['DatabaseUser'],
    password = os.environ['DatabasePassword'],
    database = os.environ['DatabaseName'],
    connection_timeout = 3
  )
  # 以下、実装

ハマったこと

複数環境にデプロイできない!

こんなコマンドを打っていたためでした。

$ sam deploy production

マニュアルを読むと、引数には必ずオプションが付くことがわかります。
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html
production とだけ書いても、コマンドは認識してくれず、defaultの staging をデプロイしようとします。
環境を指定するには、先述のsamconfig.tomlを記載した上で、

$ sam deploy --config-env production

と指定しなければいけません。

19
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?