<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: DevStories</title>
    <description>The latest articles on DEV Community by DevStories (@devstories_fca96eb46af114).</description>
    <link>https://dev.to/devstories_fca96eb46af114</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4188547%2F0ce9ddb9-f291-41a1-a25c-51f1ab05e5c6.png</url>
      <title>DEV Community: DevStories</title>
      <link>https://dev.to/devstories_fca96eb46af114</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devstories_fca96eb46af114"/>
    <language>en</language>
    <item>
      <title>Kubernetes in 2026: What It Is, How It Works, and a Production Baseline You Can Apply Today</title>
      <dc:creator>DevStories</dc:creator>
      <pubDate>Fri, 16 Oct 2026 10:00:13 +0000</pubDate>
      <link>https://dev.to/devstories_fca96eb46af114/kubernetes-in-2026-what-it-is-how-it-works-and-a-production-baseline-you-can-apply-today-28o9</link>
      <guid>https://dev.to/devstories_fca96eb46af114/kubernetes-in-2026-what-it-is-how-it-works-and-a-production-baseline-you-can-apply-today-28o9</guid>
      <description>&lt;p&gt;Kubernetes is the system most teams now use to run containers in production. In the &lt;a href="https://www.cncf.io/announcements/2026/01/20/kubernetes-established-as-the-de-facto-operating-system-for-ai-as-production-use-hits-82-in-2025-cncf-annual-cloud-native-survey/" rel="noopener noreferrer"&gt;CNCF annual survey announced on January 20, 2026&lt;/a&gt;, 82% of container users reported running Kubernetes in production, up from 66% in 2023. Operating it well is now a core engineering skill, and this post teaches it in three layers.&lt;/p&gt;

&lt;p&gt;The first layer explains what Kubernetes is, the problem it solves, and the objects you work with every day. The second shows how a cluster is built and what happens between typing &lt;code&gt;kubectl apply&lt;/code&gt; and a running container. The third is a production baseline for a stateless HTTP service: seven manifests, each explained, plus the 2026 changes that can break a cluster you have not touched in a year.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/blog/2026/08/26/kubernetes-v1-37-release/" rel="noopener noreferrer"&gt;Kubernetes 1.37 shipped on August 26, 2026&lt;/a&gt;, and the project now supports three minor versions at once. Every feature below carries its maturity level and the version that set it. Where a claim comes from a release note, a blog post or a survey, it links to that source. Where the baseline depends on something your cluster must provide, such as a Gateway API controller or a CNI plugin that enforces NetworkPolicy, the text says so.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Kubernetes is, and the problem it solves
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://kubernetes.io/docs/concepts/overview/" rel="noopener noreferrer"&gt;project's own words&lt;/a&gt;, Kubernetes is a portable, extensible, open source platform for managing containerized workloads and services, with both declarative configuration and automation. The name comes from the Greek word for helmsman or pilot, and K8s abbreviates it by counting the eight letters between the K and the s. Google open sourced the project in 2014, and it combines over 15 years of Google's experience running production workloads at scale with ideas from the community.&lt;/p&gt;

&lt;p&gt;To see why it exists, follow how deployment changed. Teams first ran applications on physical servers, where one application could take most of a machine's resources and starve the others. Virtual machines fixed that by isolating applications, but each VM runs a full operating system. Containers relax that isolation and share the host operating system, so they are lighter and portable across clouds and Linux distributions.&lt;/p&gt;

&lt;p&gt;Containers solve packaging, not operations. In production something must restart a container that dies, spread containers across many machines, send traffic only to the healthy ones, and roll out new versions without downtime. The overview puts it plainly: if a container goes down, another container needs to start, and it would be easier if a system handled that. Kubernetes is that system.&lt;/p&gt;

&lt;p&gt;The overview lists what you get from it, summarized here.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Service discovery and load balancing&lt;/td&gt;
&lt;td&gt;Exposes a container by DNS name or IP address and spreads traffic across copies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage orchestration&lt;/td&gt;
&lt;td&gt;Mounts the storage system you choose, from local disks to public cloud storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automated rollouts and rollbacks&lt;/td&gt;
&lt;td&gt;Moves the actual state to the state you describe, at a controlled rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automatic bin packing&lt;/td&gt;
&lt;td&gt;Places containers on nodes using the CPU and memory you declare for each&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-healing&lt;/td&gt;
&lt;td&gt;Restarts failed containers and withholds traffic until a container is ready&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secret and configuration management&lt;/td&gt;
&lt;td&gt;Updates secrets and configuration without rebuilding images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Batch execution&lt;/td&gt;
&lt;td&gt;Runs batch and CI workloads and replaces failed containers if you want&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Horizontal scaling&lt;/td&gt;
&lt;td&gt;Scales up or down by command, in a UI, or automatically on CPU usage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It also helps to know what Kubernetes leaves out. It is not an all-inclusive platform as a service: it does not build your code, run your CI/CD pipeline, or ship databases, message buses and caches as built-in services, and it does not choose your logging or monitoring tools. It is also not orchestration in the strict sense of running step A, then B, then C. It is a set of independent control processes that keep driving the current state toward the state you declared.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core idea: you declare, controllers converge
&lt;/h2&gt;

&lt;p&gt;Everything in Kubernetes is an object, a persistent record in the cluster. The &lt;a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/" rel="noopener noreferrer"&gt;objects documentation&lt;/a&gt; calls an object a record of intent: once you create it, the system works constantly to make it exist. Almost every object has a &lt;code&gt;spec&lt;/code&gt;, which is the state you want, and a &lt;code&gt;status&lt;/code&gt;, which Kubernetes fills in with the state it observes.&lt;/p&gt;

&lt;p&gt;Take a Deployment whose spec asks for three replicas. Kubernetes reads the spec and starts three instances. If one fails, the status no longer matches the spec, and Kubernetes starts a replacement. The component doing this work is a &lt;a href="https://kubernetes.io/docs/concepts/architecture/controller/" rel="noopener noreferrer"&gt;controller&lt;/a&gt;, which runs a control loop, a non-terminating loop that regulates the state of a system. The docs compare it to a thermostat that switches equipment on and off to bring a room toward the temperature you set.&lt;/p&gt;

&lt;p&gt;The practical consequence is that you rarely issue instructions such as "start this container". You change the declared state, and controllers work out the steps. That is why this post is built from YAML files you apply, not scripts you run.&lt;/p&gt;

&lt;h2&gt;
  
  
  The objects you use every day
&lt;/h2&gt;

&lt;p&gt;A handful of object types cover most applications. The table lists them in the order you meet them.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Object&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;How you use it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;td&gt;The smallest deployable unit: one or more tightly coupled containers with shared storage and network&lt;/td&gt;
&lt;td&gt;The unit that actually runs, normally created through a workload resource and not by hand&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ReplicaSet&lt;/td&gt;
&lt;td&gt;Keeps a stable set of replica Pods running&lt;/td&gt;
&lt;td&gt;Rarely touched directly, because a Deployment manages it for you&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Declarative updates for Pods and ReplicaSets, usually for apps that keep no state&lt;/td&gt;
&lt;td&gt;Running and updating a stateless service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service&lt;/td&gt;
&lt;td&gt;A stable network endpoint for a changing set of Pods&lt;/td&gt;
&lt;td&gt;Giving clients one name and address to call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ConfigMap&lt;/td&gt;
&lt;td&gt;Non-confidential configuration stored as key-value pairs&lt;/td&gt;
&lt;td&gt;Settings consumed as environment variables, arguments or files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secret&lt;/td&gt;
&lt;td&gt;A small amount of sensitive data such as a password, token or key&lt;/td&gt;
&lt;td&gt;Credentials kept out of images and Pod specs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Namespace&lt;/td&gt;
&lt;td&gt;A scope that isolates groups of resources inside one cluster&lt;/td&gt;
&lt;td&gt;Separating teams or projects, since names must be unique only within a namespace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node&lt;/td&gt;
&lt;td&gt;A worker machine, virtual or physical, that runs Pods&lt;/td&gt;
&lt;td&gt;The capacity underneath everything, managed for you by the control plane&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Other workload resources cover other shapes of work. A &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/" rel="noopener noreferrer"&gt;StatefulSet&lt;/a&gt; gives each Pod a sticky identity for applications that need persistent storage or a stable network identity. A &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/" rel="noopener noreferrer"&gt;DaemonSet&lt;/a&gt; runs node-local facilities such as a networking helper. A &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/job/" rel="noopener noreferrer"&gt;Job&lt;/a&gt; runs a one-off task to completion.&lt;/p&gt;

