テック技報最新号へ →
コード

Go: コンテナの CPU 制限と GOMAXPROCS(Go 1.25 から cgroup の limit を見る)

Go 1.24 までは GOMAXPROCS の既定値がノードの論理 CPU 数だったので、CPU limit 2 の Pod でも 64 コアのノードなら 64 になり、CFS のスロットリングで遅くなっていた。Go 1.25 以降は cgroup の CPU limit を既定値に使う。ただし go.mod の go 行が 1.25 以上のときだけ。

@amitsinha__07 · 投稿 2026-10-18
#go#runtime#kubernetes#performance

どんな時に気にする?

  • Kubernetes / ECS / Docker で resources.limits.cpu を付けて Go のサービスを動かしている
  • p99 レイテンシが周期的に跳ねる、container_cpu_cfs_throttled_seconds_total が増えている
  • これまで go.uber.org/automaxprocs を入れていた

確認と対処

  1. 実際の値を見る(起動ログに一行出しておくのが手軽)
    go
    slog.Info("runtime", "gomaxprocs", runtime.GOMAXPROCS(0), "numcpu", runtime.NumCPU())
  2. Go 1.25 以上でビルドし、go.mod を go 1.25 以上にする。ツールチェーンだけ新しくても、go.mod の go 行が古いと旧来の挙動のまま(GODEBUG の既定値が go 行で決まるため)。
  3. 1.25 以降の挙動
    • cgroup の CPU limit(帯域制限)がコア数より小さければ、それを既定値にする
    • limit やコア数が実行中に変わると、ランタイムが定期的に GOMAXPROCS を更新する
    • 環境変数 GOMAXPROCS や runtime.GOMAXPROCS(n) で明示した場合は、どちらも働かない
    • 無効にしたいときは GODEBUG=containermaxprocs=0 / updatemaxprocs=0
    • 明示設定を既定値に戻すには runtime.SetDefaultGOMAXPROCS()(1.25 で追加)
  4. 1.25 に上げられない場合は、従来どおり automaxprocs を blank import するか、GOMAXPROCS を limit に合わせて環境変数で渡す。

注意点

  • 見るのは limit で、request は見ない。limit を付けていない Pod では、今でもノードのコア数になる。
  • limit が小数(例: 1.5)のときは整数に切り上げて使う(細かい丸め方は公式の runtime ドキュメントで確認)。
  • 1.25 に上げた後に automaxprocs を残していても動くが、二重管理になるので外してよい。

出典

X の元の投稿を開く