Kubernetes v1.36 ships late April 2026 with approximately 80 tracked enhancements: 18 graduating to stable, 18 to beta, and 26 new alpha features. Three items are permanent removals that will break clusters on upgrade. Two widely-cited competitor posts are wrong about which features are actually new in v1.36. This guide covers what production teams need to audit before upgrading, what actually changes, and what’s worth adopting immediately after.

Kubernetes v1.36 is a minor release targeting late April 2026, with three permanent removals that break existing clusters on upgrade, 18 features graduating to stable, and Ingress-NGINX retired by SIG Security on March 24, 2026.

No changelog rehash. Start with the pre-upgrade checklist.

What Should You Audit Before Upgrading to Kubernetes 1.36?

Before touching any control plane node, run these six checks against your current cluster. Items 1 through 3 are hard blockers - the upgrade will fail or break workloads if not resolved. Items 4 through 6 are advisories with staged removal timelines.

1. Scan for gitRepo volumes (hard blocker)

kubectl get pods -A -o json | python3 -c "
import json,sys
data=json.load(sys.stdin)
for pod in data['items']:
    ns=pod['metadata']['namespace']
    name=pod['metadata']['name']
    for vol in pod.get('spec',{}).get('volumes',[]):
        if 'gitRepo' in vol:
            print(f'{ns}/{name}')
"

gitRepo volumes are permanently removed in v1.36. Pods using them will fail to schedule after the upgrade.

2. Check kube-proxy mode (hard blocker if using IPVS)

kubectl get configmap kube-proxy -n kube-system -o jsonpath='{.data.config\.conf}' | grep mode

IPVS was deprecated in v1.35. If your output shows mode: ipvs, migrate to nftables before upgrading. See the IPVS migration section below.

3. Verify containerd version (hard blocker)

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.nodeInfo.containerRuntimeVersion}{"\n"}{end}'

Kubernetes 1.36 drops support for containerd 1.x. The kubelet fallback for cgroup driver detection via the deprecated --cgroup-driver flag is removed. If any node shows containerd://1.x.x, upgrade to containerd 2.0+ before touching kubelet.

4. Scan for externalIPs services (advisory)

kubectl get svc -A -o json | python3 -c "
import json,sys
data=json.load(sys.stdin)
for svc in data['items']:
    ips=svc.get('spec',{}).get('externalIPs',[])
    if ips:
        ns=svc['metadata']['namespace']
        name=svc['metadata']['name']
        print(f'{ns}/{name}: {ips}')
"

spec.externalIPs is deprecated in v1.36 due to CVE-2020-8554 (MITM risk). Removal is staged: disabled by default around v1.40, removed from kube-proxy around v1.43. No immediate breakage, but plan the migration now.

5. Scan for Portworx in-tree PVs (hard blocker)

kubectl get pv -o json | python3 -c "
import json,sys
data=json.load(sys.stdin)
for pv in data['items']:
    if 'portworxVolume' in pv.get('spec',{}):
        print(pv['metadata']['name'])
"

The Portworx in-tree volume driver is removed in v1.36. Migrate to the Portworx CSI driver before upgrading.

6. Validate IP/CIDR format usage (advisory)

v1.36 hard-rejects non-canonical IP formats like 010.000.001.005 and ambiguous CIDRs like 192.168.1.5/24. If your CI/CD pipelines, admission webhooks, or manifests generate IPs programmatically, audit them now. This can break automation silently.


Here is the decision tree for the pre-upgrade audit:

flowchart TD
    A[Start Pre-Upgrade Audit] --> B{gitRepo volumes found?}
    B -->|Yes| C[Migrate to init container\nor git-sync sidecar]
    B -->|No| D{containerd version?}
    C --> D
    D -->|1.x| E[Upgrade to\ncontainerd 2.0+]
    D -->|2.x| F{kube-proxy mode?}
    E --> F
    F -->|ipvs| G[Migrate to\nnftables mode]
    F -->|iptables or nftables| H{Portworx in-tree PVs?}
    G --> H
    H -->|Yes| I[Migrate to\nPortworx CSI driver]
    H -->|No| J[Cluster ready\nfor v1.36 upgrade]
    I --> J