&lt;p&gt;Pods are ephemeral. The &lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/" rel="noopener noreferrer"&gt;Service documentation&lt;/a&gt; says you should not expect any individual Pod to be reliable or durable, because Pods are created and destroyed to match the desired state. Each Pod gets its own IP address, but the set of healthy Pods keeps changing. That is the reason Services exist: clients need one stable name in front of Pods that come and go.&lt;/p&gt;

&lt;p&gt;One caution about Secrets. By default they are stored unencrypted in etcd, and anyone with API access can read them, as can anyone allowed to create a Pod in the namespace. The &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/" rel="noopener noreferrer"&gt;Secret documentation&lt;/a&gt; tells you to enable encryption at rest and to restrict access with RBAC. A ConfigMap provides no secrecy at all.&lt;/p&gt;

&lt;p&gt;Here is a minimal Deployment, the object you will write most often.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# hello.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-node&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-node&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-node&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agnhost&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registry.k8s.io/e2e-test-images/agnhost:2.53&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/agnhost"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;netexec"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--http-port=8080"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read it from the top. &lt;code&gt;apiVersion&lt;/code&gt; and &lt;code&gt;kind&lt;/code&gt; name the API and the object type, and &lt;code&gt;metadata.name&lt;/code&gt; names the object. Everything under &lt;code&gt;spec&lt;/code&gt; is desired state: two replicas of a Pod built from the &lt;code&gt;template&lt;/code&gt;. The &lt;code&gt;selector&lt;/code&gt; tells the Deployment which Pods it owns by matching the template's labels, and the &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="noopener noreferrer"&gt;Deployment documentation&lt;/a&gt; says the API rejects a Deployment whose two do not match. Labels are plain key-value pairs that Services, Deployments and policies use to find Pods.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a cluster is built
&lt;/h2&gt;

&lt;p&gt;A cluster has a control plane and one or more worker nodes. The &lt;a href="https://kubernetes.io/docs/concepts/overview/components/" rel="noopener noreferrer"&gt;components overview&lt;/a&gt; says the control plane components manage the overall state of the cluster, and the node components run on every node, maintaining running Pods and providing the runtime environment.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Runs on&lt;/th&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;kube-apiserver&lt;/td&gt;
&lt;td&gt;Control plane&lt;/td&gt;
&lt;td&gt;Serves the Kubernetes HTTP API as the front end of the control plane, and scales horizontally by running more instances&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;etcd&lt;/td&gt;
&lt;td&gt;Control plane&lt;/td&gt;
&lt;td&gt;Consistent, highly available key-value store for all cluster data, which you need a backup plan for&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kube-scheduler&lt;/td&gt;
&lt;td&gt;Control plane&lt;/td&gt;
&lt;td&gt;Watches for newly created Pods with no node and selects a node for each&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kube-controller-manager&lt;/td&gt;
&lt;td&gt;Control plane&lt;/td&gt;
&lt;td&gt;Runs the controller processes, compiled into one binary and run as one process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cloud-controller-manager&lt;/td&gt;
&lt;td&gt;Control plane, optional&lt;/td&gt;
&lt;td&gt;Integrates with the underlying cloud provider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kubelet&lt;/td&gt;
&lt;td&gt;Every node&lt;/td&gt;
&lt;td&gt;Makes sure the containers described in PodSpecs are running and healthy, and ignores containers Kubernetes did not create&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kube-proxy&lt;/td&gt;
&lt;td&gt;Every node, optional&lt;/td&gt;
&lt;td&gt;Maintains the network rules that implement Services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Container runtime&lt;/td&gt;
&lt;td&gt;Every node&lt;/td&gt;
&lt;td&gt;The software that actually runs containers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNptklFr2zAQx7_K7Z42kAuDPYUxyJyWhqaridONYfVBls-xGllnJDlpVvLdi51mLF3vTeJ_v_ud0DNqrggnWFve6Ub5CIuldAAA94XE39wDe1CQzuGRywls-pJ0tBIfIEm-wTSbH8OhL9dedQ2kWSExZRc9W-isciTx4ZgZaprNC4kDJVGdCeS35AfY14F2uUpnxUeJFHUl8dM_bXl6fWoLuqGqt8e2JAGJOxV1AxlXQUBpXAWRwXFFQeK55FDp7Qmkj5KWfNIqp9b_Ebl8JB2DAE-anTaW3gLJVW_W_3E3uywk_mK_IT9anK1_s3idbim-6--pYx8hRBX7d_1vFuPdclVIHDZQxpEH37to2vNZy9WYzO5meSFxwJ-rZKeH6Dw_7UebC5DouY8UICe_NZogelXXRkuEi1fY39VRYEu-VabCyTPGhtrhI1VUq95GFMebn8obVVoKQ6ZmF69Ua-weJ5iorrOUhH2I1Ar4bo3b3Cqdj-crdlGAxJzWTHA_lyhgySVHFnBNdkvRaCVg6o2yAoJyIQnkTY1iHJKbP4PL5y_dEx4OAst1ypY9TvDDrjGR8PACjsbtaA%3Ftype%3Dpng" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNptklFr2zAQx7_K7Z42kAuDPYUxyJyWhqaridONYfVBls-xGllnJDlpVvLdi51mLF3vTeJ_v_ud0DNqrggnWFve6Ub5CIuldAAA94XE39wDe1CQzuGRywls-pJ0tBIfIEm-wTSbH8OhL9dedQ2kWSExZRc9W-isciTx4ZgZaprNC4kDJVGdCeS35AfY14F2uUpnxUeJFHUl8dM_bXl6fWoLuqGqt8e2JAGJOxV1AxlXQUBpXAWRwXFFQeK55FDp7Qmkj5KWfNIqp9b_Ebl8JB2DAE-anTaW3gLJVW_W_3E3uywk_mK_IT9anK1_s3idbim-6--pYx8hRBX7d_1vFuPdclVIHDZQxpEH37to2vNZy9WYzO5meSFxwJ-rZKeH6Dw_7UebC5DouY8UICe_NZogelXXRkuEi1fY39VRYEu-VabCyTPGhtrhI1VUq95GFMebn8obVVoKQ6ZmF69Ua-weJ5iorrOUhH2I1Ar4bo3b3Cqdj-crdlGAxJzWTHA_lyhgySVHFnBNdkvRaCVg6o2yAoJyIQnkTY1iHJKbP4PL5y_dEx4OAst1ypY9TvDDrjGR8PACjsbtaA%3Ftype%3Dpng" alt="Mermaid Diagram" width="930" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every arrow runs through the API server. The &lt;a href="https://kubernetes.io/docs/concepts/overview/kubernetes-api/" rel="noopener noreferrer"&gt;Kubernetes API documentation&lt;/a&gt; says users, the different parts of your cluster and external components all communicate with one another through it. The scheduler, the controllers and the kubelets never call each other. Each watches the API for work and writes its results back, so a component that restarts can read the current state again.&lt;/p&gt;

&lt;p&gt;Three consequences shape every manifest in this post. The &lt;a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/" rel="noopener noreferrer"&gt;scheduler reads requests&lt;/a&gt;, so wrong requests mean wrong placement. The kubelet enforces limits, so wrong limits mean CPU throttling or out-of-memory kills. Controllers retry forever, so a bad rollout never fixes itself unless a probe tells the truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when you run kubectl apply
&lt;/h2&gt;

