<?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: MetalBear</title>
    <description>The latest articles on DEV Community by MetalBear (@metalbear).</description>
    <link>https://dev.to/metalbear</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.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10935%2F5e6a0e22-733f-4582-8243-d0dfdbc47bba.png</url>
      <title>DEV Community: MetalBear</title>
      <link>https://dev.to/metalbear</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/metalbear"/>
    <language>en</language>
    <item>
      <title>A Beginner's Guide to Helm</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Wed, 03 Jun 2026 12:25:24 +0000</pubDate>
      <link>https://dev.to/metalbear/a-beginners-guide-to-helm-5fj0</link>
      <guid>https://dev.to/metalbear/a-beginners-guide-to-helm-5fj0</guid>
      <description>&lt;p&gt;The &lt;a href="https://www.cncf.io/wp-content/uploads/2026/01/CNCF_Annual_Survey_Report_final.pdf" rel="noopener noreferrer"&gt;CNCF Annual Survey&lt;/a&gt; published in January 2026 showed that Helm is the second most used CNCF project, second only to Kubernetes itself. The reason is simple: once you start working with Kubernetes, YAML files accumulate fast and managing them keeps getting harder. A single microservice can require a Deployment, a Service, a ConfigMap, and a Secret, and that's before accounting for the different sets you’ll need for your development, staging, and production environments. Helm fixes this by packaging all of your manifests into a single, versioned unit that can be installed, upgraded, and rolled back easily.&lt;/p&gt;

&lt;p&gt;In this guide, we'll cover what Helm is, some key concepts, and the main Helm commands you need to know to deploy and manage manifests using it. You’ll walk away with a complete understanding of how to use Helm so you can simplify the YAML mess you might be in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prerequisite: &lt;a href="https://metalbear.com/blog/kubernetes-guide/" rel="noopener noreferrer"&gt;Basic familiarity with Kubernetes&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is Helm in Kubernetes?
&lt;/h2&gt;

&lt;p&gt;Helm is a package manager for Kubernetes. Just as &lt;code&gt;apt&lt;/code&gt; manages software packages on Linux or &lt;code&gt;brew&lt;/code&gt; does on macOS, Helm manages Kubernetes applications and lets you install, upgrade, and roll them back as versioned, reusable units called charts.&lt;/p&gt;

&lt;p&gt;The way Helm solves the YAML management problem is easiest to understand through a programming analogy. Bare Kubernetes manifests work fine for a single, static deployment. But the moment you need multiple similar deployments (dev, staging, prod, which may differ only by a few values), you're essentially copy-pasting. Helm solves this the same way classes solve it in &lt;a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Advanced_JavaScript_objects/Object-oriented_programming" rel="noopener noreferrer"&gt;object-oriented programming:&lt;/a&gt; you define the boilerplate once in a chart, which can include things like the Deployment template, the Service definition, the ConfigMap structure, and then each Helm chart deployment only specifies what's different: the image, the environment variables, the command being run in the pods. Someone installing your chart can also supply their own values file and get a correctly configured deployment for their use case without touching the original templates.&lt;/p&gt;

&lt;p&gt;Like Kubernetes, Helm is declarative. You describe which chart to install and what values to pass in and Helm figures out how to get the cluster there and keeps it in that state.&lt;/p&gt;

&lt;p&gt;Helm is built around three core concepts: Charts, Releases, and Repositories. We'll look at each of these next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Charts
&lt;/h3&gt;

&lt;p&gt;A chart is a self-contained package of Kubernetes resource manifests. It defines everything needed to deploy an application (the Deployment, the Service, the ConfigMap, etc.) along with default values for any configurable settings. When you install a chart, Helm uses those templates and values to generate the actual Kubernetes manifests and applies them to your cluster.&lt;/p&gt;

&lt;p&gt;Charts can also declare dependencies on other charts, called subcharts. This makes it possible to build composable application definitions, for example, a chart for a web application might pull in a chart for PostgreSQL and another for Redis rather than having manifests for those dependencies within it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Releases
&lt;/h3&gt;

&lt;p&gt;Each time you install a chart, Helm creates a release which is a named instance of that chart running in your cluster. If you install the same chart three times under different names, you get three independent releases, each with its own configuration, its own Kubernetes resources, and its own revision history.&lt;/p&gt;

&lt;p&gt;It's important to understand that releases are what Helm actually manages. Helm doesn't think in terms of individual deployments or Helm charts when it comes to a Kubernetes cluster. Instead, it tracks releases and uses them to know what's deployed, what version it's at, and how to upgrade or roll back.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repositories
&lt;/h3&gt;

&lt;p&gt;A repository is a collection of charts hosted at an accessible URL. You add repositories to your local Helm installation and then install charts from them by name. The most widely used public index is &lt;a href="https://artifacthub.io" rel="noopener noreferrer"&gt;Artifact Hub&lt;/a&gt;, which aggregates charts from many sources. Most projects that run on Kubernetes publish an official Helm chart there, so in practice you'll rarely need to write a chart from scratch to deploy well-known software like nginx, PostgreSQL, or Prometheus. For example, we also publish a chart for the mirrord Kubernetes operator, which you can find on &lt;a href="https://artifacthub.io/packages/helm/metalbear/mirrord-operator" rel="noopener noreferrer"&gt;Artifact Hub here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Inside a Helm Chart
&lt;/h2&gt;

&lt;p&gt;When you clone or create a Helm chart (using &lt;code&gt;helm create chart-name&lt;/code&gt;), you get a directory with a specific structure. Here's what a typical chart looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-chart/
├── Chart.yaml
├── values.yaml
├── charts/
└── templates/
    ├── deployment.yaml
    ├── service.yaml
    ├── ...
    └── NOTES.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Chart.yaml&lt;/code&gt; is the chart's metadata file. It declares the chart's name, version, and description, and optionally lists dependencies on other charts.&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="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2&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;my-chart&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A Helm chart for my application&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.1.0&lt;/span&gt;
&lt;span class="na"&gt;appVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;apiVersion&lt;/code&gt; here refers to the Helm chart API version, not the Kubernetes API. &lt;code&gt;v2&lt;/code&gt; means the chart requires at least Helm 3 (don’t ask me why they couldn’t have made it simple by just having v3 for Helm 3). If you come across a chart with &lt;code&gt;v1&lt;/code&gt;, it was written for Helm 2, which had a different chart format but Helm 3 and later versions still support v1 for backward compatibility.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;version&lt;/code&gt; is the version of the chart itself. This follows &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;semantic versioning&lt;/a&gt; and should be bumped whenever you change the chart by doing things like adding a new template, changing a default value, or updating dependencies. It's independent of what the chart deploys.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;appVersion&lt;/code&gt; is the version of the application the chart deploys. This is purely for documentation and nothing else since Helm doesn't use it to pull images or make any decisions. You'd typically set it to the container image tag your chart defaults to, so users can tell at a glance what version of the application they're getting. You can update &lt;code&gt;appVersion&lt;/code&gt; without changing &lt;code&gt;version&lt;/code&gt;, and vice versa.&lt;/p&gt;

