<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Yaml on vishctl</title><link>https://vishctl.dev/tags/yaml/</link><description>Recent content in Yaml on vishctl</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 06 Sep 2026 03:00:00 +0800</lastBuildDate><atom:link href="https://vishctl.dev/tags/yaml/index.xml" rel="self" type="application/rss+xml"/><item><title>Kubernetes is Adding a K to YAML: Why KYAML Makes Sense</title><link>https://vishctl.dev/posts/kubernetes-kyaml/</link><pubDate>Sun, 06 Sep 2026 03:00:00 +0800</pubDate><guid>https://vishctl.dev/posts/kubernetes-kyaml/</guid><category>kubernetes</category><category>yaml</category><category>devops</category><description>Kubernetes 1.37 makes KYAML stable: how flow style eliminates silent type coercion, removes load-bearing indentation, and how to try it.</description><content:encoded><![CDATA[<p>Kubernetes 1.37 (&ldquo;Garhwal&rdquo;) just made KYAML Stable. YAML with a K bolted on, and it&rsquo;s a genuinely useful feature.</p>
<h2 id="the-problem">The problem</h2>
<p>YAML has two well known landmines.</p>
<p><strong>Type coercion.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">country</span><span class="p">:</span><span class="w"> </span><span class="kc">NO</span><span class="w">      </span><span class="c"># becomes boolean false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="kc">yes</span><span class="w">     </span><span class="c"># becomes boolean true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="m">3.10</span><span class="w">    </span><span class="c"># becomes float 3.1</span><span class="w">
</span></span></span></code></pre></div><p>Those values were meant to be strings. YAML quietly turned them into something else.</p>
<p><strong>Whitespace as structure.</strong> Indentation defines meaning in normal YAML. Get one space wrong and the file still parses. It just means something else now, silently.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">containers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">app</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="m">80</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">TCP  </span><span class="w"> </span><span class="c"># one space off, this attaches to the wrong container</span><span class="w">
</span></span></span></code></pre></div><p>No error. No warning. Just wrong.</p>
<p>Helm makes this worse, since you&rsquo;re injecting indentation from outside the YAML context and hoping it lines up.</p>
<h2 id="what-kyaml-actually-changes">What KYAML actually changes</h2>
<p>Nothing about the language. It&rsquo;s YAML&rsquo;s existing &ldquo;flow style,&rdquo; just enforced. Every KYAML file is valid YAML. Old tooling, old parsers, old <code>kubectl</code> versions all read it fine.</p>
<p>Three rules: objects use <code>{ }</code>, arrays use <code>[ ]</code>, strings are always quoted. Numbers and booleans stay bare, since they&rsquo;re actually meant to be those types.</p>
<p>One example, everything at once:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># before</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apps/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">api</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">replicas</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">automountServiceAccountToken</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">hostNetwork</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">containers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">app</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">nginx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="m">8080</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">env</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">REGION</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="kc">NO</span><span class="w">
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># after (KYAML)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;apps/v1&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Deployment&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;api&#34;</span><span class="w"> </span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w"> </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">replicas</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">template</span><span class="p">:</span><span class="w"> </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w"> </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">automountServiceAccountToken</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">hostNetwork</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">containers</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;app&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;nginx&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">ports</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>{<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="m">8080</span><span class="w"> </span>}<span class="p">],</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">env</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>{<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;REGION&#34;</span><span class="nt">, value</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;NO&#34;</span><span class="w"> </span>}<span class="p">],</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">],</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl">}<span class="w">
</span></span></span></code></pre></div><p>Everything in one shot:</p>
<ul>
<li><code>{ }</code> for objects (<code>metadata</code>, <code>spec</code>, each container)</li>
<li><code>[ ]</code> for arrays (<code>containers</code>, <code>ports</code>, <code>env</code>)</li>
<li>strings always quoted (<code>&quot;api&quot;</code>, <code>&quot;nginx&quot;</code>, <code>&quot;REGION&quot;</code>)</li>
<li><code>replicas: 2</code> and <code>containerPort: 8080</code> stay bare, they&rsquo;re real numbers</li>
<li><code>automountServiceAccountToken: false</code> and <code>hostNetwork: true</code> stay bare, they&rsquo;re real booleans</li>
<li><code>value: &quot;NO&quot;</code> is quoted, because it&rsquo;s a string that would otherwise get read as <code>false</code></li>
</ul>
<p>KYAML doesn&rsquo;t remove types, it just stops guessing which one you meant.</p>
<h2 id="why-it-matters">Why it matters</h2>
<p>Since structure comes from <code>{ }</code> and <code>[ ]</code>, not from spaces, indentation stops being load bearing. Squash a KYAML file onto one line and it means exactly the same thing. That kills the Helm whitespace problem outright.</p>
<h2 id="trying-it">Trying it</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">kubectl get deployment api -o kyaml
</span></span></code></pre></div><p>Convert existing files:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">go install github.com/google/yamlfmt/cmd/yamlfmt@latest
</span></span><span class="line"><span class="cl">yamlfmt --kyaml manifest.yaml
</span></span></code></pre></div><p>Also ships as a pre-commit hook and a Docker image for CI.</p>
<p>Nothing forces the switch. Plain YAML keeps working. Mixed repos, some converted, some not, are fine.</p>
<p>My plan if I touch this on a real repo: one directory first, verify round-trip parsing, check Helm and Kustomize don&rsquo;t reformat it differently, then expand once it&rsquo;s boring.</p>
<p>Not required. Cheap upgrade. Worth exploring.</p>
<p>For a broader breakdown of what else landed in this release, check out my notes on <a href="https://vishctl.dev/posts/kubernetes-v1-37-stability/">Kubernetes v1.37: An Operator&rsquo;s Look at Garhwal</a>.</p>
]]></content:encoded></item></channel></rss>