Kubernetes v1.36.5 - Go 1.26.8 Build and Proxy Panic


Kubernetes published v1.36.5 on 23 September 2026. A ResourceClaim whose device counts overflow an int no longer crashes kube-scheduler, and an oversized firstAvailable alternative falls through to a smaller one. The same tag rebuilds the 1.36 line with Go 1.26.8 and stops a Windows kube-proxy panic in winkernel mode.

The full release notes and downloads are on the GitHub release page. That page points at the 1.36 changelog, which holds the patch list, image names, and sha512 hashes for the tarballs. The release body also links the announce forum.

#142180 is the only feature entry. It sets .go-version to 1.26.8, up from 1.26.5. build/build-image/cross/VERSION moves from v1.36.0-go1.26.5-bullseye.0 to v1.36.0-go1.26.8-bullseye.0. That tag is what build/dependencies.yaml records for registry.k8s.io/kube-cross.

build/common.sh updates two defaults. __default_go_runner_version moves from v2.4.0-go1.26.5-bookworm.0 to v2.4.0-go1.26.8-bookworm.0, the pin for registry.k8s.io/go-runner. __default_distroless_iptables_version moves from v0.9.6 to v0.9.7. test/utils/image/manifest.go sets DistrolessIptables to the same v0.9.7 string for registry.k8s.io/distroless-iptables.

The changelog Dependencies block says nothing was added, changed, or removed. That block is the Go module list, so go.mod stays put while the image tags above move. The published sentence names Go 1.26.8 and names no CVE. Read the bump as a compiler and base image refresh.

The same changelog lists the manifest images for this tag. registry.k8s.io/kube-apiserver:v1.36.5, registry.k8s.io/kube-controller-manager:v1.36.5, registry.k8s.io/kube-scheduler:v1.36.5, registry.k8s.io/kube-proxy:v1.36.5, registry.k8s.io/kubectl:v1.36.5, and registry.k8s.io/conformance:v1.36.5 each include amd64, arm64, ppc64le, and s390x.

#141707 stops winkernel kube-proxy from exiting while it lists HNS load balancers. HNS is the Windows Host Network Service. getAllLoadBalancers in pkg/proxy/winkernel/hns.go read PortMappings[0] on every object HNS returned. An empty slice, including a nil slice, panicked with index out of range and ended the kube-proxy process. The comment on the fix says HNS can return a load balancer in that shape while creation is still incomplete.

The loop now checks len(lb.PortMappings) == 0 before the index. On an empty list it logs Skipping load balancer with no port mappings through klog.V(2), attaches hnsLbID, and continues. The code reads LoadBalancerFlagsIPv6 after that guard. The production edit is the early return in hns.go, plus winkernel unit tests. Windows nodes that run winkernel are the blast radius. One HNS load balancer with no port mappings was enough to take kube-proxy down on that node.

#141923 changes the structured allocator inside kube-scheduler. Allocate summed each request into minDevicesPerClaim with a native int, then compared the sum with AllocationResultsMaxSize. allocateOne used len(results) + numDevices - deviceIndex. Two ExactCount values of math.MaxInt/2 + 1 wrap the sum negative. The limit check then succeeds, and the slice allocation panics with makeslice: cap out of range. That panic takes the scheduler down. DeviceRequest.Count only has to be greater than zero, and the wrap is reachable with no feature gate. The stable, incubating, and experimental allocators all had the same add, under staging/src/k8s.io/dynamic-resource-allocation/structured/internal/.

The patched Allocate compares before it adds. When minDevicesPerRequest is greater than AllocationResultsMaxSize minus the devices already counted, it returns an error. The error names the claim, the request, how many devices the request would add, the limit, and how many were already counted. allocateOne compares the devices still required with the slots left under the limit. A request over the device limit on the claim is rejected with that error. An oversized firstAvailable alternative falls through to a smaller one, and the scheduler process keeps running.

#141628 changes WriteConfigToDisk in cmd/kubeadm/app/phases/kubelet/config.go. The old function called Mutate on the cluster kubelet config object, then marshaled that same object. Mutate applies settings local to the machine running kubeadm init. Where that machine uses systemd-resolved, the setting the release note calls out is resolvConf. Init uploads the cluster configuration into the shared kubelet-config ConfigMap, so other nodes inherited the path from the init node.

The function now calls DeepCopy, runs Mutate on the copy, and marshals the copy to the kubelet configuration file on disk. The cluster object stays unchanged, so the ConfigMap written at init keeps the resolvConf value from before Mutate. An object already stored by an older init remains until a later write replaces it. If the first control plane node uses systemd-resolved, read resolvConf in that ConfigMap and confirm the path exists on every node that consumes it.

#141603 changes tests only. Three conformance cases added in 1.35 are not interoperable with the static CPU manager, so this pull request demotes them to ordinary e2e tests. test/e2e/common/node/pod_resize.go switches each one from framework.ConformanceIt to ginkgo.It. test/conformance/testdata/conformance.yaml drops the three entries. The tests still run, and each name still carries [MinimumKubeletVersion:1.34].

  • 3 containers - increase cpu & mem on c1, c2, decrease cpu & mem on c3 - net increase [MinimumKubeletVersion:1.34]
  • 3 containers - increase cpu & mem on c1, decrease cpu & mem on c2, c3 - net decrease [MinimumKubeletVersion:1.34]
  • 3 containers - increase: CPU (c1,c3), memory (c2, c3) ; decrease: CPU (c2) [MinimumKubeletVersion:1.34]

A conformance run that uses the static CPU manager counts these three as ordinary e2e tests.