
インフラ
イベント
マガジン
技術ブログ
こんにちは、楽楽販売開発課のdon (頓花)です。 あるサブシステムをゼロから設計する機会があり、ADR(Architecture Decision Record/アーキテクチャ上の意思決定を記録するドキュメント)を書く場面が一気に増えました。 そこで Claude Code を検討プロセスそのものに組み込んでみたのですが、最初に作った仕組みは、実際に走らせてみるとひどいものでした。エージェントが 1 体で 約60分 動き続ける。工程の境界でユーザー確認が 20 回近く飛んでくる。レビューが 3 巡目に入ってもう何も新しい指摘が出ない。 この記事は、そこから何を直したかの記録です。 この記事で分かること 自分の検討プロセスを工程に分解して Skills に移植する手順 マルチエージェント構成で「全員が会話に参加し続ける」構成をやめた理由 前提情報をリポジトリに置いて AI に読ませる運用 動かしてみて初めて分かった、重い箇所の潰し方 【目次】 足りないのは AI の賢さではなかった 前提: 3 つの仕組みを使い分ける まず、自分が ADR を考える流れを分解する 工程をオーケストラ Skills +専門エージェントで構成 全員呼ばない、1 回に集約する 試行錯誤①: 全工程エージェントチームから、サブエージェントへ変更 試行錯誤②: 前提情報を AI が読める形に整理 試行錯誤③: ログを見て Skills 自体を改善 効果と、いまの課題 効果 課題 ADR 以外への応用 まとめ 参考リンク 足りないのは AI の賢さではなかった ADR に AI を使おうとすると下記のようなことがよく発生します。 ひとつは 単発チャット地獄 です。毎回ゼロから前提を説明し直す。「このプロダクトはこういう構成で、過去にこう決めていて……」と貼り直すだけで疲れて、本題に入る前に力尽きます。 もうひとつは 丸投げ です。「いい感じに ADR 書いて」で出てくるものは、形式は整っているのに検討が浅い。観点の抜け漏れが残り、レビューで結局やり直しになります。 どちらも AI の能力の問題ではありませんでした。足りていなかったのは、 自分の検討プロセスを AI が再現できる形にすること でした。 そしてこれは、単に開発が楽になるかどうかの話ではありません。AIへ委譲する割合を増やすことで並列で作業ができるようになり、開発速度を上げることができるようになります。 前提: 3 つの仕組みを使い分ける 本題ではないので手短に触れます。Claude Code には次の 3 つの仕組みがあります。 Skills : 「こういうときはこう進める」という手順書を Claude Code に持たせる仕組み サブエージェント(subagent) : タスクを独立したエージェントに渡し、結果だけ受け取る。呼ばれたときだけ動作するため、呼び出し元の文脈を汚さずに実施できる仕組み エージェントチーム(Agent Teams) : 複数のエージェントが互いにメッセージを送り合って議論する仕組み 。全員が会話に参加し続ける のが特徴 ※ 詳細は公式ドキュメントを参照: Skills / subagents / Agent Teams まず、自分が ADR を考える流れを分解する AI に渡す前にやったのは、 自分の頭の中の工程を言語化する ことでした。ここを飛ばして skills を書き始めると、結局「いい感じに」と書いてあるだけの手順書になります。 ADR 検討を、動詞ベースで次の工程に分けました。 前提固め → 計画 → 案出し →(検証)→ 独立評価 → 合議 → ドラフト化 →(実装) 工程 要否 やること 前提固め 前提・スコープ境界・完了条件をユーザーと対話して合意する。 既存の決定・仕様・API 定義もここで走査する 計画 この論点ではどの専門家を呼ぶか、どこまでやるかを決める 案出し 選択肢を出し、各案を最新の一次情報で詳細に調べる 検証 任意 判断に動作確認が要るなら、使い捨ての PoC を作る 独立評価 専門家が各自 独立に 案を評価する(あえて合議させない) 合議 出そろった評価をもとに方針を確定する ドラフト化 ADR 本体を書く 実装 任意 採用案を試しに実装する 設計時に気にした点は2点です。 先頭の「前提固め」で、人間の判断を最初に組み込む。 ここでスコープ境界と完了条件をこちらが合意します。後工程がいくら賢くても、前提がずれていれば的を外した ADR が出てくるだけです。 明確にステップを区切る。 これにより作業ごとにコンテキストを分けられるためトークンの節約やコンテキスト肥大化の抑制につながります。 工程をオーケストラ Skills +専門エージェントで構成 分解した工程を、ひとつの大きな Skills(オーケストラ役)が指揮し、工程ごとに専門エージェントを呼ぶ構成にしました。 編成は次のようになっています。読者のみなさんが自分のプロセスに置き換えるときの参照にしてください。 区分 体数 役割 モデル 指揮役 1 計画を立て、呼ぶ専門家を選ぶ 重め 調査・案出し役 1 前提の下調べと選択肢の整理 軽め 集約・執筆役 1 議論をまとめ ADR をドラフト 重め 検証役 1 使い捨て PoC(任意工程) 軽め 常駐レビュアー 1 全工程に伴走し観点を採点 軽め 反論役(Devil's Advocate) 1 必ず 1 件以上の反論・Blocker を出す 軽め 領域別の専門家 5 言語 2・DB・API 契約・Python 系 軽め 横断的な専門家 4 運用・インフラ・クラウド・セキュリティ 軽め プロダクト知見の専門家 1 既存プロダクトとの整合・移行・業務観点 軽め 横断ルールのチェックリストを常駐レビュアーの必須参照にし、逸脱を Blocker として報告させ、事例を追記して育てる循環 進行を指揮する役と、最後に決定をまとめる役だけ重いモデルを割り当てています。ここは判断の質が成果物に直結するためです。それ以外は軽いモデルで十分でした。 全員呼ばない、1 回に集約する エージェントを 16 体も定義すると、素直に組めばコストが爆発します。抑えるために入れた工夫が 4 つあります。 専門家を毎回全員呼ばない。 指揮役が論点を分類し、必要な数体だけ起動する。 (ex: DB の話が出てこない ADR に DB の専門家は不要なため起動しない。) 専門家の起動を 1 工程に集約する。 同じ専門家を案出しから実装まで何度も叩き直さず、独立評価の工程で 1 回だけ評価させます。 重いレビューはドラフト工程の 1 回だけにする。 別系統のレビューを挟むのは仕上げの手前だけです。 常駐の 2 体は工程ごとに起動して破棄する。 常駐レビュアーと反論役は全工程に伴走しますが、チームとして常駐させるのではなく、工程ごとにサブエージェントとして呼び直しています。 エージェントを増やすのは簡単ですが、実際に重いのは「どの工程で、どの論点のときに呼ぶか」を決める作業のほうでした。 試行錯誤①: 全工程エージェントチームから、サブエージェントへ変更 最初は 全工程をエージェントチームでやろうとしました 。 複数の専門家が議論しながら設計を詰める構成にしました。理論上はコンテキストも節約しながら進められる想定でした。 しかし、実際には全員が会話に参加し続けるので コンテキストが急速に肥大 し、評価が出そろう前から議論が混線するようになりました。それによりそれぞれの主張が曖昧になり、セッションが長くなりトークン消費量も増大しました。 ( Claude Code でMaxプランの5時間制限の30%近くを1セッションで消費しました。) そこで構成を切り替えました。 既定はサブエージェント方式 にする。独立に呼び出し、結果はファイルで受け渡す。 合議の工程も、まずは指揮役が評価を読んで直接まとめる 方式を既定にする。 エージェントチームは明示的に指定したときだけ 使う(重い論点で本当に対話が要るケース) 試しに同じタスクを比較すると、セッションの稼働時間が改善後(サブエージェント案)は改善前(エージェントチーム)の 約 1/3 になりました。 ※ ただしこれは 1セッションのみ での計測結果です。 得られた教訓は「マルチエージェント=エージェントチームを常用する」ではなかった、ということです。 対話が本当に要る工程だけチーム、それ以外は独立したサブエージェント という使い分けが、コンテキスト効率に効きました。 もっともこれは私のケースでの結果です。エージェントチームの使い方を詰めれば別の最適点があるはずで、エージェントチーム自体が悪いという話ではないと考えてはいます。 試行錯誤②: 前提情報を AI が読める形に整理 手順(Skills)が良くても、 前提が無ければ検討は浅くなります 。専門家エージェントに「このプロダクトならこの方針」という前提が無いと、教科書的な一般論しか返ってきません。 そこで前提情報を 4 カテゴリに整理して、コンテキストとしてAIに明示的に渡すようにしました。 プロダクトの特性・大方針 既存の決定 : 決定済みのADR のリスト 横断ルールのチェックリスト : 承認済みの ADR で確定した設計判断のうち、議論で逸脱されやすい項目だけを 1〜数行に圧縮 調査方針 : 学習データの記憶に頼らせず、案出しのたびに最新の一次ソースの調査を必須化 3 番目のチェックリストは、実際の失敗から生まれました。 たとえばマルチテナントのデータ分離方式を「スキーマを分ける」と決めていたとします。ところがエージェントは、論点が変わるたびに「識別カラムを持たせる方式ではどうか」と提案してきます。一般論としては妥当な案なので、毎回それらしい理屈がついてきます。決定済みの前提が渡っていないと、こうした「もっともらしい差し戻し」が延々と発生します。 これを毎回人間が指摘して回るのは無理があります。そこで確定事項をチェックリストにまとめ、 常駐レビュアーと反論役の必須参照 にしました。逸脱を見つけたら Blocker として報告させる、という構造的な対策です。 このチェックリストは、逸脱事例を観測したら都度追記する運用にしています。最初から完璧なものは書けないので、育てる前提で置いています。 試行錯誤③: ログを見て Skills 自体を改善 Skills を書いて終わりにはできませんでした。実際に ADR を通して走らせ、ログを見て重い箇所を 1 つずつ潰しました。 実走で見えた問題 直した内容 単発で 約60分 動き続けるエージェント 出力件数・文字数・想定時間に上限を設ける 工程の境界でユーザー確認が 約20回 既定で自動進行にし、Blocker 検出時だけ停止する レビューが 3巡目 で空転 レビューは2巡までとし、超えたらユーザーに引き継ぐ 通しで走らせた後に「これ ADR で扱う話?」となる事故 冒頭に適格性ゲートを1問だけ置く とくに 2 番目は、自分で書いた Skills に「条件付き自動進行」と謳っておきながら、実際は毎境界で確認を飛ばしていたという間抜けな話です。動かしてみるまで気づきませんでした。 4 番目も同じです。ドラフトまで通した後に「これは ADR ではなく機能方針の話では?」と自分で疑問を持ってしまった。なので最初に「本件は ADR で扱うべきか」だけを 1 問聞き、そうでなければ別の進め方を提案して終わる、というゲートを置きました。 ここで狙ったのは平均時間の短縮ではなく、 極端に重いケースを抑えること です。約 60 分動き続けるエージェントが 1 体いれば、平均がどうであれ体験は破綻します。 効果と、いまの課題 効果 体感として得られたものは 3 つあります。 前提の貼り直し回数が低減 毎回の説明から解放され、検討の中身に時間を使えます。 浮いた時間は、業務課題そのものを理解する側に回せるようになりました。 観点の欠落が低減 反論役が必ず 1 件以上の反論を出すので、後工程で気づいて手戻りする回数が減りました。 AI同士の議論が建設的に 変更前はAI同士の議論が追認会になることがありましたが、 独立評価 → 合議の順にしたことと、合議には反対の立場を持つメンバーを必ず 1 名入れるようにしたことにより建設的な議論になった。(気がします。) 課題 一方で課題も残っています。 効果は体感どまりで、定量的な比較ができていない 前提チェックリストや上限設定の効果は、再実走で検証待ち ADR 専用で、機能要件や詳細設計は対象外 ADR 以外への応用 ここまで ADR を例に書きましたが、同じ型は「検討プロセスを持つ仕事」全般に使えるはずです。実装設計、技術選定、障害の振り返りなど、頭の中に工程がある仕事ならどれも当てはまります。 共通する型はこうです。 プロセスを分解する → 工程を Skills 化する → 前提を AI が読める形にする → 対話が要る工程だけチームにする まとめ AI に丸投げするのでも、単発質問を繰り返すのでもなく、 自分の検討プロセスを移植する 。これが今回いちばん効いた考え方でした。 AI に任せる範囲を広げることが AI ネイティブな進め方だと思っていましたが、実際は逆でした。 人が判断する場所を先に決めるほど、残りを安心して任せられる 。冒頭に「前提固め」を置いたのは、まさにそのためです。 最初の一歩は Skills を書くことではありません。 まず自分が普段どう考えているかを書き出してみること です。 それを Skills に移植し、試し、改善していくことによってAIによる効率化を進めていくことができると思います! 参考リンク Claude Code 公式ドキュメント Extend Claude with skills Create custom subagents Agent teams
はじめに リアルタイム性の高いマルチプレイヤーゲームは、複数のプレイヤーの入力を集約し、ゲームの状態を一貫させて全員へ配信する仕組みを必要とします。この仕組みの一つに、権威あるサーバーがゲームの状態を管理する専用ゲームサーバー (Dedicated Game Server) 方式があります。対戦の公平性やチート対策、多人数の同時接続が求められるタイトルでは、専用ゲームサーバー方式が広く採られています。この方式では、マッチメイキング、ゲームサーバーの割り当て、セッション終了後のサーバー回収といったライフサイクル管理が必要になり、そのオーケストレーション基盤をどう構築・運用するかが設計上の大きなテーマとなります。 AWS で専用ゲームサーバーをホストする主な選択肢は、マネージドサービスの Amazon GameLift Servers を利用するか、 Amazon Elastic Compute Cloud (EC2) や Amazon Elastic Container Service (ECS) 、 Amazon Elastic Kubernetes Service (EKS) 上でセルフホストするかの 2 つです。GameLift Servers はインフラ構築・運用の大部分を担いますが、要件によってはより柔軟な制御が必要な場合があり、 Agones の利用が選択肢の一つとなります。Agones はオープンソースの専用ゲームサーバーホスティング向け製品で、Amazon EKS 上にデプロイでき、柔軟性を享受しつつ専用ゲームサーバーの構成を簡素化できます。しかし Kubernetes 基盤の運用は避けられず、Agones の運用には一定の負荷が存在しました。 2024 年 12 月に一般提供が始まった Amazon EKS Auto Mode は、Kubernetes の構築・運用負担を低減する機能です。Agones の基盤となる EKS クラスタで EKS Auto Mode を利用できれば、専用ゲームサーバーを柔軟かつ簡素に構築・運用できます。ただし EKS Auto Mode にはいくつかの制約もあります。 本記事では、EKS Auto Mode の制約が Agones の特性を阻害しないようにするための設計方針を紹介します。 Agones リソースの概要 本記事の内容に関連する Agones カスタムリソースについて説明します。 GameServer: プレイヤーが接続するゲームサーバープログラムが動作する Pod にあたるリソースです。状態を持ち、Ready 状態はゲーム開始可能で待機している状態、Allocated 状態はゲームプレイのためにリソースが確保された状態を表します。 Fleet: GameServer のまとまりを管理するためのリソースです。常に起動しておくべき GameServer リソースの数を指定でき、Fleet Autoscaler リソースによるスケーリング制御も可能です。 GameServer Allocation: ゲームプレイのために GameServer リソースを選択し確保する操作を行うリソースです。この操作により選択された GameServer リソースは Ready 状態から Allocated 状態となります。 コントローラ系リソース: Agones の機能を実現・制御するためのリソース群です。 EKS Auto Mode と Agones の共存における課題 EKS Auto Mode は、クラスタのノード管理を AWS の責任範囲で自動化します。例えば Karpenter をベースとしたノードのプロビジョニング・スケーリング・入れ替え、Bottlerocket による最適化された OS、各種アドオンのマネージド管理といった機能により、Kubernetes の運用を大幅に簡素化できます。 一方、ユーザー側で設定できる範囲が狭まるというトレードオフがあります。Agones の基盤として特に考慮が必要なのは、EKS Auto Mode が以下の目的のために自動で行うノードの中断です。 Consolidation: 稼働中の Pod が少ないノードを終了し、利用率の高いノードへ Pod を集約してコストを最適化する。 Drift: NodePool や NodeClass の設定変更、AMI の更新などに追従してノードを入れ替える。 Expiration: セキュリティ維持のため、一定期間が経過したノードを強制的に入れ替える。 Interruption: Spot Instance の中断通知やハードウェア障害などに応じてノードを終了する。 ※EKS Auto Mode の長期実行ワークロードでの扱いについては、builders.flash 記事「 Amazon EKS Auto Mode のノード自動更新を Deep Dive する 」もあわせて参照ください。 いずれの中断でも、対象ノード上の Pod へ SIGTERM が発行されます。Agones上で動かすような専用ゲームサーバーには「プレイ中のゲームセッションを中断させない」という強い制約があるため、対策をしないとプレイ中のゲームサーバーが強制終了されるリスクがあります。 EKS Auto Mode と Agones を共存させる設定のポイント そこで、Agones のコントローラ系とゲームプレイ中のサーバープログラムをノードの中断から保護する仕組みを、次の 6 つのポイントで構成します。以降、それぞれのポイントについて、実際の設定ファイル ( nodepools.yaml / fleet.yaml / agones-values.yaml ) を引用しながら、具体的な実装方法を説明します。 Point # 対象 内容 Point 1 共通 NodePool の expireAfter 、 terminationGracePeriod を適切に設定する Point 2 GameServer GameServer の Pod の terminationGracePeriodSeconds をゲームの最大持続時間より長い値に設定する Point 3 GameServer GameServer 上で動くサーバーアプリで、適切なシグナルハンドリングを実装する Point 4 GameServer Eviction を許可してノードの自動最適化を機能させる ( spec.eviction.safe: Always ) Point 5 コントローラ系 Agones コントローラ系と GameServer が配置される NodePool を分ける Point 6 コントローラ系 agones-allocator と agones-ping の PDB を有効にする Point 1 (共通) :NodePool の expireAfter / terminationGracePeriod を適切に設定する EKS Auto Mode では、ノードは必ずいつか中断されます。特に Expiration はノード生存期間最大21日の制約があり、必ず発生します。この expireAfter の値と、ノードが強制的に中断されるまでの猶予期間である terminationGracePeriod を、ワークロード特性に合わせて NodePool に設定することが起点になります。 NodePool とは、Karpenter ベースのノード管理機能で、Pod の要求に応じてインスタンスを自動的にプロビジョニング・スケーリングし、クラスターのコンピュートリソースを柔軟に管理するための仕組みです。 設定にあたっては、次の関係を守るようにしてください。 terminationGracePeriod は、後述する Pod の terminationGracePeriodSeconds より長く設定する (ノードが強制削除される前に、Pod が Graceful に終了しきるようにするため) 。 expireAfter + terminationGracePeriod の合計は最大 21 日に収める (EKS Auto Mode の制約) 。 また disruption.budgets の nodes: "10%" (NodePool Disruption Budgets: NDB)により、同時に中断処理へ入るノード数を全体の 10 % に制限し、一斉中断の影響を抑えます。 consolidationPolicy: WhenEmpty については Point 4 で触れます。 Point 1 を踏まえた NodePool の設定例は次の通りです( nodepools.yaml )。 # GameServer 用 NodePool apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: agones-worker spec: template: spec: # Point 1: ゲームセッション時間を考慮して設定 # terminationGracePeriod は Pod の terminationGracePeriodSeconds より長くすること expireAfter: 336h # 14日 terminationGracePeriod: 4h # expireAfter + terminationGracePeriod が21日(504h)に収まるように disruption: consolidationPolicy: WhenEmpty consolidateAfter: 30s budgets: - nodes: "10%" Point 2(GameServer):Pod の terminationGracePeriodSeconds をゲーム最大持続時間より長く設定する ノードが中断され Pod に SIGTERM が発行されてから、Pod が強制終了(SIGKILL)されるまでの猶予が terminationGracePeriodSeconds です。この値をゲームの最大持続時間より長く設定することで、進行中のゲームが途中で強制終了されることを防ぎます。 terminationGracePeriodSeconds は Pod リソースの設定値ですが、Agones では GameServer リソース定義内で設定することになります。また GameServer の制御は Fleet で行うことが一般的なため、ここでは Fleet の設定例を次の通り示します ( fleet.yaml ) apiVersion: "agones.dev/v1" kind: Fleet metadata: name: simple-game-server-fleet spec: replicas: 3 template: spec: # ... (省略) template: spec: # Point 2: ゲームセッション最大持続時間 + バッファより長い値を設定 # 例: ゲーム最大30min + クリーンアップ5min = 35min = 2100sec terminationGracePeriodSeconds: 2100 ゲームセッション 1 つの最大持続時間に、クリーンアップ処理のバッファを加えた値を設定します。Point 1 の terminationGracePeriod (ノード側の猶予) を、この terminationGracePeriodSeconds (Pod 側の猶予) より長く設定することで、 terminationGracePeriod > terminationGracePeriodSeconds > ゲーム最大持続時間 の関係が成立し、プレイ中のゲームを保護できます。 まとめると、 以下を満たすように各パラメータを設定すればよいことになります。 NodePool の terminationGracePeriod > Pod の terminationGracePeriodSeconds > ゲームの最大持続時間 NodePool の expireAfter は自由 ( terminationGracePeriod との合計は 21 日以下) Point 3 (GameServer) :適切なシグナルハンドリングを実装する Point 1・2 で猶予期間を確保しても、SIGTERM を受け取ったサーバープログラムが適切に振る舞わなければ、ゲームサーバーは安全に終了できません。GameServer 上で動くサーバープログラムでは、SIGTERM を受信したときに次の動作を実装します。 Allocated 状態 (ゲーム進行中) :進行中のゲームの終了を待ち、クリーンアップ処理を行った後に Agones SDK の sdk.Shutdown() を呼び出す。 Ready 状態 (待機中) :新規 Allocation を防ぐため、即時 sdk.Shutdown() を呼び出す。 この実装により、ノード中断のシグナルを受けても、進行中のゲームを守りつつ、待機中のサーバーは速やかに退去できます。 Point 4 (GameServer) :Eviction を許可してノードの自動最適化を機能させる ( spec.eviction.safe: Always ) Point 1〜3 でプレイ中のゲームを保護できたら、次に Agones の spec.eviction.safe を Always に設定し、EKS Auto Mode によるノードの自動最適化を機能させます ( fleet.yaml ) 。 spec: template: spec: # Point 4: eviction.safe を Always に設定 # Karpenter の Drift/Consolidation/Expiration 時に Graceful な Eviction を許可する eviction: safe: Always spec.eviction.safe は、各 GameServer の Pod に対して Agones が内部的に作成する PDB ( maxUnavailable: 0% ) を有効化するかどうかを制御します。デフォルトの Never の場合、常に eviction をブロックする動きとなります。 (表は https://agones.dev/site/docs/advanced/controlling-disruption/ より) Never のままでは、この PDB がすべての Eviction をブロックし、EKS Auto Mode 環境で次の問題が発生します。 Karpenter が Consolidation / Drift を試みても Pod に SIGTERM が発行されず退去しないため、Cordon 状態のノードが既存 Pod ごと残り続け、コスト効率が悪化する。 Drift (AMI 更新) が PDB にブロックされ、セキュリティパッチの適用が遅延する。 上記の動作の結果、近い時間帯に起動した全ノード上の Pod が Expiration まで生存し続け、それらの Pod が近い時間帯に一斉に SIGKILL されるリスクが生じる。 Always を設定すると Agones のネイティブ PDB が無効化され、Eviction が許可されます。Pod が稼働中のノードでも Drift による AMI 自動更新と、Expiration 時の Graceful なノード入れ替えが機能するようになります (Never ではこれらが PDB にブロックされます) 。プレイ中のゲームの保護は Point 1〜3 で確保した猶予期間とシグナルハンドリングが担保するため、Always にしても進行中のゲームが即座に切断されることはありません。 Always の設定でも安全に運用する目的で、Point 1 で設定した consolidationPolicy: WhenEmpty (Pod が残っているノードでは Consolidation を発動させない) と NDB ( nodes: "10%" 、同時中断ノード数の制限) を補完策として組み合わせます。Always は Drift / Expiration を有効に機能させる一方、Consolidation まで WhenEmptyOrUnderutilized にすると稼働中 Pod のあるノードも集約対象となりゲームサーバーが頻繁に Evict され得るため、Consolidation は WhenEmpty に絞り、空ノードの回収のみに留めます。Agones の Fleet 設定 spec.scheduling の値はデフォルトで Packed となっており、できるだけ既に GameServer が動作しているノードに新規 GameServer を起動するようにスケジュールするため、 WhenEmpty の設定でも十分なコスト最適化効果が見込めます。 Point 5 (コントローラ系) :Agones コントローラ系と GameServer の NodePool を分ける Point 1 で設定した expireAfter / terminationGracePeriod は NodePool 単位の設定です。Agones のコントローラ系 (controller / extensions / allocator / ping) と GameServer では、必要な猶予期間が異なります。 コントローラ系: 短時間の再起動が許容されるため、長期安定稼働を優先しつつ猶予は比較的短くてよい。 GameServer: ゲーム最大持続時間に対応した長い猶予 ( terminationGracePeriod ) が必要。 そこで、コントローラ系用と GameServer 用で NodePool を分離します ( nodepools.yaml ) 。 # コントローラ用 NodePool apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: agones-controller spec: template: metadata: labels: agones-role: controller # ラベルで役割を区別 spec: # コントローラは長期安定稼働を優先 expireAfter: 336h # 14日 terminationGracePeriod: 72h # 3日 --- # GameServer 用 NodePool (Point 1 で前掲) # labels: agones-role: gameserver / terminationGracePeriod: 4h そのうえで、GameServer 側は Fleet の nodeSelector で GameServer 用 NodePool を指定します ( fleet.yaml ) 。 template: spec: # Point 5: GameServer 用 NodePool にスケジュール nodeSelector: agones-role: gameserver コントローラ系は、Agones の Helm Values で nodeSelector を指定し、コントローラ用 NodePool に配置します ( agones-values.yaml ) 。 agones: controller: # Point 5: コントローラ用 NodePool にスケジュール nodeSelector: agones-role: controller extensions: nodeSelector: agones-role: controller allocator: nodeSelector: agones-role: controller ping: nodeSelector: agones-role: controller これにより、それぞれのワークロード特性に合った猶予期間を両立できます。 Point 6 (コントローラ系) :agones-allocator と agones-ping の PDB を有効にする 前述の通り EKS Auto Mode ではいつか必ずノードの中断が発生するため、Agones のコントローラ系サービスでも可用性維持のための設定が重要です。agones-allocator (ゲームサーバーの割り当てリクエストを受け付けるサービス) と agones-ping (レイテンシー計測用サービス) はデフォルトで PDB が無効のため、ノードが中断されてもこれらが全停止しないよう、PDB を有効化します ( agones-values.yaml ) 。 agones: allocator: replicas: 3 # Point 6: allocator の PDB を有効化 pdb: enabled: true minAvailable: 1 ping: replicas: 2 # Point 6: ping の PDB を有効化 pdb: enabled: true minAvailable: 1 minAvailable: 1 により、ノード中断時にも最低 1 レプリカが稼働し続けることを保証し、コントロールプレーンの可用性を維持します。 なお、agones-controller, agones-extensions はデフォルトで PDB が有効となっています。 さらに安定した運用のための補足 (レアケースへの対処) Point 1〜6 の設計により、通常のノード中断からのゲームサーバー保護を実現できます。さらに安定した運用のためには、次のレアケースへの対処も検討ポイントになります。いずれも各実装に依存するため、必要に応じて検討してください。 GameServerAllocation のレースコンディション Ready 状態の GameServer が SIGTERM を受信した直後から Shutdown 完了までの間に、GameServerAllocation によって Allocate される可能性がゼロではありません。これが起こると、プレイヤーが接続するころには Allocate された GameServer が既に停止しておりエラーとなるリスクがあります。以下はこれを防ぐ方法の例です。 GameServer にあらかじめラベル ( allocationblock=false 等) を付与し、GameServerAllocation 側でそのラベルを持つ Pod のみを対象とする設定を行う。SIGTERM 受信時には即座にラベルを外す。ラベル削除後も一定時間待機し、その間に Allocate された場合はゲームを継続し、終了後に Shutdown する。 起動中 Pod への SIGTERM 発行時のハンドリング不可 コンテナ起動中 (Starting / ContainerCreating) に SIGTERM が発行されると、アプリケーション側でハンドリングできず、GameServer は正常に起動し Ready 状態となる一方、 Pod は terminationGracePeriodSeconds 経過後に停止してしまう動作となり、ゲームを保護できません。これを防ぐには以下の方法が例として挙げられます。 対策例 1: GameServer にあらかじめラベル (allocationblock=false 等) を付与し、GameServerAllocation 側でそのラベルを持つ Pod のみを対象とする設定を行う。外部コントローラで Pod の deletionTimestamp を監視し、非 null、つまり削除予定がある状態なら、前述の Allocation 用ラベルを外し、新規 Allocation を防ぐ。 対策例 2: イメージサイズの削減・DaemonSet 等による事前 pullといった方法で起動時間短縮を図り、発生確率を最小化する。 まとめ 本記事では、Agones の基盤に EKS Auto Mode を採用する際、ノードの自動中断からゲームサーバーを保護する設計を 6 つのポイントで紹介しました。専用ゲームサーバーのセルフホストで、Agones の柔軟性を活かしつつ EKS Auto Mode で運用管理をシンプルにするには、EKS Auto Mode のノード中断と Agones のゲームサーバーライフサイクルの競合を解消する設計が鍵になります。 本記事で紹介した Point 1〜6 の設計パターンと実装例 ( nodepools.yaml / fleet.yaml / agones-values.yaml ) が、EKS Auto Mode 上での Agones 導入を検討する方の参考になれば幸いです。
こんにちは、クラウド&ネットワークサービス部の長田です。 Flexible InterConnect の開発・運用を担当しています。 このたび、2026年7月に愛媛県松山市で開催されたJANOG58へ参加しました。 私は2026年度入社の新入社員として参加しましたが、セッションや展示ブースを通じてネットワーク業界の最新動向や各社の取り組みを知ることができました。 本記事では、JANOG58で特に印象に残った内容と、今後のネットワーク運用の方向性について感じたことを共有します。 JANOG58とは 印象に残ったトレンド ①コンテナ型データセンター ②ネットワーク機器 ③AIエージェントとネットワーク自動化 おわりに JANOG58とは JANOG(JApan Network Operators' Group)は、インターネット技術やネットワーク運用について議論する国内最大級のコミュニティです。 今回のJANOG58は愛媛県松山市で開催され、テーマは「技術の成熟と次代への継承」でした。多くの通信事業者、クラウド事業者、データセンター事業者、機器ベンダーが参加し、最新技術や 運用ノウハウについて活発な議論が行われていました。 また、NTTドコモビジネスグループも協賛企業として参加しており、ネットワーク運用に関する展示が行われていました。 印象に残ったトレンド JANOGでは数多くの展示やセッションが実施されていました。その中で印象に残っているトレンドに関して紹介していきます。 ①コンテナ型データセンター 展示ブースで特に印象的だったのがコンテナ型データセンターです。 従来のデータセンター建設では大規模な建物や設備工事が必要ですが、コンテナ型データセンターでは設備をあらかじめコンテナ内部に集約することで、短期間かつ低コストで展開できるメリットがあります。 また、北海道など冷涼な地域への設置を前提とした取り組みもあり、電力効率や冷却効率を高める工夫が進んでいました。 特に液冷技術が注目されており、DLC(Direct Liquid Cooling)など複数の冷却方式が紹介されていました。 一方で、建物型と異なりコンテナは設置場所の施錠や監視体制の整備も求められるなど、セキュリティ面での課題についても触れられていました。 AI利用による電力消費の増加が話題となる中で、データセンターの冷却技術やセキュリティ課題へどう対処するのかが今後さらに重要になると感じました。 ②ネットワーク機器 ネットワーク機器関連の展示も非常に興味深いものでした。 光トランシーバの小型化や高密度化が進み、より高速な通信を限られたスペースで実現する製品が多数展示されていました。 また、リアルタイムでAIも活用したネットワークトラフィックを分析し、履歴として保存・可視化する計測ソリューションも数多く展示されていました。 ネットワークが大規模化する中で、 トラフィックの見える化 異常検知 キャパシティプランニング の重要性がさらに高まっていることを感じました。 またこれらに対して、AIを実際に活用することによって、人手では追いきれない大規模ネットワークにおける効率的な運用や 障害対応の迅速化と属人化の解消が実現できるのではないかと思いました。 さらに、JANOGでは、展示以外にもさまざまな企画があります。 その中のケーブル作成体験会では、Cat6細軽1mケーブルのプラグ成端を実施し、テスターで導通確認まで行いました。ケーブルにはカテゴリによって最大通信速度や伝送帯域が異なり、 少しの配線の差でも性能に影響が出ることを実際に体験しました。 また、NOCツアーでは、JANOG会場1つのネットワークを構成するためだけでケーブル総長が2500mにも及び、L3スイッチやサーバーなどが多数必要になることを目の当たりにしました。 さらに、どこにどの機器を配置すれば会場全体で通信が成立するかを事前に計算したうえで設営されていることを知り、ネットワーク設計の緻密さと物理インフラの複雑さを改めて実感しました。 普段の業務ではソフトウェアやAPIを通じてネットワークを扱うことが多いため、インフラを実際に目にしたことは貴重な経験でした。 ③AIエージェントとネットワーク自動化 今回のJANOG58では、AI活用やネットワーク自動化に関する展示やセッションが多く見られました。 私がさまざまなセッションを聞く中で、特に興味を持ったのは、「AIを導入すること」ではなく、「現場のノウハウをどうAIに継承するか」という考え方です。 近年はマルチエージェント構成やMCPを活用したシステム構築が注目されていますが、実際にはエージェントごとのチューニングや役割分担の設計が難しく、運用コストや可用性が課題になるという話もありました。 一方で、 「Agent skillsとMCP Appsを活用した伴走型AIOpsについて」 というセッションでは、Agent Skillsのような仕組みを利用して、ネットワーク運用で蓄積されたノウハウをスキルとして部品化・利用する考え方も紹介されていました。 様々なセッションを聴いていく中で、個人的には、「賢いエージェントを作る」ことよりも、「現場の知見を整理し、再利用できる形で残す」ことの方が重要ではないかと感じました。 例えば障害解析や設定確認の手順をスキルとして管理できれば、 担当者ごとの品質差を減らせる 新しいメンバーへの知識継承がしやすくなる プロンプトを毎回作り込む必要がなくなる といった効果が期待でき、タスクの削減が実現可能になります。 ただ、AI利用が進むにつれてトークン消費量や処理コストも課題になるため、必要なときだけスキルを読み込む構成や、重要な知識を階層的に整理して利用する工夫も今後重要になるのではないかと考えました。 ネットワーク運用の世界でも以前から自動化が進められてきましたが、AIの登場によって単なる作業自動化だけではなく、工夫が加わり、知識や判断の継承という新しいテーマに進化していることを実感しました。 おわりに JANOG58に新入社員として参加し、ネットワーク技術そのものだけでなく、その技術をどのように運用し、次世代へ継承していくかという視点を学ぶことができました。 今回の経験を自身の業務にも活かしながら、今後もネットワーク技術やAI活用への理解を深めていこうと思います。 また、今後もJANOGだけでなく、他のイベントやコミュニティにも積極的に参加し、つながりを広げながら、学び続けていきます。






















