
どうも、PHPerです。
先日、友人のWebアプリケーションエンジニアとIaC(Infrastructure as Code)について話す機会がありました。 話の発端は「Terraform と CDK、どっちを採用すべきか?」というよくあるテーマだったのですが、友人からこんな強烈な一言をもらいました。
「CDK一択でしょ。だってCDK(CloudFormation)はデプロイ失敗時に自動ロールバックしてくれるけど、Terraformは作りかけで止まるでしょ?怖くて使えないよ」
なるほど、確かにその視点はあります。DBのトランザクションに慣れ親しんだエンジニアからすれば、「失敗したらAtomicに元に戻る」挙動こそが正義でしょう。
しかし、普段Terraformを触っている身からすると「うーん、それは『ロールバック』の定義や運用思想が違うだけでは?」というモヤモヤが残りました。
今回は、この「IaCにおけるロールバックと復旧戦略」について、公式ドキュメント等の情報を交えながら整理してみたいと思います。
そもそも「ロールバック」とは何を指しているのか?
友人が言っていた「ロールバック」は、主に 「デプロイ(Apply)が途中でコケた時の挙動」 を指しています。
CDK の場合
CDKは、コンパイルされると最終的に AWS CloudFormation テンプレート になり、デプロイもCFnを通じて行われます。
- 挙動
スタックの更新中にエラーが発生すると、CFnは 「自動的に直前の正常な状態に戻そう」 とします。 - ステータス
UPDATE_ROLLBACK_IN_PROGRESS→UPDATE_ROLLBACK_COMPLETE
これはCloudFormationの基本機能として提供されています。
スタックの更新のロールバック - AWS CloudFormation
メリット
何もしなくても「壊れた状態」で放置されることが少ないです。
「オール・オア・ナッシング」に近い挙動をするため、整合性が保たれやすい安心感があります。
デメリット
ロールバックには時間がかかります。
リソース作成に30分かかって失敗した場合、ロールバックにも同等の時間がかかることがあります。
また、ロールバック自体が失敗するUPDATE_ROLLBACK_FAILEDという状態に陥ると、手動での介入が必要になり、復旧難易度が跳ね上がります。
参考: 更新のロールバックに失敗したスタックを更新できるようにする - AWS CloudFormation
Terraform の場合
Terraformは、AWSのAPIを直接叩いてリソースを操作します。
- 挙動
terraform apply中にエラーが発生すると、その時点で処理が停止します。 - ステータス
成功したリソースは作成済み、失敗したリソースは未作成(または中途半端)な状態で残ります。
Terraformには「自動ロールバック」という機能自体が存在しません。これはバグではなく仕様(思想)です。
HashiCorp Terraform: Command: apply
メリット
エラーの原因が明確で、「ここまでは成功した」という状態がStateファイルに保存されます。
コードを修正して再実行(terraform apply)すれば、差分のみを適用し直すため、復旧までの時間が圧倒的に短いです。
デメリット
「中途半端な状態」が一時的に発生するため、手動でのリカバリ(State操作やTaint)が必要になる場合があります。
なぜTerraformには自動ロールバックがないのか?
Terraform派の意見として、「自動ロールバックがないこと」は 「Fail Fast(早く失敗して早く直す)」 という設計思想に基づいています。
- Stateの一貫性重視
Terraformは「現在のインフラの状態」をtfstateファイルで厳密に管理します。
勝手にロールバック(過去の状態に戻すAPIコール)を行うと、ローカルのコードと現実のリソースの乖離が複雑化するリスクがあります。 State - Terraform by HashiCorp - Roll Forward(前進による修復)の推奨
インフラ変更において、失敗した場合は「元に戻す」よりも「修正して適用し直す」方が早いケースが多いです。
Terraformはplanコマンドで事前に変更内容を詳細に確認できるため、実行時エラーは「権限不足」や「パラメータ不正」などが主であり、コードを直して再Applyすれば済むことがほとんどです。
ロールバックというバージョン切り戻し
友人の言う「デプロイ失敗時の自動復旧」ではなく、「正常にデプロイしたけどアプリが動かないから昨日の構成に戻したい」 という場合のロールバックはどうでしょうか。
- CDK (CloudFormation): Gitで以前のコードに戻し、再デプロイします。 ※ CFnの自動ロールバックはあくまで「デプロイエラー時」の挙動であり、論理的なバグまでは戻してくれません。
- Terraform: Gitで以前のコードに戻し、
terraform applyします。
つまり、「正常デプロイ後の切り戻し(Revert)」に関しては、両者の手間に大きな差はありません。 どちらも「Gitを正」として、過去のコミットの状態へインフラを収束させる作業になります。
結論:どっちが良いのか?
友人の「CDKの方が優秀」という意見は、「デプロイ作業中の安全性」 に重きを置いた意見と言えます。特にアプリケーションエンジニアにとって、デプロイ失敗時に環境が散らかったままになるのは恐怖でしょう。
一方でTerraformは、「状態の透明性と制御」 に重きを置いています。「勝手に戻るより、どこで止まったか教えてくれ。俺が直すから」というスタンスです。
まとめ
- CDK (CloudFormation)
- 特徴: 失敗時は自動で元通り(トランザクション的)。
- 向いているケース
インフラの詳細なステータス管理より、デプロイパイプラインの安定性を重視したい場合。ロールバック待ち時間が許容できる場合。
- Terraform
- 特徴
失敗時はそこでストップ(即時停止)。修正して再実行(ロールフォワード)。 - 向いているケース
terraform planで事前に結果を予測し、失敗時も自分の手ですぐに復旧させたい場合。APIコールの速さを求める場合。
- 特徴
「ロールバックがあるからCDK」ではなく、「失敗時のリカバリ戦略として、自動復帰(CDK)と即時停止(Terraform)のどちらが自分たちのチームに合っているか」で選ぶのが正解ではないでしょうか。
私は……やっぱり terraform plan で「何が起きるか完全に把握してから実行する」安心感が好きですね(笑)


