Kubernetes 1.30 shipped in April 2024 and passed fairly quietly, especially compared with 1.31 in August, which grabbed most of the headlines with AppArmor in GA and sidecar reordering. That is a shame, because for anyone running clusters in production this release is exactly the kind that makes a real difference: few epic changes, many tight stitches. This article covers what is actually worth knowing and, above all, what changes in a cluster operator’s daily work.

Key takeaways

  • ValidatingAdmissionPolicy reaches GA: declarative CEL-based admission policies with no external webhooks.

  • Pod scheduling readiness lets pods declare when they are ready to be scheduled.

  • Job success policy adds granular control over which index combination constitutes success in indexed Jobs.

  • Minimum required Go version rises to 1.22; review custom base images before upgrading.

  • Upgrading from 1.29 should still go release by release, without skipping versions.

ValidatingAdmissionPolicy reaches GA: the most important change

ValidatingAdmissionPolicy reaching GA is, by far, the most practically impactful improvement in this release. For years, any moderately serious admission rule meant deploying an external webhook: rejecting a Deployment with more than X replicas, enforcing required labels, blocking images without a fixed tag. That webhook is an HTTPS service with its certificate, its high availability, its latency added to every API call, and its own failure point. If the webhook went down or slowed down, the control plane degraded.

With 1.30, the declarative model based on CEL (Common Expression Language) stops being experimental and becomes a serious option. You define the policy as a cluster resource, the API server evaluates it in-process, and you skip the entire webhook scaffolding. For simple policies (the vast majority in practice) you replace hundreds of lines of Go, a Deployment, a Service, and a cert-manager Certificate with a twenty-line YAML.

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "force-tag-not-latest"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE","UPDATE"]
      resources:   ["deployments"]
  validations:
  - expression: >
      object.spec.template.spec.containers.all(c,
        !c.image.endsWith(':latest'))
    message: "The :latest tag is not allowed in production"

Latency goes down, failure surface shrinks, and platform teams can review policies as normal PRs without auditing Go code. The only real limitation is CEL expressiveness: for complex logic with side effects (querying an external API, writing to an audit log), webhooks remain necessary.

Pod scheduling readiness: lifecycle control before scheduling

This feature, reaching GA in 1.30, solves a frequent problem in architectures with initialisation dependencies. Before 1.30, a pod created in Kubernetes entered the scheduling cycle directly: the scheduler saw it, evaluated its viability, and if it found a suitable node, assigned it. There was no way to signal to the scheduler that a pod existed but was not yet ready for scheduling.

The practical result was that pods with external dependencies (a secret not yet in the cluster, an infrastructure resource still provisioning) were assigned to nodes, failed at startup, and entered unnecessary CrashLoopBackOff loops.

With pod scheduling readiness, pods can declare scheduling gates: explicit conditions that must be satisfied before the scheduler considers them. Once a gate is removed by an external controller, the pod enters the normal cycle.

spec:
  schedulingGates:
  - name: "example.com/external-resource-ready"

The most common use case is in infrastructure operators that create pods before the associated cloud resource is available. For cluster managers who also use eBPF-based observability, this greatly simplifies the lifecycle of profiling pods.

Job success policy: what counts as success in indexed Jobs

Indexed Jobs (with completionMode: Indexed) let each index play a different role within the same Job. The problem before 1.30 is that Job success required all indices to complete successfully, with no nuance at all.

Job success policy adds a successPolicy field in the Job spec that lets you specify which combination of successful indices constitutes Job success, even if other indices fail or do not complete. This is especially useful in distributed ML workloads, Monte Carlo simulations, or any pattern where enough good indices will do:

spec:
  completions: 10
  completionMode: Indexed
  successPolicy:
    rules:
    - succeededIndexes: "0-2"
      succeededCount: 3

The release also includes improvements to the completed pods garbage collector and adjustments to retry Job handling, reducing race conditions observed in 1.29.

Other relevant changes

Beyond the three main changes, some details deserve attention:

  • Contextual logging stabilised: structured logging with propagated context reaches stable, useful for correlating control plane logs with application traces.

  • VolumeAttributesClass: new API (alpha) to modify volume attributes without recreating them; relevant for high-performance cloud PVs.

  • v1beta2 removal in FlowSchemas and PriorityLevelConfigurations: if you have these resources in old beta version, migrate before upgrading.

  • Go 1.22 required: for anyone compiling custom control-plane images, verify the toolchain first.

Official Kubernetes logo showing the seven-spoke helm, symbol of the orchestrator whose 1.30 version consolidates declarative operations tools

Upgrading from 1.29

The upgrade to 1.30 introduces no major surprises if you follow the usual sequence. Upgrade the control plane first (apiserver, controller-manager, scheduler), then worker nodes with a rolling update, then add-on components like CoreDNS and kube-proxy.

Points to verify before upgrading:

  • Check that no existing admission webhook covers rules you plan to migrate to ValidatingAdmissionPolicy; duplicating rules produces unexpected behaviour.

  • Review whether you have FlowSchemas or PriorityLevelConfigurations at v1beta2; the API is still present in 1.30 but the deprecation is advancing.

  • If you use Trivy Operator for continuous cluster auditing, updating the Helm chart before upgrading the cluster ensures API compatibility.

For the upgrade itself, the official Kubernetes documentation covers the specific steps for each component. The general recommendation of not skipping versions remains valid in 1.30.

Conclusion

Kubernetes 1.30 is a consolidation release, not a headline one. ValidatingAdmissionPolicy in GA eliminates an entire category of accidental infrastructure for admission policies. Pod scheduling readiness and job success policy add nuances that operators of complex workloads have been asking for. The cluster operator who upgrades to 1.30 comes out with fewer webhooks, fewer unnecessary CrashLoops, and more control over what constitutes success in their distributed Jobs.

Frequently asked questions

Can I remove my admission webhooks when moving to Kubernetes 1.30?

The simple ones, yes: with ValidatingAdmissionPolicy in GA, a rule such as blocking :latest images or enforcing required labels is defined in CEL as a cluster resource and evaluated in-process by the API server. That replaces hundreds of lines of Go, a Deployment, a Service and a cert-manager Certificate with a twenty-line YAML. Webhooks remain necessary for logic with side effects, such as querying an external API or writing to an audit log. Do not duplicate the same rule in a webhook and a policy: it produces unexpected behaviour.

How do I stop a pod from entering CrashLoopBackOff because its external dependency does not exist yet?

With pod scheduling readiness, GA since 1.30: the pod declares one or more named gates in spec.schedulingGates, and the scheduler does not consider it until an external controller removes them. That way a pod waiting for a secret not yet in the cluster or a cloud resource still provisioning is neither assigned to a node nor fails at startup. The most common use case is infrastructure operators that create pods before the associated resource is available.

What should I check before upgrading a cluster from 1.29 to 1.30?

Four things: that no existing admission webhook covers rules you plan to migrate to ValidatingAdmissionPolicy. Whether you have FlowSchemas or PriorityLevelConfigurations at v1beta2, since the deprecation is advancing. That your toolchain uses Go 1.22 if you compile custom control-plane images; and, if you use Trivy Operator, update its Helm chart before the upgrade. Then follow the usual sequence (control plane, worker nodes with a rolling update, add-ons like CoreDNS and kube-proxy) without skipping versions.