Address the three hard blockers before proceeding. The IP/CIDR and externalIPs advisories can follow upgrade at a planned schedule.


What Breaks When You Upgrade to Kubernetes 1.36?

gitRepo Volume Plugin: Permanent Removal

Deprecated since v1.11, the gitRepo volume plugin is permanently disabled in v1.36. No feature gate re-enables it. The security issue is direct: the plugin ran arbitrary git commands as root on cluster nodes, creating an attack vector for privilege escalation.

Migrate to an init container with git clone, or use the git-sync sidecar pattern:

initContainers:
- name: git-clone
  image: alpine/git:latest
  command: ['git', 'clone', '--depth=1', 'https://github.com/org/repo.git', '/repo']
  volumeMounts:
  - name: repo
    mountPath: /repo
volumes:
- name: repo
  emptyDir: {}

The init container runs as an unprivileged user, the repository ends up in an emptyDir volume shared with the main container, and there is no persistent root code execution on the node.

IPVS Kube-Proxy Mode: Deprecated, Removal Imminent

IPVS kube-proxy was deprecated in v1.35. The deprecation warning in kube-proxy logs reads: “The ipvs proxier is now deprecated and may be removed in a future release. Please use ‘nftables’ instead.”

If you’re still running IPVS, migrate to nftables now rather than waiting for forced migration. nftables outperforms both iptables and IPVS on large clusters and requires kernel 5.13+.

Migration is a one-field change in the kube-proxy ConfigMap:

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "nftables"

Apply the ConfigMap change and restart kube-proxy pods. Validate with:

kubectl logs -n kube-system -l k8s-app=kube-proxy | grep "Using nftables"

containerd 2.0 Required

Kubernetes 1.36 removes the kubelet fallback behavior for cgroup driver detection. In containerd 1.x, if the runtime didn’t respond correctly to the RuntimeConfig CRI RPC, the kubelet fell back to the --cgroup-driver flag. That fallback is gone in v1.36. Nodes running containerd 1.x will fail to register after upgrading kubelet.

Two things to know about containerd 2.0 beyond the version requirement:

  1. Manual --cgroup-driver flag configuration is removed. Cgroup driver is now auto-detected via CRI (GA since v1.34). Remove explicit cgroup driver flags from kubelet config.
  2. containerd 2.0 drops Docker Schema 1 image support. Images built more than five years ago using the old Schema 1 format will fail to pull. If you’re running legacy workloads with very old base images, audit image manifests before upgrading.

Check the metric kubelet_cri_losing_support on your nodes to identify containers using deprecated CRI features before upgrading.


Which Kubernetes 1.36 Features Change Production Behavior?

User Namespaces (GA): Native Rootless Containers

User namespaces graduate to stable in v1.36, completing a multi-year development cycle (beta since v1.30). With user namespaces enabled, container UID 0 (root) maps to an unprivileged host UID. A process running as root inside the container has no root privileges on the node.

graph LR
    subgraph Without User Namespaces
        A[Container root\nUID 0] -->|same as| B[Host root\nUID 0]
        B --> C[Full node access\nif container escape]
    end
    subgraph With User Namespaces
        D[Container root\nUID 0] -->|maps to| E[Host UID 65536+]
        E --> F[No node privileges\nif container escape]
    end

User namespaces break the UID equivalence between container and host, reducing container escape blast radius.

To enable on a pod:

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  hostUsers: false
  containers:
  - name: app
    image: my-app:v1.0
    securityContext:
      runAsUser: 0

Setting hostUsers: false activates user namespaces for the pod. Kubernetes also relaxes certain Pod Security Standards checks for pods with hostUsers: false, because root in-container no longer equals root on-host.

Runtime requirements: Linux kernel 6.3+, containerd 2.0+ (already required for v1.36) or CRI-O 1.25+, crun 1.9+ or runc 1.2+. The node filesystem must support idmap mounts: ext4, xfs, btrfs, overlayfs, and tmpfs all qualify. This is Linux-only.