&lt;p&gt;A good way to think about it is that &lt;code&gt;appVersion&lt;/code&gt; tracks the version of the application being deployed, while &lt;code&gt;version&lt;/code&gt; tracks releases of the chart itself. If your application is upgraded from 1.0.0 to 1.1.0, you'd update &lt;code&gt;appVersion&lt;/code&gt; to reflect that change. If the chart's default image tag is also updated, you'd typically bump the chart &lt;code&gt;version&lt;/code&gt; as well, since the chart itself has changed. But if you only modify the chart (for example by adding a new template, changing default values, or updating dependencies) while continuing to deploy the same application version, you'd bump &lt;code&gt;version&lt;/code&gt; and leave &lt;code&gt;appVersion&lt;/code&gt; unchanged.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;values.yaml&lt;/code&gt; contains the default configuration for the chart. These are the values users can override at install time. For example:&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="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.25"&lt;/span&gt;
&lt;span class="na"&gt;replicaCount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;templates/&lt;/code&gt; is where the Kubernetes manifests live. Unlike regular YAML, these files use &lt;a href="https://docs.gomplate.ca/syntax/" rel="noopener noreferrer"&gt;Go template syntax&lt;/a&gt;, which lets Helm inject values into them at render time. A template referencing the values above would look like this:&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="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="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Values.replicaCount&lt;/span&gt; &lt;span class="pi"&gt;}}&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;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;app&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Values.image.repository&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;:{{ .Values.image.tag }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When someone installs this chart and passes &lt;code&gt;--set image.tag=1.26&lt;/code&gt;, Helm substitutes that value before applying the manifest to the cluster. This is the mechanism that makes a single chart work across environments without touching the templates themselves.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;charts/&lt;/code&gt; is where subchart dependencies are bundled. If your chart depends on PostgreSQL, for example, the PostgreSQL chart will live in this folder.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NOTES.txt&lt;/code&gt; is a template file that Helm renders and prints to the terminal after a successful install. Charts typically use it to show how to connect to or use what was just deployed. This is what a simple &lt;code&gt;NOTES.txt&lt;/code&gt; could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thanks for installing {{ .Chart.Name }}.

To get more info, try:

  $ helm status {{ .Release.Name }}
  $ helm get all {{ .Release.Name }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating Your Own Chart
&lt;/h3&gt;

&lt;p&gt;Running &lt;code&gt;helm create my-chart&lt;/code&gt; scaffolds the directory structure we just walked through, with sensible defaults already filled in. The generated &lt;code&gt;values.yaml&lt;/code&gt; comes pre-populated with common settings like &lt;code&gt;replicaCount&lt;/code&gt;, &lt;code&gt;image.repository&lt;/code&gt;, and &lt;code&gt;image.tag&lt;/code&gt;, and &lt;code&gt;templates/&lt;/code&gt; includes a Deployment, Service, Ingress, and a few other Kubernetes resources you might need.&lt;/p&gt;

&lt;p&gt;The first thing to do after generating the chart is update &lt;code&gt;values.yaml&lt;/code&gt; to reflect your application. Change the &lt;code&gt;image.repository&lt;/code&gt; to point to your container image, set a default &lt;code&gt;tag&lt;/code&gt;, and remove any values that don't apply. The generated defaults are based on a generic nginx deployment, so most of them will need adjusting.&lt;/p&gt;

&lt;p&gt;The templates themselves often need less work. The generated Deployment and Service are wired up to the values in &lt;code&gt;values.yaml&lt;/code&gt; using the &lt;code&gt;{{ .Values.* }}&lt;/code&gt; syntax we saw earlier, so once your values are correct, the templates usually render correctly without modification. If your application has specific Kubernetes resources it needs that aren’t present or configured in the &lt;code&gt;templates/&lt;/code&gt; directory already, then you'd add those or modify the existing relevant template.&lt;/p&gt;

&lt;p&gt;Once you've made your changes, run &lt;code&gt;helm lint my-chart&lt;/code&gt; to catch mistakes like invalid YAML, missing required fields, broken template syntax. Then run &lt;code&gt;helm template my-chart&lt;/code&gt; to render the templates locally and review the exact Kubernetes manifests that would be applied to the cluster. This is the step where you verify your values are flowing into the right places before anything touches the cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Helm Commands
&lt;/h2&gt;

&lt;p&gt;Let's now walk through some common commands you’ll find yourself using when working with Helm. Before you can install a chart, you need to add the repository it lives in. &lt;code&gt;helm repo add&lt;/code&gt; registers a repository under a local name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add metalbear https://metalbear-co.github.io/charts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once added, run &lt;code&gt;helm repo update&lt;/code&gt; to pull the latest chart index from all registered repositories. Charts are versioned and updated frequently, so it's worth running this before installing. To find a chart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm search repo mirrord-operator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns matching charts with their versions and descriptions. You can also browse &lt;a href="https://artifacthub.io" rel="noopener noreferrer"&gt;Artifact Hub&lt;/a&gt; to discover charts. Each listing there shows the &lt;code&gt;helm repo add&lt;/code&gt; command you need.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;helm install&lt;/code&gt; deploys a chart as a named release:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm &lt;span class="nb"&gt;install &lt;/span&gt;mirrord-operator metalbear/mirrord-operator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Helm renders the chart's templates, applies the resulting manifests to the cluster, and begins tracking the deployment as a release named &lt;code&gt;mirrord-operator&lt;/code&gt;. It also prints the chart's &lt;code&gt;NOTES.txt&lt;/code&gt; which typically has instructions for what to do after installing the chart.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The chart used in the example above installs the &lt;a href="https://metalbear.com/mirrord/docs/getting-started/installing-mirrord/operator" rel="noopener noreferrer"&gt;mirrord operator&lt;/a&gt; which allows multiple developers to develop against the same cluster when using &lt;a href="https://metalbear.com/mirrord/" rel="noopener noreferrer"&gt;mirrord&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To see all releases currently running in the cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To inspect a specific release and see its status and revision number:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm status mirrord-operator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Customizing with Values
&lt;/h3&gt;

&lt;p&gt;By default, &lt;code&gt;helm install&lt;/code&gt; uses the values defined in the chart's &lt;code&gt;values.yaml&lt;/code&gt;. You can override them in two ways. For quick changes, use &lt;code&gt;--set&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm &lt;span class="nb"&gt;install &lt;/span&gt;mirrord-operator metalbear/mirrord-operator &lt;span class="nt"&gt;--set&lt;/span&gt; license.key&lt;span class="o"&gt;=&lt;/span&gt;ABC-DEF-GHI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For environment-specific configuration, a values file is easier to manage. Create a &lt;code&gt;custom-values.yaml&lt;/code&gt; with only the values you want to override, then pass it with &lt;code&gt;-f&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm &lt;span class="nb"&gt;install &lt;/span&gt;mirrord-operator metalbear/mirrord-operator &lt;span class="nt"&gt;-f&lt;/span&gt; values.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When both are used together, &lt;code&gt;--set&lt;/code&gt; takes precedence over &lt;code&gt;-f&lt;/code&gt;, which takes precedence over the chart's &lt;code&gt;values.yaml&lt;/code&gt; defaults. To see all the values a chart allows you to configure you can run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm show values metalbear/mirrord-operator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you want to update a release to a newer chart version and/or change its values use &lt;code&gt;helm upgrade&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm upgrade mirrord-operator metalbear/mirrord-operator &lt;span class="nt"&gt;--set&lt;/span&gt; limits.cpu&lt;span class="o"&gt;=&lt;/span&gt;400m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Helm applies only what changed, creates a new revision, and preserves the previous one. To see the full revision history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm &lt;span class="nb"&gt;history &lt;/span&gt;mirrord-operator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an upgrade causes problems, &lt;code&gt;helm rollback&lt;/code&gt; reverts a release to an earlier revision:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm rollback mirrord-operator 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's important to understand that a rollback creates a new revision rather than deleting the failed one which means the history stays intact so you can always see what happened.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;helm uninstall&lt;/code&gt; removes all Kubernetes resources that belong to a release:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm uninstall mirrord-operator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, Helm also deletes the release's history. To keep it for auditing or future rollbacks, pass &lt;code&gt;--keep-history&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Helm Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do I have to use Helm with Kubernetes?
&lt;/h3&gt;

&lt;p&gt;You don't strictly need Helm. For a simple application that doesn't change much, managing it with raw &lt;code&gt;kubectl apply&lt;/code&gt; and plain YAML manifests works fine. Where Helm becomes worth it is when you're managing multiple environments, deploying the same application more than once, or distributing your application for others to run. Then maintaining separate YAML files per environment costs more in terms of time and effort than just learning Helm.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I deploy a Helm Chart on Kubernetes?
&lt;/h3&gt;

&lt;p&gt;First, add the repository the chart lives in and update your local index. Then install the chart with &lt;code&gt;helm install&lt;/code&gt;, giving the release a name and pointing to the chart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add metalbear https://metalbear-co.github.io/charts
helm repo update
helm &lt;span class="nb"&gt;install &lt;/span&gt;mirrord-operator metalbear/mirrord-operator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the chart requires custom configuration, pass values with &lt;code&gt;--set&lt;/code&gt; for quick overrides or &lt;code&gt;-f your-values.yaml&lt;/code&gt; for a full config file. After installing, &lt;code&gt;helm list&lt;/code&gt; shows all running releases and &lt;code&gt;helm status &amp;lt;release-name&amp;gt;&lt;/code&gt; gives details on a specific one. The Common Helm Commands section above covers all of this in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;In this guide, we covered the fundamentals of Helm: charts, releases, and repositories, how chart structure works, and the commands you'll use day to day. These basics are enough to install and manage existing charts and start writing your own charts. If you want to go deeper from here, working toward a Helm certification like &lt;a href="https://training.linuxfoundation.org/skillcred/helm/" rel="noopener noreferrer"&gt;Developing Helm Charts (SC104)&lt;/a&gt; can be a good way to continue learning Helm. For this and other topics the &lt;a href="https://helm.sh/docs/" rel="noopener noreferrer"&gt;official Helm documentation&lt;/a&gt; is the best place to go.&lt;/p&gt;

&lt;p&gt;Or if you don’t want to prepare for a certification but want to learn how to make managing multiple charts across multiple environments easier, &lt;a href="https://helmfile.readthedocs.io/" rel="noopener noreferrer"&gt;Helmfile&lt;/a&gt; is the natural next tool to look at. It lets you declaratively define a set of Helm releases as a single unit, with per-environment values and deployment ordering.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>containers</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Four Layers of Validation in Kubernetes with Claude Code</title>
      <dc:creator>Jake Page</dc:creator>
      <pubDate>Thu, 21 May 2026 13:37:08 +0000</pubDate>
      <link>https://dev.to/metalbear/four-layers-of-validation-in-kubernetes-with-claude-code-175k</link>
      <guid>https://dev.to/metalbear/four-layers-of-validation-in-kubernetes-with-claude-code-175k</guid>
      <description>&lt;p&gt;Earlier this year, Moltbook, a social network for AI agents, launched, trended, and became a cautionary tale within the same week. Security researchers at Wiz &lt;a href="https://www.wiz.io/blog/exposed-moltbook-database-reveals-millions-of-api-keys" rel="noopener noreferrer"&gt;found a Supabase API key&lt;/a&gt; sitting in its client-side JavaScript, which was the database’s only access control, with no Row Level Security to narrow what that key could reach. The result: 1.5 million API tokens, 35,000 email addresses, and thousands of private messages exposed to anyone with a browser console.&lt;/p&gt;

&lt;p&gt;Moltbook was a greenfield project with no review process. The same class of mistake is far more serious when AI-generated code lands inside applications that already have pre-existing users, real data, and an existing trust surface. That’s &lt;a href="https://www.businessinsider.com/google-ai-generated-code-75-gemini-agents-software-2026-4" rel="noopener noreferrer"&gt;increasingly the reality&lt;/a&gt;: as organizations adopt AI coding agents, more and more AI-generated code is landing directly in production services that already hold credentials and personal details of your users. A &lt;a href="https://talent500.com/blog/ai-generated-code-trust-and-verification-gap/" rel="noopener noreferrer"&gt;recent survey&lt;/a&gt; found that 95% of developers don’t fully trust AI-generated code, while only 48% consistently review it before committing, yet it’s shipping regardless.&lt;/p&gt;

&lt;p&gt;Static review tools catch only some classes of issues: common CVEs, dependency hygiene, style violations, deterministic anti-patterns. What they can’t see are things like the actual name of your Kubernetes Secret in this cluster, whether your auth middleware is wired into the right route in this service, whether the request a real user will send makes it through the new code path without breaking something downstream.&lt;/p&gt;

&lt;p&gt;Closing that gap takes four independent layers: &lt;em&gt;AI agent skills&lt;/em&gt; that shape what gets generated, &lt;em&gt;commands&lt;/em&gt; that audit what was generated, &lt;em&gt;integration tests&lt;/em&gt; that hit staging endpoints, routing traffic to your local code, and &lt;em&gt;preview environments&lt;/em&gt; that let a human review the change against staging dependencies before merging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 1: Skills (passive, shaping what gets generated)
&lt;/h2&gt;

&lt;p&gt;Most AI coding assistants let you write down rules that shape generation. The simplest mechanism is a config file that the assistant loads into context on every prompt: &lt;code&gt;.cursorrules&lt;/code&gt; in Cursor, &lt;code&gt;CLAUDE.md&lt;/code&gt; in Claude Code, &lt;code&gt;.github/copilot-instructions.md&lt;/code&gt; in GitHub Copilot. Drop NEVER/ALWAYS rules in there and the AI follows them. The downside is that those files load on every prompt, even when you’re working on something unrelated, and every rule you add costs tokens whether or not it’s relevant.&lt;/p&gt;

&lt;p&gt;Claude Code goes a step further with &lt;strong&gt;skills&lt;/strong&gt;: structured rule sets that ship as plugins (a directory with a &lt;code&gt;SKILL.md&lt;/code&gt; and supporting reference files). Each skill has a description, and the model pulls a skill into context only when your prompt matches what that skill is meant to cover. If a skill never gets matched against the prompt, it never gets loaded, and you don’t pay for the tokens it would consume. We’ve already shipped &lt;a href="https://metalbear.com/blog/claude-code-skills-for-kubernetes/" rel="noopener noreferrer"&gt;six skills for AI agents working with mirrord&lt;/a&gt;, and this post adds a seventh focused on validation: &lt;a href="https://github.com/metalbear-co/k8s-validation-plugin" rel="noopener noreferrer"&gt;k8s-validation&lt;/a&gt;, an open-source set of NEVER/ALWAYS rules for code that runs inside a Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;The skill covers two halves: the cluster-level concerns (Secrets, RBAC, pod hardening, NetworkPolicies, supply chain, file handling) and the application-level concerns that determine whether the workload behaves correctly inside the cluster (HTTP and parameter handling, auth, output sanitisation, API contracts, env-var configuration, test coverage).&lt;/p&gt;

&lt;h3&gt;
  
  
  Before and after
&lt;/h3&gt;

&lt;p&gt;Without the skill, the model has no way of knowing about things like Kubernetes Secrets already mounted as environment variables in your pod, auth decorators other handlers in your service already use, or PII-sanitization utilities your team has already built. So it does the obvious thing: hardcodes the API key, skips the auth check, and returns the LLM output directly. With the skill loaded, the following prompt (“add a &lt;code&gt;/summarise&lt;/code&gt; endpoint that calls OpenAI’s API”) produces something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;utils.sanitize&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;filter_pii&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/summarise&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nd"&gt;@require_auth&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summarise&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarise: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;filter_pii&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;filter_pii&lt;/code&gt; here is a stand-in for any utility that strips personally identifiable information (names, SSNs, emails, etc.) out of free text. Different teams build this differently; the &lt;a href="https://github.com/microsoft/presidio" rel="noopener noreferrer"&gt;Microsoft Presidio&lt;/a&gt; library is one of the more common open-source starting points.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Three differences from what the model would produce without the skill: the key comes from an environment variable backed by a Kubernetes Secret, the endpoint sits behind &lt;code&gt;@require_auth&lt;/code&gt;, and the LLM output runs through &lt;code&gt;filter_pii&lt;/code&gt; before going back to the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  What skills can’t do
&lt;/h3&gt;

&lt;p&gt;Skills shape generation, but they don’t verify anything.&lt;/p&gt;

&lt;p&gt;In the example above, the AI correctly followed the skill: it read the API key from the environment, applied &lt;code&gt;@require_auth&lt;/code&gt;, and called &lt;code&gt;filter_pii&lt;/code&gt; from &lt;code&gt;utils.sanitize&lt;/code&gt;. But the skill has no way to verify that &lt;code&gt;filter_pii&lt;/code&gt; actually works. If the utility in your codebase only strips email addresses and misses phone numbers, the skill can’t know that. A user document containing a phone number sails straight through the filter and into the response, and the code looks correct at every layer the skill can see.&lt;/p&gt;

&lt;p&gt;Skills set a floor by preventing the obvious structural mistakes. They’re instructions to a model, not checks against reality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 2: Commands (active, checking what was generated)
&lt;/h2&gt;

&lt;p&gt;Where skills shape what the model generates, commands check what already exists. They’re explicitly invoked by a developer, an agent, or a CI step, and they run a defined set of checks against the code in front of them.&lt;/p&gt;

&lt;p&gt;The same install from Layer 1 also ships a slash command: &lt;code&gt;/k8s-validation:audit&lt;/code&gt;. It scans your codebase for the same NEVER/ALWAYS rules the skill enforces during generation, traces data flow through handlers and queries, and classifies each finding by severity. Skills don’t always load (a vague prompt, or a quick edit to a file the model didn’t classify as Kubernetes-adjacent, and the rules never enter context). The audit is the backstop: it runs on the code regardless of how the code got written.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; /k8s-validation:audit content-api/

CRITICAL 2 | HIGH 4 | MEDIUM 1 | INFO 0

[CRITICAL] src/routes/summarise.py: Hardcoded OpenAI API key → Use os.environ
[CRITICAL] src/routes/download.py: User filename in path without sanitization → Use secure_filename()
[HIGH]     src/routes/summarise.py: No authentication middleware → Add @require_auth
[HIGH]     k8s/deployment.yaml: No SecurityContext defined → Add runAsNonRoot, drop ALL
[HIGH]     src/routes/summarise.py: Reads OPENAI_API_KEY but no manifest defines it → Add to deployment.yaml env block
[HIGH]     src/routes/summarise.py: New endpoint with no integration test → Add test in tests/integration/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the output mixes security findings (hardcoded key, missing SecurityContext) with correctness findings, meaning “does the code do what was asked, given the rest of the system” (the Kubernetes deployment manifest doesn’t define the env var the code reads; the new endpoint shipped without an integration test). Both halves matter for AI-generated code.&lt;/p&gt;

&lt;p&gt;Because the audit is a command you run rather than a rule the model loads, the same invocation works in three places: a developer runs it before opening a PR, an agent runs it as part of its own loop after generating code, and CI runs it as a merge gate. You can wire it into one, two, or all three.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Validation Workflow&lt;/span&gt;
After generating or modifying any Kubernetes-related code, run &lt;span class="sb"&gt;`/k8s-validation:audit`&lt;/span&gt;
on the changed files. If any CRITICAL findings exist, fix them before proceeding.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What commands can’t do
&lt;/h3&gt;

&lt;p&gt;The audit is still static analysis. It can find “you hardcoded a secret” or “you’re missing a SecurityContext,” but it can’t tell you whether your &lt;code&gt;filter_pii&lt;/code&gt; regex actually catches the PII your users will send, or whether the environment variable you’re reading will resolve to a value in your staging cluster. Commands check the shape of the code, not the behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 3: Integration tests (runtime, proving it works)
&lt;/h2&gt;

&lt;p&gt;Your team probably already has integration tests that hit your API endpoints, check response shapes, and verify that authentication rejects bad credentials. These tests encode what “correct behavior” actually means for your application.&lt;/p&gt;

&lt;p&gt;The bottleneck is running them. Locally, you mock your database, your auth service, your message queue, and hope the mocks match reality. In CI, each cycle takes 5 to 10 minutes. For a human pushing a few times a day, it’s already frustrating enough. For an AI agent trying to fix a failing test, it’s a feedback loop far too slow to learn from: the agent burns tokens on every iteration, and the integration bugs only surface after the change has been written, pushed, and built.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metalbear.com/mirrord/" rel="noopener noreferrer"&gt;mirrord&lt;/a&gt; changes this equation by letting your local process stand in for a deployed pod. Your local code gets the environment variables from the target pod, the same cluster-level files it has access to, and the same view of internal services. In &lt;a href="https://metalbear.com/mirrord/docs/using-mirrord/incoming-traffic/steal-https" rel="noopener noreferrer"&gt;steal mode&lt;/a&gt;, traffic destined for the targeted pod is intercepted and routed to your local process instead of whatever’s deployed in staging. Your existing integration tests, pointed at staging endpoints as usual, now run against your local code in seconds, not minutes.&lt;/p&gt;

&lt;p&gt;The same pattern scales horizontally. Because mirrord can split a single pod’s incoming traffic between many local processes using header-based filters, multiple agents (or developers) can iterate against the same staging cluster simultaneously, each one routing its own slice of the traffic to its own local code. One staging environment, many concurrent agents, real downstream services for all of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this catches that the other layers can’t
&lt;/h3&gt;

&lt;p&gt;Consider a prompt like “have &lt;code&gt;/summarise&lt;/code&gt; fetch the document from our content-store service first.” The agent writes a handler that calls &lt;code&gt;http://content-store/documents/{id}&lt;/code&gt; and reads &lt;code&gt;response.json()["title"]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The catch: content-store moved to v2 months ago and now returns &lt;code&gt;{"document": {"name": ..., "text": ...}}&lt;/code&gt;. The flat title/body shape only exists in the AI’s training data. Skills generated structurally clean code (good). The audit confirmed the call was made and the response was consumed (also good). Neither layer knows what shape &lt;code&gt;content-store&lt;/code&gt; actually returns today.&lt;/p&gt;

&lt;p&gt;The setup to fix this is two processes. You or your AI agent starts a mirrord session, your e2e tests run as normal against the staging content-api endpoint:&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;# Terminal 1, run your local content-api in place of the deployed pod&lt;/span&gt;
mirrord &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--target&lt;/span&gt; deploy/content-api &lt;span class="nt"&gt;--steal&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; python &lt;span class="nt"&gt;-m&lt;/span&gt; content_api

&lt;span class="c"&gt;# Terminal 2, run the existing integration suite against staging as usual&lt;/span&gt;
pytest tests/integration/test_summarise.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the test hits staging’s &lt;code&gt;content-api&lt;/code&gt; endpoint, mirrord steals the request and reroutes it to your local process. The local handler calls &lt;code&gt;http://content-store/documents/...&lt;/code&gt;, and that outbound call also routes through mirrord, hitting the real content-store in staging. The real service returns &lt;code&gt;{"document": {"name": ..., "text": ...}}&lt;/code&gt;. The local code does &lt;code&gt;response.json()["title"]&lt;/code&gt; and crashes with &lt;code&gt;KeyError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You fix the code to read the new shape, rerun the test, it passes. The bug surfaces in your local code, against real downstream services, in seconds, instead of after a deploy cycle. The same pattern works for any other dependency the code touches: environment variables from the pod, files from mounted volumes, database queries against the real Postgres. mirrord runs your code, the cluster supplies its real environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 4: Human review in a real environment
&lt;/h2&gt;

&lt;p&gt;When the agent opens the PR, a human should still get to see the change running in a real environment, not just read the diff. mirrord’s &lt;a href="https://metalbear.com/mirrord/preview-environments/" rel="noopener noreferrer"&gt;Preview environments&lt;/a&gt; make that easy: a GitHub Action spins up an isolated pod in your staging cluster running the PR’s code, connected to all the real downstream services, and scoped to that PR via an environment key. &lt;/p&gt;

&lt;p&gt;Reviewers can click through the actual feature instead of inferring behavior from the code or having to run the whole application locally. Most of the failures the previous three layers don’t catch, UX regressions, surprising interactions, “looks right but feels wrong”, show up the first time a human uses the thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together: agents handle layers 1–3, humans handle layer 4
&lt;/h2&gt;

&lt;p&gt;Layers 1 through 3 can be run by the agent itself. Instead of generating code, opening a PR, and hoping CI catches the issues, the agent generates code shaped by skills, runs &lt;code&gt;/k8s-validation:audit&lt;/code&gt; to check for structural issues, runs the integration tests via mirrord against real infrastructure, and fixes any failures before committing. The agent doesn’t even have to write the test from scratch: Layer 1’s validation skill includes a rule that any new HTTP handler must come with an integration test, so the test gets generated alongside the endpoint. Layer 3 just runs it against real infrastructure.&lt;/p&gt;

&lt;p&gt;Layer 4 is the handoff. Once the agent has passed its own checks, it opens a PR and a human gets a live preview environment to click through rather than a diff to infer from. The failures that surface at that stage, UX regressions, surprising interactions, things that look right but feel wrong are exactly the ones that didn’t show up in the previous three layers.&lt;/p&gt;

&lt;p&gt;We’ve documented the concrete setup (per-service mirrord configs, helper scripts, and an &lt;code&gt;AGENTS.md&lt;/code&gt; that tells the agent which script to run) in our &lt;a href="https://metalbear.com/mirrord/docs/use-cases/using-mirrord-with-ai" rel="noopener noreferrer"&gt;mirrord with AI agents guide&lt;/a&gt;. The broader argument for why this matters, including the token cost of agents stuck in a feedback-less loop, is in &lt;a href="https://metalbear.com/blog/how-to-prevent-token-burn-using-mirrord-with-e2e-tests/" rel="noopener noreferrer"&gt;How to prevent token burn using mirrord with e2e tests&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adopting the layers
&lt;/h2&gt;

&lt;p&gt;The four layers are independent. Pick the ones that close your biggest gap and add the others when the next failure teaches you what’s still missing.&lt;/p&gt;

&lt;p&gt;Install the validation skill with &lt;code&gt;/plugin install k8s-validation@metalbear-co/k8s-validation-plugin&lt;/code&gt; in Claude Code, or as a local rules directory for Cursor and GitHub Copilot (see the &lt;a href="https://github.com/metalbear-co/k8s-validation-plugin" rel="noopener noreferrer"&gt;repo README&lt;/a&gt;). The &lt;code&gt;/k8s-validation:audit&lt;/code&gt; command ships in the same install. For the runtime layer, &lt;a href="https://metalbear.com/mirrord/docs/getting-started/what-is-mirrord" rel="noopener noreferrer"&gt;install mirrord&lt;/a&gt; and wrap your local service with &lt;code&gt;mirrord exec --target deploy/&amp;lt;service&amp;gt; --steal -- &amp;lt;run-command&amp;gt;&lt;/code&gt;. For preview environments on each PR, the feature is included in &lt;a href="https://metalbear.com/mirrord/preview-environments/" rel="noopener noreferrer"&gt;mirrord for Teams&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Each layer closes a different gap. Stop at any point and you’ve made things better than they were.&lt;/p&gt;

&lt;p&gt;The skills are open source. If your AI assistant generates something the skills don’t catch, &lt;a href="https://github.com/metalbear-co/k8s-validation-plugin" rel="noopener noreferrer"&gt;open a PR&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>ai</category>
      <category>software</category>
      <category>programming</category>
    </item>
    <item>
      <title>Six Claude Code Skills That Close the AI Agent Feedback Loop</title>
      <dc:creator>Eyal Bukchin</dc:creator>
      <pubDate>Wed, 13 May 2026 16:56:14 +0000</pubDate>
      <link>https://dev.to/metalbear/six-claude-code-skills-that-close-the-ai-agent-feedback-loop-10bb</link>
      <guid>https://dev.to/metalbear/six-claude-code-skills-that-close-the-ai-agent-feedback-loop-10bb</guid>
      <description>&lt;p&gt;AI agents write code that compiles, runs locally, and breaks the first time it touches your Kubernetes cluster. The cluster is full of state the model never sees: the env vars on the running pod, the schema in your real Postgres, the headers your upstream &lt;code&gt;auth-service&lt;/code&gt; sends, the topics your consumer subscribes to. Without that context, the code an agent writes for your live infrastructure is informed guessing, whether you're shipping a new feature or fixing a regression.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metalbear.com/mirrord/" rel="noopener noreferrer"&gt;mirrord&lt;/a&gt; closes that gap. It runs a local process as if it were a real pod inside your cluster: real env vars, real DNS, real network, optionally real inbound traffic. A real example: &lt;a href="https://metalbear.com/mirrord/case-study/daylight/" rel="noopener noreferrer"&gt;Daylight Security&lt;/a&gt; pairs Cursor with mirrord for daily development. Their team cut their typical edit-test cycle from 5–8 minutes to about 5 seconds. The reason isn't faster CPUs; it's that the agent now operates against the real cluster the way a senior engineer would, instead of guessing from logs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We recently shipped six &lt;a href="https://agentskills.io" rel="noopener noreferrer"&gt;Agent Skills&lt;/a&gt; that teach AI agents how and when to use mirrord. The whole bundle installs in one command.&lt;/strong&gt;&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;# Claude Code&lt;/span&gt;
/plugin marketplace add metalbear-co/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Any Agent Skills consumer&lt;/span&gt;
npx skills add metalbear-co/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what each skill does, with a concrete prompt that triggers it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;code&gt;mirrord-quickstart&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Zero-to-first-session for engineers (and agents) who have never used mirrord. Detects your OS, walks through CLI install or VS Code / IntelliJ setup, finds your target pod in the cluster, runs your first session. Your local process can now reach every service, database, and queue in the cluster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "I'm new to mirrord, help me run my Node app against my staging cluster."&lt;/p&gt;

&lt;p&gt;The agent installs mirrord, lists targets in your namespace, picks a likely match, and runs &lt;code&gt;mirrord exec --target … -- node server.js&lt;/code&gt;. No copy-paste from docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;code&gt;mirrord-config&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Generates and validates &lt;code&gt;mirrord.json&lt;/code&gt;, which tells mirrord what to do and where to do it. mirrord's config surface is wide: traffic stealing vs mirroring, filesystem modes, env injection, target selection, database and queue behavior. The skill turns "I want X behavior" into valid config without you opening the docs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "Steal traffic from &lt;code&gt;pod/api-server&lt;/code&gt;, but only requests carrying my baggage header so I don't break anyone else's session."&lt;/p&gt;

&lt;p&gt;The agent writes the right config, validates it against the schema, and explains what it does. The interesting part: the skill covers the full &lt;code&gt;mirrord.json&lt;/code&gt; surface (target selection, traffic modes, env injection, file system hooks), not just filters. Filtered steal is one of the things that lets multiple developers share one cluster without colliding, but it's only one of the patterns mirrord-config knows how to set up.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;code&gt;mirrord-operator&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Sets up the &lt;a href="https://metalbear.com/mirrord/docs/" rel="noopener noreferrer"&gt;mirrord Operator&lt;/a&gt; for teams. Mirroring traffic from a pod is concurrency-safe out of the box; you only need the operator when multiple developers want to &lt;em&gt;steal&lt;/em&gt; the same pod's traffic with different filters, share branched databases, or split a Kafka topic. The operator brokers session boundaries, RBAC, and the routing rules that make those interactions work without collisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "Install the operator on our EKS cluster and configure RBAC so only the &lt;code&gt;dev&lt;/code&gt; group can use it."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://monday.com" rel="noopener noreferrer"&gt;monday.com&lt;/a&gt; runs 350+ engineers on a single shared staging cluster this way. The operator is what makes that scale work: concurrent filtered steal so multiple devs share one pod, queue splitting so they share one SQS topic, DB branching so they share one database, RBAC so they don't touch workloads they shouldn't, and the rest of the routing rules that let 350 developers work on the same cluster at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;code&gt;mirrord-ci&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Run integration tests in CI in isolation against your staging cluster, instead of spinning up an ephemeral test environment for each PR. The service under test runs in the CI runner with mirrord; mirrord steals the cluster traffic destined for it and routes it to your build, so test traffic follows the same path it would in production, with only that one service swapped. That catches the integration bugs mocks miss, with one shared staging cluster instead of one ephemeral cluster per PR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "Set up GitHub Actions to run our integration tests against the staging cluster."&lt;/p&gt;

&lt;p&gt;The agent writes the workflow, injects your kubeconfig from a secret, sets &lt;code&gt;MIRRORD_CI_API_KEY&lt;/code&gt;, and wires &lt;code&gt;mirrord ci start&lt;/code&gt; around your service and &lt;code&gt;mirrord ci stop&lt;/code&gt; in the cleanup hook.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;code&gt;mirrord-db-branching&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Per-developer database branches. Copy-on-write Postgres (or &lt;a href="https://metalbear.com/mirrord/docs/sharing-the-cluster/db-branching" rel="noopener noreferrer"&gt;any supported DB&lt;/a&gt;), so two engineers can develop against "the same" database without stepping on each other's writes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "Give me an isolated DB branch off the staging Postgres for this feature."&lt;/p&gt;

&lt;p&gt;The agent provisions the branch via the operator, points your local process at the branch, and tears down when the session ends. No more "who deleted the test users?" Slack threads.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;code&gt;mirrord-kafka&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Kafka queue splitting. Each developer gets a slice of the topic that only they consume, while the original consumer keeps running in the cluster. Lets you run a real Kafka workload locally without intercepting messages other people care about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "Set up queue splitting on the &lt;code&gt;orders.created&lt;/code&gt; topic for my local consumer."&lt;/p&gt;

&lt;p&gt;The agent configures the operator's Kafka splitter, gives your local process a per-developer consumer group, and confirms message routing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Claude Code&lt;/span&gt;
/plugin marketplace add metalbear-co/skills

&lt;span class="c"&gt;# Any Agent Skills consumer&lt;/span&gt;
npx skills add metalbear-co/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;a href="https://github.com/metalbear-co/skills" rel="noopener noreferrer"&gt;github.com/metalbear-co/skills&lt;/a&gt;. Issues and PRs welcome; we ship updates fast.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>ai</category>
      <category>claude</category>
      <category>devops</category>
    </item>
    <item>
      <title>New Features We Find Exciting in the Kubernetes 1.34 Release</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Thu, 04 Sep 2025 10:54:31 +0000</pubDate>
      <link>https://dev.to/metalbear/new-features-we-find-exciting-in-the-kubernetes-134-release-2mhl</link>
      <guid>https://dev.to/metalbear/new-features-we-find-exciting-in-the-kubernetes-134-release-2mhl</guid>
      <description>&lt;p&gt;The Kubernetes 1.34 release, “Of Wind &amp;amp; Will (O’ WaW)”, sets sail with a collection of features that may not grab headlines, but instead improve the day-to-day experience of running and managing clusters. Think of it as steady winds filling the sails, incremental but powerful improvements that help cluster administrators navigate smoother waters. And since combing through the full release notes can feel like charting a course through rough seas, we’ve pulled together some of the most useful highlights from this release to keep you on course.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2z3iv9f5knxws01l7rk3.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2z3iv9f5knxws01l7rk3.png" alt="Kubernetes 1.34 logo" width="720" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Features Moving to Stable: Anchored and Ready for the Voyage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dynamic Resource Allocation with Structured Parameters
&lt;/h3&gt;

&lt;p&gt;Today where most companies are running (or trying to) run AI workloads on Kubernetes, we feel this feature is going to be the most important one from this release. &lt;/p&gt;

&lt;p&gt;Before this change, Kubernetes didn’t really “see” specialized hardware devices like GPUs. Instead, the device drivers running on each node were responsible for keeping track of hardware availability and assigning it to pods. Kubernetes itself had no awareness of what devices existed, how many were available, or where they were located.&lt;/p&gt;

&lt;p&gt;This lack of visibility introduced a number of challenges. For example, if two pods requested a GPU on the same node, the driver had to resolve the conflict on its own, without the scheduler knowing what was going on. Sharing GPU resources across pods was equally messy, since Kubernetes couldn’t reason about device capacity or availability and only knew that a pod needed “a GPU,” not whether the hardware was free or oversubscribed.&lt;/p&gt;

&lt;p&gt;With Kubernetes v1.34, this changes. The new &lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/" rel="noopener noreferrer"&gt;Dynamic Resource Allocation (DRA)&lt;/a&gt; framework, along with by structured parameters, lets Kubernetes manage specialized hardware devices directly. Structured parameters let hardware drivers describe the exact capabilities and constraints of a device in a standardized format that Kubernetes can understand. For example, instead of just saying “this node has 1 GPU,” the driver can specify details like GPU memory, supported features, or whether the device can be shared across multiple pods.&lt;/p&gt;

&lt;p&gt;With this feature, instead of drivers silently handling everything, they now publish available devices as Kubernetes objects called &lt;code&gt;ResourceSlice&lt;/code&gt;. These slices describe what hardware exists on each node and expose details that Kubernetes can use to make better scheduling decisions.&lt;/p&gt;

&lt;p&gt;In other words, Kubernetes is no longer “blind” to hardware like GPUs, it can see what’s available, allocate it fairly, and even support sharing more reliably. Here’s a simple example:&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="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;resource.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;ResourceSlice&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;resourceslice&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;nodeName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker-1&lt;/span&gt;
  &lt;span class="na"&gt;pool&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;gpu-pool&lt;/span&gt;
    &lt;span class="na"&gt;generation&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;resourceSliceCount&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;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dra.example.com&lt;/span&gt;
  &lt;span class="na"&gt;sharedCounters&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;gpu-memory&lt;/span&gt;
      &lt;span class="na"&gt;counters&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="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8Gi&lt;/span&gt;
  &lt;span class="na"&gt;devices&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;gpu-1&lt;/span&gt;
      &lt;span class="na"&gt;consumesCounters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;counterSet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gpu-memory&lt;/span&gt;
          &lt;span class="na"&gt;counters&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="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8Gi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example shows a single GPU on node &lt;code&gt;worker-1&lt;/code&gt;, grouped into a pool called &lt;code&gt;gpu-pool&lt;/code&gt;. The GPU has 8 GB of memory, published through &lt;code&gt;sharedCounters&lt;/code&gt;. Because this information is now visible to Kubernetes, the scheduler knows exactly how much memory the device provides and can place pods accordingly, instead of relying on the driver to manage it behind the scenes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Allowing Only Anonymous Authentication for Configured Endpoints
&lt;/h3&gt;

&lt;p&gt;With Kubernetes v1.34, you can now safely expose specific API server endpoints like &lt;code&gt;/healthz&lt;/code&gt;, &lt;code&gt;/readyz&lt;/code&gt;, and &lt;code&gt;/livez&lt;/code&gt; without accidentally granting broader anonymous access.&lt;/p&gt;

&lt;p&gt;By default, Kubernetes treats unauthenticated requests as anonymous, assigning them the identity &lt;code&gt;system:anonymous&lt;/code&gt; and group &lt;code&gt;system:unauthenticated&lt;/code&gt;. While this design supports useful cases such as health checks, it also comes with risks. If a &lt;code&gt;RoleBinding&lt;/code&gt; or &lt;code&gt;ClusterRoleBinding&lt;/code&gt; is accidentally applied to &lt;code&gt;system:anonymous&lt;/code&gt;, even unauthenticated code running in a pod could gain access to the API server. &lt;/p&gt;

&lt;p&gt;The new update fixes scenarios like these by giving administrators fine-grained control over which paths are available to anonymous users. Instead of having to disable anonymous access entirely, which can break important functionality, you can now define a safe list of allowed endpoints using the new &lt;code&gt;AuthenticationConfiguration&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Here’s an example:&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="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apiserver.config.k8s.io/v1beta1&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;AuthenticationConfiguration&lt;/span&gt;
&lt;span class="na"&gt;anonymous&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&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;conditions&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="s"&gt;/livez&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this configuration, anonymous requests are permitted only to the health check endpoints, while all other anonymous requests are denied, even if misconfigured RoleBindings exist. &lt;/p&gt;

&lt;h3&gt;
  
  
  Relaxed DNS Search String Validation
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;dnsConfig.searches&lt;/code&gt; field in a Pod manifest controls how short hostnames are resolved. If your pod looks up &lt;code&gt;myserver&lt;/code&gt;, Kubernetes will automatically append each domain listed under &lt;code&gt;dnsConfig.searches&lt;/code&gt; and try them in order. For example, &lt;code&gt;myserver.first-domain&lt;/code&gt;, then &lt;code&gt;myserver.second-domain&lt;/code&gt;, and so on until it finds a match. This mechanism is especially important when migrating legacy applications into Kubernetes since many older services rely on custom DNS search domains, sometimes with underscores (&lt;code&gt;_&lt;/code&gt;) or leading dots (&lt;code&gt;.&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;Until now, Kubernetes didn’t allow these in &lt;code&gt;dnsConfig.searches&lt;/code&gt;, which meant some services simply couldn’t be deployed without changing their DNS assumptions which is a task that can be both risky and time-consuming.&lt;/p&gt;

&lt;p&gt;With Kubernetes v1.34, these restrictions are lifted. You can now include underscores and dots in DNS search domains, which makes it much easier to bring legacy workloads into Kubernetes without rewriting configurations or service names.&lt;/p&gt;

&lt;p&gt;Here’s what that looks like in practice:&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="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;Pod&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;app-1&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;app-1&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;nginx&lt;/span&gt;
  &lt;span class="na"&gt;dnsPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;None"&lt;/span&gt;
  &lt;span class="na"&gt;dnsConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nameservers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;10.244.0.69&lt;/span&gt;
    &lt;span class="na"&gt;searches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;abc_d.staging.com&lt;/span&gt;  &lt;span class="c1"&gt;# Now valid&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;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;Pod&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;app-2&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;app-2&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;nginx&lt;/span&gt;
  &lt;span class="na"&gt;dnsPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;None"&lt;/span&gt;
  &lt;span class="na"&gt;dnsConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nameservers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;10.244.0.69&lt;/span&gt;
    &lt;span class="na"&gt;searches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;   &lt;span class="c1"&gt;# Now valid&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;default.svc.cluster.local&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;svc.cluster.local&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster.local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app-1&lt;/code&gt; can now resolve fully qualified names like &lt;code&gt;test.abc_d.staging.com&lt;/code&gt; without issue.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app-2&lt;/code&gt; can use the special &lt;code&gt;"."&lt;/code&gt; search entry to resolve hostnames exactly as written **before Kubernetes appends cluster defaults like &lt;code&gt;svc.cluster.local&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So to sum up, if you’re migrating older workloads or working with services that depend on unconventional DNS naming conventions, Kubernetes no longer forces you to rework your DNS setup. &lt;/p&gt;

&lt;h2&gt;
  
  
  Features Moving to Beta: Stronger Winds Filling the Sails
&lt;/h2&gt;

&lt;h3&gt;
  
  
  PreferSameNode Traffic Distribution
&lt;/h3&gt;

&lt;p&gt;Routing traffic efficiently in Kubernetes can be challenging, especially when services span multiple nodes or zones. By default, Kubernetes load-balances traffic across all healthy endpoints of a service, even if some are farther away. This can create unnecessary cross-node or cross-zone hops, which add latency and waste bandwidth. For many workloads, especially latency-sensitive applications like real-time inference, gaming backends, or high-throughput APIs, those extra hops can noticeably hurt performance.&lt;/p&gt;

&lt;p&gt;Kubernetes v1.34 introduces new traffic distribution policies to address this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PreferSameNode&lt;/code&gt;: Services can now prefer pods on the same node when the traffic originates from that node. This reduces latency and avoids network overhead from cross-node traffic.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PreferSameZone&lt;/code&gt;: The existing &lt;code&gt;PreferClose&lt;/code&gt; policy has been renamed to &lt;code&gt;PreferSameZone&lt;/code&gt; to make its behavior clearer. This helps workloads prioritize pods in the same zone for lower latency and reduced cross-zone costs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an example of both in action:&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="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;http-echo-service-1&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;selector&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;http-echo-pod-1&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;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5678&lt;/span&gt;
  &lt;span class="na"&gt;trafficDistribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PreferSameNode&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;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;http-echo-service-2&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;selector&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;http-echo-pod-2&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;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5678&lt;/span&gt;
  &lt;span class="na"&gt;trafficDistribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PreferSameZone&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;http-echo-service-1&lt;/code&gt; routes traffic to a pod on the same node when possible. If none are available, it will fall back to another node.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http-echo-service-2&lt;/code&gt; routes traffic to a pod in the same zone first, and only if necessary, sends it to a different zone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  VolumeSource: OCI Artifact and/or Image
&lt;/h3&gt;

&lt;p&gt;In some deployments, multiple pods need access to the same configuration or data files. Traditionally, this might mean baking files into a ConfigMap or copying them into each pod, which can get messy as files grow larger or more complex.&lt;/p&gt;

&lt;p&gt;With Kubernetes v1.34, you now have a cleaner option: image volumes. This feature lets Kubernetes mount an OCI image as a read-only volume that can be shared across multiple pods. Instead of duplicating files or manually syncing them, you package the files once into an image and then mount them wherever they’re needed.&lt;/p&gt;

&lt;p&gt;Here’s an example:&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="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;Pod&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;nginx&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;nginx&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;nginx-container&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;nginx&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;80&lt;/span&gt;
    &lt;span class="na"&gt;env&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;POD_NAME&lt;/span&gt;
      &lt;span class="na"&gt;valueFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;fieldRef&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;v1&lt;/span&gt;
          &lt;span class="na"&gt;fieldPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;metadata.name&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;oci-volume&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;/data&lt;/span&gt;
      &lt;span class="na"&gt;subPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello.txt&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;oci-volume&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;/data/&lt;/span&gt;
      &lt;span class="na"&gt;subPathExpr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(POD_NAME).txt&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;oci-volume&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;reference&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;your-oci-image&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;oci-volume&lt;/code&gt; references an OCI image that contains files. The pod mounts specific files from that image, &lt;code&gt;hello.txt&lt;/code&gt;, into its container. Since the volume is read-only, multiple pods can safely share the same source without conflicts. &lt;/p&gt;

&lt;p&gt;For developers using &lt;a href="https://metalbear.co/mirrord/" rel="noopener noreferrer"&gt;mirrord&lt;/a&gt;, this also means that you can now run your local code against a pod that already mounts an image volume in the cluster. Your local process will gain the same access to the shared files, so you can test how your code interacts with the data without deploying or modifying the cluster setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features Moving to Alpha: New Currents on the Horizon
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Allows Setting any FQDN as the Pod's Hostname
&lt;/h3&gt;

&lt;p&gt;Prior to this feature, setting a pod’s fully qualified domain name (FQDN) wasn’t straightforward. You had to combine multiple fields: &lt;code&gt;hostname&lt;/code&gt;, &lt;code&gt;subdomain&lt;/code&gt;, and &lt;code&gt;setHostnameAsFQDN: true&lt;/code&gt;, to build an FQDN. The result always followed Kubernetes’ enforced pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;hostname&amp;gt;.&amp;lt;subdomain&amp;gt;.&amp;lt;namespace&amp;gt;.svc.&amp;lt;cluster-domain&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any part of that was misconfigured, the final FQDN wouldn’t resolve as expected. This could cause serious issues for systems that rely on strict hostname matching, such as &lt;a href="https://www.ibm.com/docs/en/aix/7.1.0?topic=network-kerberos" rel="noopener noreferrer"&gt;Kerberos&lt;/a&gt;, where authentication breaks if hostnames don’t line up exactly.&lt;/p&gt;

&lt;p&gt;This pain point is now addressed through a new field: &lt;code&gt;hostnameOverride&lt;/code&gt;. This field allows you to explicitly set the pod’s internal kernel hostname to whatever value you need, bypassing Kubernetes’ enforced DNS naming convention.&lt;/p&gt;

&lt;p&gt;Here’s an example:&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="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;Pod&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;app&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;hostnameOverride&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app.nginx.example.domain&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;app&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;nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this configuration, the pod’s internal hostname is set directly to &lt;code&gt;app.nginx.example.domain&lt;/code&gt;. Unlike before, you don’t need to stitch together multiple fields or follow Kubernetes’ strict naming rules. &lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways From Of Wind &amp;amp; Will Kubernetes Release
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;Of Wind &amp;amp; Will&lt;/em&gt; release is not about grand, sweeping changes, but it’s about steady progress. The kind of refinements that make Kubernetes a sturdier ship for the long journey ahead. One of the standout improvements is the graduation of Dynamic Resource Allocation (DRA), a huge step forward for teams running AI workloads. With DRA, Kubernetes finally gains proper visibility into GPUs and other specialized hardware, making scheduling and sharing these resources far more reliable. For anyone working on machine learning or high-performance computing, this is a game-changer.&lt;/p&gt;

&lt;p&gt;Security also gets tighter with more fine-grained anonymous access controls, ensuring only the right endpoints are exposed without weakening cluster safety. And for those migrating legacy systems, features like &lt;code&gt;hostnameOverride&lt;/code&gt; and expanded DNS search support smooth out long-standing pain points, making Kubernetes more welcoming to applications that weren’t originally built for it.&lt;br&gt;
Together, these updates may feel like adjustments to the rigging rather than rebuilding the ship, but that’s what makes them powerful. They reduce friction, close gaps, and make Kubernetes more adaptable to the real-world seas we sail in. With 1.34, the community hands cluster administrators and developers not just new features, but stronger winds and steadier will to keep moving forward.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloud</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
