Kubernetes 1.37: What Actually Landed Before Code Freeze
Kubernetes 1.37 is not released yet, general availability is Wednesday, 26 August 2026, and the release schedule still has two release candidates ahead of it: RC0 on 5 August, RC1 on 19 August.
What has happened is code and test freeze, which passed on 23 July. The feature set is effectively settled, and the newest published artifact is v1.37.0-beta.0. That makes this a good moment to look at the release. It is also a bad moment to trust the summaries circulating about it, several of which describe features that do not appear in the codebase at all.
This article works from the CHANGELOG-1.37.md file, searched by exact string match rather than skimmed. Where a claim comes from a proposal thread rather than merged code, it is labelled as such. Everything below reflects v1.37.0-beta.0; stages can still move before GA, and this post will be updated once the release lands.
Key Takeaways
- 1.37 is not out. GA is 26 August 2026. Code freeze passed 23 July;
v1.37.0-beta.0is the newest tag (release schedule)- nftables does not become the default kube-proxy backend. The changelog says the switch happens "in a future release". 1.37 only adds a warning
SELinuxMountis on by default and can break workloads. This is the single change most likely to cost you an outage (release note, SELinux blog)- Two scheduling feature gates were deleted mid-cycle.
GangSchedulingandWorkloadAwarePreemptionwere replaced byGenericWorkloadinalpha.2- The containerd 2.0 deadline was 1.36, not 1.37. v1.35 was the last release supporting containerd 1.x; one 1.37 removal was actually deferred to 1.38
Where the release actually is
| Milestone | Date |
|---|---|
| Cycle start | 18 May 2026 |
| Production Readiness Freeze | 9/10 June 2026 |
| Enhancements Freeze | 16/17 June 2026 |
| Feature Blog Freeze | 9/10 July 2026 |
| Code & Test Freeze | 22/23 July 2026 |
| Docs Freeze | 5/6 August 2026 |
| Release Candidate 0 | 5 August 2026 |
| Release Candidate 1 | 19 August 2026 |
| General Availability | 26 August 2026 |
Fifteen weeks, four pre-release tags so far: alpha.1, alpha.2, alpha.3, beta.0. The release name has not been announced yet.
For context on what you are upgrading from: 1.36 reaches end of life on 28 June 2027, 1.35 on 28 February 2027, and 1.34 on 27 October 2026 (releases page). If you are on 1.34, the clock matters more than the feature list.
Three claims worth correcting
nftables is not becoming the default
This is the most repeated 1.37 headline and it is wrong. The actual release note, verbatim:
"Kube-proxy now warns you if you start it without explicitly specifying the proxy mode that you want (iptables, ipvs, or nftables), because the default on Linux will be switching from 'iptables' to 'nftables' in a future release."
A warning. That is the whole change. The kubeadm-side note is equally explicit: setting the mode explicitly is "part of the plan to switch the default mode to 'nftables' in a future release."
Two further details get lost in the retellings. The nftables mode has been generally available since 1.33, so it is not new, and 1.37 does not change its maturity. And iptables is still the default: a separate kubeadm note describing the ipvs deprecation states plainly that for older kernel versions "users can use 'iptables', which is still the default."
The actionable part is small but real: set mode explicitly in your KubeProxyConfiguration now, so that the eventual default flip is a no-op for you rather than a surprise. ipvs is deprecated as of 1.35 and users on newer kernels should be moving to nftables, but nothing is removed in 1.37.
Two unrelated kube-proxy fixes are worth knowing about: nftables comments are now truncated to the kernel's 128-byte limit before programming service maps, which fixes sync failures on long Service names, and stale conntrack entries are now cleared when a UDP service scales to zero endpoints, preventing one-way UDP flows from being blackholed to deleted Pod IPs.
The containerd 2.0 deadline already passed
Several 1.37 write-ups tell you to upgrade to containerd 2.0 before 1.37. That deadline was real, but it was a release earlier. From the v1.35 sneak peek:
"Kubernetes v1.35 is the last release to offer this support (aligned with containerd 1.7 EOL)." "This is a final warning that if you are using containerd 1.X, you must switch to 2.0 or later before upgrading Kubernetes to the next version."
The next version after 1.35 is 1.36. Searching the 1.37 changelog for containerd returns Go module version bumps and one appearance inside the deprecated cAdvisor flag list. There is no runtime version policy change at all.
In fact 1.37 moved a deadline in the opposite direction:
"Kubelet: defer the configurations flags (and the related fallback behavior) deprecation removal timeline from 1.37 to 1.38 to align with containerd v1.7 support"
If you want to know whether any node is at risk, the metric to watch is kubelet_cri_losing_support, which the v1.35 post introduced for exactly this purpose.
cgroup v1 gets the same treatment. It is deprecated as of v1.35, and the kubelet already "will no longer start on a cgroup v1 node by default," with failCgroupV1: false as the documented escape hatch. None of that is new in 1.37: the cgroup-related entries in this changelog are MemoryQoS bug fixes. Both of these are genuine blockers if you have not dealt with them; neither is a 1.37 story.
Two feature gates no longer exist
If you are templating feature gates from the release highlights discussion, check this one. From alpha.2:
"The GangScheduling and WorkloadAwarePreemption feature gates were removed, and GenericWorkload is used instead to enable all core workload-aware scheduling functionalities altogether."
Anyone who wrote GangScheduling=true into a kube-scheduler config based on pre-freeze summaries will be setting a gate that is not there.
One caveat, and it is a useful illustration of how to read a changelog: a later entry in beta.0 still refers to "the WorkloadAwarePreemption feature gate," and another references a PodGroupPreemptionPolicy gate. Per-PR release notes are written when the PR merges and are not reconciled afterwards, so changelog prose is not a reliable index of the final gate set. Verify gate names against the released binary, either kube-scheduler --help or the 1.37 feature gates reference once docs freeze lands on 6 August.
Separately, PreventStaticPodAPIReferences "has been removed and cannot be disabled anymore," allowing static Pods to reference API resources unconditionally.
The change most likely to break your cluster
SELinuxMount is now GA and enabled by default. The release note carries an unusually direct warning:
"Graduated the
SELinuxMountfeature gate to GA.SELinuxMountis now enabled by default in Kubernetes 1.37, which may break existing workloads in Kubernetes clusters with SELinux enabled."
The mechanism is worth understanding, because it explains exactly which workloads are at risk. Historically, giving a volume the right SELinux label meant the container runtime walked every inode on that volume and relabelled it. On a volume with a large file count, or on a remote filesystem, that walk dominates container startup time.
The new behaviour mounts the volume with -o context=<label> instead, so the kernel applies the label to the whole mount at once. As the Kubernetes blog on the change puts it, "such a mount will happen in a constant time and the container runtime will not need to recursively relabel any files on it."
The breakage follows directly from that. A label applied at mount time is a property of the mount, not of individual files, so a volume can no longer carry different labels for different consumers. The blog names the failure case: "sharing one volume between privileged and unprivileged Pods on the same node." Under recursive relabelling that worked; under mount-time labelling it does not.
What to do:
- If your nodes do not use SELinux, ignore this entirely. The release note is explicit that "admins of clusters without SELinux enabled can ignore this release note, as nothing changes for them," and the kubelet skips the SELinux path when SELinux is unavailable or disabled in the kernel.
- If they do, audit for Pods sharing a single volume at the same mount path with different SELinux contexts and without
subPath. The blog states that "Kubernetes v1.36 is the right release to audit your cluster", meaning the audit is meant to happen before you upgrade. - The opt-out is per-Pod, via
spec.securityContext.seLinuxChangePolicy.
Urgent upgrade notes, in full
Three items in this release will stop a kubelet from starting or silently change its behaviour.
| Change | What breaks | Action |
|---|---|---|
| Deprecated cAdvisor flags now fatal | The kubelet "will fail to start if any are set". Only --housekeeping-interval survives |
Remove --boot-id-file, --containerd, --containerd-namespace, --machine-id-file, --container-hints, --enable-load-reader, --log-cadvisor-usage, the --event-storage-* and --storage-driver-* flags, --application-metrics-count-limit, --global-housekeeping-interval |
| cAdvisor metrics removed | container_cpu_load_average_10s, container_cpu_load_d_average_10s and container_tasks_state are no longer exported; custom container_application_* families and userDefinedMetrics in /stats/summary are gone |
Grep dashboards and alert rules for those series before upgrading |
eventRecordQPS: 0 reversed meaning |
0 was treated as "use the default"; it now means genuinely unlimited | "if your kubelet configuration setting eventRecordQPS to 0 and you want to preserve the previous behavior, please change the value to 50" |
| Kubelet logs effective config at start | Configuration values now appear in node logs | "review permissions to only allow trusted users to nodes/logs cluster role" |
The cAdvisor change is the one that will bite quietly. A removed metric does not fail an upgrade; it just makes a dashboard go flat and an alert stop firing.
What graduated
To GA / stable:
| Feature | Note |
|---|---|
SELinuxMount |
On by default (see above) |
| Node declared features | Promoted to GA |
StorageVersionMigration |
GA and enabled by default, with the StorageMigration/v1 API. Migration progress now surfaces in SVM conditions |
| DRA device taints and tolerations | GA via the resource.k8s.io/v1 API |
HPAConfigurableTolerance |
Promoted to GA |
| ClusterTrustBundle + ClusterTrustBundleProjection | Stable and enabled by default, along with the ClusterTrustBundle API |
metrics.k8s.io |
Promoted from v1beta1 to v1 "without any modifications" |
kubectl get -o kyaml |
Promoted to stable |
To beta, enabled by default:
| Feature | Effect |
|---|---|
EtcdRangeStream |
Watch cache initialises by streaming from etcd in a single RangeStream RPC instead of paginated Range requests |
PersistentVolumeClaimUnusedSinceTime |
PVCs report an Unused condition showing how long they have gone unused |
WatchListCompression |
gzip responses for WatchList requests when the client sends Accept-Encoding: gzip. Regular watches unaffected |
ManifestBasedAdmissionControlConfig |
File-based admission configuration at startup |
NativeHistograms |
Prometheus native histograms for Kubernetes metrics |
ExcludeAdmissionWebhookVirtualResources |
Webhooks skip auth virtual resources such as tokenreviews and subjectaccessreviews |
WebhookRoundTripLoadBalancing |
With --enable-aggregator-routing=true, requests are load-balanced across webhook endpoints instead of pinned to one by connection caching |
MaxUnavailableStatefulSet |
Now enabled by default |
| HPA scaling to and from zero | "Enable scaling to and from zero by default" |
The EtcdRangeStream graduation deserves a note, because it pairs with a dependency change: the default etcd version in 1.37 moved to 3.7.0. RangeStream requires etcd v3.7.0 or later. The etcd 3.7 announcement describes the old behaviour: etcd would "buffer the full result set before sending, leading to unpredictable latency and memory usage, both on the server and the client". The same post says Kubernetes users "should see a significant decrease in overall CPU usage by the etcd members, compared with v3.6." Note that when that post was published on 8 July it described RangeStream as opt-in via the gate; it was enabled by default afterwards, in beta.0. If you run etcd externally and are below 3.7.0, this is a compatibility item to check rather than a free win.
Workload-aware scheduling is still moving
The workload scheduling API saw more churn between alphas than any other area, which is the honest headline for it. Within a single cycle:
CompositePodGroupwas added toscheduling.k8s.io/v1alpha3PodGroupTemplateRefwas converted to a "simpler and more direct"WorkloadRef- A
PreemptionPolicyfield was added to both PodGroup and PodGroupTemplate - The
PodGroupScheduledcondition was renamedPodGroupInitiallyScheduled, to make clear it reflects first successful scheduling rather than current state MinCountbecame mutable after being set- A
PodGroupPostFilterextension point replaced "internal hardcoding forWorkloadAwarePreemption", and PostFilter plugins no longer run during the PodGroup cycle - Two scheduler metrics were added:
queued_entitiesandqueue_incoming_entities_total, both counting pods or podgroups
Workload-aware preemption also changed strategy: it "now runs only one scheduling attempt, on a cluster with all potential victims removed," explicitly trading optimal victim selection for performance.
The sig-release highlights discussion targets beta for the Workload and PodGroup APIs. The changelog does not contain a beta graduation note for them, and workload.k8s.io does not appear in it at all, so this article makes no stage claim. If you are building on these APIs, read the 1.37 API reference at GA rather than any pre-release summary, including this one.
Smaller changes worth knowing
- StatefulSet
Recreateupdate strategy, mirroring the Deployments strategy: deletes all Pods and waits for full termination before creating new ones according topodManagementPolicy kubectl explain --recursivegains--max-depthto cap nested field outputkubectl run --filename/-fis deprecated (it was already ignored)--concurrent-disruption-syncsadded to kube-controller-manager to tune disruption controller workers- Node Lifecycle Conditions introduced
- Core Conditional Authorization machinery implemented
- NodeRestriction gained a defence-in-depth check for PodCertificateRequests: a node may only create one for a signer the Pod actually mounts, or with an explicit authorization check
- Pod-level resources only determine QoS when they contain an actual request or limit; empty values no longer affect the calculation
- Two new safe sysctls:
net.ipv4.tcp_slow_start_after_idleandnet.ipv4.tcp_notsent_lowat - DRA gains
resource.kubernetes.io/numaNodeas a standard device attribute with sysfs-based helpers for drivers (KEP-6072) - In-place Pod resize preemption is available in alpha: the scheduler preempts lower-priority Pods to make room for
Deferredresizes of higher-priority ones. The changelog spells the gateInPlacePodVertifcalScalingSchedulerPreemption, which appears to be a typo. Check the actual string before putting it in a config - Built with Go 1.26.5; CoreDNS bumped to 1.14.6
A note on what is not here
Round-ups of 1.37 published before code freeze list a number of alpha features: pod-level checkpoint/restore, bind mount options for volume mounts, HTTP/2 cleartext probes, TLS for gRPC probes, emptyDir permission modes, CSI volume health monitoring, and default Pod sysctls via kubelet configuration. They also list a set of API removals covering IPAddress, ServiceCIDR and VolumeAttributesClass v1beta1.
An exact-match search of CHANGELOG-1.37.md at v1.37.0-beta.0 returns zero occurrences for every one of those. That does not prove none of them landed; a change can merge without a release note. It does mean none of them can be confirmed from the changelog today, so they are omitted here rather than repeated. They will be re-checked against the final release notes after 26 August.
Pre-upgrade checklist
- Audit SELinux volume sharing. Look for Pods sharing one volume at the same path with different SELinux contexts and no
subPath. Do this on 1.36, before upgrading. Skip entirely if SELinux is not enabled on your nodes - Set kube-proxy
modeexplicitly so the eventual nftables default flip changes nothing for you - Grep kubelet config for the deprecated cAdvisor flags. Any one of them prevents startup
- Search dashboards and alerts for
container_cpu_load_average_10s,container_cpu_load_d_average_10s,container_tasks_stateandcontainer_application_* - Check for
eventRecordQPS: 0and change it to50if you wanted the old default - Review who can read
nodes/logs. Kubelet configuration is now logged at startup - Confirm etcd is at 3.7.0+ if you run it externally
- Replace removed gate names.
GangSchedulingandWorkloadAwarePreemptionare gone; verify the current set against the released binary - Confirm containerd ≥ 2.0 and cgroup v2 if you have not already. These were 1.35/1.36 deadlines, not 1.37 ones, but they still block upgrades
FAQ
When is Kubernetes 1.37 released? 26 August 2026. Code and test freeze passed on 23 July 2026, with release candidates on 5 and 19 August.
Is nftables the default kube-proxy backend in 1.37? No. 1.37 adds a warning when the proxy mode is not set explicitly. The changelog states the default switches from iptables to nftables "in a future release." The nftables mode itself has been GA since 1.33.
What breaks when SELinuxMount is enabled by default? Workloads that rely on recursive SELinux relabelling, most notably a single volume shared between privileged and unprivileged Pods on the same node with different labels. Clusters without SELinux enabled are unaffected. The per-Pod opt-out is spec.securityContext.seLinuxChangePolicy.
Do I need containerd 2.0 for Kubernetes 1.37? The containerd 1.x cutoff came with 1.36. v1.35 was the last release to support containerd 1.x. There is no new containerd requirement in 1.37; one related kubelet removal was deferred from 1.37 to 1.38. Monitor kubelet_cri_losing_support to find affected nodes.
Does cgroup v1 still work in 1.37? cgroup v1 was deprecated in v1.35, and since then the kubelet does not start on a cgroup v1 node by default. failCgroupV1: false remains the documented opt-out. Nothing about this changed in 1.37.
Which feature gates were removed in 1.37? GangScheduling and WorkloadAwarePreemption, replaced by GenericWorkload, and PreventStaticPodAPIReferences, which can no longer be disabled.
Sources
CHANGELOG-1.37.md, kubernetes/kubernetes (verified atv1.37.0-beta.0)- Kubernetes v1.37 release schedule, kubernetes.dev
- Kubernetes releases and support windows
- SELinux Volume Label Changes goes GA (and likely implications in v1.37)
- Announcing etcd v3.7.0
- Kubernetes v1.35 Sneak Peek
- cgroup v2 documentation
- Kubernetes 1.37 Release Highlights Discussion (proposal stage, cited as targets only)
Comments 0