CloudFormationのスタック(Stack)を更新しても、更新されないリソース
まえおき
CloudFormationを使っているとスタック(Stack)の更新をすることがある。今までCloudFormation内をリソースを更新したときに、更新されなくて戸惑った3つの場合について書いてみる。
1. LambdaのコードをS3に保存した場合
当たり前かもしれないけど、その更新は最新のCloudFormationのテンプレートと旧テンプレートの差分より更新される。つまり、「テンプレートに変更がないとスタック内のリソースに更新は発生しない」ということだ。AWS::Lambda::Function
のCode
属性の記載方法には2つがある。テンプレート内に直接記載する方法とS3にファイルをアップロードし、そのバケット名とパスを記載する方法だ(関連ドキュメント)。ここで更新時に問題になるのはS3にLambdaファイルを更新する場合だ。S3のファイルを更新しても、CloudFormationテンプレート内のコードは変わることなく、S3ファイルの変化の検知もしないので、Lambdaが更新されない。私は以下の2つの方法で更新した。
方法1 S3パスを更新する
シンプルな方法である。AWS::Lambda::Function
のCode
属性を変更すれば、テンプレートに変更点が発生するのでLambdaを更新するkとおができる。私は日付ごとにフォルダを作成、更新するLambdaをおきテンプレートを修正するようにしていた。しかし、当時はCI/CD環境ではなかったので、テストでLambdaに修正点があれば、都度S3にファイルをアップロードして日付を修正&デプロイまたはテンプレートをロールバック&デプロイする必要があった。ミスも多く発生していた。そこで、CI/CD環境を整えることと同時に方法2の方法を利用することにした。
方法2 SAMを利用する(おすすめ)
SAM(Serverless Application Package) を利用する方法だ。SAMテンプレートを書いて、コマンドを実行すると以下が実行される。
- Lambdaファイルはランダム文字列のファイル名でS3にアップロードされる
- テンプレートをCloudFormationテンプレートに変換して、S3にアップロードしたLambdaのパスが記載してくれる。
ちなみに、SAMテンプレートにはCloudFormationの内容も記載できるので、SAMを利用したいところだけSAM文法で書けばよい。変換コマンドAWS CLIのaws cloudformation pacakge
とSAMのsam pacakge
を利用する。sam package
コマンドは、aws cloudformation package
のエイリアスなので、違いはない。ただ、下のStepfunctionに出るが最新のアップデートはsam package
の方でアップデートされ、まだaws cloudformation package
ではできない場合もあるので、sam package
を利用した方がいいかもしれない。この方法の短所は変換過程が必要なことと、1つのLambdaを直しても変換をするときにテンプレート内のすべての(SAMで記述された)lambda関数に対してアップロードをされるので、微々たるものだけどS3容量の無駄(?)が発生すること。でも、アップロードする手間を防げる点では方法1よりはこっちの方法をおすすめする。ついでに、CodePipelineでCodeCommit(またはGithub)→CodeBuild(ここで変換)→Cloudformationのパイプラインを組んでおくと楽に変換とデプロイができる。
参考ページ
2. StepFunctionsをS3に保存した場合
上記のLambdaと同じようにStepFunctionsのテンプレートコードをAWS::StepFunctions::StateMachine
のDefinitionS3Location
属性を利用してS3上ファイルに保存した場合にDefinitionS3Location
内の内容が変更されないと変更がないこととなり、StateMachineが更新されない。詳細は前回書いたCloudFormationテンプレート内のStep functionsのState machine定義をS3に置けるようになったを参照。更新方法としてもLambdaと同じように、S3パスを更新するか、SAMを利用すればよい。SAMを利用する場合は、DefinitionS3Location
は割と最新アップデートなので、SAMやCLIのバージョンが古いとうまく変換&アップロードしてくれないことに注意する必要がある。(私が何か月前に触ったときはSAM package
はできたが、Cloudformation pacakge
ではエラーとなった)
3. REST API Gatewayを更新してもデプロイされない
REST API形式のAPI Gatewayを利用している場合は、設定を更新するとデプロイを行う必要がある。問題はCloudformationでAPI Gatewayを更新する場合、設定の更新はされるがデプロイまではしてくれないことだ。ネットを探しても、手動でデプロイするか、カスタムリソースを使ってデプロイをする方法しかないみたい。
- CloudFormation doesn't deploy to API gateway stages on update
- Mastering CloudFormation for API Gateway Deployments
またはsam deploy
を利用してデプロイまで行えばできそうな気もするが、SAM CLIでアプリケーションを管理しないといけなさそうだったので、まだ試してはいない。ちなみに業務では手動でデプロイする方法を利用している。リリースルール上、決められたリリース日に本番環境に入ってリリースをしないといけないので、パイプラインで配布が終わった後にAPIGatewayのデプロイをする流れでやっている。
ちなみに、このことについて記事?ネット情報があまりなかったけど、みんな当たり前なことだと思っているのかな?私はデプロイされないことを知って結構驚いたけど…。
まとめ
Cloudformationでスタックを更新しても更新されない場合について書いてみた。ここら辺のことは、学習時はわからない場合が多く、実際に業務を行ってからわかるようになることが多いように思われる。今後、追加で更新されないことがあれば追記するようにしたい。