MutatingAdmissionPolicy (GA): Drop Your Webhook Servers

MutatingAdmissionPolicy (KEP-3962) moves from beta (v1beta1 in v1.34) to stable in v1.36. Define resource mutations as native Kubernetes objects using CEL expressions. No webhook servers, no TLS certificate management, no external availability dependency.

sequenceDiagram
    participant API as API Server
    participant WH as Webhook Server
    participant CEL as In-Process CEL

    Note over API,WH: With Webhooks
    API->>WH: HTTP call (TLS, network hop)
    WH-->>API: Mutation response
    Note left of WH: External server, HA required

    Note over API,CEL: With MutatingAdmissionPolicy
    API->>CEL: In-process evaluation
    CEL-->>API: Mutation applied
    Note right of CEL: No network, no server

MutatingAdmissionPolicy eliminates the network hop and external server dependency that webhook-based mutation requires.

Example: inject a sidecar into every new pod that doesn’t already have one.

apiVersion: admissionregistration.k8s.io/v1
kind: MutatingAdmissionPolicy
metadata:
  name: inject-mesh-proxy
spec:
  matchConstraints:
    resourceRules:
    - apiGroups: [""]
      apiVersions: ["v1"]
      resources: ["pods"]
      operations: ["CREATE"]
  matchConditions:
  - name: no-existing-proxy
    expression: '!object.spec.initContainers.exists(c, c.name == "mesh-proxy")'
  failurePolicy: Fail
  mutations:
  - patchType: ApplyConfiguration
    applyConfiguration:
      expression: >
        Object{
          spec: Object.spec{
            initContainers: [
              Object.spec.initContainers{
                name: "mesh-proxy",
                image: "mesh/proxy:v1.0.0",
                args: ["proxy", "sidecar"],
                restartPolicy: "Always"
              }
            ]
          }
        }

Two mutation modes are supported: Server-Side Apply (merge-based, shown above, recommended for new work) and JSON Patch (migration path from existing webhooks).

Note: The brief notes that the API version for the stable release should be verified against the v1.36 changelog at release. The beta API used v1beta1; the stable version will use v1.

OCI VolumeSource (GA): ML Model Delivery Without Fat Images

OCI artifacts - model weights, config files, datasets - can be mounted directly as pod volumes. This decouples model deployment from application container image builds.

graph TD
    subgraph Old Approach
        A[App code 500MB] --> C[Single Image 10GB+]
        B[Model weights 9.5GB] --> C
        C --> D[Slow pull on every pod]
        C --> E[Rebuild image for\nmodel weight updates]
    end
    subgraph New Approach with OCI VolumeSource
        F[App code 500MB] --> G[App Image 500MB]
        H[Model weights 9.5GB] --> I[OCI Artifact\nindependent registry push]
        G --> J[Pod mounts model\nat /models at runtime]
        I --> J
        G --> K[Update app code\nwithout touching models]
        I --> L[Update model weights\nwithout rebuilding app]
    end

OCI VolumeSource separates the update cycle of application code from model weights, eliminating the fat image anti-pattern.

apiVersion: v1
kind: Pod
metadata:
  name: inference-server
spec:
  containers:
  - name: inference
    image: myregistry.io/inference-server:v2.1
    volumeMounts:
    - name: model-weights
      mountPath: /models
      readOnly: true
  volumes:
  - name: model-weights
    image:
      reference: myregistry.io/ml-models/llama-3.3-70b:latest
      pullPolicy: IfNotPresent

The model artifact and the application image have independent versioning and update cycles. A new model checkpoint does not require rebuilding or redeploying the application container.

SELinux Mount Relabeling (GA): Pod Startups From Minutes to Milliseconds

On SELinux-enforcing nodes, the old approach recursively relabeled every file in a volume before pod startup, touching each inode one by one. A volume with hundreds of thousands of files could take minutes. v1.36 graduates the mount -o context=XYZ approach to stable, applying SELinux labels at mount time in a single kernel call.

Enable per-pod with spec.securityContext.seLinuxOptions and the feature gate SELinuxMount: true. For large data volumes on SELinux nodes, this is one of the most impactful performance changes in the v1.36 cycle.