&lt;p&gt;Follow one command through the system. The CLI turns your file into API calls, as the &lt;a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/" rel="noopener noreferrer"&gt;objects documentation&lt;/a&gt; describes, and from there the work passes between components without any of them calling another directly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNptkkFv2zAMhf8Kq7N8GLCTDwHStMWGYMBQIz3lQktMzEUWPYlumxX574PipkWSHsX3PT0-QW_GiSdTm0x_R4qO7hi3Cft1BAAYMCk7HjAqrAAz7MaWnIZrdX5SKxw4U3qmdA3dF4jU-WtpUaSFRE0SAqV8TTQfCdl15MfwVcLyBAVSkAgIUTxN3KqazeY1uESoBNoR3NEQZN9T1ImYV7PZfQ1ZJU2AtH_IvYuLyZ7p0mtPVyI80hDYYUNfez7lD89v8e9dm0-2DOGFtYMoxwIWWo4eCF0HKmetlhe2VsboC6Qd5wtuWQPm3XEVJ1GRIyVIY1TuqViyYtJzOZ-lJBokaQkqrI7ZWNNT6pG9qd-MdtSXv-Rpg2NQY6fJEybGNlAuzEaiPmDPYW9qU-EwBKryPiv1Fm4Dx90vdM3x_CDlbdemoa0QrH6ujYVHaUXFwg8Kz6Ts0MI8MQYLGWOuMiXeGHsMafhf2eXb9-HVHA7WtNuFBEmmNjcvHSuZw39Yjv-6%3Ftype%3Dpng" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNptkkFv2zAMhf8Kq7N8GLCTDwHStMWGYMBQIz3lQktMzEUWPYlumxX574PipkWSHsX3PT0-QW_GiSdTm0x_R4qO7hi3Cft1BAAYMCk7HjAqrAAz7MaWnIZrdX5SKxw4U3qmdA3dF4jU-WtpUaSFRE0SAqV8TTQfCdl15MfwVcLyBAVSkAgIUTxN3KqazeY1uESoBNoR3NEQZN9T1ImYV7PZfQ1ZJU2AtH_IvYuLyZ7p0mtPVyI80hDYYUNfez7lD89v8e9dm0-2DOGFtYMoxwIWWo4eCF0HKmetlhe2VsboC6Qd5wtuWQPm3XEVJ1GRIyVIY1TuqViyYtJzOZ-lJBokaQkqrI7ZWNNT6pG9qd-MdtSXv-Rpg2NQY6fJEybGNlAuzEaiPmDPYW9qU-EwBKryPiv1Fm4Dx90vdM3x_CDlbdemoa0QrH6ujYVHaUXFwg8Kz6Ts0MI8MQYLGWOuMiXeGHsMafhf2eXb9-HVHA7WtNuFBEmmNjcvHSuZw39Yjv-6%3Ftype%3Dpng" alt="Mermaid Diagram" width="1343" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A chain of hand-offs turns that file into running containers. The API server accepts and stores the Deployment. The Deployment controller creates a ReplicaSet, and the ReplicaSet creates the Pods, which the &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="noopener noreferrer"&gt;Deployment documentation&lt;/a&gt; describes as happening in the background. The scheduler sees Pods without a node and picks one for each. The kubelet on that node starts the containers through the runtime and reports status back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it on a local cluster
&lt;/h2&gt;

&lt;p&gt;You need a cluster and &lt;code&gt;kubectl&lt;/code&gt;. The &lt;a href="https://kubernetes.io/docs/setup/learning-environment/" rel="noopener noreferrer"&gt;learning environment page&lt;/a&gt; lists kind, which runs cluster nodes as Docker containers, and minikube, which runs a single-node cluster on your machine, among other options. Install one of them and &lt;a href="https://kubernetes.io/docs/tasks/tools/#kubectl" rel="noopener noreferrer"&gt;kubectl&lt;/a&gt;, then confirm that &lt;code&gt;kubectl get nodes&lt;/code&gt; shows a node in the Ready state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; hello.yaml
kubectl get deployments
kubectl get pods

kubectl scale deployment/hello-node &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4
kubectl get pods

kubectl delete pod &amp;lt;one-of-the-pod-names&amp;gt;
kubectl get pods

kubectl get events
kubectl port-forward deployment/hello-node 8080:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run them in order. The first creates the Deployment and, through it, two Pods. Scaling to four changes the desired state, and Kubernetes starts two more. Deleting a Pod does not lower the count: the ReplicaSet notices the gap and creates a replacement, the behavior the docs list as &lt;a href="https://kubernetes.io/docs/concepts/architecture/self-healing/" rel="noopener noreferrer"&gt;replica replacement under self-healing&lt;/a&gt;. &lt;code&gt;kubectl get events&lt;/code&gt; shows the hand-offs from the previous section as they happened.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;port-forward&lt;/code&gt; command tunnels local port 8080 to a Pod, so you can open &lt;code&gt;http://localhost:8080&lt;/code&gt; and see the test image echo your request back, the same image the official &lt;a href="https://kubernetes.io/docs/tutorials/hello-minikube/" rel="noopener noreferrer"&gt;Hello Minikube tutorial&lt;/a&gt; uses. It does not return until you stop it with Ctrl+C. When you are done, run &lt;code&gt;kubectl delete -f hello.yaml&lt;/code&gt; to remove the Deployment and its Pods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Kubernetes stands in October 2026
&lt;/h2&gt;

&lt;p&gt;That demo skipped everything production needs: pinned versions, resource limits, probes, security controls and a safe way to take traffic. The rest of this post adds them, starting with the versions you can choose from.&lt;/p&gt;

&lt;p&gt;The project &lt;a href="https://kubernetes.io/releases/" rel="noopener noreferrer"&gt;maintains release branches for the three most recent minor releases&lt;/a&gt; and supports each patch series for &lt;a href="https://kubernetes.io/releases/patch-releases/" rel="noopener noreferrer"&gt;roughly fourteen months&lt;/a&gt;: twelve in the standard period, then two in maintenance mode, when new releases cover only CVE fixes, dependency issues and critical core component issues. As of October 10, 2026, the releases page lists the following.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Minor&lt;/th&gt;
&lt;th&gt;Latest patch listed&lt;/th&gt;
&lt;th&gt;End of life&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1.37&lt;/td&gt;
&lt;td&gt;1.37.1 (September 15, 2026)&lt;/td&gt;
&lt;td&gt;October 28, 2027&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.36&lt;/td&gt;
&lt;td&gt;1.36.5&lt;/td&gt;
&lt;td&gt;June 28, 2027&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.35&lt;/td&gt;
&lt;td&gt;1.35.9&lt;/td&gt;
&lt;td&gt;February 28, 2027&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.34&lt;/td&gt;
&lt;td&gt;1.34.12&lt;/td&gt;
&lt;td&gt;October 27, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The next patch releases for all four lines are &lt;a href="https://kubernetes.io/releases/" rel="noopener noreferrer"&gt;scheduled for October 13, 2026&lt;/a&gt;, so the patch numbers above will be stale within days. The fourth row, 1.34, is in maintenance mode, which began on August 27, 2026, and its end of life is &lt;a href="https://kubernetes.io/releases/" rel="noopener noreferrer"&gt;under three weeks away&lt;/a&gt;. Plan the move to 1.35 or later now, and upgrade one minor version at a time, because &lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/" rel="noopener noreferrer"&gt;kubeadm does not support skipping minor versions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The last two releases were large. &lt;a href="https://kubernetes.io/blog/2026/04/22/kubernetes-v1-36-release/" rel="noopener noreferrer"&gt;Kubernetes 1.36 (Haru)&lt;/a&gt;, released April 22, 2026, had 70 enhancements: 18 Stable, 25 Beta and 25 Alpha. &lt;a href="https://kubernetes.io/blog/2026/08/26/kubernetes-v1-37-release/" rel="noopener noreferrer"&gt;Kubernetes 1.37 (Garhwal)&lt;/a&gt; had 67: 16 Stable, 23 Beta, 27 Alpha and one deprecation or removal. You do not need most of them. You need the handful that change how you write manifests.&lt;/p&gt;

&lt;h2&gt;
  
  
  The baseline, one manifest at a time
&lt;/h2&gt;

