代表的な面接トピック

Goコーディング面接:Go 1.25はコンテナ内でGOMAXPROCSをどのように計算するか?

コーディング難しい
Offer.cc 編集チーム公開日 更新日

質問

Go 1.25はコンテナ内でGOMAXPROCSをどのように計算しますか?

プロンプト

Goサービスが、64論理CPUを持つノード上のKubernetes Podで実行されており、PodのCPU制限は2.5に設定されています。Go 1.25にアップグレードした後、デフォルトのGOMAXPROCS、CPU requestsとの関係、cgroupの変更が追従されるかどうか、およびテールレイテンシー、スループット、GC動作をどのように検証するかを説明してください。また、手動でのGOMAXPROCSまたはGODEBUGの設定が何を無効化するかを述べてください。

面接官がテストしていること

ここでは、ランタイムの並行性、コンテナリソースのセマンティクス、およびパフォーマンス診断がテストされます。論理CPU、CPU制限(limits)、CPU要求(requests)、プロセスアフィニティ、およびGOMAXPROCSを区別してください。Go 1.25はLinux cgroupの平均CPUスループット制限を読み取り、デフォルト値を定期的に更新しますが、手動によるオーバーライドはその動作を無効化します。端数のクォータ、バースト時のレイテンシー、ロールバックを考慮せずに「2に設定する」と答えるだけでは不完全です。

確認のための質問

  1. どのGoバージョン、Linux cgroupバージョン、コンテナランタイムが使用されていますか?
  2. PodはCPU limit、request、またはその両方を設定していますか?また、limitは変更可能ですか?
  3. 目標はスループット、P99レイテンシー、GC一時停止、またはコストのいずれですか?また、バーストは予想されますか?
  4. GOMAXPROCSは環境変数、起動フラグ、またはコードによってすでに設定されていますか?

30秒フレームワーク

デフォルト値は、論理CPU数、CPUアフィニティ、およびcgroupの平均CPUスループット制限の最小値から導出されます。端数の制限は切り上げられ、マシンまたはアフィニティのCPU数が2未満でない限り、ランタイムは通常2未満を選択しません。Requestsは使用されません。その上で、オーバーライドの優先順位、更新、オブザーバビリティ、およびロールバックについて説明します。

ステップバイステップの設計

1. デフォルト値の理解

GOMAXPROCS環境変数の値やruntime.GOMAXPROCSの呼び出しがない場合、Linux上のGo 1.25はcgroupのCPU quota/periodを平均スループット制限として読み取ります。また、論理CPUとプロセスアフィニティも考慮し、通常はその最小値を選択します。2.5 CPUの制限は3に切り上げられます。Requestはスケジューリングの保証であり、ハードなスループット制限ではないため、このデフォルト値の計算には使用されません。

2. 更新とオーバーライドの優先順位

ランタイムは、論理CPU数、アフィニティ、およびcgroupクォータの変更を定期的に確認します(通常は1秒に1回以下)。GOMAXPROCS環境変数を設定するか、runtime.GOMAXPROCSを呼び出すと自動更新が無効になります。runtime.SetDefaultGOMAXPROCS()はランタイムのデフォルトを復元します。GODEBUG=containermaxprocs=0はcgroup制限を無視し、updatemaxprocs=0は更新を無効にします。

3. スケジューリングおよびスロットリングとの関連付け

GOMAXPROCSはGoユーザーコードの同時実行を制限します。これはコンテナのCPU上限ではなく、システムコールでブロックされたスレッドを制限するものでもありません。CPU制限を大幅に超える値を設定すると、カーネルのスロットリングやテールレイテンシーのスパイクが引き起こされる可能性があります。値が低すぎると、スループットとGCの並列性が低下する可能性があります。Kubernetesのlimits、requests、ノードのオーバーコミットと合わせて分析してください。

4. 計装と検証

起動時にruntime.GOMAXPROCS(0)runtime.NumCPU()、アフィニティ、cgroup quota/period、およびGODEBUGを記録します。/sched/gomaxprocs:threads、CPUスロットリング、ランキュー、P99、GC CPU割合、スループット、およびエラーを関連付けて分析します。制限を変更した後は、単一の起動ログに頼るのではなく、GOMAXPROCSがそれに追従していることを確認します。

