インフラエンジニアの羅針盤

インフラエンジニア1〜3年目のための技術ガイド

GKE導入判定|不採用7条件と要件定義書の書き方

公開

Kubernetes導入プロジェクトのキックオフで、インフラエンジニアが最初にやるべき仕事はYAMLを書くことではありません。「このプロジェクトは本当にKubernetesでなければならないのか」という問いに対して、定量的な根拠をもって答えを出すことです。

答えがNoであれば、そのプロジェクトをK8sから引き剥がすのがアーキテクトの責任です。答えがYesであれば、運用フェーズ(Day-2)で運用が破綻しないよう、プロジェクトの初期段階で握るべき要件を一つ残らず言語化しておく必要があります。

本記事は、その判断と言語化のための設計書――「K8s導入判定・システム要件定義書」の書き方を扱います。

目次
  1. アーキテクトの最初の仕事は「No」と言うことである
  2. Kubernetes「不採用」7条件のスクリーニング
  3. 関門1:技術的失格条件 ― 金額では解決できない3条件
    1. 条件1:ローカルI/Oレイテンシに依存するステートフルアプリケーション
    2. 条件2:Graceful Shutdownに耐えられない処理を抱えている
    3. 条件3:水平にスケールできないシングルトン処理を抱えている
  4. 関門2:投資判断条件 ― 許容できるなら採用してよい4条件
    1. 条件4:プラットフォームエンジニアを専任で2名以上アサインできない
    2. 条件5:サービス境界が定義されておらず、分割の計画もない
    3. 条件6:マネージドPaaS/CaaSの制約に抵触していない
    4. 条件7:「K8s税」を上回るROIを証明できない
  5. ステークホルダーとの合意形成:Day-2で運用チームを守る合意事項
    1. ビジネス目標の定量化
    2. ヒアリングで握るべき3つの要件
    3. ROIの算出と提示
  6. 【実務テンプレート】K8s導入判定・システム要件定義書
  7. 次回予告

アーキテクトの最初の仕事は「No」と言うことである

「コンテナ化したい」「マイクロサービスにしたい」「Kubernetesを使いたい」――こうした要望が開発チームや経営層から降ってきたとき、インフラエンジニアの立場でまず確認すべきことがあります。それは技術的な実現可能性ではなく、「その要望の背後にあるビジネス上の課題は何か」という点です。

ビジネス課題が曖昧なままK8s導入に踏み切ると、構築フェーズでは問題が顕在化しません。問題が噴出するのは運用フェーズです。年3回前後で来るマイナーバージョンへの追従、非推奨APIの棚卸しとアプリケーション側の修正、アドオンの互換性確認、ノードイメージの更新――これらのDay-2オペレーションを回す体制とコストを、プロジェクト開始時点で誰も見積もっていなかったという状況に陥ります。

なお本記事は、第3回以降の設計と揃えるためGoogle Cloud(GKE)を前提に金額と製品名を記載します。判定の考え方と閾値そのものはクラウドに依存しないため、他のクラウドを使う場合も判断基準はそのまま流用できます。実費のみ自環境の料金で置き換えてください。

アーキテクトとして成長するための第一歩は、「どう作るか」ではなく「作るべきかどうか」を判断する力を身につけることです。以下で解説する7つの不採用条件は、その判断を客観的な基準で下すためのフレームワークとして機能します。

Kubernetes「不採用」7条件のスクリーニング

不採用条件は7つありますが、これらを1つのチェックリストとして並列に扱うと判断を誤ります。7条件は性質の異なる2種類に分かれており、それぞれ判定の重みが違うからです。

  • 関門1:技術的失格条件(条件1〜3) ― K8sに載せた時点でシステムが成立しない、あるいはK8sの前提と構造的に噛み合わない条件です。予算をいくら積んでも解決できません。1つでも該当すればNo-Goです
  • 関門2:投資判断条件(条件4〜7) ― K8s上で動くことは動くが、投資に見合う便益が出るかどうかが問われる条件です。該当していても、コストと体制を許容できるのであれば採用して構いません。最終的にはすべて条件7のROI判定に集約されます

この区別が重要な理由は、経営層との会議で使う論法が変わるからです。関門1に該当する場合は「技術的に成立しません」と言い切ります。関門2に該当する場合に「できません」と言うと、それは技術者の怠慢と受け取られます。関門2で提示すべきなのは「この金額とこの体制を確保できるなら実行します」という条件付きの合意です。

Kubernetes不採用7条件を、金額で解決できない技術的失格条件3件と、コストと体制で判断する投資判断条件4件の2つの関門に分けて上から順に判定し、すべて非該当のときだけGoとするスクリーニングフロー図
7条件のスクリーニングフロー。上段の関門1は該当時点でNo-Go、下段の関門2はコストを許容できるなら採用可能です。各条件の右側には代替手段を示しています。

プロジェクトのキックオフ時にこのチェックリストを関係者に提示し、各条件の該当・非該当と判断根拠を記録に残してください。

関門1:技術的失格条件 ― 金額では解決できない3条件

