Kubernetes Blog The Kubernetes blog is used by the project to communicate new features, community reports, and any news that might be relevant to the Kubernetes community.
-
Kubernetes v1.35 Sneak Peek
on November 26, 2025 at 12:00 am
As the release of Kubernetes v1.35 approaches, the Kubernetes project continues to evolve. Features may be deprecated, removed, or replaced to improve the project’s overall health. This blog post outlines planned changes for the v1.35 release that the release team believes you should be aware of to ensure the continued smooth operation of your Kubernetes cluster(s), and to keep you up to date with the latest developments. The information below is based on the current status of the v1.35 release and is subject to change before the final release date. Deprecations and removals for Kubernetes v1.35 cgroup v1 support On Linux nodes, container runtimes typically rely on cgroups (short for “control groups”). Support for using cgroup v2 has been stable in Kubernetes since v1.25, providing an alternative to the original v1 cgroup support. While cgroup v1 provided the initial resource control mechanism, it suffered from well-known inconsistencies and limitations. Adding support for cgroup v2 allowed use of a unified control group hierarchy, improved resource isolation, and served as the foundation for modern features, making legacy cgroup v1 support ready for removal. The removal of cgroup v1 support will only impact cluster administrators running nodes on older Linux distributions that do not support cgroup v2; on those nodes, the kubelet will fail to start. Administrators must migrate their nodes to systems with cgroup v2 enabled. More details on compatibility requirements will be available in a blog post soon after the v1.35 release. To learn more, read about cgroup v2; you can also track the switchover work via KEP-5573: Remove cgroup v1 support. Deprecation of ipvs mode in kube-proxy Many releases ago, the Kubernetes project implemented an ipvs mode in kube-proxy. It was adopted as a way to provide high-performance service load balancing, with better performance than the existing iptables mode. However, maintaining feature parity between ipvs and other kube-proxy modes became difficult, due to technical complexity and diverging requirements. This created significant technical debt and made the ipvs backend impractical to support alongside newer networking capabilities. The Kubernetes project intends to deprecate kube-proxy ipvs mode in the v1.35 release, to streamline the kube-proxy codebase. For Linux nodes, the recommended kube-proxy mode is already nftables. You can find more in KEP-5495: Deprecate ipvs mode in kube-proxy Kubernetes is deprecating containerd v1.y support While Kubernetes v1.35 still supports containerd 1.7 and other LTS releases of containerd, as a consequence of automated cgroup driver detection, the Kubernetes SIG Node community has formally agreed upon a final support timeline for containerd v1.X. 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. You are able to monitor the kubelet_cri_losing_support metric to determine if any nodes in your cluster are using a containerd version that will soon be unsupported. You can find more in the official blog post or in KEP-4033: Discover cgroup driver from CRI Featured enhancements of Kubernetes v1.35 The following enhancements are some of those likely to be included in the v1.35 release. This is not a commitment, and the release content is subject to change. Node declared features When scheduling Pods, Kubernetes uses node labels, taints, and tolerations to match workload requirements with node capabilities. However, managing feature compatibility becomes challenging during cluster upgrades due to version skew between the control plane and nodes. This can lead to Pods being scheduled on nodes that lack required features, resulting in runtime failures. The node declared features framework will introduce a standard mechanism for nodes to declare their supported Kubernetes features. With the new alpha feature enabled, a Node reports the features it can support, publishing this information to the control plane through a new .status.declaredFeatures field. Then, the kube-scheduler, admission controllers and third-party components can use these declarations. For example, you can enforce scheduling and API validation constraints, ensuring that Pods run only on compatible nodes. This approach reduces manual node labeling, improves scheduling accuracy, and prevents incompatible pod placements proactively. It also integrates with the Cluster Autoscaler for informed scale-up decisions. Feature declarations are temporary and tied to Kubernetes feature gates, enabling safe rollout and cleanup. Targeting alpha in v1.35, node declared features aims to solve version skew scheduling issues by making node capabilities explicit, enhancing reliability and cluster stability in heterogeneous version environments. To learn more about this before the official documentation is published, you can read KEP-5328. In-place update of Pod resources Kubernetes is graduating in-place updates for Pod resources to General Availability (GA). This feature allows users to adjust cpu and memory resources without restarting Pods or Containers. Previously, such modifications required recreating Pods, which could disrupt workloads, particularly for stateful or batch applications. Previous Kubernetes releases already allowed you to change infrastructure resources settings (requests and limits) for existing Pods. This allows for smoother vertical scaling, improves efficiency, and can also simplify solution development. The Container Runtime Interface (CRI) has also been improved, extending the UpdateContainerResources API for Windows and future runtimes while allowing ContainerStatus to report real-time resource configurations. Together, these changes make scaling in Kubernetes faster, more flexible, and disruption-free. The feature was introduced as alpha in v1.27, graduated to beta in v1.33, and is targeting graduation to stable in v1.35. You can find more in KEP-1287: In-place Update of Pod Resources Pod certificates When running microservices, Pods often require a strong cryptographic identity to authenticate with each other using mutual TLS (mTLS). While Kubernetes provides Service Account tokens, these are designed for authenticating to the API server, not for general-purpose workload identity. Before this enhancement, operators had to rely on complex, external projects like SPIFFE/SPIRE or cert-manager to provision and rotate certificates for their workloads. But what if you could issue a unique, short-lived certificate to your Pods natively and automatically? KEP-4317 is designed to enable such native workload identity. It opens up various possibilities for securing pod-to-pod communication by allowing the kubelet to request and mount certificates for a Pod via a projected volume. This provides a built-in mechanism for workload identity, complete with automated certificate rotation, significantly simplifying the setup of service meshes and other zero-trust network policies. This feature was introduced as alpha in v1.34 and is targeting beta in v1.35. You can find more in KEP-4317: Pod Certificates Numeric values for taints Kubernetes is enhancing taints and tolerations by adding numeric comparison operators, such as Gt (Greater Than) and Lt (Less Than). Previously, tolerations supported only exact (Equal) or existence (Exists) matches, which were not suitable for numeric properties such as reliability SLAs. With this change, a Pod can use a toleration to “opt-in” to nodes that meet a specific numeric threshold. For example, a Pod can require a Node with an SLA taint value greater than 950 (operator: Gt, value: “950”). This approach is more powerful than Node Affinity because it supports the NoExecute effect, allowing Pods to be automatically evicted if a node’s numeric value drops below the tolerated threshold. You can find more in KEP-5471: Enable SLA-based Scheduling User namespaces When running Pods, you can use securityContext to drop privileges, but containers inside the pod often still run as root (UID 0). This simplicity poses a significant challenge, as that container UID 0 maps directly to the host’s root user. Before this enhancement, a container breakout vulnerability could grant an attacker full root access to the node. But what if you could dynamically remap the container’s root user to a safe, unprivileged user on the host? KEP-127 specifically allows such native support for Linux User Namespaces. It opens up various possibilities for pod security by isolating container and host user/group IDs. This allows a process to have root privileges (UID 0) within its namespace, while running as a non-privileged, high-numbered UID on the host. Released as alpha in v1.25 and beta in v1.30, this feature continues to progress through beta maturity, paving the way for truly “rootless” containers that drastically reduce the attack surface for a whole class of security vulnerabilities. You can find more in KEP-127: User Namespaces Support for mounting OCI images as volumes When provisioning a Pod, you often need to bundle data, binaries, or configuration files for your containers. Before this enhancement, people often included that kind of data directly into the main container image, or required a custom init container to download and unpack files into an emptyDir. You can still take either of those approaches, of course. But what if you could populate a volume directly from a data-only artifact in an OCI registry, just like pulling a container image? Kubernetes v1.31 added support for the image volume type, allowing Pods to pull and unpack OCI container image artifacts into a volume declaratively. This allows for seamless distribution of data, binaries, or ML models using standard registry tooling, completely decoupling data from the container image and eliminating the need for complex init containers or startup scripts. This volume type has been in beta since v1.33 and will likely be enabled by default in v1.35. You can try out the beta version of image volumes, or you can learn more about the plans from KEP-4639: OCI Volume Source. Want to know more? New features and deprecations are also announced in the Kubernetes release notes. We will formally announce what’s new in Kubernetes v1.35 as part of the CHANGELOG for that release. The Kubernetes v1.35 release is planned for December 17, 2025. Stay tuned for updates! You can also see the announcements of changes in the release notes for: Kubernetes v1.34 Kubernetes v1.33 Kubernetes v1.32 Kubernetes v1.31 Kubernetes v1.30 Get involved The simplest way to get involved with Kubernetes is by joining one of the many Special Interest Groups (SIGs) that align with your interests. Have something you’d like to broadcast to the Kubernetes community? Share your voice at our weekly community meeting, and through the channels below. Thank you for your continued feedback and support. Follow us on Bluesky @kubernetes.io for the latest updates Join the community discussion on Discuss Join the community on Slack Post questions (or answer questions) on Server Fault or Stack Overflow Share your Kubernetes story Read more about what’s happening with Kubernetes on the blog Learn more about the Kubernetes Release Team
-
Kubernetes Configuration Good Practices
on November 25, 2025 at 12:00 am
Configuration is one of those things in Kubernetes that seems small until it’s not. Configuration is at the heart of every Kubernetes workload. A missing quote, a wrong API version or a misplaced YAML indent can ruin your entire deploy. This blog brings together tried-and-tested configuration best practices. The small habits that make your Kubernetes setup clean, consistent and easier to manage. Whether you are just starting out or already deploying apps daily, these are the little things that keep your cluster stable and your future self sane. This blog is inspired by the original Configuration Best Practices page, which has evolved through contributions from many members of the Kubernetes community. General configuration practices Use the latest stable API version Kubernetes evolves fast. Older APIs eventually get deprecated and stop working. So, whenever you are defining resources, make sure you are using the latest stable API version. You can always check with kubectl api-resources This simple step saves you from future compatibility issues. Store configuration in version control Never apply manifest files directly from your desktop. Always keep them in a version control system like Git, it’s your safety net. If something breaks, you can instantly roll back to a previous commit, compare changes or recreate your cluster setup without panic. Write configs in YAML not JSON Write your configuration files using YAML rather than JSON. Both work technically, but YAML is just easier for humans. It’s cleaner to read and less noisy and widely used in the community. YAML has some sneaky gotchas with boolean values: Use only true or false. Don’t write yes, no, on or off. They might work in one version of YAML but break in another. To be safe, quote anything that looks like a Boolean (for example “yes”). Keep configuration simple and minimal Avoid setting default values that are already handled by Kubernetes. Minimal manifests are easier to debug, cleaner to review and less likely to break things later. Group related objects together If your Deployment, Service and ConfigMap all belong to one app, put them in a single manifest file. It’s easier to track changes and apply them as a unit. See the Guestbook all-in-one.yaml file for an example of this syntax. You can even apply entire directories with: kubectl apply -f configs/ One command and boom everything in that folder gets deployed. Add helpful annotations Manifest files are not just for machines, they are for humans too. Use annotations to describe why something exists or what it does. A quick one-liner can save hours when debugging later and also allows better collaboration. The most helpful annotation to set is kubernetes.io/description. It’s like using comment, except that it gets copied into the API so that everyone else can see it even after you deploy. Managing Workloads: Pods, Deployments, and Jobs A common early mistake in Kubernetes is creating Pods directly. Pods work, but they don’t reschedule themselves if something goes wrong. Naked Pods (Pods not managed by a controller, such as Deployment or a StatefulSet) are fine for testing, but in real setups, they are risky. Why? Because if the node hosting that Pod dies, the Pod dies with it and Kubernetes won’t bring it back automatically. Use Deployments for apps that should always be running A Deployment, which both creates a ReplicaSet to ensure that the desired number of Pods is always available, and specifies a strategy to replace Pods (such as RollingUpdate), is almost always preferable to creating Pods directly. You can roll out a new version, and if something breaks, roll back instantly. Use Jobs for tasks that should finish A Job is perfect when you need something to run once and then stop like database migration or batch processing task. It will retry if the pods fails and report success when it’s done. Service Configuration and Networking Services are how your workloads talk to each other inside (and sometimes outside) your cluster. Without them, your pods exist but can’t reach anyone. Let’s make sure that doesn’t happen. Create Services before workloads that use them When Kubernetes starts a Pod, it automatically injects environment variables for existing Services. So, if a Pod depends on a Service, create a Service before its corresponding backend workloads (Deployments or StatefulSets), and before any workloads that need to access it. For example, if a Service named foo exists, all containers will get the following variables in their initial environment: FOO_SERVICE_HOST=<the host the Service runs on> FOO_SERVICE_PORT=<the port the Service runs on> DNS based discovery doesn’t have this problem, but it’s a good habit to follow anyway. Use DNS for Service discovery If your cluster has the DNS add-on (most do), every Service automatically gets a DNS entry. That means you can access it by name instead of IP: curl http://my-service.default.svc.cluster.local It’s one of those features that makes Kubernetes networking feel magical. Avoid hostPort and hostNetwork unless absolutely necessary You’ll sometimes see these options in manifests: hostPort: 8080 hostNetwork: true But here’s the thing: They tie your Pods to specific nodes, making them harder to schedule and scale. Because each <hostIP, hostPort, protocol> combination must be unique. If you don’t specify the hostIP and protocol explicitly, Kubernetes will use 0.0.0.0 as the default hostIP and TCP as the default protocol. Unless you’re debugging or building something like a network plugin, avoid them. If you just need local access for testing, try kubectl port-forward: kubectl port-forward deployment/web 8080:80 See Use Port Forwarding to access applications in a cluster to learn more. Or if you really need external access, use a type: NodePort Service. That’s the safer, Kubernetes-native way. Use headless Services for internal discovery Sometimes, you don’t want Kubernetes to load balance traffic. You want to talk directly to each Pod. That’s where headless Services come in. You create one by setting clusterIP: None. Instead of a single IP, DNS gives you a list of all Pods IPs, perfect for apps that manage connections themselves. Working with labels effectively Labels are key/value pairs that are attached to objects such as Pods. Labels help you organize, query and group your resources. They don’t do anything by themselves, but they make everything else from Services to Deployments work together smoothly. Use semantics labels Good labels help you understand what’s what, even after months later. Define and use labels that identify semantic attributes of your application or Deployment. For example; labels: app.kubernetes.io/name: myapp app.kubernetes.io/component: web tier: frontend phase: test app.kubernetes.io/name : what the app is tier : which layer it belongs to (frontend/backend) phase : which stage it’s in (test/prod) You can then use these labels to make powerful selectors. For example: kubectl get pods -l tier=frontend This will list all frontend Pods across your cluster, no matter which Deployment they came from. Basically you are not manually listing Pod names; you are just describing what you want. See the guestbook app for examples of this approach. Use common Kubernetes labels Kubernetes actually recommends a set of common labels. It’s a standardized way to name things across your different workloads or projects. Following this convention makes your manifests cleaner, and it means that tools such as Headlamp, dashboard, or third-party monitoring systems can all automatically understand what’s running. Manipulate labels for debugging Since controllers (like ReplicaSets or Deployments) use labels to manage Pods, you can remove a label to “detach” a Pod temporarily. Example: kubectl label pod mypod app- The app- part removes the label key app. Once that happens, the controller won’t manage that Pod anymore. It’s like isolating it for inspection, a “quarantine mode” for debugging. To interactively remove or add labels, use kubectl label. You can then check logs, exec into it and once done, delete it manually. That’s a super underrated trick every Kubernetes engineer should know. Handy kubectl tips These small tips make life much easier when you are working with multiple manifest files or clusters. Apply entire directories Instead of applying one file at a time, apply the whole folder: # Using server-side apply is also a good practice kubectl apply -f configs/ –server-side This command looks for .yaml, .yml and .json files in that folder and applies them all together. It’s faster, cleaner and helps keep things grouped by app. Use label selectors to get or delete resources You don’t always need to type out resource names one by one. Instead, use selectors to act on entire groups at once: kubectl get pods -l app=myapp kubectl delete pod -l phase=test It’s especially useful in CI/CD pipelines, where you want to clean up test resources dynamically. Quickly create Deployments and Services For quick experiments, you don’t always need to write a manifest. You can spin up a Deployment right from the CLI: kubectl create deployment webapp –image=nginx Then expose it as a Service: kubectl expose deployment webapp –port=80 This is great when you just want to test something before writing full manifests. Also, see Use a Service to Access an Application in a cluster for an example. Conclusion Cleaner configuration leads to calmer cluster administrators. If you stick to a few simple habits: keep configuration simple and minimal, version-control everything, use consistent labels, and avoid relying on naked Pods, you’ll save yourself hours of debugging down the road. The best part? Clean configurations stay readable. Even after months, you or anyone on your team can glance at them and know exactly what’s happening.
-
Ingress NGINX Retirement: What You Need to Know
on November 11, 2025 at 6:30 pm
To prioritize the safety and security of the ecosystem, Kubernetes SIG Network and the Security Response Committee are announcing the upcoming retirement of Ingress NGINX. Best-effort maintenance will continue until March 2026. Afterward, there will be no further releases, no bugfixes, and no updates to resolve any security vulnerabilities that may be discovered. Existing deployments of Ingress NGINX will continue to function and installation artifacts will remain available. We recommend migrating to one of the many alternatives. Consider migrating to Gateway API, the modern replacement for Ingress. If you must continue using Ingress, many alternative Ingress controllers are listed in the Kubernetes documentation. Continue reading for further information about the history and current state of Ingress NGINX, as well as next steps. About Ingress NGINX Ingress is the original user-friendly way to direct network traffic to workloads running on Kubernetes. (Gateway API is a newer way to achieve many of the same goals.) In order for an Ingress to work in your cluster, there must be an Ingress controller running. There are many Ingress controller choices available, which serve the needs of different users and use cases. Some are cloud-provider specific, while others have more general applicability. Ingress NGINX was an Ingress controller, developed early in the history of the Kubernetes project as an example implementation of the API. It became very popular due to its tremendous flexibility, breadth of features, and independence from any particular cloud or infrastructure provider. Since those days, many other Ingress controllers have been created within the Kubernetes project by community groups, and by cloud native vendors. Ingress NGINX has continued to be one of the most popular, deployed as part of many hosted Kubernetes platforms and within innumerable independent users’ clusters. History and Challenges The breadth and flexibility of Ingress NGINX has caused maintenance challenges. Changing expectations about cloud native software have also added complications. What were once considered helpful options have sometimes come to be considered serious security flaws, such as the ability to add arbitrary NGINX configuration directives via the “snippets” annotations. Yesterday’s flexibility has become today’s insurmountable technical debt. Despite the project’s popularity among users, Ingress NGINX has always struggled with insufficient or barely-sufficient maintainership. For years, the project has had only one or two people doing development work, on their own time, after work hours and on weekends. Last year, the Ingress NGINX maintainers announced their plans to wind down Ingress NGINX and develop a replacement controller together with the Gateway API community. Unfortunately, even that announcement failed to generate additional interest in helping maintain Ingress NGINX or develop InGate to replace it. (InGate development never progressed far enough to create a mature replacement; it will also be retired.) Current State and Next Steps Currently, Ingress NGINX is receiving best-effort maintenance. SIG Network and the Security Response Committee have exhausted our efforts to find additional support to make Ingress NGINX sustainable. To prioritize user safety, we must retire the project. In March 2026, Ingress NGINX maintenance will be halted, and the project will be retired. After that time, there will be no further releases, no bugfixes, and no updates to resolve any security vulnerabilities that may be discovered. The GitHub repositories will be made read-only and left available for reference. Existing deployments of Ingress NGINX will not be broken. Existing project artifacts such as Helm charts and container images will remain available. In most cases, you can check whether you use Ingress NGINX by running kubectl get pods \–all-namespaces \–selector app.kubernetes.io/name=ingress-nginx with cluster administrator permissions. We would like to thank the Ingress NGINX maintainers for their work in creating and maintaining this project–their dedication remains impressive. This Ingress controller has powered billions of requests in datacenters and homelabs all around the world. In a lot of ways, Kubernetes wouldn’t be where it is without Ingress NGINX, and we are grateful for so many years of incredible effort. SIG Network and the Security Response Committee recommend that all Ingress NGINX users begin migration to Gateway API or another Ingress controller immediately. Many options are listed in the Kubernetes documentation: Gateway API, Ingress. Additional options may be available from vendors you work with.
-
Announcing the 2025 Steering Committee Election Results
on November 9, 2025 at 8:10 pm
The 2025 Steering Committee Election is now complete. The Kubernetes Steering Committee consists of 7 seats, 4 of which were up for election in 2025. Incoming committee members serve a term of 2 years, and all members are elected by the Kubernetes Community. The Steering Committee oversees the governance of the entire Kubernetes project. With that great power comes great responsibility. You can learn more about the steering committee’s role in their charter. Thank you to everyone who voted in the election; your participation helps support the community’s continued health and success. Results Congratulations to the elected committee members whose two year terms begin immediately (listed in alphabetical order by GitHub handle): Kat Cosgrove (@katcosgrove), Minimus Paco Xu (@pacoxu), DaoCloud Rita Zhang (@ritazh), Microsoft Maciej Szulik (@soltysh), Defense Unicorns They join continuing members: Antonio Ojea (@aojea), Google Benjamin Elder (@BenTheElder), Google Sascha Grunert (@saschagrunert), Red Hat Maciej Szulik and Paco Xu are returning Steering Committee Members. Big thanks! Thank you and congratulations on a successful election to this round’s election officers: Christoph Blecker (@cblecker) Nina Polshakova (@npolshakova) Sreeram Venkitesh (@sreeram-venkitesh) Thanks to the Emeritus Steering Committee Members. Your service is appreciated by the community: Stephen Augustus (@justaugustus), Bloomberg Patrick Ohly (@pohly), Intel And thank you to all the candidates who came forward to run for election. Get involved with the Steering Committee This governing body, like all of Kubernetes, is open to all. You can follow along with Steering Committee meeting notes and weigh in by filing an issue or creating a PR against their repo. They have an open meeting on the first Wednesday at 8am PT of every month. They can also be contacted at their public mailing list steering@kubernetes.io. You can see what the Steering Committee meetings are all about by watching past meetings on the YouTube Playlist. This post was adapted from one written by the Contributor Comms Subproject. If you want to write stories about the Kubernetes community, learn more about us. This article was revised in November 2025 to update the information about when the steering committee meets.
-
Gateway API 1.4: New Features
on November 6, 2025 at 5:00 pm
Ready to rock your Kubernetes networking? The Kubernetes SIG Network community presented the General Availability (GA) release of Gateway API (v1.4.0)! Released on October 6, 2025, version 1.4.0 reinforces the path for modern, expressive, and extensible service networking in Kubernetes. Gateway API v1.4.0 brings three new features to the Standard channel (Gateway API’s GA release channel): BackendTLSPolicy for TLS between gateways and backends supportedFeatures in GatewayClass status Named rules for Routes and introduces three new experimental features: Mesh resource for service mesh configuration Default gateways to ease configuration burden** externalAuth filter for HTTPRoute Graduations to Standard Channel Backend TLS policy Leads: Candace Holman, Norwin Schnyder, Katarzyna Łach GEP-1897: BackendTLSPolicy BackendTLSPolicy is a new Gateway API type for specifying the TLS configuration of the connection from the Gateway to backend pod(s). . Prior to the introduction of BackendTLSPolicy, there was no API specification that allowed encrypted traffic on the hop from Gateway to backend. The BackendTLSPolicy validation configuration requires a hostname. This hostname serves two purposes. It is used as the SNI header when connecting to the backend and for authentication, the certificate presented by the backend must match this hostname, unless subjectAltNames is explicitly specified. If subjectAltNames (SANs) are specified, the hostname is only used for SNI, and authentication is performed against the SANs instead. If you still need to authenticate against the hostname value in this case, you MUST add it to the subjectAltNames list. BackendTLSPolicy validation configuration also requires either caCertificateRefs or wellKnownCACertificates. caCertificateRefs refer to one or more (up to 8) PEM-encoded TLS certificate bundles. If there are no specific certificates to use, then depending on your implementation, you may use wellKnownCACertificates, set to “System” to tell the Gateway to use an implementation-specific set of trusted CA Certificates. In this example, the BackendTLSPolicy is configured to use certificates defined in the auth-cert ConfigMap to connect with a TLS-encrypted upstream connection where pods backing the auth service are expected to serve a valid certificate for auth.example.com. It uses subjectAltNames with a Hostname type, but you may also use a URI type. apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: tls-upstream-auth spec: targetRefs: – kind: Service name: auth group: “” sectionName: “https” validation: caCertificateRefs: – group: “” # core API group kind: ConfigMap name: auth-cert subjectAltNames: – type: “Hostname” hostname: “auth.example.com” In this example, the BackendTLSPolicy is configured to use system certificates to connect with a TLS-encrypted backend connection where Pods backing the dev Service are expected to serve a valid certificate for dev.example.com. apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: tls-upstream-dev spec: targetRefs: – kind: Service name: dev group: “” sectionName: “btls” validation: wellKnownCACertificates: “System” hostname: dev.example.com More information on the configuration of TLS in Gateway API can be found in Gateway API – TLS Configuration. Status information about the features that an implementation supports Leads: Lior Lieberman, Beka Modebadze GEP-2162: Supported features in GatewayClass Status GatewayClass status has a new field, supportedFeatures. This addition allows implementations to declare the set of features they support. This provides a clear way for users and tools to understand the capabilities of a given GatewayClass. This feature’s name for conformance tests (and GatewayClass status reporting) is SupportedFeatures. Implementations must populate the supportedFeatures field in the .status of the GatewayClass before the GatewayClass is accepted, or in the same operation. Here’s an example of a supportedFeatures published under GatewayClass’ .status: apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass … status: conditions: – lastTransitionTime: “2022-11-16T10:33:06Z” message: Handled by Foo controller observedGeneration: 1 reason: Accepted status: “True” type: Accepted supportedFeatures: – HTTPRoute – HTTPRouteHostRewrite – HTTPRoutePortRedirect – HTTPRouteQueryParamMatching Graduation of SupportedFeatures to Standard, helped improve the conformance testing process for Gateway API. The conformance test suite will now automatically run tests based on the features populated in the GatewayClass’ status. This creates a strong, verifiable link between an implementation’s declared capabilities and the test results, making it easier for implementers to run the correct conformance tests and for users to trust the conformance reports. This means when the SupportedFeatures field is populated in the GatewayClass status there will be no need for additional conformance tests flags like –suported-features, or –exempt or –all-features. It’s important to note that Mesh features are an exception to this and can be tested for conformance by using Conformance Profiles, or by manually providing any combination of features related flags until the dedicated resource graduates from the experimental channel. Named rules for Routes GEP-995: Adding a new name field to all xRouteRule types (HTTPRouteRule, GRPCRouteRule, etc.) Leads: Guilherme Cassolato This enhancement enables route rules to be explicitly identified and referenced across the Gateway API ecosystem. Some of the key use cases include: Status: Allowing status conditions to reference specific rules directly by name. Observability: Making it easier to identify individual rules in logs, traces, and metrics. Policies: Enabling policies (GEP-713) to target specific route rules via the sectionName field in their targetRef[s]. Tooling: Simplifying filtering and referencing of route rules in tools such as gwctl, kubectl, and general-purpose utilities like jq and yq. Internal configuration mapping: Facilitating the generation of internal configurations that reference route rules by name within gateway and mesh implementations. This follows the same well-established pattern already adopted for Gateway listeners, Service ports, Pods (and containers), and many other Kubernetes resources. While the new name field is optional (so existing resources remain valid), its use is strongly encouraged. Implementations are not expected to assign a default value, but they may enforce constraints such as immutability. Finally, keep in mind that the name format is validated, and other fields (such as sectionName) may impose additional, indirect constraints. Experimental channel changes Enabling external Auth for HTTPRoute Giving Gateway API the ability to enforce authentication and maybe authorization as well at the Gateway or HTTPRoute level has been a highly requested feature for a long time. (See the GEP-1494 issue for some background.) This Gateway API release adds an Experimental filter in HTTPRoute that tells the Gateway API implementation to call out to an external service to authenticate (and, optionally, authorize) requests. This filter is based on the Envoy ext_authz API, and allows talking to an Auth service that uses either gRPC or HTTP for its protocol. Both methods allow the configuration of what headers to forward to the Auth service, with the HTTP protocol allowing some extra information like a prefix path. A HTTP example might look like this (noting that this example requires the Experimental channel to be installed and an implementation that supports External Auth to actually understand the config): apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: require-auth namespace: default spec: parentRefs: – name: your-gateway-here rules: – matches: – path: type: Prefix value: /admin filters: – type: ExternalAuth externalAuth: protocol: HTTP backendRef: name: auth-service http: # These headers are always sent for the HTTP protocol, # but are included here for illustrative purposes allowedHeaders: – Host – Method – Path – Content-Length – Authorization backendRefs: – name: admin-backend port: 8080 This allows the backend Auth service to use the supplied headers to make a determination about the authentication for the request. When a request is allowed, the external Auth service will respond with a 200 HTTP response code, and optionally extra headers to be included in the request that is forwarded to the backend. When the request is denied, the Auth service will respond with a 403 HTTP response. Since the Authorization header is used in many authentication methods, this method can be used to do Basic, Oauth, JWT, and other common authentication and authorization methods. Mesh resource Lead(s): Flynn GEP-3949: Mesh-wide configuration and supported features Gateway API v1.4.0 introduces a new experimental Mesh resource, which provides a way to configure mesh-wide settings and discover the features supported by a given mesh implementation. This resource is analogous to the Gateway resource and will initially be mainly used for conformance testing, with plans to extend its use to off-cluster Gateways in the future. The Mesh resource is cluster-scoped and, as an experimental feature, is named XMesh and resides in the gateway.networking.x-k8s.io API group. A key field is controllerName, which specifies the mesh implementation responsible for the resource. The resource’s status stanza indicates whether the mesh implementation has accepted it and lists the features the mesh supports. One of the goals of this GEP is to avoid making it more difficult for users to adopt a mesh. To simplify adoption, mesh implementations are expected to create a default Mesh resource upon startup if one with a matching controllerName doesn’t already exist. This avoids the need for manual creation of the resource to begin using a mesh. The new XMesh API kind, within the gateway.networking.x-k8s.io/v1alpha1 API group, provides a central point for mesh configuration and feature discovery (source). A minimal XMesh object specifies the controllerName: apiVersion: gateway.networking.x-k8s.io/v1alpha1 kind: XMesh metadata: name: one-mesh-to-mesh-them-all spec: controllerName: one-mesh.example.com/one-mesh The mesh implementation populates the status field to confirm it has accepted the resource and to list its supported features ( source): status: conditions: – type: Accepted status: “True” reason: Accepted supportedFeatures: – name: MeshHTTPRoute – name: OffClusterGateway Introducing default Gateways Lead(s): Flynn GEP-3793: Allowing Gateways to program some routes by default. For application developers, one common piece of feedback has been the need to explicitly name a parent Gateway for every single north-south Route. While this explicitness prevents ambiguity, it adds friction, especially for developers who just want to expose their application to the outside world without worrying about the underlying infrastructure’s naming scheme. To address this, we have introduce the concept of Default Gateways. For application developers: Just “use the default” As an application developer, you often don’t care about the specific Gateway your traffic flows through, you just want it to work. With this enhancement, you can now create a Route and simply ask it to use a default Gateway. This is done by setting the new useDefaultGateways field in your Route’s spec. Here’s a simple HTTPRoute that uses a default Gateway: apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: my-route spec: useDefaultGateways: All rules: – backendRefs: – name: my-service port: 80 That’s it! No more need to hunt down the correct Gateway name for your environment. Your Route is now a “defaulted Route.” For cluster operators: You’re still in control This feature doesn’t take control away from cluster operators (“Chihiro”). In fact, they have explicit control over which Gateways can act as a default. A Gateway will only accept these defaulted Routes if it is configured to do so. You can also use a ValidatingAdmissionPolicy to either require or even forbid for Routes to rely on a default Gateway. As a cluster operator, you can designate a Gateway as a default by setting the (new) .spec.defaultScope field: apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-default-gateway namespace: default spec: defaultScope: All # … other gateway configuration Operators can choose to have no default Gateways, or even multiple. How it works and key details To maintain a clean, GitOps-friendly workflow, a default Gateway does not modify the spec.parentRefs of your Route. Instead, the binding is reflected in the Route’s status field. You can always inspect the status.parents stanza of your Route to see exactly which Gateway or Gateways have accepted it. This preserves your original intent and avoids conflicts with CD tools. The design explicitly supports having multiple Gateways designated as defaults within a cluster. When this happens, a defaulted Route will bind to all of them. This enables cluster operators to perform zero-downtime migrations and testing of new default Gateways. You can create a single Route that handles both north-south traffic (traffic entering or leaving the cluster, via a default Gateway) and east-west/mesh traffic (traffic between services within the cluster), by explicitly referencing a Service in parentRefs. Default Gateways represent a significant step forward in making the Gateway API simpler and more intuitive for everyday use cases, bridging the gap between the flexibility needed by operators and the simplicity desired by developers. Configuring client certificate validation Lead(s): Arko Dasgupta, Katarzyna Łach GEP-91: Address connection coalescing security issue This release brings updates for configuring client certificate validation, addressing a critical security vulnerability related to connection reuse. HTTP connection coalescing is a web performance optimization that allows a client to reuse an existing TLS connection for requests to different domains. While this reduces the overhead of establishing new connections, it introduces a security risk in the context of API gateways. The ability to reuse a single TLS connection across multiple Listeners brings the need to introduce shared client certificate configuration in order to avoid unauthorized access. Why SNI-based mTLS is not the answer One might think that using Server Name Indication (SNI) to differentiate between Listeners would solve this problem. However, TLS SNI is not a reliable mechanism for enforcing security policies in a connection coalescing scenario. A client could use a single TLS connection for multiple peer connections, as long as they are all covered by the same certificate. This means that a client could establish a connection by indicating one peer identity (using SNI), and then reuse that connection to access a different virtual host that is listening on the same IP address and port. That reuse, which is controlled by client side heuristics, could bypass mutual TLS policies that were specific to the second listener configuration. Here’s an example to help explain it: apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: wildcard-tls-gateway spec: gatewayClassName: example listeners: – name: foo-https protocol: HTTPS port: 443 hostname: foo.example.com tls: certificateRefs: – group: “” # core API group kind: Secret name: foo-example-com-cert # SAN: foo.example.com – name: wildcard-https protocol: HTTPS port: 443 hostname: “*.example.com” tls: certificateRefs: – group: “” # core API group kind: Secret name: wildcard-example-com-cert # SAN: *.example.com I have configured a Gateway with two listeners, both having overlapping hostnames. My intention is for the foo-http listener to be accessible only by clients presenting the foo-example-com-cert certificate. In contrast, the wildcard-https listener should allow access to a broader audience using any certificate valid for the *.example.com domain. Consider a scenario where a client initially connects to foo.example.com. The server requests and successfully validates the foo-example-com-cert certificate, establishing the connection. Subsequently, the same client wishes to access other sites within this domain, such as bar.example.com, which is handled by the wildcard-https listener. Due to connection reuse, clients can access wildcard-https backends without an additional TLS handshake on the existing connection. This process functions as expected. However, a critical security vulnerability arises when the order of access is reversed. If a client first connects to bar.example.com and presents a valid bar.example.com certificate, the connection is successfully established. If this client then attempts to access foo.example.com, the existing connection’s client certificate will not be re-validated. This allows the client to bypass the specific certificate requirement for the foo backend, leading to a serious security breach. The solution: per-port TLS configuration The updated Gateway API gains a tls field in the .spec of a Gateway, that allows you to define a default client certificate validation configuration for all Listeners, and then if needed override it on a per-port basis. This provides a flexible and powerful way to manage your TLS policies. Here’s a look at the updated API definitions (shown as Go source code): // GatewaySpec defines the desired state of Gateway. type GatewaySpec struct { … // GatewayTLSConfig specifies frontend tls configuration for gateway. TLS *GatewayTLSConfig `json:”tls,omitempty”` } // GatewayTLSConfig specifies frontend tls configuration for gateway. type GatewayTLSConfig struct { // Default specifies the default client certificate validation configuration Default TLSConfig `json:”default”` // PerPort specifies tls configuration assigned per port. PerPort []TLSPortConfig `json:”perPort,omitempty”` } // TLSPortConfig describes a TLS configuration for a specific port. type TLSPortConfig struct { // The Port indicates the Port Number to which the TLS configuration will be applied. Port PortNumber `json:”port”` // TLS store the configuration that will be applied to all Listeners handling // HTTPS traffic and matching given port. TLS TLSConfig `json:”tls”` } Breaking changes Standard GRPCRoute – .spec field required (technicality) The promotion of GRPCRoute to Standard introduces a minor but technically breaking change regarding the presence of the top-level .spec field. As part of achieving Standard status, the Gateway API has tightened the OpenAPI schema validation within the GRPCRoute CustomResourceDefinition (CRD) to explicitly ensure the spec field is required for all GRPCRoute resources. This change enforces stricter conformance to Kubernetes object standards and enhances the resource’s stability and predictability. While it is highly unlikely that users were attempting to define a GRPCRoute without any specification, any existing automation or manifests that might have relied on a relaxed interpretation allowing a completely absent spec field will now fail validation and must be updated to include the .spec field, even if empty. Experimental CORS support in HTTPRoute – breaking change for allowCredentials field The Gateway API subproject has introduced a breaking change to the Experimental CORS support in HTTPRoute, concerning the allowCredentials field within the CORS policy. This field’s definition has been strictly aligned with the upstream CORS specification, which dictates that the corresponding Access-Control-Allow-Credentials header must represent a Boolean value. Previously, the implementation might have been overly permissive, potentially accepting non-standard or string representations such as true due to relaxed schema validation. Users who were configuring CORS rules must now review their manifests and ensure the value for allowCredentials strictly conforms to the new, more restrictive schema. Any existing HTTPRoute definitions that do not adhere to this stricter validation will now be rejected by the API server, requiring a configuration update to maintain functionality. Improving the development and usage experience As part of this release, we have improved some of the developer experience workflow: Added Kube API Linter to the CI/CD pipelines, reducing the burden of API reviewers and also reducing the amount of common mistakes. Improving the execution time of CRD tests with the usage of envtest. Additionally, as part of the effort to improve Gateway API usage experience, some efforts were made to remove some ambiguities and some old tech-debts from our documentation website: The API reference is now explicit when a field is experimental. The GEP (GatewayAPI Enhancement Proposal) navigation bar is automatically generated, reflecting the real status of the enhancements. Try it out Unlike other Kubernetes APIs, you don’t need to upgrade to the latest version of Kubernetes to get the latest version of Gateway API. As long as you’re running Kubernetes 1.26 or later, you’ll be able to get up and running with this version of Gateway API. To try out the API, follow the Getting Started Guide. As of this writing, seven implementations are already conformant with Gateway API v1.4.0. In alphabetical order: Agent Gateway (with kgateway) Airlock Microgateway Envoy Gateway GKE Gateway Istio kgateway Traefik Proxy Get involved Wondering when a feature will be added? There are lots of opportunities to get involved and help define the future of Kubernetes routing APIs for both ingress and service mesh. Check out the user guides to see what use-cases can be addressed. Try out one of the existing Gateway controllers. Or join us in the community and help us build the future of Gateway API together! The maintainers would like to thank everyone who’s contributed to Gateway API, whether in the form of commits to the repo, discussion, ideas, or general support. We could never have made this kind of progress without the support of this dedicated and active community. Related Kubernetes blog articles Gateway API v1.3.0: Advancements in Request Mirroring, CORS, Gateway Merging, and Retry Budgets (June 2025) Gateway API v1.2: WebSockets, Timeouts, Retries, and More (November 2024) Gateway API v1.1: Service mesh, GRPCRoute, and a whole lot more (May 2024) New Experimental Features in Gateway API v1.0 (November 2023) Gateway API v1.0: GA Release (October 2023)
