40分後に気づいた

CloudFormationのスタック更新を実行して、別の作業に移りました。

40分後、ふとAWSコンソールを開いたら、EC2インスタンスが10台ずつ、合計50台起動していました。

「え?」

最初は状況が理解できませんでした。なんでこんなにインスタンスが立ってるんだ?

次の瞬間、理解しました。

「あぁ、やっちゃった」

焦りというより、「まずいな」という冷静な認識が先に来ました。これまでいろんな経験をしてきたので、このくらいでパニックにはなりません。でも、まずい。さっさと止めて、直さなければ。

そして、じわじわと広がる後悔。

「なんで確認しなかったんだ」

気になったのは、やっぱりコストでした。スポットインスタンスとはいえ、50台が40分。これ、いくらになるんだろう。

何が起きたのか

今回の作業は、Jenkins Agentとして使うSpotFleetに、複数のインスタンスサイズパターン(t-nano、t-small、t-medium、t-large、c-xlarge)を追加するものでした。

Claude Codeと対話しながら、CloudFormationテンプレートを修正していました。差分は大きく、LaunchTemplateが増え、SpotFleetリソースが5つに分かれ、パラメータも追加されました。

CloudFormationテンプレートで5つのSpotFleetリソースを定義し、それぞれに以下のような設定を書いていました:

TargetCapacity: !Ref MaxTargetCapacity

MaxTargetCapacity パラメータは 10 に設定していました。つまり、各SpotFleetが10台ずつインスタンスを起動する設定になっていたのです。

本来、この構成では Jenkins EC2 Fleet Plugin がSpotFleetのTargetCapacityを動的に管理する設計でした。

つまり、CloudFormationテンプレート側で初期TargetCapacityを設定すべきではありませんでした。正しくは:

TargetCapacity: 0

TargetCapacityについては、知っていました。でも、見落としました。

スタック更新を実行した後、別の作業に移りました。CloudFormationは時間がかかります。その間、他の作業をするのは自然な流れでした。

40分後、確認しました。

50台起動していました。

小さなミスの積み重ね

今回のトラブルを振り返って、気づいたことがあります。

これは、単一のミスではありませんでした。

複数のチェックポイントをすり抜けた結果でした。

すり抜けたチェックポイント

1. 設計段階:デフォルト値を「安全側」に倒す

テンプレート設計時に、TargetCapacity: 0 というデフォルト値を設定していませんでした。「安全側」に倒すという設計思想が欠けていました。

ここでデフォルト値を0にしていれば、そもそも起動しませんでした。

2. レビュー段階:AI生成コードの重要パラメータを確認

差分が大きすぎて、細かくレビューする気力がありませんでした。「まあ大丈夫だろう」と思って流してしまいました。

ここでTargetCapacityの設定に気づいていれば、防げました。

3. 実行後段階:スタック更新完了の通知を設定

スタック更新完了の通知を設定していませんでした。EventBridgeやSNSを使えば、スタック更新完了を自動通知できます。

ここで通知があれば、確認を忘れませんでした。

4. 確認段階:通知後の即座確認を習慣化

スタック更新を実行した後、すぐに確認すればよかったのですが、CloudFormationは時間がかかるため、その間、他の作業に移りました。

ここで確認していれば、もっと早く気づけました。

どれか一つでもあれば、防げた

これらのチェックポイントのうち、どれか一つでも機能していれば、50台起動は防げました。

でも、すべてがすり抜けました。

小さなミスの積み重ねが、大きなトラブルになりました。

こういうトラブルは、いつもそうです。単一のミスで起きるわけではありません。複数のチェックポイントをすり抜けて、初めて起きるのです。

緊急対応:AI駆動開発の「凄さ」を知る

50台起動を確認した瞬間、頭の中でいくつかの選択肢が浮かびました。

  1. CloudFormationテンプレートを修正して、再度スタック更新する
  2. AWS CLIで直接SpotFleetのTargetCapacityを0にする
  3. コンソールから手動でインスタンスを終了する

「まず止める」

これを最優先にしました。

ここで、Claude Codeに対応を依頼しました。

「50台起動してしまった。まずSpotFleetのTargetCapacityを0にして、起動中のインスタンスを終了させたい」

Claude Codeは、丁寧に実行条件を整理してから対応してくれました。

まず、起動中のSpotFleetリクエストをすべて確認。次に、各SpotFleetのTargetCapacityを0に設定するコマンドを正確に生成してくれました:

aws ec2 modify-spot-fleet-request \
  --spot-fleet-request-id sfr-xxx \
  --target-capacity 0

5つのSpotFleetすべてに対して、正確なIDを指定して実行。

次に、起動中のインスタンスIDをすべて取得して、一括で終了させるコマンドを生成してくれました:

aws ec2 terminate-instances \
  --instance-ids i-xxx i-yyy i-zzz ...

このプロセスが、驚くほど早かったです。