以下の3条件は、いずれもワークロードの構造そのものがK8sの前提と噛み合わないケースです。該当した場合、予算を追加しても、優秀なエンジニアを追加でアサインしても解決しません。該当するシステムをK8sから外すか、アプリケーションを改修して前提を満たすかの二択になります。

条件1:ローカルI/Oレイテンシに依存するステートフルアプリケーション

「ステートフルだからK8sに向かない」という単純な話ではありません。StatefulSetとCSIドライバーの組み合わせで、K8s上でステートフルワークロードを稼働させること自体は可能です。問題は、アプリケーションがローカルディスクへの低レイテンシI/Oに依存しているかどうかです。

CSI経由でPersistent DiskやHyperdiskをマウントした場合、I/Oはネットワーク越しになります。Googleはこれらを「ネットワークブロックデバイスとしてインスタンスにアタッチされ、読み書きはネットワーク上で転送される」と明記しています。物理マシンに接続されたディスクではありません。ローカルディスク前提で設計されたアプリケーションにとって、この差は無視できません。

どのようなワークロードが該当するのか

抽象的な条件に見えますが、実務で遭遇する対象はある程度決まっています。以下に該当するものがあれば、詳細な調査に進んでください。

ワークロードローカルI/Oに依存する理由
セルフホストのRDBMS(PostgreSQL / MySQL)コミットのたびにWAL(PostgreSQL)やredoログ(MySQL InnoDB)をfsyncします。synchronous_commit = onのPostgreSQLでは1トランザクションにつき最低1回の同期書き込みが発生します。秒間1,000トランザクションを捌く構成であれば、1回あたり1ミリ秒の増加がそのままコミット待ち時間に積み上がります
SQLiteをデータストアに使うアプリケーションSQLiteはPOSIXアドバイザリロック(fcntl)でトランザクションの排他を行います。SQLite公式は、多くのNFS実装でこのロックが正しく動作せず、データベース破損につながるとして、ネットワークファイルシステム上での使用を避けるよう明記しています。これはレイテンシ以前に、動作の正しさが保証されない領域です
レガシー基幹バッチ(固定長ファイルの順次処理)1レコード書き込むごとにfsyncを発行する実装が残っていることがあります。300万レコードの処理は300万回の同期書き込みになり、1回あたり1ミリ秒の増加は単純計算で約50分の延長です。夜間バッチの実行枠に収まらなくなります
セルフホストのElasticsearch / OpenSearchセグメントのマージとリフレッシュで大量のランダムI/Oが発生します。公式にローカルSSDが推奨される構成です
大量の小ファイルを扱う処理(帳票の一括生成、サムネイル生成)ファイル1件あたりのopen / write / close / fsyncのオーバーヘッドが、件数分だけ積み上がります。1件あたりは軽くても、数万件単位で処理時間の差が顕在化します

確認すべき具体的な指標は以下の通りです。

  • アプリケーションがO_DIRECTフラグやPOSIXファイルロック(flock/fcntl)を使用しているか
  • 1トランザクションあたりのfsync回数が100回を超えるか
  • ディスクI/Oレイテンシの許容値が1ms未満か

ただし、「レイテンシ要件が1ミリ秒未満だから不採用」と機械的に判定しないでください。Persistent Diskで性能が足りない場合の選択肢としてHyperdisk Extremeがあり、ストレージクラスの変更だけで要件を満たせる可能性があります。確認すべきなのは、実測値が要件を満たすかどうかと、標準構成との価格差です。価格差は条件7のROI計算に加算してください。

Local SSDという逃げ道には、条件3への接続がある

もう一つの選択肢がLocal SSDです。ノードに物理的に接続されるため、Hyperdiskより低いレイテンシと高いIOPSが得られます。ただし、この選択には代償があります。

  • Local SSDのボリュームは特定のノードに固定され、別のノードへ移動できません
  • エフェメラルであり、インスタンスが停止または終了した場合、データは失われる可能性があります
  • GKEでLocal SSDを使ったエフェメラルストレージはPodのライフサイクルに紐づき、Podが終了した時点で削除されます

ここで注意すべきなのは、Local SSDを選んだ瞬間に「Podはどのノードにも再スケジュールされうる」というKubernetesの前提と衝突する点です。ノードアフィニティで特定ノードに固定する対処はできますが、それは実質的に後述する条件3(水平にスケールできないシングルトン処理)に該当する状態を自ら作り出すことになります。条件1をLocal SSDで回避しようとすると条件3に引っかかる、という構造を理解した上で判断してください。

実測しても要件を満たせない場合は、K8sではなくCompute Engine上での稼働を推奨します。RDBMSに該当する場合は、セルフホストをやめてマネージドサービス(Cloud SQL / AlloyDB)へ寄せる選択肢が最初に来ます。

なお、ここで判定するのは「K8sに載せられるかどうか」までです。StatefulSetとマネージドDBのどちらを選ぶか、StorageClassをどう設計するかは、第7回のデータ・ストレージ設計書で扱います。

条件2:Graceful Shutdownに耐えられない処理を抱えている