&lt;p&gt;The target is one service called &lt;code&gt;api&lt;/code&gt; in a namespace called &lt;code&gt;shop&lt;/code&gt;, behind a shared Gateway, with three replicas spread across zones. Replace the names, the host, the image digest and the GatewayClass. Everything else is meant to be applied as written.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNpdUk2P2jAQ_SvTOTsrsXDKYSU-urBSq0aEsge8hyEZiFUnjuwJlF3x3ysnLS31yX5v3nszI39g4UrGFA_WnYuKvMCXtW4AAOY7jXNruBGNb5AkT7B83WlckvCZLimsNpssh8lkrPFtUCxf-7LVeqcxsmvXCadQuSBATQktSQW-sxxuktW6l-TbmJazP5mCU5jbLgj7l-xWl2_nfWH2bZEPSOj2R09t1UM7jZkrA4TWM5VAhXchgFSeGd5d809gPKXxXIhxDWxmf9FsNLioXgF0J8ke78j9PTm-I4sbyU05XBafs53GBbfWXerbRkGjd9YGcJ1o_G--VTaNa8ymKYxBHIwewXNrTUGhVz-AxsAS_qBQuC4aw0PyFPMGl2wxG3pbmOC7Ng4968ojSwojIAECMTXfDK2pjQTgk-n3E37bxa5QYc2-JlNi-oFScR2_TckH6qygGpAteUN7yyHWHFwjz1Qbe8EUE2pby0m4BOFawcya5sdXKvL-_ewaURA_wNExfH_RqGDt9k6cghXbE4spSMHUG7IKAjUhCezNAVUfkpv32Mto0v7E61Xh_jh31nlM8dO5MsJ4_QXRbuXo%3Ftype%3Dpng" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNpdUk2P2jAQ_SvTOTsrsXDKYSU-urBSq0aEsge8hyEZiFUnjuwJlF3x3ysnLS31yX5v3nszI39g4UrGFA_WnYuKvMCXtW4AAOY7jXNruBGNb5AkT7B83WlckvCZLimsNpssh8lkrPFtUCxf-7LVeqcxsmvXCadQuSBATQktSQW-sxxuktW6l-TbmJazP5mCU5jbLgj7l-xWl2_nfWH2bZEPSOj2R09t1UM7jZkrA4TWM5VAhXchgFSeGd5d809gPKXxXIhxDWxmf9FsNLioXgF0J8ke78j9PTm-I4sbyU05XBafs53GBbfWXerbRkGjd9YGcJ1o_G--VTaNa8ymKYxBHIwewXNrTUGhVz-AxsAS_qBQuC4aw0PyFPMGl2wxG3pbmOC7Ng4968ojSwojIAECMTXfDK2pjQTgk-n3E37bxa5QYc2-JlNi-oFScR2_TckH6qygGpAteUN7yyHWHFwjz1Qbe8EUE2pby0m4BOFawcya5sdXKvL-_ewaURA_wNExfH_RqGDt9k6cghXbE4spSMHUG7IKAjUhCezNAVUfkpv32Mto0v7E61Xh_jh31nlM8dO5MsJ4_QXRbuXo%3Ftype%3Dpng" alt="Mermaid Diagram" width="1801" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save each block below as its own file, in order, using the file name in the first comment line.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Namespace: enforce Pod Security Admission
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 00-namespace.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Namespace&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shop&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;pod-security.kubernetes.io/enforce&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;restricted&lt;/span&gt;
    &lt;span class="na"&gt;pod-security.kubernetes.io/enforce-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latest&lt;/span&gt;
    &lt;span class="na"&gt;pod-security.kubernetes.io/warn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;restricted&lt;/span&gt;
    &lt;span class="na"&gt;pod-security.kubernetes.io/audit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;restricted&lt;/span&gt;
    &lt;span class="na"&gt;shared-gateway-access&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pod Security Admission has been &lt;a href="https://kubernetes.io/blog/2022/08/25/pod-security-admission-stable/" rel="noopener noreferrer"&gt;stable since 1.25&lt;/a&gt;. The &lt;code&gt;restricted&lt;/code&gt; profile rejects Pods that run as root, allow privilege escalation, keep default Linux capabilities or lack a seccomp profile. Setting enforce, warn and audit together means you see violations in three places. The last label is used by the Gateway in step 4.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Deployment
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 01-deployment.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shop&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# replicas is omitted on purpose: the HPA in step 6 owns it&lt;/span&gt;
  &lt;span class="na"&gt;revisionHistoryLimit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt;
    &lt;span class="na"&gt;rollingUpdate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;maxUnavailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
      &lt;span class="na"&gt;maxSurge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;hostUsers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="na"&gt;automountServiceAccountToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="na"&gt;terminationGracePeriodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;45&lt;/span&gt;
      &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runAsNonRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10001&lt;/span&gt;
        &lt;span class="na"&gt;runAsGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10001&lt;/span&gt;
        &lt;span class="na"&gt;seccompProfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RuntimeDefault&lt;/span&gt;
      &lt;span class="na"&gt;topologySpreadConstraints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;maxSkew&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
          &lt;span class="na"&gt;topologyKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;topology.kubernetes.io/zone&lt;/span&gt;
          &lt;span class="na"&gt;whenUnsatisfiable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ScheduleAnyway&lt;/span&gt;
          &lt;span class="na"&gt;labelSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
          &lt;span class="c1"&gt;# Pin by digest. Replace this placeholder with your real image digest.&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registry.example.com/shop/api@sha256:0000000000000000000000000000000000000000000000000000000000000000&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
              &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
          &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;250m&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;256Mi&lt;/span&gt;
            &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;256Mi&lt;/span&gt;
          &lt;span class="na"&gt;resizePolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;resourceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cpu&lt;/span&gt;
              &lt;span class="na"&gt;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NotRequired&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;resourceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;memory&lt;/span&gt;
              &lt;span class="na"&gt;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RestartContainer&lt;/span&gt;
          &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
            &lt;span class="na"&gt;readOnlyRootFilesystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;drop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ALL"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
          &lt;span class="na"&gt;startupProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/healthz&lt;/span&gt;
              &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
            &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
            &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
          &lt;span class="na"&gt;readinessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/readyz&lt;/span&gt;
              &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
            &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
            &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
          &lt;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/healthz&lt;/span&gt;
              &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
            &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
            &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
          &lt;span class="na"&gt;lifecycle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;preStop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
          &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tmp&lt;/span&gt;
              &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp&lt;/span&gt;
      &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tmp&lt;/span&gt;
          &lt;span class="na"&gt;emptyDir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;sizeLimit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;64Mi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four settings carry most of the weight. &lt;code&gt;hostUsers: false&lt;/code&gt; puts the Pod in its own user namespace, so root inside the container maps to an unprivileged user on the node. &lt;a href="https://kubernetes.io/blog/2026/04/23/kubernetes-v1-36-userns-ga/" rel="noopener noreferrer"&gt;User namespaces reached GA in 1.36&lt;/a&gt; and are Linux-only. The &lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/user-namespaces/" rel="noopener noreferrer"&gt;concept page&lt;/a&gt; lists the node requirements: Linux 6.3 or later for idmap mounts on tmpfs, runc 1.2 or later or crun 1.9 or later, and containerd 2.0 or later or CRI-O 1.25 or later. Check your nodes before relying on the setting.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;maxUnavailable: 0&lt;/code&gt; with &lt;code&gt;maxSurge: 1&lt;/code&gt; makes a rollout add one new Pod and wait for it to be Ready before removing an old one. The topology spread constraint keeps replicas balanced across zones. &lt;code&gt;ScheduleAnyway&lt;/code&gt; means a zone outage does not leave Pods Pending. Switch to &lt;code&gt;DoNotSchedule&lt;/code&gt; only if imbalance is worse than reduced capacity for your service.&lt;/p&gt;

&lt;p&gt;The three probes answer three different questions. The startup probe allows a slow boot of up to 60 seconds (30 failures at 2 second intervals) before the other probes begin. Readiness decides whether the Pod receives traffic, and should check dependencies you cannot serve without. Liveness should check only that the process is not wedged. Never make liveness depend on a database, or a database outage becomes a restart storm.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;preStop&lt;/code&gt; sleep and the 45 second grace period solve a race. Endpoint removal and SIGTERM happen at about the same time, so for a few seconds a terminating Pod can still receive requests. Sleeping 10 seconds before SIGTERM gives proxies time to stop sending traffic. Your application must still handle SIGTERM by finishing in-flight requests inside the remaining 35 seconds.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;sleep&lt;/code&gt; hook action is Stable since 1.34, when the &lt;code&gt;PodLifecycleSleepAction&lt;/code&gt; &lt;a href="https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/" rel="noopener noreferrer"&gt;feature gate&lt;/a&gt; became locked on, so every supported minor has it. The &lt;a href="https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/" rel="noopener noreferrer"&gt;lifecycle hooks page&lt;/a&gt; lists it beside the &lt;code&gt;exec&lt;/code&gt; and HTTP handlers. The kubelet runs it, so your image needs no &lt;code&gt;sleep&lt;/code&gt; binary.&lt;/p&gt;