自分でやろうとしたら、SpotFleetのIDを確認して、コマンドを書いて、実行して、インスタンスIDを確認して、また書いて、実行して...という手順を踏む必要がありました。ミスも起きるかもしれません。

でも、Claude Codeは正確にコマンドを書いて、実行条件を整理してから実行してくれました。人よりも早い。

リカバリースピードは、ものすごく早かったです。

止まりました。

AI駆動開発の両面性

今回の経験で、AI駆動開発の「怖さ」と「凄さ」を同時に知りました。

怖さ

凄さ

AI駆動開発は、失敗も引き起こすし、リカバリーも助けてくれます。

テンプレートを修正する

緊急対応が終わったら、次はCloudFormationテンプレートの修正です。

TargetCapacity: 0  # Jenkins EC2 Fleet Plugin に管理を委ねる

コメントも追加しました。「なぜ0なのか」を明記しておかないと、また同じミスをするかもしれません。

修正をコミットして、再度スタック更新を実行しました。今度は、画面を見ながら確認しました。インスタンスが起動しないことを確認するまで。

起動しませんでした。

ほっとしました。

コストはどうなったか

落ち着いてから、気になっていたコストを計算してみました。

稼働状況

内訳(us-west-2、Spot料金):

推定コスト:約 $1.41 USD

Spot料金のおかげで、予想していたよりずっと安く済みました。

「$1.41で済んだ」と思った瞬間、肩の力が抜けました。でも同時に、「これでいいのか?」という疑問も浮かびました。

$1.41で済んだから、学びが薄れるんじゃないか。

もし気づくのがもっと遅れていたら。もしオンデマンドインスタンスだったら。もし本番環境だったら。

考えたくないですが、考えなければいけません。

次に向けて:チェックポイントを増やす

今回のトラブルは、複数のチェックポイントをすり抜けた結果でした。

では、次はどうすればよいのでしょうか。

チェックポイントを増やせばよいのです。

具体的なチェックポイント

1. 設計段階:デフォルト値を「安全側」に倒す

TargetCapacity、MinSize、MaxSizeなどのパラメータは、デフォルト値を0または最小値にします。「何もしない」が安全な状態にするのです。

2. レビュー段階:重要パラメータを必ず確認する

差分が大きいときこそ、丁寧にレビューします。特に、容量やサイズに関するパラメータは必ず確認します。

3. 実行後段階:スタック更新完了の通知を設定する

EventBridgeとSNSを使って、スタック更新完了を自動通知します。Slackやメール、スマホの通知でもよいでしょう。

4. 確認段階:通知が来たら即座に確認する

CloudFormationは時間がかかるので、他の作業に移るのは仕方ありません。でも、通知が来たらすぐに確認する。それを習慣にします。

一つが失敗しても、他でカバーできる

チェックポイントを増やす意味は、一つが失敗しても、他でカバーできるようにすることです。

今回の教訓は:

そして、もう一つ。

知っていることと、実践することは違う。

TargetCapacityについては知っていました。でも、見落としました。知識と実践の間には、常にギャップがあります。

そのギャップを埋めるのは、チェックポイントです。


この記事で触れた「チェックポイントを増やす」という考え方は、SRE(Site Reliability Engineering)の基本的な思想と通じます。Googleの経験に基づくこの書籍では、障害を前提としたシステム設計や、人間のミスを仕組みでカバーする方法が体系的に解説されています。

[📦 商品リンク: moshimo-book-sre-google]

クラウドインフラを扱う上で、サーバやネットワークの基礎知識は欠かせません。SpotFleetやCloudFormationを使いこなすためにも、こちらの書籍で基本を押さえておくことをお勧めします。

[📦 商品リンク: moshimo-book-server-infra]

AWS運用の基本から実践的なノウハウまで体系的に学べる一冊です。EC2やSpotFleetの適切な設定方法を理解し、今回のようなインシデントを未然に防ぐために役立ちます。

[📦 商品リンク: moshimo-book-aws-operations]


次はもっとうまくやれるはずだ(でも本当にそうだろうか)

$1.41で済んだことに、安堵している自分がいます。でも、それでいいのでしょうか。

いや、この経験を活かして、次に繋げていきたいと思います。

チェックポイントを増やしていきます。

一つが失敗しても、他でカバーできる。

次は、もっとうまくやれるはずです。

でも、本当にそうでしょうか。

また忘れた頃に、同じことを繰り返すんじゃないか。

チェックポイントを増やすと決めても、実際に設定するのは面倒です。EventBridgeの設定を後回しにして、そのまま忘れるかもしれません。通知が来ても、「あとで確認しよう」と思って、また40分後になるかもしれません。

人間は忘れる生き物です。そして、「大丈夫だろう」と油断する生き物です。

今回の教訓を活かせるかどうかは、結局、未来の自分次第です。

未来の自分を、どこまで信じられるか。

その問いに、まだ答えは出ていません。