Podは恒久的な実行環境ではありません。デプロイのたび、ノードの更新のたび、オートスケーラーがノードを整理するたびに、Podは停止と再作成を繰り返します。この前提に耐えられない処理がシステムに含まれている場合、K8sは選択肢から外れます。

判定軸は「ステートフルかどうか」ではありません。1回の処理が完了するまでに何秒かかり、その上限を見積もれるかです。K8sはPodに終了シグナル(SIGTERM)を送ってからterminationGracePeriodSecondsだけ待ち、その時間を過ぎればSIGKILLで強制終了します。処理時間がこの猶予を超えるなら、その処理は途中で切られます。

猶予時間には、自分で決められない上限が複数存在します。以下の閾値が判定基準になります。

最大処理時間何が起きるか
15秒超デフォルト構成のSpot VMが使えなくなります。GKEのSpot VMのプリエンプション猶予は全体で30秒ですが、通常のPodに割り当てられるのはそのうち15秒です(次項で詳述)
30秒超terminationGracePeriodSecondsのデフォルト値(30秒)を超過します。値の明示的な設定が必須になります
数分〜数十分ノードプールのアップグレードやスケールダウンでノードが削除される際、ドレインの待ち時間が長くなります。1台あたりの待ち時間がそのままノード台数分の作業時間に積み上がります
見積もり不能terminationGracePeriodSecondsに設定すべき値が決まりません。設計として成立しません

GKEでアプリケーションPodに与えられるのは15秒

Compute EngineがSpot VMのリソースを回収する際、プリエンプション通知が送られ、続いてACPI G2ソフトオフ信号によってシャットダウン期間が始まります。この期間を過ぎてもインスタンスが停止しない場合はACPI G3 Mechanical Offが送られます。これは電源を落とす操作に相当し、アプリケーション側で受け止める手段はありません。

問題は、この猶予が何秒あるかです。GKEクラスタのデフォルトでは、プリエンプション通知からPodのシャットダウンまでの正常終了期間は30秒です。ただしこの30秒は分割されています。

  • 通常のPodのシャットダウンに15秒
  • その後、システムPod(priorityClasssystem-cluster-criticalまたはsystem-node-criticalのもの)のシャットダウンに15秒

つまり、アプリケーションのPodに実際に与えられる猶予は15秒です。30秒ではありません。この点を取り違えて設計すると、想定の半分の時間で切られます。

ここが判定上の要点です。terminationGracePeriodSecondsをどれだけ延ばしても、Spot VM上ではこの猶予を超えられません。Kubernetesの設定はゲストOSの中の話であり、その外側で電源が落ちるためです。

正常終了期間を120秒へ延長する構成は提供されていますが、制約があります。執筆時点ではプレビュー版であり、コントロールプレーンが一定バージョン以上である必要があり、Standardモードでのみサポートされます。ノードシステム構成をカスタマイズして特定のノードプールに設定する形になるため、Autopilotでは選択できません。採用を検討する場合は、提供ステージが自社の本番利用ポリシーを満たすかを確認してください。

したがってGoogle Cloudでは、15秒以内に終わらない処理を抱えた時点で、デフォルト構成のSpot VMという選択肢が消えます。第4回で扱うコスト最適化の主要な手段を1つ失うことになり、その分は条件7のROI計算に響きます。

この条件に該当しやすいワークロードは以下の通りです。

  • 大容量ファイルのアップロード受信:所要時間がクライアント側の回線速度に依存するため、上限を見積もれません。同じ100MBのファイルでも、モバイル回線からのアップロードでは10分を超えることがあります
  • 長時間バッチ処理:数時間を要するジョブは、マイナーバージョンアップに伴うノードの入れ替えと衝突します
  • WebSocketや長時間のgRPCストリーム接続
  • 途中で中断すると整合性が壊れる非冪等な処理(決済の確定、在庫の引き当て等)

回避策は存在しますが、いずれも何かを代償として支払います。この対応表を理解した上で判断してください。

回避策代償として失うもの
terminationGracePeriodSecondsを延長するノード1台のドレインに同じ時間がかかります。10分に設定したクラスタでノードを50台入れ替える場合、バージョンアップが現実的な作業時間に収まらなくなります。そしてSpot VM上では、この延長は効きません
PodDisruptionBudgetやcluster-autoscaler.kubernetes.io/safe-to-evict: "false"で保護するこれらが止められるのは自発的な中断(オートスケーラーによるスケールダウン等)だけです。Spot VMのプリエンプション、ノードの自動修復、ノードプールのアップグレードといった強制的な中断は止められません。「設定したから安全」という理解は誤りです
Spot VMをやめ、専用ノードプールに隔離してオンデマンドで固定するビンパッキングによる集約とSpot VM活用という、コスト最適化の主要な手段を放棄します。そこまでするなら、Compute Engine上での直接実行のほうが運用は単純です
処理をキューに載せ、冪等で再実行可能な形にアプリケーションを改修する失うものはありません。技術的に正しい解決策です。ただし改修の工数と期間が必要になります

