DevOps · Kubernetes

Kubernetes 1.31 New Features — A Complete Guide

A practical look at what Kubernetes 1.31 (released August 2024) actually ships: AppArmor support graduating to GA with a proper pod spec field, PVC last-phase-transition tracking, and the steady drumbeat of API deprecations you need to plan around before upgrading.

John Kihiu12 min read

Kubernetes 1.31 shipped in August 2024, and like most minor releases in the 1.2x/1.3x era, it's less a single headline feature than a batch of graduations, deprecations, and small kubelet/scheduler improvements that only matter once you actually try to upgrade a cluster running on an older API surface. The one change worth planning around deliberately is AppArmor support reaching general availability as a structured field in the pod spec, which quietly changes how you should be writing security policy for new workloads.

AppArmor graduates to a real API field

Before 1.31, applying an AppArmor profile to a pod meant setting an annotation — container.apparmor.security.beta.kubernetes.io/<container-name> — which worked but never felt like a first-class part of the API. It wasn't validated the way typed fields are, it was easy to typo without any complaint from the API server, and it lived outside the normal securityContext you already use for run-as-user, capabilities, and seccomp. 1.31 moves AppArmor into securityContext.appArmorProfile, structured the same way seccomp profiles already are, with a type of RuntimeDefault, Localhost, or Unconfined and a localhostProfile name when you're pointing at a custom profile loaded on the node.

YAML · POD SECURITYCONTEXT
apiVersion: v1
kind: Pod
metadata:
  name: payments-worker
spec:
  containers:
    - name: worker
      image: registry.internal/payments-worker:1.4.2
      securityContext:
        appArmorProfile:
          type: Localhost
          localhostProfile: profiles/payments-worker
        seccompProfile:
          type: RuntimeDefault
        allowPrivilegeEscalation: false

The annotation form still works during the transition, but new manifests should use the field. It's validated at admission, shows up in kubectl get pod -o yaml next to the rest of your security posture instead of buried in annotations, and it's the form that future kubectl tooling and policy engines (Kyverno, OPA Gatekeeper) will assume you're using.

Check node support before you migrate profiles

AppArmor is a Linux LSM feature, and it's only enforced if the node's kernel has it enabled and the container runtime supports it — this hasn't changed in 1.31, only the API shape has. A profile referenced in securityContext.appArmorProfile that isn't loaded on the node will still fail the pod at scheduling, same as it did with the annotation.

Knowing when a PVC actually changed phase

A smaller but genuinely useful addition is PersistentVolumeLastPhaseTransitionTime, which stamps a PVC's status with the timestamp of its last phase change — Pending to Bound, Bound to Lost, and so on. Before this, if a PVC got stuck in Pending, you had no reliable, API-native way to answer "how long has it actually been stuck" without cross-referencing events or your own monitoring's first-seen timestamp. Storage troubleshooting on clusters with a lot of dynamic provisioning — CI runners, stateful workloads that come and go — benefits from this in a way that's easy to underrate until you've spent an afternoon reconstructing a timeline from event logs that already rotated out.

The deprecation treadmill keeps moving

As with every minor release, part of the real work of 1.31 is deprecation and removal of old API surface: continued removal of in-tree cloud provider code for clouds that have finished migrating to out-of-tree providers, further hardening of structured authentication and authorization configuration (moving cluster auth config out of ad hoc flags and into a versioned config file), and the usual set of alpha features graduating to beta or beta to stable that changes which feature gates you need to set explicitly. None of this is dramatic on its own, but it's the accumulation that bites teams who skip two or three minor versions and then try to jump straight to the latest — by the time you get there, several APIs you depended on have moved or been removed outright.

Read the deprecated API list before every upgrade, not just the big ones

Kubernetes removes beta APIs on a predictable cadence, and it's rarely the release that removes something you use — it's the release two or three versions later, after you stopped checking. Run kubectl convert or pluto detect-helm against your manifests before every version bump, not just the ones that look like they matter.

StatefulSet PVC auto-deletion and the smaller stuff

StatefulSet's PVC auto-deletion policy — letting you configure whether PersistentVolumeClaims created by a StatefulSet get deleted when the StatefulSet itself is deleted, or when a replica is scaled down — continues to mature after being introduced a few releases earlier. It's a small thing that solves a real annoyance: previously, scaling a StatefulSet down and back up left orphaned PVCs around forever unless you cleaned them up by hand, which is exactly the kind of manual step that gets skipped under pressure and turns into slowly accumulating storage cost. Beyond that, 1.31 carries the usual kubelet and scheduler refinements — tightened resource handling, incremental work on in-place pod resource resize, and networking-adjacent fixes — none of which change how you write manifests, but all of which are worth reading the full changelog for if you run anything at meaningful scale.

Wrapping up

The pattern with 1.31, like most recent Kubernetes releases, is that the interesting change is structural rather than a new capability: AppArmor moving into securityContext is worth adopting in new manifests immediately, PVC phase-transition timestamps are a small quality-of-life win for storage debugging, and the deprecation list is worth reading in full even when nothing on it looks urgent — that's exactly the kind of thing that turns a routine upgrade into an incident two versions later.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.