Fine-Grained Kubelet API Authorization (GA): Limit Blast Radius from Compromised Nodes

KEP-2862 graduates to stable, allowing endpoint-level RBAC for kubelet APIs. Instead of granting broad nodes/proxy access to monitoring agents and node management tooling, grant only the specific endpoints needed:

  • nodes/healthz for health checks
  • nodes/pods for pod listing
  • nodes/configz for configuration inspection

A compromised node credential using nodes/proxy could access any kubelet API. With fine-grained authorization, credentials scoped to nodes/healthz cannot read pods or exec into containers. Tighten RBAC for monitoring agents immediately after upgrading.


What Is Actually New in Dynamic Resource Allocation for Kubernetes 1.36?

Most competitor articles attribute Dynamic Resource Allocation going GA to v1.36. This is incorrect. Core DRA APIs (resource.k8s.io/v1) graduated to stable in Kubernetes v1.34 (August 2025).

What v1.36 actually adds:

DRA Admin Access (GA in v1.36): The adminAccess flag on ResourceClaims allows centralized device management by cluster administrators. Useful for GPU pool operators who need to inspect or manage claims across namespaces without granting namespace-level access.

apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
  name: gpu-claim
spec:
  devices:
    requests:
    - name: gpu
      deviceClassName: nvidia-gpu
      count: 2
      selectors:
      - cel:
          expression: "device.attributes['gpu.nvidia.com'].memory.isGreaterThan(quantity('40Gi'))"

Device Taints and Tolerations (Beta in v1.36): Works like node taints. Mark a GPU as maintenance=true:NoSchedule during an NVIDIA driver update, and only pods with the matching toleration will schedule onto that device. Drains device workloads without draining the entire node.

Scheduler Performance (v1.36): The DRA scheduler filter stage is approximately 50% faster in v1.36, achieved by splitting ResourceSlice into shared (cluster-wide) and per-node categories. The filter stage can skip per-node slices when evaluating cluster-scoped devices.

If you’re already running DRA-based GPU workloads on v1.34+, these changes are additive. If you haven’t adopted DRA yet, v1.34 was when it became production-viable - v1.36 is not the starting point.


How Does HPA Scale-to-Zero Work in Kubernetes 1.36?

The HPAScaleToZero feature gate has been alpha since v1.16. It is graduating in v1.36 (expected to move to beta/enabled by default - verify final status against the official changelog at release, as the KEP GitHub tracking shows the enhancement in active development for this cycle).

Set minReplicas: 0 on any HPA resource:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: batch-processor
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: batch-processor
  minReplicas: 0
  maxReplicas: 20
  metrics:
  - type: External
    external:
      metric:
        name: queue_messages_ready
        selector:
          matchLabels:
            queue: "batch-jobs"
      target:
        type: AverageValue
        averageValue: "10"

Critical limitation that most articles miss: Scale-to-zero only works with object or external metrics. Queue depth, custom Prometheus metrics, HTTP request count. Standard CPU and memory resource metrics do not support scaling to zero. If you set minReplicas: 0 with only CPU metrics configured, the HPA will not scale to zero.

The default stabilization window is 300 seconds (5 minutes) before scaling to zero. Cold starts after a scale-to-zero event are a real trade-off - batch processing and event-driven workloads are the primary use cases. Avoid scale-to-zero for latency-sensitive services where a cold start would violate SLOs.


How Do You Migrate from Ingress-NGINX After the Retirement?

SIG Security retired the Ingress-NGINX project on March 24, 2026. Existing deployments continue to function - artifacts and Helm charts remain available - but there will be no security patches, bugfixes, or new releases. Given multiple critical CVEs in recent years (including CVE-2025-1974, a critical remote code execution vulnerability), running unpatched Ingress-NGINX is a compounding security risk.

The fastest migration path is Gateway API using ingress2gateway 1.0, released March 20, 2026.

# Install via Homebrew
brew install ingress2gateway

# Or via Go
go install github.com/kubernetes-sigs/[email protected]

