SAMを使って別のAWSアカウントへLambdaをデプロイする方法
やりたいこと
AWSアカウントAにあるLambda関数をAWSアカウントBにも作成したい
悩ましいところ
Layerは移行すべきか
->今回はAWSアカウントAのLayerをAWSアカウントBでも使用できるようにします。
Lambda関数のIAM Roleをどうするか
->今回はAWSアカウントBにも同名のIAM Roleを作成します。
やりかた
SAMテンプレートは既にある前提で話をします。
公式ドキュメント
適当にSAMのtemplate.ymlを用意しました。
Lambdaの関数とそのLambdaに紐づくIAM Roleを作成するテンプレートです。
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
Youre description here
Parameters:
EnvName:
Type: String
Default: "Development"
AllowedValues:
- Production
- Development
- Staging
Resources:
LambdaFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: app/
Environment:
Variables:
EnvName: !Ref EnvName
Handler: app.lambda_handler
FunctionName: !Sub "${EnvName}-test-function"
Layers:
- arn:aws:lambda:ap-northeast-1:123456789:layer:your-layer-name:6
MemorySize: 256
Runtime: python3.8
Role: !GetAtt LambdaIamRole.Arn
Timeout: 60
LambdaIamRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
Description: A Role for Lambda to save file to s3
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonS3FullAccess
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
MaxSessionDuration: 3600
# Path: String
# PermissionsBoundary: String
RoleName: !Sub "${EnvName}testrole"
Tags:
- Key: LambdaName
Value: !Sub "${EnvName}-test-function"
まず、AWSアカウントAのLayerを使えるようにする必要があるので、その設定を行います。
ドンピシャな公式ドキュメントがありました。
コンソールから出来ないのか疑問ですが、CLIで以下のコマンドをたたけば一発です。
aws lambda add-layer-version-permission --layer-name your-layer-name --statement-id xaccount --action lambda:GetLayerVersion --principal 987654321 --version-number 1 --output text
次に、SAMテンプレートをAWS CLIを使ってデプロイします。
普通にやるなら、sam deploy --capabilities CAPABILITY_NAMED_IAMですね。
今回はIAM Roleを作成しているので、CAPABILITY_NAMED_IAMを指定しています。
sam deployコマンドを実行すると、AWSアカウントAにデプロイされます。
では、どうやってAWSアカウントBにデプロイするかというと、AWS CLIのProfileで別アカウントのProfileを使います。
私の場合は、スイッチロール出来るロールをAWSアカウントBに用意し、profileに設定します。
.aws/configファイルにスイッチロールするロールを記述するということです。
configファイルについての公式ドキュメント↓
こんな感じですね。
[default]
region=ap-northeast-1
output=text
[profile accountb]
region=ap-northeast-1
role_arn=arn:aws:iam::987654321:role/accountb-admin
source_profile=default
これで、accountbのprofileを使うとLambda関数がaccountbに作成されます。
なのでデプロイ時のコマンドは以下のようになります。
sam deploy --profile accountb --capabilities CAPABILITY_NAMED_IAM
ちなみに、
AWSアカウントAを開発環境、AWSアカウントBを本番環境とするなら、EnvNameをDevelopmentやProductionと変更することで、アカウント毎に環境の違うLambdaをデプロイできます。
2021/12/22追記
SAMデプロイ時のパラメータはsamconfig.tomlファイルに保存されています。sam deploy --guidedした時にsamconfig.tomlへ設定情報を書き込む、にYesを答えれば毎回パラメータを入力しないですみます。
このsamconfig.tomlですが、複数環境(複数のAWSアカウント)を設定することもできます。
結果的に今の私のsamconfig.tomlは以下のようになっています。(バケット名などはぼかしています)。
version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "your-stack-name"
s3_bucket = "accounta-bucket-name"
region = "ap-northeast-1"
confirm_changeset = true
capabilities = "CAPABILITY_IAM"
parameter_overrides = EnvName=\"Production\""
[accontb]
[accontb.deploy]
[accontb.deploy.parameters]
stack_name = "your-stack-name"
s3_bucket = "accontb-bucket-name"
region = "ap-northeast-1"
confirm_changeset = true
capabilities = "CAPABILITY_NAMED_IAM"
parameter_overrides = EnvName=\"Development\""
この設定ファイルを使って、普段はdefaultのバケット(アカウントA)へデプロイしていて、アカウントBへデプロイしたいときだけaccountbを使いたいです。
そのためのパラメータが--config-envというパラメータです。
なのでデプロイ時のコマンドは以下のようになります。
capabilitiesもsamconfig.tomlに書かれているので、わざわざ書く必要がなくなりました。
sam deploy --profile accountb --config-eng accountb
注意点ですが、--profileはAWSの認証情報でどれを使うかなのでAWSのconfigファイルを見に行っています。--config-envはSAMデプロイ時にどの環境でデプロイするかなのでsamconfig.tomlを見に行っています。
2022/1/20追記
次はLambdaではなくChalice(API Gateway)のデプロイ先をアカウントA、Bで切り替えたいケースが発生しました。Chaliceの設定ではsamconfig.tomlのようなファイルはないのでどうしようと思ったのですが、単純に--config-envのオプションを外せばよいだけでした。
つまり、下のコマンドでアカウントA(デフォルト)へデプロイできます。
chalice deploy
そして下のコマンドでアカウントB(profile=devのアカウント)へデプロイできます。
sam deploy --profile accountb
以上
Discussion