一覧に戻る
    AWS SpotFleetが意図せず50台起動していた話
    開発ラボ
    PRこの記事には広告が含まれています

    AWS SpotFleetが意図せず50台起動していた話

    15 分で読める

    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を動的に管理する設計でした。

    • ジョブキューにジョブがあれば、Pluginが必要な分だけTargetCapacityを増やす
    • ジョブがなければ、Pluginが0に戻す

    つまり、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なのか」を明記しておかないと、また同じミスをするかもしれません。

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

    起動しませんでした。

    ほっとしました。

    コストはどうなったか

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

    稼働状況

    • 合計インスタンス数:50台
    • 稼働時間:約50分(気づくまで40分 + 対応に10分)
    • 価格体系:Spot料金

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

    • c8i.xlarge × 10台:$0.0680/時間 × 10 × 0.833時間 = $0.57
    • t3.nano × 10台:$0.0011/時間 × 10 × 0.833時間 = $0.009
    • t3.small × 10台:$0.0044/時間 × 10 × 0.833時間 = $0.037
    • t3.medium × 10台:$0.0088/時間 × 10 × 0.833時間 = $0.073
    • t3.large × 10台:$0.0176/時間 × 10 × 0.833時間 = $0.147

    推定コスト:約 $1.41 USD

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    今回の教訓は:

    • 小さなミスの積み重ねで、大きなトラブルになる
    • チェックポイントを増やせば、どれか一つでも機能すれば防げる
    • AI駆動開発でも、最終判断は自分がする
    • デフォルト値は「安全側」に倒す
    • AIはリカバリーの強力な味方になる

    そして、もう一つ。

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

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

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


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

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

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


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

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

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

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

    • デフォルト値を「安全側」に倒すテンプレート設計を心がけます
    • 重要パラメータのレビューを徹底します
    • EventBridgeで通知を飛ばすように設定します
    • 通知が来たら即座に確認する習慣を作ります

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

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

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

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

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

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

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

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

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

    この記事は役に立ちましたか?

    Coffee cup

    この記事が、何かの整理につながったら

    コーヒー1杯分の応援をもらえると嬉しいです。

    ※ これは応援とは別の話ですが、

    同じようなテーマを自分の文脈で整理したい場合は、 (文章だけだと詰まりやすい人向けに) 思考整理の壁打ちという形で対話の時間も取っています。

    対話の時間について