2番目の回避策については、現場で誤解されている場面を繰り返し見ています。PodDisruptionBudgetは自発的な中断(Voluntary Disruption)に対してのみ機能する仕組みです。ノードのハードウェア障害やSpot VMのプリエンプションのような非自発的な中断は、その定義上PDBの対象外です。「PDBを設定したからPodは落ちない」という保証は存在しません。

判定基準は明確です。4番目のアプリケーション改修が、プロジェクトの予算とスケジュールに含まれていないのであれば、この条件は「該当」です。長時間バッチはCloud Run JobsやCloud Batchへ、大容量アップロードは署名付きURLによるCloud Storageへの直接アップロードへ切り出した上で、残りの部分だけをK8sに載せるかを再検討してください。

条件3:水平にスケールできないシングルトン処理を抱えている

条件2が「1つのPodが停止するときに処理を完了できるか」という時間軸の問題だったのに対し、条件3は「そもそもPodを2つ以上に増やせるか」という水平軸の問題です。両者は独立しており、片方だけに該当するケースもあります。大容量アップロードを受けるステートレスなWeb APIはレプリカを増やせますが停止には耐えられず、逆にホスト単位ライセンスのミドルウェアは停止には耐えられてもスケールできません。

判定は以下の観点で行います。1つでも該当すれば、そのワークロードはシングルトン制約を持っています。

  • replicasを2以上にすると業務データが壊れる(ファイルの二重取り込み、採番の重複、バッチの多重起動)
  • 排他制御をアプリケーションの外部(データベースのロック、分散ロック)へ持ち出せない
  • ライセンスの課金単位がホスト単位・CPU単位・IPアドレス単位である
  • 相手システムが送信元IPアドレスを固定で許可リストに登録している
  • 固定のホスト名・固定ポートでの待ち受けを外部から要求されている

シングルトン制約があると、K8sの主要な便益がほぼすべて無効化されます。

K8sの便益シングルトン制約下での状態
HPAによるスケールアウトreplicas: 1固定のため使えません
ローリングアップデート(ゼロダウンタイム)maxSurgeによって一時的に2台が同時起動するため使えません。Recreate戦略のみとなり、更新のたびに停止時間が発生します
ビンパッキングによる集約・Spot VM活用ホスト単位ライセンスや固定IP要件と両立しません
セルフヒーリング(Podの自動再作成)唯一有効に機能します

残る便益はセルフヒーリングだけです。これはCompute Engineの自動再起動や、サイズを1に固定したマネージドインスタンスグループでも実現できます。クラスタ管理手数料の月額約$73と運用体制を、Podの自動再起動1つのために負担する判断が妥当かどうかを検討してください。

具体例:ファイル転送ミドルウェア

HULFTに代表されるファイル転送製品が典型例です。K8s上に載せようとすると、以下が同時に問題になります。

  • ライセンスの課金単位がホスト単位であり、オートスケーラーやノードの自動アップグレードによってノードが動的に入れ替わる環境と整合しません
  • 集信側は固定IPでの待ち受けを前提としており、相手先企業のファイアウォールに送信元IPが登録済みであるケースが多くあります。Pod IPは再作成のたびに変わるため、Cloud NATや静的な外部IPで出口を縛る設計が必要になりますが、そこまで作り込むとK8s上に置く必然性が残りません
  • 集信ジョブを2台で同時に動かすと、同じファイルを二重に取り込みます。排他制御を製品の外側から掛ける手段は限られます
  • 転送中の一時ファイルがローカルディスクに置かれます。PVによる永続化は可能ですが、条件1のI/O問題に接続します

シングルトン制約を持つワークロードは、Compute Engine上での稼働を推奨します。ただし、システム全体をK8sから外す必要はありません。ファイル転送やジョブスケジューラのような一部のコンポーネントだけをCompute Engineに残し、水平分散できるアプリケーション部分をK8sに載せるハイブリッド構成は現実的な解です。この場合、両者を跨ぐネットワーク設計が必要になります(第3回で扱います)。

関門2:投資判断条件 ― 許容できるなら採用してよい4条件

ここからの4条件は性質が変わります。該当していてもK8sは動きます。問題は、支払うコストに便益が見合うかどうかです。したがって、これらの条件に該当した場合の正しい対応は「導入をやめる」ことではなく、「コストを提示して意思決定を仰ぐ」ことです。

条件5と条件6は、最終的に条件7のROI計算に流れ込みます。ROIを構成する個別の要素を先に洗い出すための項目だと理解してください。

条件4だけは扱いが異なります。専任エンジニアの人件費はROIのコスト増に計上しますが、条件4の該当・非該当そのものをROIで判断してはいけません。金額で比較すると必ず誤った結論に行き着きます。その理由は条件4のセクションで詳しく述べます。

条件4:プラットフォームエンジニアを専任で2名以上アサインできない

K8sクラスタの運用は「構築して終わり」ではありません。以下のDay-2タスクが、クラスタが存在する限り永続的に発生します。

  • 年3回前後で来るマイナーバージョンへの追従と、その事前検証
  • 非推奨APIの棚卸しと、アプリケーション側の追従修正の調整
  • CSIドライバー、Gatewayコントローラー、cert-manager等のアドオンの互換性確認とアップデート
  • ノードイメージの更新と、ノードプールのアップグレードに伴うワークロードの退避
  • RBACポリシーやNetworkPolicyの継続的な見直し

