AWS SAMでマルチアカウントデプロイ
概要
AWS SAMにて、マルチアカウントデプロイを設定する機会がありました。
その際、以下の点で悩みました。
- AWSアカウントを指定して
sam deploy
コマンドを実行するにはどうしたらよいか - Cloudformationテンプレート(
template.yaml
) にて、AWSアカウント別に、IDなどの固定パラメータを設定するにはどうすればよいか- 固定パラメータの例) 既に生成しているVPC(およびサブネット)のID など
自分の頭を整理する意味も込めて、自分が選択した解決策を投下します。
想定する状況
以下のどちらにも当てはまる状況を想定します。
- AWS SAMで開発したアプリケーションを、複数環境へデプロイしたい場合
- 複数環境を、異なるAWSアカウントで管理している場合
- 言い換えると、一つのAWSアカウントにて、開発/本番の両環境を運用している場合は対象外
- AWSアカウント別に、固定パラメータを設定してデプロイしたい場合
- VPCIDなど
話さないこと
- AWS SAMとは何か
- AWS SAMの導入方法
- Cloudformation とは何か
結論
アカウント指定
AWSアカウントを指定してデプロイするには、sam deploy --profile
オプションを活用する。
固定パラメータ設定
環境情報(dev/prodなど)をやり取りできるよう、SAMプロジェクトを設定する。
Cloudformation側で環境情報を受け取り、環境情報に応じて参照するパラメータを変更できるようにする。
アカウント指定
方針
sam deploy --profile
オプションにて、aws/credentials
に設定したクレデンシャル名を指定できる。
この機能を利用する。
手順
- デプロイしたいAWSアカウントのクレデンシャル情報を設定する
-
--profile
オプションでクレデンシャル名 を指定する
1. デプロイしたいAWSアカウントのクレデンシャル情報を設定する
.aws/credentials
内
[default]
...
[prod_myproject]
aws_access_key_id = xxx
aws_secret_access_key = xxx
--profile
オプションでクレデンシャル名 を指定する
2. 公式ドキュメントに則り、--profile
オプションにて、クレデンシャル名を指定します。
--profile TEXT
| AWS 認証情報を取得する、認証情報ファイルから特定のプロファイルです。
デプロイコマンド
sam deploy --profile prod_myproject
以上。
prod_myproject
部分に、任意の値をご使用ください。
固定パラメータ設定
方針
CLIからCloudformationへ環境情報(dev/prodなど)をやり取りさせ、環境情報に応じて参照するパラメータを変更できるようにする。
- Cloudformationテンプレートに環境情報を渡せるよう、 SAMプロジェクトを設定する
- 同時に、
sam deploy --config-env
オプションにて、CLIから環境情報を指定できるようになる
- 同時に、
- Cloudformationテンプレートでは、上記環境情報を受け取り、環境情報に応じて固定パラメータを使い分けられるようにする
手順
- Cloudformationテンプレートに環境情報(dev/prodなど)を渡せるよう、
samconfig.toml
を設定する - Cloudformationテンプレートの Parametersセクションにて、手順1で設定した環境情報を定義
- Cloudformationテンプレートの Mappingsセクションを作成する
- ここで、環境情報別のID情報を定義する
- 必要に応じて、手順3で設定したマッピング情報を参照する
samconfig.toml
を設定する
1. Cloudformationテンプレートに環境情報(dev/prodなど)を渡せるよう、 samconfig.yanl
を編集し、Cloudformationテンプレートに渡すパラメータを追記します。
[prod.deploy.parameters] // ココに、cliで指定する環境名
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
resolve_s3 = true
s3_prefix = "sample-app"
region = "ap-northeast-1"
image_repositories = []
parameter_overrides = "ENV=\"prod\"" // ココに、Cloudformationへ渡す変数名&値
parameter_overrides
部分で、Cloudformationテンプレートに渡す環境情報を設定します。
上記の記述では、Cloudformation側に ENV
という変数名で、prod
という値を渡すことになります。
テーブル名 ( 先頭の、[prod.deploy.parameters]
部分)は、以下のルールに則って記述します。
- コマンドの場合、テーブルヘッダーの形式は
[`environment`.`command`.parameters]
になります。例えば、default
環境のsam deploy
コマンドでは、設定テーブルのヘッダーが[default.deploy.parameters]
になります。
引用 : 公式ドキュメント
テーブル名の environment
部分は、sam deploy
コマンドの --config-env
で 指定します。
- デフォルトの環境名は
default
です。デフォルトの環境名は、--config-env
パラメータを使用して上書きできます。
引用 : 公式ドキュメント
以上をまとめると、[prod.deploy.parameters]
設定を呼び出す、最終的な sam deploy
コマンドは以下の通りです。
sam deploy --config-env prod
プロファイルも、併せて指定できます。
sam deploy --profile ${.aws/credentialsで定義したクレデンシャル名} --config-env prod
このコマンドを実行すると、 [prod.deploy.parameters]
部分の設定を読み込みつつ、 Cloudformationテンプレートを読み込み、 デプロイ処理が走ります。
2. Cloudformationテンプレートの Parametersセクションにて、手順1で設定した環境情報を定義する
Cloudformation の Parametersセクション部分の文法に則り、samconfig.toml
の parameter_overrides
から渡ってくる環境情報を定義します。
Parameters:
ENV: // samconfig.tomlのparameter_overridesで指定した変数名
Type: String
Default: "dev"
AllowedValues: //使用したい環境情報名を定義
- prod
- dev
3. Cloudformationテンプレートの Mappingsセクションを作成する
Cloudformation の Parametersセクション部分の文法に則り、環境(≒AWSアカウント)別に個別定義したい固定パラメータを定義します。
Mappings:
EnvResourceMap: // 任意の名前
"dev": // Parametersセクションで定義した、AllowedValuesの値
"SecurityGrouId": xxx // ここに、AWSアカウント別に指定したいパラメータを設定していく
"Subnet1": xxx
"Subnet2": xxx
"prod":
"SecurityGroupId": yyy
"Subnet1": yyy
"Subnet2": yyy
4. 必要に応じて、手順3で設定したマッピング情報を参照する
Cloudformation 組込み関数である Fn::FindInMap
関数を使用して、手順3で設定したMappingsセクションの値を参照します。
構文は、公式ドキュメントをご確認ください。
template.yaml
サンプル
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sample-app
Sample SAM Template for sample-app
Parameters:
ENV:
Type: String
Default: "dev"
AllowedValues:
- prod
- dev
Mappings:
EnvResourceMap:
"dev":
"SecurityGroupId": xxx
"Subnet1": xxx
"Subnet2": xxx
"prod":
"SecurityGroupId": yyy
"Subnet1": yyy
"Subnet2": yyy
Resources:
...
Mapping
参照部分
VpcConfig:
SecurityGroupIds:
- !FindInMap [EnvResourceMap, !Ref ENV, SecurityGroupId]
SubnetIds:
- !FindInMap [EnvResourceMap, !Ref ENV, Subnet1]
- !FindInMap [EnvResourceMap, !Ref ENV, Subnet2]
以上。
所感
これらの設定により、以下の状況を作り出すことが出来ました。
-
sam deploy
オプションをいじるだけで、デプロイしたいAWS環境を変更できる - パラメータを追加したい場合は、CloudformationのMappingsセクションをいじるだけ
もしかしたら、他に優れた手法が存在するかもしれませんが、現状はこの設定で満足できそうです。
同じ問題で悩んでいる方の参考になればと思います。
参考文献
- https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html
- https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-anatomy.html
- https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html
- https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
Discussion