概要
「平均値」ではなく「p95・ピーク+マージン」で見積もる
実測平均使用量ぴったりにrequestsを合わせると、月8日発生する高負荷日のピーク帯で不足が起きる。平均は「典型的な日」しか表していない。
CPU不足とメモリ不足は質的に違う
CPUは圧縮性リソースでスロットリング(遅延)で済むが、メモリは非圧縮性リソースのため不足するとPodが強制終了(OOMKill)される。
リトライは根本原因を解決しない
requests不足が原因のOOMKillは、RetryStrategyでリトライしても同条件で再発する。無駄なコンピュート費と最終的な手動対応コストが積み上がるだけ。
削減額とOOMKill対応コストは同じ通貨で比較する
「53%削減」という数字だけを見ると魅力的だが、比較対象であるオンコール対応の人件費(今回は月4万円)を金額換算しない限り、意思決定の土台が成立しない。
問題
ECサイト MOps チームのシニアエンジニアとして、レコメンド再計算バッチ(recommendation-batch-job、Argo Workflows on GKE Autopilot)のリソースコストレビューを任された。後輩エンジニアが「Podのrequestsを実測平均値ぴったりに合わせればコストを53%削減できる」という Bad コスト比較メモを作成し、来週のインフラ定例でこのまま提案する予定だという。
以下の Bad メモから 試算・設計上の問題(7点)を洗い出し、Bad案が実際には運用コストを増大させることの金額換算・通常時/高負荷時のプロファイル分割設計・現状案/Bad案/Good案の比較・実装工数とROI・インフラ定例への推奨文までを一気通貫で回答してください。
制約・前提条件
- GKE Autopilot 料金前提(東京リージョン、Regular Pod、オンデマンド): CPU $0.0445/vCPU時間 / メモリ $0.0049/GiB時間 / 為替1USD=150円 / 本問固有の単純化ルールとして、Autopilot Podのリソースはrequestsに基づき課金されCPU 0.25vCPU単位・メモリ 0.25GiB単位で切り上げ
- recommendation-batch-job構成: Argo Workflows CronWorkflowとして1日4回(06:00/12:00/18:00/22:00)実行、月120回。現行requests: CPU 2vCPU / Memory 4GiB、平均実行時間40分/回。RetryStrategy:
retries: 2(最大3回試行) - 過去30日の実測(DataDog): CPU 平均0.9vCPU / 通常日p95 1.2vCPU / 高負荷日ピーク1.9vCPU。メモリ 平均2.1GiB / 通常日p95 2.6GiB / 高負荷日ピーク3.9GiB
- 「高負荷日」は月8日(カタログ更新日・セール前日)、該当実行は12:00と18:00のみ(高負荷実行16回/月、残り104回は通常実行)
- OOMKill実績: requestsを平均値まで下げた場合、高負荷実行16回全てでOOMKillが発生。リトライ2回も同条件で失敗し、最終的にオンコール対応(30分/回)が必要。失敗試行は25分/回で打ち切られ、手動再実行(緊急設定CPU1.9vCPU/Memory3.9GiB)は40分。通常実行104回も軽微なスロットリングで40分→44分に延伸
- エンジニア単価: 80万円/月(160時間=5,000円/時間)。日別プロファイル分割の実装工数: 3人日
悪いコスト比較メモ (Before)
件名: recommendation-batch-job リソースコスト削減のご提案
現状: Pod requests = CPU 2vCPU / Memory 4GiB で固定運用
過去30日の実測を確認したところ、CPU平均使用率0.9vCPU、
メモリ平均使用量2.1GiBしか使っておらず、requestsが過剰。
← 問題①: 平均値のみを見て、p95・ピーク帯の不足リスク未検討
改善案: requestsを実測平均値ぴったりに変更する
CPU requests: 2vCPU → 0.9vCPU(55%削減)
Memory requests: 4GiB → 2.1GiB(47.5%削減)
← 問題②③⑥: CPUスロットリング・メモリOOMKillの
質的な違いを未検討、切り上げ課金の刻みも未考慮
Autopilotはrequestsに対して課金されるため、平均使用量に
合わせれば無駄なく最適化でき、月間コストを約53%削減できる。
← 問題④⑤⑦: RetryStrategyが根本原因を解決しないことを見落とし
通常/高負荷を一律に扱い、運用コストとROI比較していない
よってrequestsを実測平均値へ変更することを提案します。
ヒント(段階的開示)
ヒント1 — 方向性
ヒント2 — アプローチ
- 問題①: Podのrequestsを実測「平均値」に合わせており、通常日p95(1.2vCPU/2.6GiB)・高負荷日ピーク(1.9vCPU/3.9GiB)での不足リスクを検討していない
- 問題②: CPU requestsを平均値まで引き下げるとピーク帯でCPUスロットリングが発生し、ジョブの完了時間が延びる可能性を検討していない → Autopilotは秒単位課金のため、実行時間が延びればコスト増要因にもなる
- 問題③: メモリ requestsを平均値まで引き下げると、ピーク時にメモリ使用量がrequestsを超過しOOMKillが発生するリスクを見落としている
- 問題④: Argo WorkflowsのRetryStrategyがOOMKillの根本原因を解消しないため、リトライしても同条件で再度OOMKillされ、最終的に手動対応が必要になる運用コストを試算していない
- 問題⑤: 通常時と高負荷時(カタログ更新日・セール前日)を単一のrequests設定で一律に扱っており、時間帯・日付別のプロファイル分割という選択肢を検討していない
- 問題⑥: Autopilot Podのリソースが一定の刻み幅で切り上げ課金されることを考慮せず、切りの良い数値での見積もりをしていない
- 問題⑦: コンピュートコストの削減額のみを見て「53%削減」と結論づけ、OOMKillによる失敗リトライの無駄なコンピュートコスト・手動対応の人件費という運用コストと比較(ROI)していない
ヒント3 — 誘導
【現行コスト再検証】
月間実行回数 = 4回/日 × 30日 = 120回
CPU時間 = 2vCPU × (40分/60) × 120回
Memory時間 = 4GiB × (40分/60) × 120回
【Bad案の実質コスト】
高負荷実行16回 × (失敗3試行×25分 + 手動再実行1回×40分)
→ 失敗試行分のコンピュートコスト + 緊急設定での再実行コンピュートコスト
→ オンコール対応: 16回 × 30分 × 5,000円/時間
【Good案: 通常/高負荷プロファイル分割】
通常実行requests = p95 × 安全マージン → 0.25単位で切り上げ
高負荷実行requests = ピーク × 安全マージン → 0.25単位で切り上げ
問題点分析(7点)
| # | 問題点 | 分類 | 改善方法 |
|---|---|---|---|
| 1 | 平均値のみでrequestsを決め、p95・ピークの不足リスク未検討 | 試算欠如 | p95・ピーク実測値を根拠に含める |
| 2 | CPU requests引き下げでスロットリング・実行時間延伸を未検討 | 運用リスク | ピーク帯でのスロットリング影響を試算 |
| 3 | メモリrequests引き下げでOOMKill発生リスクを見落とし | 運用リスク | ピーク使用量に対する安全マージンを確保 |
| 4 | RetryStrategyが根本原因を解消せず運用コスト未試算 | 試算欠如 | リトライ失敗×オンコール対応コストを算出 |
| 5 | 通常/高負荷を単一requestsで一律に扱う | 設計不足 | 実行日カレンダーでプロファイル分割 |
| 6 | 切り上げ課金の刻み幅を考慮せず概算 | 試算欠如 | 0.25単位切り上げで正確に見積もる |
| 7 | 削減額のみでROI比較せず結論 | 意思決定プロセス | コンピュート費と運用費を同一通貨で比較 |
コストとリスクの非対称性 — requests平均値一律変更 vs 通常/高負荷プロファイル分割
模範解答
修正⑥: 現行コスト再検証
| 項目 | 計算式 | 値 |
|---|---|---|
| 月間実行回数 | 4回/日 × 30日 | 120回 |
| CPU時間 | 2vCPU × (40/60)h × 120回 | 160.0 vCPU時間 |
| CPU費 | 160.0 × $0.0445 | $7.12 |
| Memory時間 | 4GiB × (40/60)h × 120回 | 320.0 GiB時間 |
| Memory費 | 320.0 × $0.0049 | $1.568 |
| 合計(月額) | - | $8.688 ≒ 1,303円 |
修正②③④: Bad案の実質コスト試算
表面上の主張(実行時間が変わらない前提)
| 項目 | 計算式 | 値 |
|---|---|---|
| CPU時間 | 0.9vCPU × (40/60)h × 120回 | 72.0 vCPU時間 |
| CPU費 | 72.0 × $0.0445 | $3.204 |
| Memory時間 | 2.1GiB × (40/60)h × 120回 | 168.0 GiB時間 |
| Memory費 | 168.0 × $0.0049 | $0.823 |
| 合計(月額) | - | $4.027 ≒ 604円(53.6%減) |
実際に起きること(高負荷実行16回 + 通常実行104回)
| 項目 | 計算式 | 値 |
|---|---|---|
| 失敗試行のCPU時間 | 0.9vCPU×(25/60)h×3試行×16回 | 18.0 vCPU時間 |
| 失敗試行のMemory時間 | 2.1GiB×(25/60)h×3試行×16回 | 42.0 GiB時間 |
| 手動再実行のCPU時間 | 1.9vCPU×(40/60)h×16回 | 20.27 vCPU時間 |
| 手動再実行のMemory時間 | 3.9GiB×(40/60)h×16回 | 41.6 GiB時間 |
| 通常実行104回のCPU時間 | 0.9vCPU×(44/60)h×104回 | 68.64 vCPU時間 |
| 通常実行104回のMemory時間 | 2.1GiB×(44/60)h×104回 | 160.16 GiB時間 |
| 実質コンピュート費合計 | - | $5.952 ≒ 893円 |
| オンコール対応労務費 | 16回×0.5h×5,000円/h | 40,000円 |
修正①⑤⑥: 通常/高負荷プロファイル分割設計とROI
| プロファイル | 対象実行 | CPU requests | Memory requests | 算出根拠 |
|---|---|---|---|---|
| 通常プロファイル | 通常実行104回 | 1.5vCPU | 3.25GiB | p95(1.2vCPU/2.6GiB)×マージン1.2→0.25単位切り上げ |
| 高負荷プロファイル | 高負荷日の実行16回 | 2.25vCPU | 4.5GiB | ピーク(1.9vCPU/3.9GiB)×マージン1.1→0.25単位切り上げ |
| 項目 | 計算式 | 値 |
|---|---|---|
| 通常実行CPU費 | 1.5vCPU×(40/60)h×104回×$0.0445 | $4.628 |
| 通常実行Memory費 | 3.25GiB×(40/60)h×104回×$0.0049 | $1.104 |
| 高負荷実行CPU費 | 2.25vCPU×(40/60)h×16回×$0.0445 | $1.068 |
| 高負荷実行Memory費 | 4.5GiB×(40/60)h×16回×$0.0049 | $0.235 |
| 合計(月額) | - | $7.035 ≒ 1,055円 |
- 実装工数(Argo Workflowテンプレート設計・検証・監視ダッシュボード設定): 3人日 × 4万円/人日 = 12万円
- 直接効果のみのペイバック期間: 120,000円 ÷ (1,303円−1,055円=248円/月) ≒ 484ヶ月(40年、非現実的)
- リスク回避ベースのペイバック期間: 120,000円 ÷ (40,893円−1,303円=39,590円/月) ≒ 3.0ヶ月
現状・Bad案・Good案の3案比較
| 案 | 見かけの月額コンピュート費 | 実質コンピュート費 | 運用対応費 | 実質合計/月 | 判定 |
|---|---|---|---|---|---|
| 現状(requests固定) | 1,303円 | 1,303円 | 0円 | 1,303円 | 安定だが最適化余地あり |
| Bad案(平均値へ一律変更) | 604円(53.6%減) | 893円 | 40,000円 | 40,893円(現行比31.4倍) | 表面上最安だが実質最悪 |
| Good案(プロファイル分割) | 1,055円 | 1,055円 | 0円 | 1,055円(19.0%減) | 最適 |
インフラ定例への推奨文
requestsを実測平均値(CPU0.9vCPU/Memory2.1GiB)へ一律変更
する提案(Bad案)は、月間コンピュートコストを53.6%削減
できるという試算です。しかし recommendation-batch-job は
月8日の高負荷日にメモリ使用量がピーク3.9GiBまで達する特性
があり、requestsを2.1GiBまで下げるとメモリ不足による
OOMKill(Pod強制終了)が発生します。ArgoのRetryStrategyで
リトライしても同条件で再度OOMKillされるため、最終的には
オンコール対応による手動再実行が必要になり、人件費だけで
月40,000円、実質コンピュートコストも含めると月40,893円
(現行比約31.4倍)に膨らむことが試算で分かりました。
代わりに、通常時(requests CPU1.5vCPU/Memory3.25GiB)と
高負荷時(requests CPU2.25vCPU/Memory4.5GiB)でプロファイル
を分割する設計を提案します。実装工数12万円に対し、直接
コンピュートコストを19.0%削減(1,303円→1,055円/月)しつつ、
OOMKillによる運用リスクを完全に排除でき、リスク回避ベースで
は約3ヶ月で投資を回収できます。
ポイント解説
実務への応用
MOpsチームのように月末・セール前など予測可能な高負荷日を持つバッチ処理では、「実測平均値に合わせればコスト最適」という発想に流れやすい。しかし実務では、リソース使用量の分布(平均・p95・ピーク)を必ず確認し、削減対象の設定がどのシナリオ(通常時/ストレス時)に紐づいているかを見極める必要がある。Argo WorkflowsのCronWorkflowにパラメータとして実行日カレンダーを渡す仕組みは、Terraformでの構成管理と組み合わせれば「高負荷日の判定を誰かが手動で更新し忘れる」という属人的な事故も防げる。
今日のまとめ
次のステップ
- 発展問題: Good案の運用開始から3ヶ月後、商品カタログが1.5倍に増加し、通常日のメモリ使用量もp95 3.1GiBまで上昇、通常プロファイルでもOOMKillが散発するようになったとする。(1) どのタイミング・トリガーでrequestsプロファイルを再チューニングすべきか、(2) VPA(Vertical Pod Autoscaler)recommenderやDataDogのメモリ使用率アラートをどう設計して次の劣化を早期検知するか、(3) カタログ成長ペースを踏まえた見直しサイクルをどう定義するか、を踏まえた運用ルールを提案せよ。
- 参考: GKE Autopilot / Pod requests・limits / OOMKilled / CPU throttling / Argo Workflows RetryStrategy / Vertical Pod Autoscaler / p95見積もり