GKEを使う場合、コントロールプレーンの冗長化、etcdのバックアップ、APIサーバー証明書のローテーションはGoogle側が担います。リリースチャンネルを設定すればバージョンアップ自体も自動化できます。ただし、自動化されるのは「上げる作業」だけです。上げてよいかどうかを事前に検証し、非推奨APIを使っているアプリケーションを開発チームに直してもらう調整は、自動化されません。

これらのタスクは、アプリケーション開発と兼任している体制では確実に後回しにされます。検証を伴わない自動アップグレードは、ある朝に本番のワークロードが起動しなくなる形で顕在化します。「忙しくて検証できなかった」結果として、サポート期間の切れたバージョンのまま稼働を続け、追加料金を払いながら既知のCVEを放置する――これは現実に多くの現場で起きている問題です。

最低2名としている理由は、1名体制では休暇や退職時にSPOF(Single Point of Failure)になるためです。ナレッジの共有と相互レビューが機能する最小単位が2名です。

この条件をコストで判断してはいけない

後述する条件7で、バージョンアップを先送りするとクラスタ管理手数料が6倍になり、3クラスタで年間約$13,000の追加負担が生じることを示します。1ドル165円換算で約215万円です。一方、専任エンジニア2名の人件費は、単価100万円で計算すると年間2,400万円になります。

つまり、金額だけを並べれば、人を雇わずに追加課金を払い続けるほうが10倍以上安く見えます。この条件を費用対効果で判断すると、必ず「専任を置かずに拡張サポート料金を払う」という結論になります。そしてその結論は誤りです。

2名を確保すべき理由は、金額に現れないところにあります。

  • 拡張サポートで買えるのは猶予であって、回避ではありません。留まれるのは最長24ヶ月です。その後はいずれ必ず上げることになり、しかもその時点では複数バージョン分の差分が積み上がっています。毎回追従する場合より、一度にまとめて上げるほうがはるかに危険です。追加課金を払い続けても、リスクは先送りされるだけで消えません
  • 検証なしのアップグレードは、ある朝に本番が起動しなくなる形で顕在化します。そのときに復旧できる人間が1名しかいなければ、その1名が不在の日に復旧手段が消えます。これは金額で埋められません
  • サポートが完全に切れたクラスタには、既知の脆弱性へのパッチが提供されなくなります。これは支出の多寡ではなく、セキュリティインシデントが起きる確率の問題です

条件4は、支払える金額の問題ではありません。支払っても買えないもの――復旧できる人間と、検証済みという状態――の問題です。経営層に提示する際も、コスト比較の表に載せてはいけません。「この体制を確保できないなら、24ヶ月後に高い確率で本番が止まります」という、確率とリスクの言葉で説明してください。

条件5:サービス境界が定義されておらず、分割の計画もない

K8sは複数の独立したサービスを1つのクラスタ上で効率的に運用するためのプラットフォームです。Namespace単位のリソース隔離、NetworkPolicyによるサービス間通信制御、HPAによるサービス単位の個別スケーリング――これらの機能は、アプリケーションが複数のデプロイ単位に分割されていることを前提としています。

モノリシックなアプリケーションが1つだけ存在し、今後も分割する計画がない場合、K8sのこれらの機能は活用されません。単一のDeploymentと単一のServiceだけが存在するクラスタは、Cloud Runで代替できます。

注意すべき点として、「将来マイクロサービス化する予定がある」という曖昧な計画は根拠になりません。具体的なドメイン分析(DDDにおける境界付けられたコンテキストの特定)が完了し、最初に切り出すサービスの候補が決まっている段階で初めて、K8s導入の前提条件を満たします。

条件6:マネージドPaaS/CaaSの制約に抵触していない

Cloud Runに代表されるマネージドサービスは、コントロールプレーンの運用責任をクラウドベンダーに完全に委譲できます。K8sを自前で運用するよりも、運用コストは大幅に低くなります。

この条件を判定する際、数年前の知識で「Cloud Runでは足りない」と決めつけないでください。制約は継続的に緩和されており、かつてK8sを選ぶ理由になっていた項目のいくつかは、すでに理由として成立しなくなっています。サイドカーコンテナはCloud Runでも利用できます(1つのイングレスコンテナに加えて複数のサイドカーを配置できます)。GPUも利用できます(1インスタンスあたり1基まで、かつ1つのコンテナにのみアタッチ可能という制約はあります)。

これらのサービスを不採用にする正当な理由は、サービス固有の制約に現在のワークロードが抵触している場合に限られます。主な制約は以下の通りです。

  • 1回の処理時間の上限(Cloud Run Jobsのタスクタイムアウトは最大60分)
  • インスタンスあたりのメモリ上限(Cloud Runは最大32 GiB)
  • VPC内リソースへのアクセス要件(プライベートIPのみで公開されたCloud SQL等への接続)
  • gRPCやWebSocketなどのプロトコル要件
  • 1インスタンスに2基以上のGPUが必要、または複数コンテナからGPUを共有する要件
  • DaemonSetのように、ノード単位で常駐させるプロセスが必要な要件
  • Podのスケジューリングを細かく制御する必要(ノードアフィニティ、taint / toleration、topologySpreadConstraints)