5. ワークロード実験の実行

同じGoバージョンと同じデータを用いて、CPUヘビー、I/O待機、およびバースト性のある短時間リクエストの負荷下で、デフォルト設定、明示的な値、および以前のGoバージョンを比較します。定常状態とバーストを測定します。Goのガイダンスでは、GOMAXPROCSを低く設定するとスロットリングを削減できる一方で、スパイクの多いワークロードでは並行性が制限された場合にレイテンシーが高くなる可能性があると指摘されています。P95/P99とコストの両方を考慮して判断してください。

6. ロールアウトとロールバック

固定の制限と明示的なゲートを用いてGo 1.25をカナリアリリースします。スロットリング、P99、またはGCが悪化した場合は、イメージをロールバックするか、実験的に正当化された明示的な値を使用し、それによって自動更新が無効になることを文書化します。オーバーライドを削除してSetDefaultGOMAXPROCSを呼び出すと、デフォルトの計算が復元されます。クォータ変更後に再度検証してください。

7. 障害モードと制限事項の提示

Requestを制限(limit)として扱ったり、runtime.NumCPU()を利用可能な並行性とみなしたり、cgroupsがどこでも同一であるとみなしたりしないでください。Linux以外のシステム、クォータの未設定、手動設定、および古いGoバージョンでは動作が異なります。リリースチェックリストにGoバージョン、GODEBUG、リソース仕様、およびロールバック担当者を記録してください。

優れた回答例

「明示的なオーバーライドがない場合、Linux上のGo 1.25はcgroupのquota/periodを読み取り、そのスループット制限、論理CPU、アフィニティの最小値を取得します。2.5 CPUは3に切り上げられ、requestsは使用されません。ランタイムはクォータの変更を定期的に確認しますが、環境変数の値、runtime.GOMAXPROCS、またはGODEBUG=containermaxprocs=0/updatemaxprocs=0によって動作が変わります。私ならGOMAXPROCS、cgroupデータ、/sched/gomaxprocs、スロットリング、P99、スループット、GCを記録し、CPUヘビーおよびバースト負荷の下でデフォルト、明示的な値、古いバージョンを比較します。ゲートを超過したカナリアはロールバックし、オーバーライド時に自動更新が無効になることをランブックに記録します。」

よくある失敗パターン

  • GoがCPU requestsを直接使用すると主張すること。
  • 端数クォータと最小値ルールを説明せずに制限値を丸めること。
  • 環境変数値、コードによる呼び出し、GODEBUGが自動更新を無効化することを忘れること。
  • スロットリング、P99、GC、バーストレイテンシーを無視してスループットのみを測定すること。
  • GOMAXPROCSをコンテナのCPU上限やシステムコールスレッドの制限として扱うこと。

フォローアップの方向性

なぜ2.5 CPUが3になるのか?

GOMAXPROCSは正の整数であるため、ランタイムはクォータを最大限活用するために端数のスループット制限を切り上げます。

なぜCPU requestは除外されるのか?

Requestは、余剰キャパシティがある場合に超過可能なソフトなスケジューリング保証であり、安定したハードなスループット上限ではないためです。

自動更新をどのように検証するか?

cgroupクォータを変更し、環境変数の値とGODEBUG設定を確認しながら、ログと/sched/gomaxprocs:threadsを監視します。

どのような場合に手動で設定するか?

実験によってワークロード、プラットフォーム、またはレイテンシー目標に固定の並行性が必要であることが示された場合に設定し、明示的なロールバック設定を維持します。

Go 1.24についてはどうか?

移行措置として明示的な値やcgroup対応の互換性アプローチを使用し、Go 1.25にアップグレードした後に制限、アフィニティ、スロットリングを再テストします。

参考資料

Go 1.25「Release Notes」、Go Blog「Container-aware GOMAXPROCS」、およびpkg.go.dev「runtime」。

公開情報ソース

関連する質問

関連面接ツール

コーディング問題にはスクリーンショットを使用

問題をキャプチャし、制約条件、解法アプローチ、コード、エッジケース、計算量の順に進めます。

ツールを見る