【AWS SAM 入門⑤】ステージ管理する

 AWS Serverless Application Model 入門ハンズオンシリーズ - log4ketancho の第5弾です。

 前回の記事では、SAM で REST API を構築する方法について紹介しました。今回は本番環境、検証環境などの複数の環境(ステージ)がある場合に、SAM のテンプレートをどのように構築していくべきかをまとめていきます。

 ・・・「まとめていきます」と書いたのですが、これが最適解なのかはイマイチ自信がないです。もっといい方法がございましたら、ご教示いただけるとありがたいです。

なぜステージ管理が必要なのか

 通常、本番環境と検証環境はなるべく同じ条件にすべきです。ただし、下記のような設定、変数はどうしても差分が出てしまいます。

  • アクセストークンやキー情報(Twitter のアクセストークン、Google Map の API キー、など)
  • AWS リソースやミドルウェアの設定(検証よりも本番のインスタンスタイプを大きいものにしたい、など)

このような差分をどのように吸収すべきでしょうか。

 例えば、環境ごとにテンプレートを分けるのはどうでしょうか?この方法でも要件は満たせると思います。しかし、環境毎に共通の設定がある(大半は共通なはず)のにそれをバラバラのファイルで定義してしまっては、テンプレートの二重管理になってしまいます。これではコード化したメリットが低くなってしまいますし、修正漏れなどで不具合が発生してしまうリスクが大きくなります。

 そこでこの記事では、ひとつのテンプレートの中で、環境によって変更がある部分だけ動的に変更させるようにテンプレートを改良してみます。

ステージ管理の方法

 CloudFormation の機能を用いてステージ管理することにしました。ざっくりとした流れは、

  • Parameters セクションで環境名のリストを定義する
  • Mappings セクションで環境ごとの差分(アクセストークンなど)を定義する
  • Parameters で選ばれた環境によって、 Mappings の値を取り分けるように、テンプレートを修正する
  • deploy 時にパラメータを指定する

となります。

Parameters セクションで環境名のリストを定義する

 CloudFormation のテンプレートを実行するときに、値を入力させることができます。例えば、EC2 インスタンスのインスタンスタイプを選択してもらう、などです。このような値の入力は Parameters セクションで定義することができます。

 例えば、 Env という変数を prodstg から選択してもらう場合は下記のように定義します。

Parameters:
  Env: # prod: 本番環境、stg: 検品環境
    Type: String
    AllowedValues:
      - prod
      - stg
    Default: stg

Mappings セクションで環境ごとの差分(アクセストークンなど)を定義する

 続いて、条件によって変更する設定値のリストを作成します。これは CloudFormation テンプレートの Mappings セクションで定義することができます。例として、Twitter のアクセストークン、シークレットトークンを環境によって変更したい場合は、

Mappings:
  EnvMap:
    prod:
      TwitterAccessToken: '941****'
      TwitterAccessTokenSecret: '6zi***'
    stg:
      TwitterAccessToken: '949***'
      TwitterAccessTokenSecret: 'NKU***'

のように EnvMap というマッピングを定義します。

Parameters で選ばれた環境種別によって、 Mappings の値を取り分けるように、テンプレートを修正する

 最後に環境によって設定値を変えます。!FindInMap 関数を使って、

!FindInMap [ (マッピング名), !Ref (パラメータ名), TwitterAccessToken ]

とすると、実行時に動的に値を埋め込むことができます。

Globals:
  Function:
    Runtime: python3.6
    Timeout: 30
    MemorySize: 128
    Environment:
      Variables:
        TWITTER_ACCESS_TOKEN: !FindInMap [ EnvMap, !Ref Env, TwitterAccessToken ]
        TWITTER_ACCESS_TOKEN_SECRET: !FindInMap [ EnvMap, !Ref Env, TwitterAccessTokenSecret ]

CloudFormation のデプロイ時にパラメータを指定する

 parameter-overrides オプションを用いて、デプロイ時に環境変数を指定します。

$ aws cloudformation deploy \
 --template-file packaged-template.yaml \
 --stack-name stg-stack \
 --capabilities CAPABILITY_IAM \
 --profile sam-sample \
 --parameter-overrides Env=stg

デプロイされた Lambda Function を確認してみてください。うまくデプロイできたでしょうか?

まとめと今後

 SAM を用いて、ひとつのテンプレートで複数の環境を構築する方法を解説しました。もし、もっといい方法がございましたら、ぜひ教えていただけるとうれしいです。

 SAM を効率的に利用するには、CloudFormation の知識が必要になります。関数を用いることで、環境に依存しない&再利用しやすいテンプレートを作ることができます。CloudFormation の関数のうち代表的なものについては、下記の本で解説させていただきました。(この記事の実装をする際も何度か参照しました。なかなか便利ですよー!という宣伝ですw)

Amazon Web Services 業務システム設計・移行ガイド (Informatics&IDEA)

Amazon Web Services 業務システム設計・移行ガイド (Informatics&IDEA)

 この記事は、AWS Serveless Application Model 入門シリーズの第5弾です。もしよろしければ1つ目の記事から手を動かしていただければと思います。不明点がございましたら何なりとご連絡ください。

www.ketancho.net