最後の2項目が、実務では最も多くK8sを選ぶ理由になります。「Cloud Runでは配置を制御できない」というのは、裏を返せば配置の制御が要らないワークロードならCloud Runで十分だということです。

これらの制約のいずれにも抵触しないのであれば、K8sの採用は見送り、PaaSに委譲することを強く推奨します。「将来的に制約に引っかかるかもしれない」は根拠になりません。引っかかった時点でK8sへの移行を検討すれば十分です。

条件7:「K8s税」を上回るROIを証明できない

K8sクラスタを維持するだけで発生する固定費を「K8s税」と呼びます。GKEを例に、ワークロードがゼロの空クラスタでも発生する月額コストを整理します。

まず、クラスタの数だけ確実に発生する部分から押さえます。クラスタ管理手数料は $0.10/クラスタ/時で、運用モード・クラスタサイズ・トポロジーによらず一律です。Autopilotでもリージョンクラスタでも同額であり、730時間で月約$73になります。

ここで見落とされやすいのが無料枠の条件です。GKEには課金アカウントあたり月$74.40のクレジットがあり、これはクラスタ1つ分の管理手数料にほぼ相当します。ただしこのクレジットが適用されるのはゾーンStandardクラスタとAutopilotクラスタだけで、リージョンクラスタには適用されません。本番環境をリージョンクラスタにする以上、その分は必ず課金されます。

GKE 空クラスタの月額コスト試算(東京リージョン・1環境あたり・730時間)

  • クラスタ管理手数料($0.10/時): $73.00
  • ワーカーノード最小構成(e2-medium $0.04298286/時 × 2台): 約$62.76
  • ロードバランサー転送ルール × 1($0.025/時): 約$18.25
  • Cloud NAT ゲートウェイ($0.0014/時 × VM 2台): 約$2.04
  • Cloud NAT 外部IPアドレス × 1($0.005/時): 約$3.65
  • Cloud NAT データ処理($0.045/GiB)とログ取り込み: 量に依存

1環境あたりの月額合計: 約$160(データ処理・ログ取り込みを除く)

Prod・Stg・Devの3環境を構築すると、ワークロードが空でも月額 約$407が固定費として発生します。Devをゾーンクラスタにすれば無料枠が管理手数料$73をカバーするため、単純な3倍にはなりません。ここにDatadogやNew Relicなどの監視SaaSのコスト(ホスト課金やカスタムメトリクス課金)が加算されます。

他のクラウドでの経験からK8s税を見積もっている場合、ネットワーク周りを過大に見積もっている可能性があります。Cloud NATはゲートウェイの時間料金がVM台数に連動する課金体系で、上限も32台分($0.044/時)で頭打ちになります。上の試算ではNAT関連は月$6程度です。マネージドNATの固定費が月$90前後かかるクラウドから移ってくると、ここの差が1環境あたり月$85ほど効いてきます。

バージョンアップを先送りすると、この固定費が6倍になります。GKEでは、クラスタのマイナーバージョンが拡張サポート期間に入ると、通常のクラスタ管理手数料に加えて$0.50/クラスタ/時の拡張期間手数料が課金されます。通常の$0.10/時と合わせて$0.60/クラスタ/時です。

金額に直すと、1クラスタあたりの管理手数料は月額$73が月額$438になります。Prod・Stg・Devの3クラスタすべてが拡張サポート期間に入れば、管理手数料だけで月額約$1,314、年額では約$15,800です。標準サポート内に収め続けていれば年額約$2,600で済みます。差額は年間で約$13,000です。

拡張サポートを使えば同一のマイナーリリースに最長24ヶ月留まれますが、その間はこの追加課金が続きます。K8s税を見積もる際は、この6倍の可能性をリスクとして計上してください。

ただし、この金額を根拠に条件4(専任2名)の要否を判断しないでください。年間$13,000は1ドル165円換算で約215万円であり、専任2名の人件費(単価100万円で年間2,400万円)の10分の1以下です。金額で比較すれば、追加課金を払い続けるほうが安いという結論にしかなりません。条件4で述べたとおり、あれはコストの問題ではなく体制の問題です。ROI計算に載せるのは、あくまでK8s税の変動要因としてのこの6倍だけにしてください。

この固定費を回収する原資は、K8sがもたらす便益を金額に換算したものです。ここで、条件4から条件6の判定結果に加えて、以下の2つの指標が計算に効いてきます。

デプロイ頻度