&lt;p&gt;Memory request equals memory limit, and there is no CPU limit. Memory cannot be compressed, so an equal limit makes OOM behavior predictable. CPU can be throttled, and a CPU limit often throttles bursts the node could have served. The Pod still gets a CPU guarantee through its request. Revisit this choice if you run a multi-tenant cluster that needs hard caps.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 02-service.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shop&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Service gives the Pods one stable virtual IP and a DNS name, &lt;code&gt;api.shop.svc&lt;/code&gt;. It is &lt;code&gt;ClusterIP&lt;/code&gt; on purpose. Traffic from outside the cluster enters through the Gateway, not through a Service of type &lt;code&gt;LoadBalancer&lt;/code&gt; per application, and not through the deprecated &lt;code&gt;externalIPs&lt;/code&gt; field covered later.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Gateway and HTTPRoute
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 03-gateway-and-route.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway.networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Gateway&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;public&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway-system&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;gatewayClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example-gateway-class&lt;/span&gt;
  &lt;span class="na"&gt;listeners&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https&lt;/span&gt;
      &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTPS&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;443&lt;/span&gt;
      &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.example.com&lt;/span&gt;
      &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Terminate&lt;/span&gt;
        &lt;span class="na"&gt;certificateRefs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Secret&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api-example-com-tls&lt;/span&gt;
      &lt;span class="na"&gt;allowedRoutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;namespaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Selector&lt;/span&gt;
          &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;shared-gateway-access&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway.networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTPRoute&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shop&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;parentRefs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;public&lt;/span&gt;
      &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway-system&lt;/span&gt;
      &lt;span class="na"&gt;sectionName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https&lt;/span&gt;
  &lt;span class="na"&gt;hostnames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;api.example.com&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;matches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PathPrefix&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
      &lt;span class="na"&gt;backendRefs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gateway API splits ownership. The platform team owns the Gateway and its listeners, and application teams own the routes that attach to it. Gateway and HTTPRoute have been GA since &lt;a href="https://kubernetes.io/blog/2023/10/31/gateway-api-ga/" rel="noopener noreferrer"&gt;Gateway API v1.0&lt;/a&gt;. &lt;a href="https://kubernetes.io/blog/2026/08/03/gateway-api-v1-6-release/" rel="noopener noreferrer"&gt;Gateway API v1.6.0, released June 30, 2026&lt;/a&gt;, also moved TCPRoute and UDPRoute to the Standard channel at API version &lt;code&gt;v1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Gateway API is not built into the API server. You install its CRDs and a controller that implements your GatewayClass, and &lt;code&gt;example-gateway-class&lt;/code&gt; is a placeholder for that controller's class name. The &lt;code&gt;allowedRoutes&lt;/code&gt; selector is why step 1 labeled the &lt;code&gt;shop&lt;/code&gt; namespace: a route from an unlabeled namespace is not allowed to attach.&lt;/p&gt;

&lt;p&gt;The manifest assumes two objects already exist: the &lt;code&gt;gateway-system&lt;/code&gt; namespace, and a &lt;code&gt;kubernetes.io/tls&lt;/code&gt; Secret named &lt;code&gt;api-example-com-tls&lt;/code&gt; inside it. Per the &lt;a href="https://github.com/kubernetes-sigs/gateway-api/blob/v1.6.0/config/crd/standard/gateway.networking.k8s.io_gateways.yaml" rel="noopener noreferrer"&gt;Gateway CRD at v1.6.0&lt;/a&gt;, a certificate reference into another namespace is invalid unless a ReferenceGrant allows it, and the listener then reports &lt;code&gt;ResolvedRefs&lt;/code&gt; as False with the reason &lt;code&gt;RefNotPermitted&lt;/code&gt;. Create both before you apply this file.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. PodDisruptionBudget
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 04-pdb.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;policy/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PodDisruptionBudget&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shop&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;maxUnavailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A PodDisruptionBudget limits voluntary evictions, such as a node drain during an upgrade. With it, a drain can take one &lt;code&gt;api&lt;/code&gt; Pod at a time and must wait for the replacement to be Ready. It does not protect against crashes or node failures. Prefer &lt;code&gt;maxUnavailable&lt;/code&gt; over &lt;code&gt;minAvailable&lt;/code&gt;, so the budget keeps working when the HPA changes the replica count.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. HorizontalPodAutoscaler
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 05-hpa.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;autoscaling/v2&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HorizontalPodAutoscaler&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shop&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
  &lt;span class="na"&gt;minReplicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;maxReplicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;
  &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Resource&lt;/span&gt;
      &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cpu&lt;/span&gt;
        &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Utilization&lt;/span&gt;
          &lt;span class="na"&gt;averageUtilization&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;
  &lt;span class="na"&gt;behavior&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;scaleDown&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;stabilizationWindowSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;
      &lt;span class="na"&gt;policies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Percent&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;
          &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leaving &lt;code&gt;spec.replicas&lt;/code&gt; out of the Deployment makes the HPA the only writer of the replica count. If both write, every &lt;code&gt;kubectl apply&lt;/code&gt; resets it. On the first apply the Deployment starts at one replica until the HPA raises it to &lt;code&gt;minReplicas&lt;/code&gt;, so apply both in the same command. CPU utilization is measured against the request, which is why requests must be honest.&lt;/p&gt;

&lt;p&gt;Resource metrics come from the &lt;code&gt;metrics.k8s.io&lt;/code&gt; API, usually served by metrics-server. That API &lt;a href="https://kubernetes.io/blog/2026/08/27/kubernetes-v1-37-metrics-api-ga/" rel="noopener noreferrer"&gt;graduated to Stable in 1.37 after nearly nine years in Beta&lt;/a&gt;. The scale-down policy above removes at most 25% of replicas per minute, and only after five minutes of consistently lower demand, which avoids flapping on spiky traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. NetworkPolicy
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 06-networkpolicy.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NetworkPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default-deny&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shop&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Egress&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NetworkPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;allow-gateway-to-api&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shop&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
  &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;namespaceSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;kubernetes.io/metadata.name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway-system&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NetworkPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;allow-dns-egress&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shop&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Egress&lt;/span&gt;
  &lt;span class="na"&gt;egress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;namespaceSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;kubernetes.io/metadata.name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kube-system&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UDP&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;53&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;53&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NetworkPolicy objects are enforced only if your CNI plugin implements them. On a plugin that does not, these manifests are accepted and silently do nothing, so test with a throwaway Pod that should be blocked. Default-deny egress also blocks your database and every external API, so add one allow rule per destination before you ship. Some Gateway controllers run their data plane in a namespace other than &lt;code&gt;gateway-system&lt;/code&gt;; adjust the selector to match.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apply and verify
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;--dry-run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;server &lt;span class="nt"&gt;-f&lt;/span&gt; 00-namespace.yaml
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; 00-namespace.yaml
kubectl apply &lt;span class="nt"&gt;--dry-run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;server &lt;span class="nt"&gt;-f&lt;/span&gt; 01-deployment.yaml &lt;span class="nt"&gt;-f&lt;/span&gt; 02-service.yaml &lt;span class="nt"&gt;-f&lt;/span&gt; 04-pdb.yaml &lt;span class="nt"&gt;-f&lt;/span&gt; 05-hpa.yaml &lt;span class="nt"&gt;-f&lt;/span&gt; 06-networkpolicy.yaml
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; 01-deployment.yaml &lt;span class="nt"&gt;-f&lt;/span&gt; 02-service.yaml &lt;span class="nt"&gt;-f&lt;/span&gt; 04-pdb.yaml &lt;span class="nt"&gt;-f&lt;/span&gt; 05-hpa.yaml &lt;span class="nt"&gt;-f&lt;/span&gt; 06-networkpolicy.yaml
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; 03-gateway-and-route.yaml

kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; shop rollout status deploy/api
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; shop get deploy,hpa,pdb,pods &lt;span class="nt"&gt;-o&lt;/span&gt; wide
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; shop get httproute api &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.status.parents[*].conditions[*].type}{"\n"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server-side dry run catches schema errors and admission rejections, including Pod Security violations, without creating anything. The last command prints the route's status condition types; look for &lt;code&gt;Accepted&lt;/code&gt; and &lt;code&gt;ResolvedRefs&lt;/code&gt;, and read each condition's &lt;code&gt;status&lt;/code&gt; field when either is missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resize a running Pod without restarting it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/blog/2025/12/19/kubernetes-v1-35-in-place-pod-resize-ga/" rel="noopener noreferrer"&gt;In-place Pod resize reached Stable in 1.35&lt;/a&gt;, after starting as Alpha in 1.27. A container's &lt;code&gt;resources&lt;/code&gt; are now the desired state, the Pod status shows what is actually applied, and you change the desired values through the Pod's &lt;code&gt;resize&lt;/code&gt; subresource. Per the &lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/" rel="noopener noreferrer"&gt;task documentation&lt;/a&gt;, the server must be at 1.33 or later and kubectl at 1.32 or later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; shop patch pod &amp;lt;pod-name&amp;gt; &lt;span class="nt"&gt;--subresource&lt;/span&gt; resize &lt;span class="nt"&gt;--patch&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'{"spec":{"containers":[{"name":"api","resources":{"requests":{"cpu":"500m"}}}]}}'&lt;/span&gt;

kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; shop get pod &amp;lt;pod-name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.status.containerStatuses[0].resources}{"\n"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;resizePolicy&lt;/code&gt; in step 2 decides the cost. With CPU set to &lt;code&gt;NotRequired&lt;/code&gt;, the container keeps running while the kubelet applies the change. With memory set to &lt;code&gt;RestartContainer&lt;/code&gt;, a memory change restarts that container, because many runtimes cannot change their heap bounds on the fly. If one patch changes both, the container restarts, as the documentation states.&lt;/p&gt;

&lt;p&gt;A resize edits one Pod. The Deployment template still holds the old values, so replacement Pods start with them. Use resize for emergency relief and for autoscalers, since the Vertical Pod Autoscaler's &lt;code&gt;InPlaceOrRecreate&lt;/code&gt; mode, which the same post reports as &lt;a href="https://kubernetes.io/blog/2025/12/19/kubernetes-v1-35-in-place-pod-resize-ga/" rel="noopener noreferrer"&gt;Beta and built on this feature&lt;/a&gt;, and change the template for anything lasting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scale a worker to zero
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/blog/2026/09/02/kubernetes-v1-37-hpa-scale-to-zero-beta/" rel="noopener noreferrer"&gt;HorizontalPodAutoscaler scale to zero reached Beta in 1.37 and is on by default&lt;/a&gt;: the &lt;code&gt;HPAScaleToZero&lt;/code&gt; feature gate is enabled on both the kube-apiserver and the kube-controller-manager. It works only with an object metric or an external metric. CPU and memory come from running Pods, and at zero replicas there is nothing left to measure, so there would be no signal to scale back up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# queue-worker-hpa.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;autoscaling/v2&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HorizontalPodAutoscaler&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;queue-worker&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shop&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;queue-worker&lt;/span&gt;
  &lt;span class="na"&gt;minReplicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
  &lt;span class="na"&gt;maxReplicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
  &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;External&lt;/span&gt;
      &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;metric&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;queue_consumer_lag&lt;/span&gt;
          &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker_tasks&lt;/span&gt;
        &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AverageValue&lt;/span&gt;
          &lt;span class="na"&gt;averageValue&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;30"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This HPA asks for one replica per 30 queued tasks and drops to zero when the queue is empty. The external metric must be served through the External Metrics API by an adapter such as Prometheus Adapter, and you can confirm Kubernetes can read it with &lt;code&gt;kubectl get --raw&lt;/code&gt; before creating the HPA.&lt;/p&gt;

&lt;p&gt;The target type matters. The release post's example uses &lt;code&gt;Value&lt;/code&gt;, but in the &lt;a href="https://github.com/kubernetes/kubernetes/blob/v1.37.1/pkg/controller/podautoscaler/replica_calculator.go" rel="noopener noreferrer"&gt;controller source at v1.37.1&lt;/a&gt; a &lt;code&gt;Value&lt;/code&gt; target multiplies the metric-to-target ratio by the number of ready Pods, so a queue that stays long keeps multiplying the replica count. &lt;code&gt;AverageValue&lt;/code&gt; computes the queue length divided by 30, rounded up, and the &lt;a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/" rel="noopener noreferrer"&gt;HPA walkthrough&lt;/a&gt; uses it for its own queue example.&lt;/p&gt;

&lt;p&gt;Start the Deployment with at least one replica. &lt;a href="https://kubernetes.io/blog/2026/09/02/kubernetes-v1-37-hpa-scale-to-zero-beta/" rel="noopener noreferrer"&gt;The release post&lt;/a&gt; says manually setting a Deployment to zero has always paused autoscaling, and a workload at zero is resumed only if the HPA itself scaled it down and recorded the &lt;code&gt;ScaledToZero&lt;/code&gt; condition.&lt;/p&gt;

&lt;p&gt;Do not use this for the &lt;code&gt;api&lt;/code&gt; service. The release notes are explicit that &lt;a href="https://kubernetes.io/blog/2026/09/02/kubernetes-v1-37-hpa-scale-to-zero-beta/" rel="noopener noreferrer"&gt;Kubernetes Services do not buffer requests while no Pods are ready&lt;/a&gt;, so request-driven HTTP workloads need a separate buffering layer. Scale to zero fits work that can wait in a durable queue, where a cold start costs seconds of latency and nobody is waiting on a socket.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to fix before you upgrade
&lt;/h2&gt;

&lt;p&gt;Four 2026 changes can bite a cluster that has been quiet. This script covers the two you can detect from the API. The other two need a look at your nodes and your release notes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# preflight.sh: run with cluster-admin credentials&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"== 1. Is ingress-nginx still running?"&lt;/span&gt;
kubectl get pods &lt;span class="nt"&gt;--all-namespaces&lt;/span&gt; &lt;span class="nt"&gt;--selector&lt;/span&gt; app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;ingress-nginx

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"== 2. Services that still set spec.externalIPs"&lt;/span&gt;
kubectl get svc &lt;span class="nt"&gt;--all-namespaces&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; json &lt;span class="se"&gt;\&lt;/span&gt;
  | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.items[]
           | select((.spec.externalIPs // []) | length &amp;gt; 0)
           | "\(.metadata.namespace)/\(.metadata.name)"'&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"== 3. Client and server versions"&lt;/span&gt;
kubectl version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ingress NGINX is retired
&lt;/h3&gt;

&lt;p&gt;The Kubernetes project said &lt;a href="https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/" rel="noopener noreferrer"&gt;best-effort maintenance of Ingress NGINX would continue until March 2026&lt;/a&gt;. After that there would be no releases, no bug fixes and no security updates, although existing deployments keep working. That date has passed, and the &lt;a href="https://github.com/kubernetes/ingress-nginx" rel="noopener noreferrer"&gt;GitHub repository now shows it as archived on March 24, 2026&lt;/a&gt; and read-only. A &lt;a href="https://kubernetes.io/blog/2026/01/29/ingress-nginx-statement/" rel="noopener noreferrer"&gt;statement from the Steering and Security Response Committees&lt;/a&gt;, citing internal Datadog research, put its use at about 50% of cloud native environments.&lt;/p&gt;

&lt;p&gt;The statement is blunt about the cost of waiting: staying on a retired controller leaves you and your users vulnerable to attack, and none of the alternatives is a direct drop-in replacement. Install a Gateway API controller next to Ingress NGINX, translate your routes (the project's ingress2gateway tool &lt;a href="https://kubernetes.io/blog/2026/03/20/ingress2gateway-1-0-release/" rel="noopener noreferrer"&gt;reached 1.0 in March 2026&lt;/a&gt;), test, then move traffic over gradually.&lt;/p&gt;

&lt;p&gt;Review the translated output by hand. The ingress2gateway 1.0 post shows the tool warning that it &lt;a href="https://kubernetes.io/blog/2026/03/20/ingress2gateway-1-0-release/" rel="noopener noreferrer"&gt;does not support the&lt;/a&gt; &lt;code&gt;configuration-snippet&lt;/code&gt; &lt;a href="https://kubernetes.io/blog/2026/03/20/ingress2gateway-1-0-release/" rel="noopener noreferrer"&gt;annotation&lt;/a&gt;, and the &lt;a href="https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/" rel="noopener noreferrer"&gt;retirement notice&lt;/a&gt; names the "snippets" annotations, which add arbitrary NGINX configuration directives, as an option now considered a serious security flaw. Rebuild what each snippet did with Gateway API features instead of copying it across.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service externalIPs is deprecated
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;.spec.externalIPs&lt;/code&gt; field was &lt;a href="https://kubernetes.io/blog/2026/05/14/kubernetes-v1-36-deprecation-and-removal-of-service-externalips/" rel="noopener noreferrer"&gt;formally deprecated in 1.36&lt;/a&gt; because it assumes every user in the cluster is trusted, which enables the attacks described in CVE-2020-8554. A future minor release will drop the behavior from kube-proxy and require conformant implementations not to support it.&lt;/p&gt;

&lt;p&gt;If the preflight script prints anything, plan a replacement. The same post calls a hand-assigned &lt;code&gt;LoadBalancer&lt;/code&gt; IP the easiest option and also the worst, because users who may set it can still replicate the CVE. It lists two better routes: a load balancer controller such as MetalLB, or a Gateway whose address you set in &lt;code&gt;.spec.addresses&lt;/code&gt;. As a precaution, enable the &lt;code&gt;DenyServiceExternalIPs&lt;/code&gt; admission controller so nobody adds new uses.&lt;/p&gt;

&lt;h3&gt;
  
  
  cgroup v1 nodes will not start
&lt;/h3&gt;

&lt;p&gt;Support for cgroup v2 has been stable since 1.25, and cgroup v1 went into maintenance mode in 1.31. Starting with 1.35, the kubelet option &lt;code&gt;failCgroupV1&lt;/code&gt; defaults to &lt;code&gt;true&lt;/code&gt;, so &lt;a href="https://kubernetes.io/blog/2026/10/06/kubernetes-cgroups-v2-shift/" rel="noopener noreferrer"&gt;the kubelet refuses to start on a cgroup v1 node&lt;/a&gt; unless you set it to &lt;code&gt;false&lt;/code&gt;, a temporary override while removal is tracked in KEP-5573. On each node, &lt;code&gt;stat -fc %T /sys/fs/cgroup&lt;/code&gt; prints &lt;code&gt;cgroup2fs&lt;/code&gt; for v2 and &lt;code&gt;tmpfs&lt;/code&gt; for v1. Fix every v1 node before the upgrade, not during it.&lt;/p&gt;

&lt;h3&gt;
  
  
  SELinux volume labeling changes
&lt;/h3&gt;

&lt;p&gt;In 1.37 the &lt;code&gt;SELinuxMount&lt;/code&gt; and &lt;code&gt;SELinuxChangePolicy&lt;/code&gt; features &lt;a href="https://kubernetes.io/blog/2026/08/26/kubernetes-v1-37-release/" rel="noopener noreferrer"&gt;reached Stable and are enabled by default&lt;/a&gt;. Volumes then mount with one SELinux context instead of being relabeled recursively, but only for CSI drivers that opt in with &lt;code&gt;.spec.seLinuxMount: true&lt;/code&gt;. Pods with different SELinux labels that share a volume on one node can therefore fail to start.&lt;/p&gt;

&lt;p&gt;The release notes advise setting &lt;code&gt;.spec.seLinuxChangePolicy&lt;/code&gt; to &lt;code&gt;Recursive&lt;/code&gt; on a Pod to keep the old behavior, and they say clusters without SELinux see no effect. If your nodes enforce SELinux, as on the RHEL family, read the project's post on &lt;a href="https://kubernetes.io/blog/2026/04/22/breaking-changes-in-selinux-volume-labeling/" rel="noopener noreferrer"&gt;SELinux volume label changes and their implications in 1.37&lt;/a&gt; before upgrading, and test any workload where Pods share a volume.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where AI workloads fit
&lt;/h2&gt;

&lt;p&gt;The same CNCF survey found that &lt;a href="https://www.cncf.io/announcements/2026/01/20/kubernetes-established-as-the-de-facto-operating-system-for-ai-as-production-use-hits-82-in-2025-cncf-annual-cloud-native-survey/" rel="noopener noreferrer"&gt;66% of organizations hosting generative AI models use Kubernetes for some or all of their inference&lt;/a&gt;. It also found that only 7% of organizations deploy models daily and that 44% do not yet run AI or ML workloads on Kubernetes. Most teams are early, which makes the platform choices you make now easy to get right and expensive to redo.&lt;/p&gt;

&lt;p&gt;The baseline in this post is the right foundation for an inference service, with one change: GPUs and other devices should be requested through Dynamic Resource Allocation, not through the old device-plugin counters. &lt;a href="https://kubernetes.io/blog/2025/09/01/kubernetes-v1-34-dra-updates/" rel="noopener noreferrer"&gt;DRA reached GA in 1.34&lt;/a&gt;, and in 1.37 the &lt;code&gt;ResourceClaim&lt;/code&gt; &lt;code&gt;.status.devices&lt;/code&gt; field &lt;a href="https://kubernetes.io/blog/2026/08/26/kubernetes-v1-37-release/" rel="noopener noreferrer"&gt;graduated to Stable&lt;/a&gt;, which lets drivers report device-specific status. Read the DRA concept pages before designing GPU scheduling.&lt;/p&gt;

&lt;h2&gt;
  
  
  A seven-day rollout plan
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Day&lt;/th&gt;
&lt;th&gt;Do this&lt;/th&gt;
&lt;th&gt;Done when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Run preflight.sh, check node cgroup versions, list your supported-version dates&lt;/td&gt;
&lt;td&gt;You know which of the four 2026 changes apply to you&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Apply steps 1 to 3 and 5 to 6 in a staging namespace&lt;/td&gt;
&lt;td&gt;rollout status succeeds and the HPA reports metrics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Install a Gateway API controller in staging, create gateway-system and the TLS Secret, then apply step 4&lt;/td&gt;
&lt;td&gt;The HTTPRoute shows Accepted and ResolvedRefs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Apply step 7 and add one egress rule per real dependency&lt;/td&gt;
&lt;td&gt;A blocked test Pod fails and the app still works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Enable hostUsers: false on one workload&lt;/td&gt;
&lt;td&gt;The Pod starts and passes its probes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Drain a node and watch the PodDisruptionBudget&lt;/td&gt;
&lt;td&gt;Drain completes with at most one api Pod down at a time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Upgrade staging one minor version, then production&lt;/td&gt;
&lt;td&gt;Both clusters pass preflight.sh on the new version&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Closing notes
&lt;/h2&gt;

&lt;p&gt;None of this requires a new tool. Every manifest above is plain Kubernetes, and every feature labeled Stable is safe to depend on. Features labeled Beta, such as HPA scale to zero, are on by default in 1.37, but they can still change, so pin your cluster version and read the release notes before each upgrade.&lt;/p&gt;

&lt;p&gt;Managed Kubernetes services often lag the upstream release by weeks or months. Run &lt;code&gt;kubectl version&lt;/code&gt; and check your provider's release calendar before assuming a 1.37 feature is available to you. The upstream support dates in this post apply to the community project, and your provider may set its own.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Published via &lt;a href="https://devstories.blog/kubernetes-in-2026-what-it-is-how-it-works-and-a-production-baseline-you-can-apply-today-0eg0q?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=syndication" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt; — Write once in Markdown, auto-backup to GitHub, and syndicate to Dev.to, Medium &amp;amp; Hashnode in 1 click.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>kubernetesarchitecture</category>
      <category>kubernetesbestpractices</category>
    </item>
    <item>
      <title>Googlebook: Google's Biggest Laptop Bet Since the Chromebook</title>
      <dc:creator>DevStories</dc:creator>
      <pubDate>Fri, 16 Oct 2026 09:59:51 +0000</pubDate>
      <link>https://dev.to/devstories_fca96eb46af114/googlebook-googles-biggest-laptop-bet-since-the-chromebook-47d4</link>
      <guid>https://dev.to/devstories_fca96eb46af114/googlebook-googles-biggest-laptop-bet-since-the-chromebook-47d4</guid>
      <description>&lt;p&gt;Fifteen years ago, Google convinced the world that a laptop could be little more than a browser. It was cheap, it booted in seconds, and it quietly took over classrooms. Now the company is asking for belief in a very different idea: a laptop whose most important feature isn't the chip, the screen, or even the operating system. It's the cursor.&lt;/p&gt;

&lt;p&gt;Meet the &lt;strong&gt;Googlebook&lt;/strong&gt;. It was announced on May 12 at The Android Show, opened for pre-order on September 21, and went on sale in the US on October 4, with Canada, the UK, Ireland, France, Germany and Australia following on October 5. The hardware is here. The real question is whether the idea behind it is any good.&lt;/p&gt;

&lt;p&gt;A quick note on sources: what follows rests on Google's own announcements, partner details and early press coverage. Independent, long-term testing is still thin, so treat the big promises accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Googlebook actually is
&lt;/h2&gt;

&lt;p&gt;A Googlebook is a laptop that runs Googlebook OS, a new Android-based system that Google says blends the best of Android with the best of ChromeOS. From Android it takes the Google Play app catalog and a modern, AI-ready foundation. From ChromeOS it takes Chrome and its extension ecosystem.&lt;/p&gt;

&lt;p&gt;Google's own framing is revealing. Its pitch is that computing is moving from an operating system to an intelligence system, the same way the Chromebook once represented a shift to cloud-first computing. In plain terms: the Chromebook assumed the cloud did the work. The Googlebook assumes an AI model sits next to everything you do and helps in real time.&lt;/p&gt;

&lt;p&gt;It's also a break in Google's hardware strategy. Google's last laptop under its own name was the Pixelbook Go, roughly six and a half years ago. This time Google leads on software and design language, and partners build the machines.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cursor is the product
&lt;/h2&gt;

&lt;p&gt;If you remember one feature, make it &lt;strong&gt;Magic Pointer&lt;/strong&gt;. Google built it with its DeepMind team, and the idea is disarmingly simple: wiggle your cursor, and Gemini looks at whatever you're pointing at and offers to help.&lt;/p&gt;

&lt;p&gt;The examples Google has shown are deliberately mundane, which is exactly why they matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Point at a date inside an email, and Gemini offers to set up a meeting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select two images, and Gemini offers to compare or combine them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use ask, compare and combine actions across whatever is on screen, without opening a separate chatbot window.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a genuinely different interaction model. Most AI on laptops today lives in a sidebar or a dedicated key: you stop what you're doing, switch context, explain your situation, and paste things back and forth. Magic Pointer flips that. The context is already on screen, so the pointer carries it for you.&lt;/p&gt;

&lt;p&gt;There are two companions. &lt;strong&gt;Create My Widget&lt;/strong&gt; lets you describe a dashboard in natural language and have Gemini assemble it from the web, Gmail and Calendar. And early launch coverage describes &lt;strong&gt;Rambler&lt;/strong&gt;, a dedicated key that turns speech into structured text in real time.&lt;/p&gt;

&lt;p&gt;If these work as shown, they remove friction that has quietly annoyed everyone for years. If they don't, the Googlebook is a Chromebook with a nicer chassis.&lt;/p&gt;

&lt;h2&gt;
  
  
  The phone is the other half of the pitch
&lt;/h2&gt;

&lt;p&gt;The most underrated part of this launch isn't AI at all. It's continuity.&lt;/p&gt;

&lt;p&gt;Google is positioning the Googlebook as the natural partner for an Android phone, much like a Mac relates to an iPhone:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quick Access&lt;/strong&gt; lets you browse, search and insert files from your phone directly in the laptop's file browser, with no manual transfers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cast My Apps&lt;/strong&gt; streams your phone's apps onto the laptop screen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Continue On&lt;/strong&gt; lets you pick up phone activity on the laptop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt; brings over your saved passwords, Wi-Fi networks and settings when you sign in.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apple has owned this story for over a decade, and it's a big reason people stay inside its ecosystem. Android has had pieces of it, but never a laptop that treats the phone as a first-class citizen from the first boot. That is Google's real opening. A billion-plus Android owners are a far larger audience than people who actively want an AI laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hardware: five makers, one glowing strip
&lt;/h2&gt;

&lt;p&gt;The launch lineup comes from Acer, ASUS, Dell, HP and Lenovo, using Intel and Qualcomm chips with neural processing units for on-device AI. Every model carries the &lt;strong&gt;Glowbar&lt;/strong&gt;, an illuminated strip on the exterior that works as a deliberate brand signature, the way the Chromebook's logo did for the last decade.&lt;/p&gt;

&lt;p&gt;Here's the lineup based on launch reports, with US starting prices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Acer Googlebook 14&lt;/strong&gt; from $899: the entry point, with Intel Core Ultra 5 or 7, 16 GB of RAM and a 14-inch 2.8K OLED convertible display.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dell XPS Googlebook&lt;/strong&gt; from $1,199: a 13.4-inch 2.5K touchscreen in a machined aluminum chassis, with Snapdragon X Elite.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;HP Googlebook 14&lt;/strong&gt; from $1,299: Snapdragon X Elite and a 14-inch 2.8K OLED panel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ASUS Googlebook 14&lt;/strong&gt; from $1,299: Intel-powered, with a 32 GB option and a haptic touchpad.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lenovo Googlebook 15&lt;/strong&gt;: the large-screen option, with a 15.3-inch OLED display. Reported pricing varies between sources, so check the retailer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The price floor is the clearest signal of Google's intent. At $899 and up, this is not a cheap-and-cheerful Chromebook. Google is aiming at premium buyers and putting itself next to Apple's low-cost MacBooks and Windows Copilot+ PCs. Launch coverage also mentions bundled extras, including a year of Google AI Pro, though bundles can differ by region and retailer, so verify before you buy.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, is the Chromebook dead?
&lt;/h2&gt;

&lt;p&gt;Google has been careful here. It describes the Googlebook as a new category, not a Chromebook replacement, and it has said existing Chromebooks will keep receiving updates through their current support commitments. In practice, most observers read it as the Chromebook's premium successor, and it's hard to argue otherwise: the naming, the Glowbar and the Chrome-plus-Android DNA all point the same way.&lt;/p&gt;

&lt;p&gt;What's still unclear is the lower end. The Chromebook's superpower was never prestige. It was a $250 machine that made computers affordable for schools and families. A product that starts at $899 doesn't serve that audience, and Google hasn't yet explained who will.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the Googlebook will be judged
&lt;/h2&gt;

&lt;p&gt;Four tests will decide whether this launch matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Does Magic Pointer survive real life?&lt;/strong&gt; Demos are curated. The real test is a messy inbox, a crowded desktop and a half-finished document. If the pointer suggests the right thing most of the time, it becomes a habit. If it interrupts, people will switch it off within a week.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Do Android apps feel native on a big screen?&lt;/strong&gt; Google is already pushing developers to design for desktop-class screens, with better information density, full keyboard, mouse, trackpad, stylus and controller support, custom cursors, plus proper file handling and printing. That's the right list. But Android apps stretched onto a laptop have a poor track record, and the Googlebook's value depends on apps that look and behave like they belong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Does the value math work?&lt;/strong&gt; Memory and component costs are high in 2026, and the Googlebook has to justify its premium against mature alternatives. Features that only help if you already live in Google's ecosystem will narrow the audience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Do the gaps get filled?&lt;/strong&gt; Early comparison pieces note practical limits, such as no direct OneDrive support in the Files app, and questions about how freely you can run multiple instances of the same app. Availability is also limited for now to the seven launch markets, which leaves much of the world waiting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should care right now
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Android power users&lt;/strong&gt; who already juggle files and messages between phone and laptop will feel the benefit first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gemini and Google Workspace regulars&lt;/strong&gt; get the most from Magic Pointer, since the best examples lean on Gmail, Calendar and Google apps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developers&lt;/strong&gt; should treat this as a nudge to polish large-screen and input handling. Googlebook support is also good for the wider Android tablet and foldable experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cautious buyers&lt;/strong&gt; should wait for independent reviews. A first-generation platform with a headline AI feature is the classic case where the second batch of reviews is more useful than the first.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;The Googlebook is the most ambitious thing Google has done in personal computing in years, and it's ambitious in the right place. Rather than bolting a chatbot onto a laptop, Google is rethinking the most basic interaction on the machine, pointing at things, and pairing it with a phone relationship that rivals can't easily copy.&lt;/p&gt;

&lt;p&gt;Whether it becomes as significant as the Chromebook did in 2011 depends on one thing: whether Gemini feels useful when you're not watching a keynote. If the pointer earns its place in your daily routine, Google has a new category. If it doesn't, it has an expensive Chromebook with a glowing stripe.&lt;/p&gt;

&lt;p&gt;We'll know within a few months. For now, it's the most interesting laptop launch of the year, and a reminder that the next big shift in computing may not come from a new screen or chip, but from the humble cursor.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Published via &lt;a href="https://devstories.blog/googlebook-google-s-biggest-laptop-bet-since-the-chromebook-ro50m?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=syndication" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt; — Write once in Markdown, auto-backup to GitHub, and syndicate to Dev.to, Medium &amp;amp; Hashnode in 1 click.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>chromebook</category>
      <category>gemini</category>
      <category>googlebook</category>
    </item>
  </channel>
</rss>
