Go 1.25 전에는 GOMAXPROCS 기본값이 머신의 논리 CPU 개수였어요. 논리 CPU가 32개인 호스트에서 CPU 두 개로 제한된 컨테이너도 32를 받았어요. P 32개가 고루틴을 돌리는데 쿼터는 주기마다 CPU 두 개 분량이라, 프로세스는 쿼터를 일찍 다 쓰고 주기의 나머지 동안 스로틀링에 걸려 있어요.
Go 1.25가 Linux에서 기본값을 바꿨어요. 런타임이 cgroup CPU 대역폭 한도를 읽고, CPU 개수보다 낮으면 그 값을 써요. 소수 한도는 올림해요. 머신 자체 CPU가 두 개 미만이 아니면 기본값은 2 밑으로 내려가지 않아요. 주기적으로 다시 확인도 해서, 실행 중에 한도가 바뀌면 따라가요.
이걸 못 받는 길은 세 가지예요. 환경 변수 GOMAXPROCS, 값을 넣은 runtime.GOMAXPROCS 호출, 그리고 go.mod의 go 줄이 1.24 이하인 경우예요. 거기서는 containermaxprocs=0이 기본값이거든요. 그리고 한도만 읽어요. 한도 없이 CPU 요청만 있으면 아무것도 안 바뀌어요. Kubernetes로 말하면 limits.cpu이고, requests.cpu만 있는 파드는 예전 기본값 그대로예요.
확인할 때는 두 줄을 찍는 프로그램을 써요.
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("GOMAXPROCS", runtime.GOMAXPROCS(0))
fmt.Println("NumCPU", runtime.NumCPU())
}
새 기본값이 적용되도록 이런 go.mod로 빌드해요.
module probe
go 1.25
NumCPU는 예전 기본값이 쓰던 숫자예요. CPU 개수보다 낮은 한도가 걸린 컨테이너에서 두 줄이 같게 나오면, 위의 세 가지 중 하나가 막고 있는 거예요.
그러니까 제가 보는 숫자는 실행 가능한 P 32개에서 두 개로 줄었어요.