Argo CDによるGitOps、カナリアリリース、自動ロールバックといったデリバリーパイプラインは、1日に数回から数十回のデプロイを行う環境で大きな効果を出します。デプロイ頻度が月に2〜3回であれば、GitHub ActionsからCompute EngineやCloud Runへ直接デプロイするシンプルなパイプラインでも要件は満たせるため、削減できる工数は限られます。DORA(DevOps Research and Assessment)の指標で「週1回未満」に分類される組織では、デリバリー改善による便益をROIにほとんど計上できません。

トラフィックの変動幅

ピーク時と平常時の差が2倍未満で、負荷のパターンが完全に予測可能な環境では、HPA(Horizontal Pod Autoscaler)やノードのオートスケーリングによる動的なリソース調整で削減できる金額はほとんど発生しません。社内向け業務システムで利用時間が平日9時〜18時に限定されているケースや、夜間バッチが中心で日中のリクエスト数がほぼゼロのケースがこれに当たります。

ここで注意すべき点があります。デプロイ頻度が低いことも、トラフィックが平坦であることも、それ自体はK8sの不採用理由にはなりません。これらは回収原資が1つ減ることを意味するだけです。固定費を許容できる予算があり、運用の標準化や環境払い出しの高速化といった他の便益で投資を正当化できるのであれば、採用して問題ありません。判断すべきなのは「GitOpsやオートスケーリングが効くかどうか」ではなく「総額として投資を回収できるかどうか」です。

この固定費を上回るROIを提示できない場合、K8sの導入は不採用とします。ROIの具体的な算出方法は、後述のセクションで解説します。

ステークホルダーとの合意形成:Day-2で運用チームを守る合意事項

7条件のスクリーニングを通過し、Go判定が下された場合、次に行うのはステークホルダーとの合意形成です。ここで握るべき内容は、Day-2(運用フェーズ)で運用チームが窮地に陥ることを防ぐ、事前の合意事項として機能します。

ビジネス目標の定量化

「ダウンタイムをゼロにしたい」「デプロイを高速化したい」といった定性的な目標は、設計の判断基準として機能しません。以下のように、必ず金額や時間に換算してください。

  • 「リリースに伴うメンテナンス停止(月2回 × 30分)により、月間売上のX%にあたるYYY万円の機会損失が発生している。ゼロダウンタイムデプロイの実現により、この損失を排除する」
  • 「インフラ構築のリードタイム(現状: 新環境の払い出しに2週間)を短縮し、開発チームの待機コスト(エンジニア単価 × 待機日数 × 年間発生回数)を削減する」

この定量化が、後続フェーズでのあらゆる技術選定の判断軸になります。たとえば、監視ツールの選定(第6回で扱う)においてDatadog(有償)とPrometheus + Grafana(OSS)のどちらを採用するかは、ここで定義したビジネス目標の規模感と予算制約によって決まります。

ヒアリングで握るべき3つの要件

プロジェクト開始前に、以下の3点を必ず関係部門からヒアリングし、文書化してください。これらの情報が欠落したまま設計に入ると、後から手戻りが発生します。

1. コスト按分の要否(財務部門)

「インフラコストを部門やチームごとに按分する必要があるか」を確認します。按分が必要な場合、Namespace単位でのコスト可視化とラベリング戦略の設計が初期段階から必要になります。GKEには費用の割り当てという組み込み機能があるため、多くの場合は別途ツールを導入せずに済みますが、按分の単位を決めてラベルを設計する作業自体は発生します。この要件は、第4回で扱うFinOps・スケーリング設計にそのまま引き継がれます。按分が不要であれば、この領域の設計をスキップできるため、初期構築のスコープを大幅に絞ることができます。

2. コンプライアンス・監査要件(セキュリティ部門)

監査ログの保存期間、暗号化要件(保存時・転送時)、外部ネットワークへの通信制限など、コンプライアンス上の制約を確認します。これらの要件は、第5回で扱うゼロトラスト・ガバナンス設計に直接影響します。後から追加されると、クラスタの再構築が必要になるケースもあるため、必ず初期段階で確定させてください。

3. 移行対象システムの棚卸し(開発チーム)

K8s上に移行するアプリケーションの一覧と、それぞれの特性(ステートレス/ステートフル、使用プロトコル、リソース消費量の目安、現在のデプロイ方式、1回の処理にかかる最長時間)を洗い出します。最長処理時間は条件2の判定に直接使う値であり、ここで漏らすと後からGraceful Shutdownの設計が破綻します。この棚卸しの結果が、第3回で扱うクラスタトポロジー設計と第11回で扱うPodリソース設計の入力情報になります。

財務・セキュリティ・開発の各部門へのヒアリングで得た3要件が、後続の第4回・第5回・第3回/第11回の設計判断へ流れ込む関係と、未確定のまま進めた場合の手戻りを示した図
3つのヒアリング項目と、それぞれが影響する後続の設計書。第1回で確定させないまま進めると、下段に挙げた手戻りが発生します。

ROIの算出と提示

経営層からK8s導入のコミットメント(予算と人員の確保)を引き出すために、ROIを定量的に提示します。以下のフレームワークに沿って算出してください。