# Convert a specific namespace
ingress2gateway print --namespace my-api --providers=ingress-nginx > gwapi.yaml

# Convert all namespaces
ingress2gateway print --providers=ingress-nginx --all-namespaces > gwapi.yaml

# With vendor-specific emitter (e.g., Envoy Gateway)
ingress2gateway print --namespace my-api --providers=ingress-nginx --emitter envoy-gateway > gwapi.yaml

The 1.0 release expanded from 3 to more than 30 supported Ingress-NGINX annotations, including CORS, backend TLS, regex matching, path rewrite, proxy body size, proxy timeouts, and custom headers via configuration snippets. The tool generates Gateway API resources and runs integration tests against live controllers to verify behavioral equivalence - not just YAML structure.

Treat the generated output as a starting point for review, not a one-shot production deploy. Validate routing, rewrites, and TLS termination in a staging environment before cutting over.

Alternative controllers: If Gateway API is not yet suitable for your environment, Envoy Gateway, Traefik, HAProxy Ingress, and Kong Ingress Controller all remain actively maintained Ingress controller options.


Which Features Are Worth Adopting After Upgrading to Kubernetes 1.36?

kubectl kuberc (Beta, Enabled by Default)

kubectl kuberc separates user preferences from cluster config. Store command defaults (kubectl --namespace default, kubectl --output yaml) in ~/.kube/kuberc rather than in kubeconfig context entries. No more KUBECTL_KUBERC=true env var required in v1.36.

# ~/.kube/kuberc
preferences:
  defaults:
  - command: get
    options:
      output: wide
  - command: create
    options:
      namespace: my-namespace

Changes apply per-user without touching cluster config, making preference sharing between kubeconfig users cleaner.

Service Account Token External Signing (GA)

Service account token signing can now be delegated to external key management systems - cloud KMS or hardware security modules. For environments with key rotation requirements or hardware security mandates, this removes the need to store signing keys directly on the API server.


Frequently Asked Questions

Can I skip directly from Kubernetes 1.34 to 1.36?

No. Kubernetes only supports upgrading one minor version at a time: 1.34 to 1.35, then 1.35 to 1.36. Skipping versions is unsupported and risks encountering multiple breaking changes simultaneously without a safe rollback path. The official support window covers three most recent minor versions (N, N-1, N-2). Check kubernetes.io/releases for current support status.

Does HPA scale-to-zero work with CPU and memory metrics?

No. Scale-to-zero (minReplicas: 0) only works with object or external metrics: queue depth, custom Prometheus metrics, HTTP request count. Standard CPU and memory resource metrics do not support scaling to zero. You must configure at least one object or external metric alongside any CPU/memory metrics you use for normal autoscaling. This limitation is by design and is not changing in v1.36.

What should I use instead of gitRepo volumes?

Use an init container with git clone or a sidecar like git-sync (maintained by the Kubernetes project at registry.k8s.io/git-sync/git-sync) writing into an emptyDir volume shared with your main container. This avoids running arbitrary git operations as root on the node. The init container approach shown in the Breaking Changes section above is production-ready and requires no additional tooling beyond standard kubectl and your existing container registry.

Do I need to upgrade containerd before upgrading to Kubernetes 1.36?

Yes. containerd must be at version 2.0 or later before or at the same time as upgrading kubelet to v1.36. The fallback cgroup driver detection is removed in v1.36 - containerd 1.x nodes will fail to register. Also note: containerd 2.0 drops Docker Schema 1 image support. Images older than approximately five years pushed in Schema 1 format will fail to pull. Audit legacy workloads with nerdctl image inspect before upgrading.

Is Ingress-NGINX still usable after its retirement?

Existing deployments continue to function, and existing Helm charts and container images remain available. However, SIG Security retired the project effective March 24, 2026 - meaning no security patches, no bugfixes, no new releases. Given the track record of critical vulnerabilities (CVE-2025-1974 was rated critical and allowed remote code execution), running an unpatched version is a risk that compounds with each passing month. Use the ingress2gateway migration timeline to plan a structured cutover rather than waiting for an incident to force it.