コスト増(K8s導入によって増加する費用)

  • K8s税(前述の固定費)× 環境数 × 12ヶ月
  • バージョンアップを先送りした場合に発生するExtended Supportの追加管理手数料(リスクとして計上する)
  • プラットフォームエンジニアの人件費(最低2名 × 年間)
  • 監視・CI/CDツールのライセンス費(Datadog、Argo CD Enterprise等)
  • 初期構築の外部コンサルティング費(必要な場合)

コスト減(K8s導入によって削減される費用)

  • リリース停止に伴う機会損失の排除(前述の定量値)
  • 開発者のデプロイ待ち時間削減(エンジニア単価 × 削減時間 × 年間回数)
  • インフラのオートスケーリングによるリソース効率化(ピーク時以外のコスト削減)
  • 既存インフラ(VMベース)の運用工数削減

「コスト減 − コスト増」がプラスになるまでの月数が、投資回収期間です。経営層に対して「Xヶ月で初期投資を回収し、以降は月額Y万円のコストメリットが継続する」というロジックで提示してください。投資回収期間が18ヶ月を超える場合は、スコープの縮小(移行対象システムの絞り込み)を検討すべきです。

【実務テンプレート】K8s導入判定・システム要件定義書

ここまでの内容を統合した、実務でそのまま使用できる要件定義書のテンプレートを提示します。プロジェクトのキックオフ時にこのテンプレートを埋め、関係者の署名(承認)を得た上で、後続の設計フェーズに進んでください。

K8s導入判定・システム要件定義書

プロジェクト名: ________________
作成日: ____/____/____
作成者: ________________
承認者: ________________


セクション1: 不採用7条件スクリーニング

各条件について「該当」または「非該当」を記入し、判断根拠を併記すること。

[関門1]技術的失格条件 ― 1つでも該当すればNo-Go(金額では解決不可)

1. ローカルI/O依存のステートフルアプリ: [該当 / 非該当]
 根拠: _______________________________________________

2. Graceful Shutdownに耐えられない処理の存在: [該当 / 非該当]
 根拠: 最長処理の所要時間___分 / 上限の見積もり [可 / 不可]
 該当時のアプリ改修: [計画あり / 計画なし]

3. 水平分散できないシングルトン処理の存在: [該当 / 非該当]
 根拠: 対象コンポーネント___________________________
 制約要因: [replicas 2以上で破綻 / ホスト単位ライセンス / 固定IP要件 / 固定ホスト名・ポート要件]
 ハイブリッド構成での切り出し: [可 / 不可]

[関門2]投資判断条件 ― 該当してもコストを許容できるなら採用可

4. 専任プラットフォームエンジニア2名未満: [該当 / 非該当]
 根拠: アサイン予定者___名(氏名: ___________________)
 該当時に確保する追加予算: ________万円/年

5. サービス境界の未定義: [該当 / 非該当]
 根拠: 分割済みサービス数___、切り出し候補_______________

6. PaaS制約に非抵触: [該当 / 非該当]
 根拠: 抵触する制約___________________________________

7. K8s税を上回るROI不在: [該当 / 非該当]
 根拠: 投資回収期間___ヶ月(算出根拠はセクション3に記載)
 ROIの減算要因: [デプロイ頻度が週1回未満 / ピーク比2倍未満](実測値はセクション3)

総合判定: [Go / No-Go]
No-Goの場合の代替手段: ________________________________


セクション2: ビジネス目標

目標1: ________________________________________________
 定量指標: ____________________________________________
目標2: ________________________________________________
 定量指標: ____________________________________________


セクション3: コスト・制約

K8s税(月額・3環境合計): $________________
運用チーム年間人件費: ________万円
現在のデプロイ頻度: ____回/____(日・週・月)
 ※週1回未満の場合、デリバリー改善による便益はROIに計上しない
Extended Supportの追加手数料をROIに織り込んだか: [済 / 未]
ピーク/平常トラフィック比: ____倍
 ※2倍未満の場合、オートスケーリングによる削減額はROIに計上しない
投資回収期間: ____ヶ月
コスト按分要否: [要 / 不要]
コンプライアンス要件: __________________________________
カットオーバー期限: ____/____/____


セクション4: 移行対象システム棚卸し

システムA: [ステートレス / ステートフル] / プロトコル: ______ / 月間リクエスト数: ______ / 最長処理時間: ____分
システムB: [ステートレス / ステートフル] / プロトコル: ______ / 月間リクエスト数: ______ / 最長処理時間: ____分
システムC: [ステートレス / ステートフル] / プロトコル: ______ / 月間リクエスト数: ______ / 最長処理時間: ____分

次回予告

本記事では、K8s導入の可否を判定するための7条件と、プロジェクト開始時に握るべきシステム要件の定義方法を解説しました。この要件定義書がGoの判定で承認された後、最初に直面する組織的な課題は「誰がマニフェストを書くのか」「Podが落ちたとき、誰が最初に動くのか」という責任境界の不在です。

次回の第2回「責任境界定義書(RACIマトリクス)」では、開発チームと運用チームの間で必ず発生するこの境界紛争を、RACIマトリクスとマニフェスト所有権モデルによって事前に解決する設計手法を扱います。

前の記事
次の記事