<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://nativehub-chi.vercel.app/blog</id>
    <title>NativeHub Blog</title>
    <updated>2026-05-25T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://nativehub-chi.vercel.app/blog"/>
    <subtitle>Practical cloud native engineering, straight from the terminal.</subtitle>
    <icon>https://nativehub-chi.vercel.app/img/favicon.svg</icon>
    <rights>Copyright © 2026 NativeHub.</rights>
    <entry>
        <title type="html"><![CDATA[What is an OCI bundle? Understanding config.json and container runtimes]]></title>
        <id>https://nativehub-chi.vercel.app/blog/what-is-oci-bundle</id>
        <link href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle"/>
        <updated>2026-05-25T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[An OCI bundle is a rootfs directory plus a config.json. Here is what is inside that file — process, namespaces, mounts, capabilities — and how a runtime turns it into a running container.]]></summary>
        <content type="html"><![CDATA[<p>Container images get all the attention, but the thing a low-level runtime actually consumes is not
an image. It is a <strong>bundle</strong>: a directory on disk containing an extracted root filesystem and a
single JSON file. Understanding that file is the clearest possible explanation of what a container
is.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="image-and-bundle-are-different-things">Image and bundle are different things<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#image-and-bundle-are-different-things" class="hash-link" aria-label="Direct link to Image and bundle are different things" title="Direct link to Image and bundle are different things" translate="no">​</a></h2>
<p>The Open Container Initiative publishes three separate specifications, and it is worth being
precise about which does what:</p>
<table><thead><tr><th>Specification</th><th>Describes</th><th>Consumed by</th></tr></thead><tbody><tr><td><strong>Image spec</strong></td><td>The distributable artifact: layers, manifest, config, index</td><td>containerd, CRI-O, Podman</td></tr><tr><td><strong>Runtime spec</strong></td><td>The <em>bundle</em>: a <code>rootfs</code> directory plus <code>config.json</code></td><td>runc, crun, runsc, Kata</td></tr><tr><td><strong>Distribution spec</strong></td><td>The registry HTTP API for push and pull</td><td>GHCR, ECR, Docker Hub, Harbor</td></tr></tbody></table>
<p>The step between them is the one people miss. A container manager pulls an image, unpacks its layers
into a single directory, merges the image's config with any runtime overrides you supplied, and
writes the result as <code>config.json</code>. Only then does it hand the directory to a runtime.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">image (registry)  →  unpack layers + merge config  →  bundle (on disk)  →  runc  →  process</span><br></div></code></pre></div></div>
<p>An image can produce many bundles; a bundle is a single container's complete instructions.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="making-one-by-hand">Making one by hand<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#making-one-by-hand" class="hash-link" aria-label="Direct link to Making one by hand" title="Direct link to Making one by hand" translate="no">​</a></h2>
<p>This is the fastest way to make the abstraction real. It takes about a minute on any Linux host with
Docker and runc installed.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">mkdir</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-p</span><span class="token plain"> /tmp/bundle/rootfs </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;&amp;</span><span class="token plain"> </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">cd</span><span class="token plain"> /tmp/bundle</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># 1. Get a root filesystem. `docker export` flattens an image's layers into a tar.</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">export</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$(</span><span class="token string variable function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token string variable" style="color:hsl(221, 87%, 60%)"> create alpine:3.21</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">)</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">tar</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-C</span><span class="token plain"> rootfs </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-xf</span><span class="token plain"> -</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># 2. Generate a default config.json</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">runc spec</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">ls</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-la</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># config.json  rootfs/</span><br></div></code></pre></div></div>
<p>That is the entire bundle. Two entries:</p>
<ul>
<li class=""><strong><code>rootfs/</code></strong> — the filesystem the container will see as <code>/</code>.</li>
<li class=""><strong><code>config.json</code></strong> — everything else.</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> runc run demo</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># / # cat /etc/os-release</span><br></div></code></pre></div></div>
<p>No image, no daemon, no registry. A directory and a JSON file.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="inside-configjson">Inside config.json<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#inside-configjson" class="hash-link" aria-label="Direct link to Inside config.json" title="Direct link to Inside config.json" translate="no">​</a></h2>
<p>The spec version generated by <code>runc spec</code> is long but every section has a clear purpose. Here is an
annotated tour of the parts that matter.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ociversion-and-process">ociVersion and process<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#ociversion-and-process" class="hash-link" aria-label="Direct link to ociVersion and process" title="Direct link to ociVersion and process" translate="no">​</a></h3>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"ociVersion"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"1.2.0"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"process"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"terminal"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(35, 99%, 36%)">true</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"user"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"uid"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"gid"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"additionalGids"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"args"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"sh"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"env"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"TERM=xterm"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"cwd"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"noNewPrivileges"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(35, 99%, 36%)">true</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"rlimits"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"RLIMIT_NOFILE"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"hard"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1024</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"soft"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1024</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></div></code></pre></div></div>
<p><code>process.args</code> is the container's PID 1 — this is where a Dockerfile's <code>ENTRYPOINT</code> and <code>CMD</code> end
up after being concatenated. <code>noNewPrivileges</code> sets the kernel's <code>no_new_privs</code> bit, which is
exactly what Kubernetes' <code>allowPrivilegeEscalation: false</code> produces.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="capabilities">capabilities<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#capabilities" class="hash-link" aria-label="Direct link to capabilities" title="Direct link to capabilities" translate="no">​</a></h3>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token property" style="color:hsl(5, 74%, 59%)">"capabilities"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"bounding"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"CAP_CHOWN"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"CAP_NET_BIND_SERVICE"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"CAP_KILL"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"effective"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain">   </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"CAP_CHOWN"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"CAP_NET_BIND_SERVICE"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"CAP_KILL"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"permitted"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain">   </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"CAP_CHOWN"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"CAP_NET_BIND_SERVICE"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"CAP_KILL"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"inheritable"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"ambient"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain">     </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></div></code></pre></div></div>
<p>Linux capabilities split root's power into ~40 separate privileges. A "root" process in a container
is normally root with most of them removed — which is why containerised root cannot load kernel
modules (<code>CAP_SYS_MODULE</code>) or change the system clock (<code>CAP_SYS_TIME</code>).</p>
<p>The five sets are not interchangeable:</p>
<table><thead><tr><th>Set</th><th>Meaning</th></tr></thead><tbody><tr><td><code>bounding</code></td><td>The ceiling — nothing outside this can ever be acquired</td></tr><tr><td><code>permitted</code></td><td>What the process may enable</td></tr><tr><td><code>effective</code></td><td>What is active for permission checks right now</td></tr><tr><td><code>inheritable</code></td><td>Preserved across <code>execve()</code> of a file with matching bits</td></tr><tr><td><code>ambient</code></td><td>Preserved across <code>execve()</code> of an unprivileged binary</td></tr></tbody></table>
<p>Kubernetes' <code>capabilities.drop: ["ALL"]</code> empties all of these. <code>CAP_NET_BIND_SERVICE</code> is the one
people add back, to bind port 80 as a non-root user.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="root-and-hostname">root and hostname<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#root-and-hostname" class="hash-link" aria-label="Direct link to root and hostname" title="Direct link to root and hostname" translate="no">​</a></h3>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token property" style="color:hsl(5, 74%, 59%)">"root"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"path"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"rootfs"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"readonly"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(35, 99%, 36%)">false</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token property" style="color:hsl(5, 74%, 59%)">"hostname"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"runc"</span><br></div></code></pre></div></div>
<p><code>root.path</code> is relative to the bundle directory. <code>readonly: true</code> is what Kubernetes'
<code>readOnlyRootFilesystem: true</code> sets.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="mounts">mounts<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#mounts" class="hash-link" aria-label="Direct link to mounts" title="Direct link to mounts" translate="no">​</a></h3>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token property" style="color:hsl(5, 74%, 59%)">"mounts"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"destination"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/proc"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"proc"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"source"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"proc"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"destination"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/dev"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"tmpfs"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"source"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"tmpfs"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"options"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"nosuid"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"strictatime"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"mode=755"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"size=65536k"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"destination"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/sys"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"sysfs"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"source"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/sys"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"options"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"nosuid"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"noexec"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"nodev"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"ro"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"destination"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/data"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"bind"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"source"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/var/lib/myapp"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token property" style="color:hsl(5, 74%, 59%)">"options"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"rbind"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"rw"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><br></div></code></pre></div></div>
<p>Every Kubernetes volume mount, every <code>docker -v</code>, every ConfigMap projection ultimately becomes an
entry in this array. <code>/proc</code>, <code>/sys</code>, and <code>/dev</code> are mounted fresh inside the container's mount
namespace so it sees its own process table and device nodes rather than the host's.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="linuxnamespaces">linux.namespaces<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#linuxnamespaces" class="hash-link" aria-label="Direct link to linux.namespaces" title="Direct link to linux.namespaces" translate="no">​</a></h3>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token property" style="color:hsl(5, 74%, 59%)">"linux"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"namespaces"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"pid"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"network"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"ipc"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"uts"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"mount"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"cgroup"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></div></code></pre></div></div>
<p>This is the heart of it. Each entry with no <code>path</code> means "create a new one." An entry <strong>with</strong> a
<code>path</code> means "join this existing namespace":</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"type"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"network"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"path"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/proc/1234/ns/net"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></div></code></pre></div></div>
<p>That single line is how a Kubernetes Pod works. Every container in a Pod joins the same network
namespace — the pause container's — which is why they share an IP address and reach each other on
<code>localhost</code>. It is also what <code>docker run --network=container:other</code> and <code>kubectl debug --target</code>
produce.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="linuxresources">linux.resources<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#linuxresources" class="hash-link" aria-label="Direct link to linux.resources" title="Direct link to linux.resources" translate="no">​</a></h3>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token property" style="color:hsl(5, 74%, 59%)">"resources"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"memory"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"limit"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">268435456</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"cpu"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"shares"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1024</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"quota"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">100000</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"period"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">100000</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"pids"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"limit"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">512</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></div></code></pre></div></div>
<p>These are written straight into the cgroup filesystem. A Kubernetes <code>limits.memory: 256Mi</code> becomes
<code>memory.limit</code> here, and exceeding it is what triggers the kernel OOM killer and the <code>OOMKilled</code>
status you see in <code>kubectl describe</code>.</p>
<p>CPU is expressed as a <code>quota</code> per <code>period</code>: 100000/100000 is one full core, 50000/100000 is half a
core, and exceeding it results in throttling rather than a kill.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="linuxseccomp">linux.seccomp<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#linuxseccomp" class="hash-link" aria-label="Direct link to linux.seccomp" title="Direct link to linux.seccomp" translate="no">​</a></h3>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token property" style="color:hsl(5, 74%, 59%)">"seccomp"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"defaultAction"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"SCMP_ACT_ERRNO"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"architectures"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"SCMP_ARCH_X86_64"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"syscalls"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token property" style="color:hsl(5, 74%, 59%)">"names"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"accept"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"read"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"write"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"openat"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"close"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token property" style="color:hsl(5, 74%, 59%)">"action"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"SCMP_ACT_ALLOW"</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></div></code></pre></div></div>
<p>A syscall allow-list enforced by the kernel. The default action is to deny; listed syscalls are
permitted. Docker's default profile blocks around 44 syscalls, which is what Kubernetes'
<code>seccompProfile: { type: RuntimeDefault }</code> applies.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="linuxuidmappings">linux.uidMappings<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#linuxuidmappings" class="hash-link" aria-label="Direct link to linux.uidMappings" title="Direct link to linux.uidMappings" translate="no">​</a></h3>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token property" style="color:hsl(5, 74%, 59%)">"uidMappings"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"containerID"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"hostID"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">100000</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"size"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">65536</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token property" style="color:hsl(5, 74%, 59%)">"gidMappings"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"containerID"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"hostID"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">100000</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"size"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">65536</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><br></div></code></pre></div></div>
<p>User-namespace remapping: UID 0 inside the container is UID 100000 on the host. Root in the
container is an unprivileged user outside it, so a container escape lands on a nobody account. This
is what "rootless containers" means, and Kubernetes exposes it as <code>hostUsers: false</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-lifecycle-a-runtime-implements">The lifecycle a runtime implements<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#the-lifecycle-a-runtime-implements" class="hash-link" aria-label="Direct link to The lifecycle a runtime implements" title="Direct link to The lifecycle a runtime implements" translate="no">​</a></h2>
<p>The runtime spec defines operations, not just a file format. runc implements each as a subcommand:</p>
<table><thead><tr><th>Operation</th><th>What happens</th></tr></thead><tbody><tr><td><code>create</code></td><td>Namespaces and cgroups are set up, the rootfs is pivoted into, and the process is started <strong>but held</strong> before <code>execve</code></td></tr><tr><td><code>start</code></td><td>The held process is released and <code>execve</code> runs <code>process.args</code></td></tr><tr><td><code>state</code></td><td>Report the container's status and PID</td></tr><tr><td><code>kill</code></td><td>Deliver a signal to the container process</td></tr><tr><td><code>delete</code></td><td>Tear down the cgroup and remove state</td></tr></tbody></table>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> runc create demo</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> runc state demo        </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># "status": "created"</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> runc start demo        </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># now "running"</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> runc list</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> runc </span><span class="token function" style="color:hsl(221, 87%, 60%)">kill</span><span class="token plain"> demo </span><span class="token environment constant" style="color:hsl(35, 99%, 36%)">TERM</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> runc delete demo</span><br></div></code></pre></div></div>
<p>The split between <code>create</code> and <code>start</code> is what makes hooks possible. Between the two, a
<code>createRuntime</code> or <code>createContainer</code> hook can run on the host with the container's namespaces
already in place — which is precisely how a <strong>CNI plugin attaches a network interface</strong> to a
container before its process ever executes.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token property" style="color:hsl(5, 74%, 59%)">"hooks"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"createRuntime"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"path"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/usr/local/bin/setup-network.sh"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"args"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"setup-network.sh"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token property" style="color:hsl(5, 74%, 59%)">"poststop"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"path"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/usr/local/bin/cleanup.sh"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(5, 74%, 59%)">"args"</span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">"cleanup.sh"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="seeing-the-real-thing-on-a-kubernetes-node">Seeing the real thing on a Kubernetes node<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#seeing-the-real-thing-on-a-kubernetes-node" class="hash-link" aria-label="Direct link to Seeing the real thing on a Kubernetes node" title="Direct link to Seeing the real thing on a Kubernetes node" translate="no">​</a></h2>
<p>Every running container on a node has a bundle. On a node using containerd:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># List containers in the kubelet's namespace</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> ctr </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-n</span><span class="token plain"> k8s.io containers list</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Dump the actual OCI spec containerd generated for one</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> ctr </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-n</span><span class="token plain"> k8s.io containers info </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token plain">container-id</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> jq </span><span class="token string" style="color:hsl(119, 34%, 47%)">'.Spec'</span><br></div></code></pre></div></div>
<p>Compare that output against the Pod's YAML and the mapping is direct — <code>securityContext</code> fields
appear under <code>process</code> and <code>linux</code>, volume mounts appear in <code>mounts</code>, and resource limits appear
under <code>linux.resources</code>. Every Kubernetes field you set is a translation into this document.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-this-is-worth-knowing">Why this is worth knowing<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#why-this-is-worth-knowing" class="hash-link" aria-label="Direct link to Why this is worth knowing" title="Direct link to Why this is worth knowing" translate="no">​</a></h2>
<ul>
<li class=""><strong>It demystifies containers.</strong> There is no magic: a JSON file describes namespaces, cgroups,
mounts, and a process, and a runtime asks the kernel for exactly that.</li>
<li class=""><strong>It explains Kubernetes fields.</strong> <code>runAsNonRoot</code>, <code>readOnlyRootFilesystem</code>, <code>capabilities.drop</code>,
<code>seccompProfile</code> — each one is a line in this document, and knowing which line tells you exactly
what it does and does not protect.</li>
<li class=""><strong>It explains why runtimes are swappable.</strong> crun, gVisor, and Kata read the same <code>config.json</code>.
They differ only in <em>how</em> they satisfy it — a C implementation, a user-space kernel, or a
microVM.</li>
<li class=""><strong>It makes debugging possible.</strong> When a container behaves unexpectedly, dumping its actual spec
answers the question far faster than guessing at the layers above.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc">Docker vs containerd vs runc</a> — who produces this bundle and
who consumes it.</li>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/docs/learn/kubernetes-security-basics">Kubernetes security basics</a> — the <code>securityContext</code>
fields that map onto these sections.</li>
<li class="">The <a href="https://github.com/opencontainers/runtime-spec/blob/main/spec.md" target="_blank" rel="noopener noreferrer" class="">OCI runtime specification</a>
itself — genuinely readable, and shorter than you expect.</li>
</ul>]]></content>
        <author>
            <name>Md Raiyan</name>
            <uri>https://github.com/mdryaaan</uri>
        </author>
        <category label="Containers" term="Containers"/>
        <category label="OCI" term="OCI"/>
        <category label="Runtimes" term="Runtimes"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Common kubectl commands every developer should know]]></title>
        <id>https://nativehub-chi.vercel.app/blog/common-kubectl-commands</id>
        <link href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands"/>
        <updated>2026-05-12T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A practical reference for get, describe, logs, exec, port-forward, and apply — with the flags that actually matter day to day.]]></summary>
        <content type="html"><![CDATA[<p>There are hundreds of <code>kubectl</code> subcommands and you will use about fifteen. This is that fifteen,
with the flags that turn each one from "prints something" into "answers the question."</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-mental-model">The mental model<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#the-mental-model" class="hash-link" aria-label="Direct link to The mental model" title="Direct link to The mental model" translate="no">​</a></h2>
<p><code>kubectl</code> is a REST client. Every command is an HTTP request to the API server, and you can see
exactly which one:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-v</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token number" style="color:hsl(35, 99%, 36%)">6</span><span class="token plain">            </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># show the request URLs</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-v</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token plain">            </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># show full request and response bodies</span><br></div></code></pre></div></div>
<p>That is genuinely useful when a command behaves unexpectedly — you can see whether the problem is
your query or the cluster's answer.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="get--what-exists">get — what exists<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#get--what-exists" class="hash-link" aria-label="Direct link to get — what exists" title="Direct link to get — what exists" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-A</span><span class="token plain">                      </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># every namespace</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> wide                 </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># + node, pod IP, nominated node</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pod web-abc </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> yaml          </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># the full object as stored</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get deploy,svc,ing </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">app</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web    </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># several kinds at once</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-flags-worth-memorising">The flags worth memorising<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#the-flags-worth-memorising" class="hash-link" aria-label="Direct link to The flags worth memorising" title="Direct link to The flags worth memorising" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Watch changes as they happen</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-w</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Filter server-side by field (cheaper than grep, and exact)</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods --field-selector</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">status.phase</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">Running</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get events --field-selector </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">type</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">Warning</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Sort by anything in the object</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods --sort-by</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">.status.containerStatuses</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain">.restartCount</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get events --sort-by</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">.lastTimestamp</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Pull out exactly the columns you want</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> custom-columns</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">'NAME:.metadata.name,NODE:.spec.nodeName,IMAGE:.spec.containers[*].image'</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># JSONPath for scripting</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">jsonpath</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string" style="color:hsl(119, 34%, 47%)">'{.items[*].spec.nodeName}'</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get svc web </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">jsonpath</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string" style="color:hsl(119, 34%, 47%)">'{.spec.clusterIP}'</span><br></div></code></pre></div></div>
<p><code>kubectl api-resources</code> is the command that makes the rest discoverable — it lists every kind the
cluster knows about, along with its short name and whether it is namespaced.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl api-resources </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">head</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-20</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl explain deployment.spec.strategy.rollingUpdate    </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># inline schema docs</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="describe--why-it-is-in-that-state">describe — why it is in that state<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#describe--why-it-is-in-that-state" class="hash-link" aria-label="Direct link to describe — why it is in that state" title="Direct link to describe — why it is in that state" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl describe pod web-abc</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl describe </span><span class="token function" style="color:hsl(221, 87%, 60%)">node</span><span class="token plain"> worker-1</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl describe svc web</span><br></div></code></pre></div></div>
<p><code>describe</code> is not just a prettier <code>get</code>. It joins the object with related state — most importantly
its <strong>Events</strong>, which appear at the bottom and are where the actual explanation lives:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Events:</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  Type     Reason     Age   From               Message</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  ----     ------     ----  ----               -------</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  Warning  Failed     2m    kubelet            Error: ImagePullBackOff</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  Warning  Unhealthy  1m    kubelet            Readiness probe failed: connection refused</span><br></div></code></pre></div></div>
<p>Always read the bottom of <code>describe</code> first. It answers "why" more often than the logs do.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Two high-value describe habits</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl describe pod web-abc </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">sed</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-n</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'/Events:/,$p'</span><span class="token plain">         </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># events only</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl describe </span><span class="token function" style="color:hsl(221, 87%, 60%)">node</span><span class="token plain"> worker-1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">sed</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-n</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'/Allocated/,$p'</span><span class="token plain">     </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># what is claimed on a node</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="logs--what-the-application-said">logs — what the application said<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#logs--what-the-application-said" class="hash-link" aria-label="Direct link to logs — what the application said" title="Direct link to logs — what the application said" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl logs web-abc</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl logs web-abc </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain">                  </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># follow</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl logs web-abc </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--tail</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token number" style="color:hsl(35, 99%, 36%)">100</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl logs web-abc </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--since</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">15m</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl logs web-abc </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-c</span><span class="token plain"> sidecar          </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># a specific container in the Pod</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-two-flags-people-miss">The two flags people miss<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#the-two-flags-people-miss" class="hash-link" aria-label="Direct link to The two flags people miss" title="Direct link to The two flags people miss" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># The container that CRASHED, not the one that just started</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl logs web-abc </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--previous</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Every Pod behind a label, with the pod name prefixed on each line</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl logs </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">app</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web --all-containers </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--prefix</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--tail</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token number" style="color:hsl(35, 99%, 36%)">50</span><br></div></code></pre></div></div>
<p><code>--previous</code> is the single most important debugging flag in kubectl. On a <code>CrashLoopBackOff</code> Pod,
plain <code>kubectl logs</code> shows a container that has been alive for two seconds and has nothing to say.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Timestamps are not on by default</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl logs web-abc </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--timestamps</span><span class="token plain"> --since-time</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string" style="color:hsl(119, 34%, 47%)">'2026-05-18T10:00:00Z'</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="exec--get-inside">exec — get inside<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#exec--get-inside" class="hash-link" aria-label="Direct link to exec — get inside" title="Direct link to exec — get inside" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token plain"> web-abc -- </span><span class="token function" style="color:hsl(221, 87%, 60%)">env</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">sort</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-it</span><span class="token plain"> web-abc -- </span><span class="token function" style="color:hsl(221, 87%, 60%)">sh</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-it</span><span class="token plain"> web-abc </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-c</span><span class="token plain"> sidecar -- </span><span class="token function" style="color:hsl(221, 87%, 60%)">bash</span><br></div></code></pre></div></div>
<p>The <code>--</code> matters: everything after it is passed to the container rather than parsed by kubectl.
Without it, <code>kubectl exec web-abc ls -la</code> tries to interpret <code>-la</code> as a kubectl flag.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Useful one-liners from inside a Pod</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token plain"> web-abc -- </span><span class="token function" style="color:hsl(221, 87%, 60%)">cat</span><span class="token plain"> /etc/resolv.conf</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token plain"> web-abc -- </span><span class="token function" style="color:hsl(221, 87%, 60%)">nslookup</span><span class="token plain"> db.default.svc.cluster.local</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token plain"> web-abc -- </span><span class="token function" style="color:hsl(221, 87%, 60%)">wget</span><span class="token plain"> -qO- </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--timeout</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token plain"> localhost:8080/healthz</span><br></div></code></pre></div></div>
<p>When the image has no shell — distroless, scratch — <code>exec</code> cannot help. Use an ephemeral debug
container instead, which joins the running Pod's namespaces:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl debug </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-it</span><span class="token plain"> web-abc </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--image</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">nicolaka/netshoot </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">app</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="port-forward--reach-it-from-your-laptop">port-forward — reach it from your laptop<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#port-forward--reach-it-from-your-laptop" class="hash-link" aria-label="Direct link to port-forward — reach it from your laptop" title="Direct link to port-forward — reach it from your laptop" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl port-forward pod/web-abc </span><span class="token number" style="color:hsl(35, 99%, 36%)">8080</span><span class="token plain">:8080</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl port-forward svc/web </span><span class="token number" style="color:hsl(35, 99%, 36%)">8080</span><span class="token plain">:80        </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># picks one backing Pod</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl port-forward deploy/web </span><span class="token number" style="color:hsl(35, 99%, 36%)">8080</span><span class="token plain">:8080</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Bind on all interfaces (careful on shared networks)</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl port-forward </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--address</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0.0</span><span class="token plain">.0.0 svc/web </span><span class="token number" style="color:hsl(35, 99%, 36%)">8080</span><span class="token plain">:80</span><br></div></code></pre></div></div>
<p>This is a tunnel through the API server, so it works even when the Service is <code>ClusterIP</code>-only and
the cluster is behind a bastion. It is the fastest way to reach a database or an admin UI you would
never expose.</p>
<p>Note that forwarding to a Service still selects <strong>one</strong> Pod and stays with it — it is not load
balanced. For testing balancing behaviour, use a NodePort or an Ingress.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="apply--declare-the-desired-state">apply — declare the desired state<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#apply--declare-the-desired-state" class="hash-link" aria-label="Direct link to apply — declare the desired state" title="Direct link to apply — declare the desired state" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain"> deployment.yaml</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain"> k8s/                    </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># a whole directory</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-k</span><span class="token plain"> overlays/prod           </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># kustomize</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain"> https://example.com/manifest.yaml</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="before-you-apply">Before you apply<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#before-you-apply" class="hash-link" aria-label="Direct link to Before you apply" title="Direct link to Before you apply" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Validate against the server's schema without changing anything</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain"> deployment.yaml --dry-run</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">server</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># See exactly what would change on the live object</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl </span><span class="token function" style="color:hsl(221, 87%, 60%)">diff</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain"> deployment.yaml</span><br></div></code></pre></div></div>
<p><code>kubectl diff</code> is underused and excellent — it is <code>git diff</code> for the cluster, and it catches the
"someone edited this by hand in production" case immediately.</p>
<div style="margin-top:1.25rem"></div>
<p><strong>apply vs create vs replace.</strong> <code>create</code> fails if the object exists. <code>replace</code> overwrites the whole
object, dropping fields you did not send. <code>apply</code> performs a three-way merge between your manifest,
the live object, and the last-applied configuration — which is why it is the only one safe to run
repeatedly.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rollouts">Rollouts<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#rollouts" class="hash-link" aria-label="Direct link to Rollouts" title="Direct link to Rollouts" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl rollout status deployment/web </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--timeout</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">120s</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl rollout </span><span class="token function" style="color:hsl(221, 87%, 60%)">history</span><span class="token plain"> deployment/web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl rollout </span><span class="token function" style="color:hsl(221, 87%, 60%)">history</span><span class="token plain"> deployment/web </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--revision</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token number" style="color:hsl(35, 99%, 36%)">3</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl rollout undo deployment/web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl rollout undo deployment/web --to-revision</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl rollout restart deployment/web     </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># recreate every Pod, no spec change</span><br></div></code></pre></div></div>
<p><code>rollout restart</code> is the clean way to force a restart — it patches an annotation on the Pod
template, which triggers a normal rolling update. Deleting Pods by hand skips the surge and
availability guarantees.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quick-reference">Quick reference<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#quick-reference" class="hash-link" aria-label="Direct link to Quick reference" title="Direct link to Quick reference" translate="no">​</a></h2>
<section class="nh-cheatsheet"><h3 class="nh-cheatsheet__title">The commands worth committing to memory</h3><div class="nh-cheatsheet__controls"><label class="nh-cheatsheet__search"><span class="sr-only">Filter <!-- -->The commands worth committing to memory</span><svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><circle cx="11" cy="11" r="7"></circle><path d="m20 20-3.5-3.5"></path></svg><input type="search" placeholder="Filter commands…" value=""></label><div class="nh-cheatsheet__groups" role="group" aria-label="Filter by category"><button type="button" aria-pressed="true" class="nh-cheatsheet__chip nh-cheatsheet__chip--active">All</button><button type="button" aria-pressed="false" class="nh-cheatsheet__chip">Inspect</button><button type="button" aria-pressed="false" class="nh-cheatsheet__chip">Debug</button><button type="button" aria-pressed="false" class="nh-cheatsheet__chip">Change</button><button type="button" aria-pressed="false" class="nh-cheatsheet__chip">Access</button><button type="button" aria-pressed="false" class="nh-cheatsheet__chip">Context</button></div></div><div class="nh-cheatsheet__scroll"><table class="nh-cheatsheet__table"><thead><tr><th scope="col">Command</th><th scope="col">What it does</th></tr></thead><tbody><tr><td><code>kubectl get pods -o wide</code></td><td>Pods with node and IP columns</td></tr><tr><td><code>kubectl get all -n &lt;ns&gt;</code></td><td>Common resource kinds in a namespace</td></tr><tr><td><code>kubectl describe pod &lt;pod&gt;</code></td><td>Full state plus the events that explain it</td></tr><tr><td><code>kubectl explain &lt;kind&gt;.&lt;field&gt;</code></td><td>Schema documentation, offline</td></tr><tr><td><code>kubectl api-resources</code></td><td>Every kind the cluster knows, with short names</td></tr><tr><td><code>kubectl logs &lt;pod&gt; --previous</code></td><td>Logs from the container that crashed</td></tr><tr><td><code>kubectl logs -l app=web --prefix -f</code></td><td>Follow logs from every matching Pod</td></tr><tr><td><code>kubectl exec -it &lt;pod&gt; -- sh</code></td><td>Interactive shell in a container</td></tr><tr><td><code>kubectl debug -it &lt;pod&gt; --image=nicolaka/netshoot --target=&lt;c&gt;</code></td><td>Ephemeral debug container sharing the Pod namespaces</td></tr><tr><td><code>kubectl get events --sort-by=.lastTimestamp</code></td><td>Cluster events in chronological order</td></tr><tr><td><code>kubectl top pod --containers</code></td><td>Live CPU and memory per container</td></tr><tr><td><code>kubectl apply -f &lt;file&gt;</code></td><td>Create or update via three-way merge</td></tr><tr><td><code>kubectl diff -f &lt;file&gt;</code></td><td>Show what applying would change</td></tr><tr><td><code>kubectl scale deploy/&lt;name&gt; --replicas=5</code></td><td>Change replica count immediately</td></tr><tr><td><code>kubectl rollout restart deploy/&lt;name&gt;</code></td><td>Roll every Pod without a spec change</td></tr><tr><td><code>kubectl rollout undo deploy/&lt;name&gt;</code></td><td>Revert to the previous ReplicaSet</td></tr><tr><td><code>kubectl port-forward svc/&lt;name&gt; 8080:80</code></td><td>Tunnel a Service port to localhost</td></tr><tr><td><code>kubectl cp &lt;pod&gt;:/path ./local</code></td><td>Copy files out of a container</td></tr><tr><td><code>kubectl auth can-i &lt;verb&gt; &lt;resource&gt;</code></td><td>Check your own RBAC permissions</td></tr><tr><td><code>kubectl config get-contexts</code></td><td>List configured clusters</td></tr><tr><td><code>kubectl config use-context &lt;name&gt;</code></td><td>Switch cluster</td></tr><tr><td><code>kubectl config set-context --current --namespace=&lt;ns&gt;</code></td><td>Set the default namespace</td></tr></tbody></table></div></section>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="make-it-faster">Make it faster<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#make-it-faster" class="hash-link" aria-label="Direct link to Make it faster" title="Direct link to Make it faster" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockTitle_OeMC">~/.bashrc or ~/.zshrc</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Completion and a short alias that keeps completion working</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">source</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">kubectl completion </span><span class="token function" style="color:hsl(221, 87%, 60%)">bash</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">alias</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">k</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">kubectl</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">complete </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> default </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-F</span><span class="token plain"> __start_kubectl k</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Stop typing -n every time</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">alias</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">kn</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string" style="color:hsl(119, 34%, 47%)">'kubectl config set-context --current --namespace'</span><br></div></code></pre></div></div>
<p>Two tools that pay for themselves in a week:</p>
<ul>
<li class=""><strong>kubectx / kubens</strong> — switch cluster and namespace in one word.</li>
<li class=""><strong>k9s</strong> — a terminal UI over the cluster. Logs, exec, describe, and delete without typing a
command; it replaces most of the <code>get</code>/<code>describe</code> loop.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-habits-that-matter">The habits that matter<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#the-habits-that-matter" class="hash-link" aria-label="Direct link to The habits that matter" title="Direct link to The habits that matter" translate="no">​</a></h2>
<ol>
<li class="">Read the <strong>Events</strong> at the bottom of <code>describe</code> before anything else.</li>
<li class="">Use <code>--previous</code> on any Pod that has restarted.</li>
<li class="">Run <code>kubectl diff</code> before <code>kubectl apply</code> on a cluster you care about.</li>
<li class="">Use <code>--dry-run=server</code> to validate manifests in CI.</li>
<li class="">Set the namespace in your context instead of typing <code>-n</code> two hundred times a day.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://nativehub-chi.vercel.app/blog/common-kubectl-commands#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/tools">The kubectl cheat sheet</a> — the full searchable reference on this site.</li>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/docs/guides/debugging-pod-failures">Debugging pod failures</a> — these commands applied to a
specific problem.</li>
<li class="">The official <a href="https://kubernetes.io/docs/reference/kubectl/" target="_blank" rel="noopener noreferrer" class="">kubectl reference</a>.</li>
</ul>]]></content>
        <author>
            <name>Md Raiyan</name>
            <uri>https://github.com/mdryaaan</uri>
        </author>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="kubectl" term="kubectl"/>
        <category label="Tooling" term="Tooling"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Setting up your first multi-node cluster with kind]]></title>
        <id>https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind</id>
        <link href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind"/>
        <updated>2026-04-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A real three-node Kubernetes cluster on your laptop in under ten minutes — with ingress, a local registry, and node failure simulation.]]></summary>
        <content type="html"><![CDATA[<p><strong>kind</strong> — Kubernetes IN Docker — runs each Kubernetes node as a Docker container. That sounds like
a toy, but the nodes run real kubelets, a real control plane, and real container runtimes, which
makes it the closest you can get to a production topology on a laptop. It is also what the
Kubernetes project itself uses for conformance testing.</p>
<p>Every command below has been written to run as-is.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="install">Install<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#install" class="hash-link" aria-label="Direct link to Install" title="Direct link to Install" translate="no">​</a></h2>
<p><strong>Prerequisites:</strong> Docker running, and at least 4 GB of memory available to it (8 GB is comfortable
for three nodes).</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># macOS</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">brew </span><span class="token function" style="color:hsl(221, 87%, 60%)">install</span><span class="token plain"> kind kubectl</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Linux (amd64)</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$(</span><span class="token string variable function" style="color:hsl(221, 87%, 60%)">uname</span><span class="token string variable" style="color:hsl(221, 87%, 60%)"> </span><span class="token string variable parameter variable" style="color:hsl(221, 87%, 60%)">-m</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">)</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> x86_64 </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-Lo</span><span class="token plain"> ./kind https://kind.sigs.k8s.io/dl/v0.30.0/kind-linux-amd64</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">chmod</span><span class="token plain"> +x ./kind </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">mv</span><span class="token plain"> ./kind /usr/local/bin/kind</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Windows</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">winget </span><span class="token function" style="color:hsl(221, 87%, 60%)">install</span><span class="token plain"> Kubernetes.kind</span><br></div></code></pre></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kind version</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> info </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-E</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'Total Memory|Server Version'</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-single-node-is-one-command">A single node is one command<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#a-single-node-is-one-command" class="hash-link" aria-label="Direct link to A single node is one command" title="Direct link to A single node is one command" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kind create cluster </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--name</span><span class="token plain"> quickstart</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl cluster-info </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--context</span><span class="token plain"> kind-quickstart</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kind delete cluster </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--name</span><span class="token plain"> quickstart</span><br></div></code></pre></div></div>
<p>Useful for a smoke test. It teaches you nothing about scheduling, because there is only one node —
and it is a control-plane node carrying a taint, which kind removes so your Pods can land somewhere.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-multi-node-cluster">The multi-node cluster<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#the-multi-node-cluster" class="hash-link" aria-label="Direct link to The multi-node cluster" title="Direct link to The multi-node cluster" translate="no">​</a></h2>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockTitle_OeMC">kind-config.yaml</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token key atrule" style="color:hsl(35, 99%, 36%)">kind</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> Cluster</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">apiVersion</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> kind.x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain">k8s.io/v1alpha4</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> nativehub</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">nodes</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">role</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> control</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain">plane</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">kubeadmConfigPatches</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token scalar string" style="color:hsl(119, 34%, 47%)"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token scalar string" style="color:hsl(119, 34%, 47%)">        kind: InitConfiguration</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token scalar string" style="color:hsl(119, 34%, 47%)">        nodeRegistration:</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token scalar string" style="color:hsl(119, 34%, 47%)">          kubeletExtraArgs:</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token scalar string" style="color:hsl(119, 34%, 47%)">            node-labels: "ingress-ready=true"</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">extraPortMappings</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">containerPort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">80</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">hostPort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">80</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">protocol</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> TCP</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">containerPort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">443</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">hostPort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">443</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">protocol</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> TCP</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">role</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> worker</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">labels</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">topology.kubernetes.io/zone</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> zone</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain">a</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">node-type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> general</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">role</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> worker</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">labels</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">topology.kubernetes.io/zone</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> zone</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain">b</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">node-type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> general</span><br></div></code></pre></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kind create cluster </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--config</span><span class="token plain"> kind-config.yaml</span><br></div></code></pre></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get nodes </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> wide</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">NAME                      STATUS   ROLES           VERSION</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">nativehub-control-plane   Ready    control-plane   v1.34.0</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">nativehub-worker          Ready    &lt;none&gt;          v1.34.0</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">nativehub-worker2         Ready    &lt;none&gt;          v1.34.0</span><br></div></code></pre></div></div>
<p>Each node is a Docker container — this is not a metaphor:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">ps</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--filter</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"name=nativehub"</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--format</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"table {{.Names}}</span><span class="token string entity" style="color:hsl(230, 8%, 24%)">\t</span><span class="token string" style="color:hsl(119, 34%, 47%)">{{.Image}}</span><span class="token string entity" style="color:hsl(230, 8%, 24%)">\t</span><span class="token string" style="color:hsl(119, 34%, 47%)">{{.Status}}"</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-it</span><span class="token plain"> nativehub-worker crictl </span><span class="token function" style="color:hsl(221, 87%, 60%)">ps</span><br></div></code></pre></div></div>
<p>Note <code>crictl</code>, not <code>docker</code>. Inside the node, containerd is the runtime; there is no Docker daemon
in there.</p>
<div style="margin-top:1.25rem"></div>
<p>Two details in that config do real work:</p>
<ul>
<li class=""><strong><code>extraPortMappings</code></strong> publishes ports from the control-plane container to your host, which is
how browser traffic on <code>localhost:80</code> reaches an Ingress controller inside the cluster.</li>
<li class=""><strong><code>node-labels: ingress-ready=true</code></strong> marks that node so the ingress-nginx manifest — which
includes a matching <code>nodeSelector</code> — schedules there.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pin-the-kubernetes-version">Pin the Kubernetes version<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#pin-the-kubernetes-version" class="hash-link" aria-label="Direct link to Pin the Kubernetes version" title="Direct link to Pin the Kubernetes version" translate="no">​</a></h2>
<p>kind's default node image tracks the kind release. To match a specific cluster version, pass a
digest-pinned image:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kind create cluster </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--config</span><span class="token plain"> kind-config.yaml </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--image</span><span class="token plain"> kindest/node:v1.34.0</span><br></div></code></pre></div></div>
<p>Each kind release supports a specific set of node images — check the release notes rather than
guessing, since an unsupported combination fails during <code>kubeadm init</code> with an unhelpful timeout.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="install-an-ingress-controller">Install an ingress controller<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#install-an-ingress-controller" class="hash-link" aria-label="Direct link to Install an ingress controller" title="Direct link to Install an ingress controller" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain"> https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0/deploy/static/provider/kind/deploy.yaml</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl </span><span class="token function" style="color:hsl(221, 87%, 60%)">wait</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--namespace</span><span class="token plain"> ingress-nginx </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--for</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">condition</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">ready pod </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--selector</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">app.kubernetes.io/component</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">controller </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--timeout</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">180s</span><br></div></code></pre></div></div>
<p>That manifest is the kind-specific variant: it uses <code>hostPort</code> and the <code>ingress-ready</code> node
selector, which is what makes the <code>extraPortMappings</code> above line up.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deploy-something-and-route-to-it">Deploy something and route to it<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#deploy-something-and-route-to-it" class="hash-link" aria-label="Direct link to Deploy something and route to it" title="Direct link to Deploy something and route to it" translate="no">​</a></h2>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockTitle_OeMC">demo.yaml</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token key atrule" style="color:hsl(35, 99%, 36%)">apiVersion</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> apps/v1</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">kind</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> Deployment</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">metadata</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">spec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">replicas</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">4</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">selector</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">matchLabels</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">app</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">template</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">metadata</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">labels</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">app</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">spec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Spread replicas across zones so a "zone" outage cannot take everything.</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">topologySpreadConstraints</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">maxSkew</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">topologyKey</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> topology.kubernetes.io/zone</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">whenUnsatisfiable</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> ScheduleAnyway</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">labelSelector</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">            </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">matchLabels</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">app</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">containers</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> echo</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">image</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> ealen/echo</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain">server</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain">0.9.2</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">ports</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">            </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">containerPort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">80</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">resources</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">            </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">requests</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">cpu</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> 25m</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">memory</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> 32Mi </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">            </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">limits</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">memory</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> 64Mi </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">---</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">apiVersion</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">kind</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> Service</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">metadata</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">spec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">selector</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">app</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">ports</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">port</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">80</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">targetPort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">80</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">---</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">apiVersion</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> networking.k8s.io/v1</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">kind</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> Ingress</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">metadata</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">spec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">ingressClassName</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> nginx</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">rules</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">http</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">paths</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">path</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> /</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">            </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">pathType</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> Prefix</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">            </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">backend</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">              </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">service</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">                </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">                </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">port</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">                  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">number</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">80</span><br></div></code></pre></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain"> demo.yaml</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl rollout status deployment/web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-s</span><span class="token plain"> localhost/ </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> jq </span><span class="token string" style="color:hsl(119, 34%, 47%)">'.host, .request.headers."x-forwarded-for"'</span><br></div></code></pre></div></div>
<p>Check where the scheduler put things:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">app</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> custom-columns</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">'NAME:.metadata.name,NODE:.spec.nodeName,IP:.status.podIP'</span><br></div></code></pre></div></div>
<p>With <code>topologySpreadConstraints</code>, the four replicas are split evenly across the two labelled
workers. That is genuinely useful to see — it is the same mechanism that keeps production workloads
spread across availability zones.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="load-local-images-without-a-registry">Load local images without a registry<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#load-local-images-without-a-registry" class="hash-link" aria-label="Direct link to Load local images without a registry" title="Direct link to Load local images without a registry" translate="no">​</a></h2>
<p>The most common kind papercut: you build an image locally, reference it in a manifest, and the Pod
sits in <code>ErrImagePull</code>. The nodes are separate containers with their own image stores — your host's
Docker images are not visible to them.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> build </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-t</span><span class="token plain"> myapp:dev </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kind load docker-image myapp:dev </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--name</span><span class="token plain"> nativehub</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Verify it landed</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-it</span><span class="token plain"> nativehub-worker crictl images </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">grep</span><span class="token plain"> myapp</span><br></div></code></pre></div></div>
<p>Set <code>imagePullPolicy: IfNotPresent</code> in the manifest. With the default <code>Always</code> behaviour for
untagged or <code>:latest</code> images, the kubelet will try to pull from Docker Hub and fail anyway.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-local-registry-the-better-workflow">A local registry (the better workflow)<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#a-local-registry-the-better-workflow" class="hash-link" aria-label="Direct link to A local registry (the better workflow)" title="Direct link to A local registry (the better workflow)" translate="no">​</a></h2>
<p><code>kind load</code> copies the image into every node on every build, which gets slow. A local registry the
cluster can pull from is faster and closer to reality:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockTitle_OeMC">setup-registry.sh</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token shebang important" style="color:hsl(230, 8%, 24%);font-weight:bold">#!/usr/bin/env bash</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">set</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-euo</span><span class="token plain"> pipefail</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">reg_name</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string" style="color:hsl(119, 34%, 47%)">'kind-registry'</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">reg_port</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string" style="color:hsl(119, 34%, 47%)">'5001'</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># 1. Start a registry container if it is not already running</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$(</span><span class="token string variable function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token string variable" style="color:hsl(221, 87%, 60%)"> inspect </span><span class="token string variable parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token string variable" style="color:hsl(221, 87%, 60%)"> </span><span class="token string variable string" style="color:hsl(119, 34%, 47%)">'{{.State.Running}}'</span><span class="token string variable" style="color:hsl(221, 87%, 60%)"> </span><span class="token string variable string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable string variable" style="color:hsl(221, 87%, 60%)">${reg_name}</span><span class="token string variable string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)"> </span><span class="token string variable operator file-descriptor important" style="color:hsl(230, 8%, 24%);font-weight:bold">2</span><span class="token string variable operator" style="color:hsl(221, 87%, 60%)">&gt;</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">/dev/null </span><span class="token string variable operator" style="color:hsl(221, 87%, 60%)">||</span><span class="token string variable" style="color:hsl(221, 87%, 60%)"> </span><span class="token string variable boolean" style="color:hsl(35, 99%, 36%)">true</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">)</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">!=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'true'</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-d</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--restart</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">always </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-p</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"127.0.0.1:</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">${reg_port}</span><span class="token string" style="color:hsl(119, 34%, 47%)">:5000"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--network</span><span class="token plain"> bridge </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--name</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">${reg_name}</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"> registry:2</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fi</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># 2. Create the cluster, telling containerd where to find the mirror</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">cat</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;&lt;</span><span class="token string" style="color:hsl(119, 34%, 47%)">EOF</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)"> </span><span class="token string bash punctuation operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)"> kind create cluster </span><span class="token string bash punctuation parameter variable" style="color:hsl(221, 87%, 60%)">--name</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)"> nativehub </span><span class="token string bash punctuation parameter variable" style="color:hsl(221, 87%, 60%)">--config</span><span class="token string bash punctuation operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token string" style="color:hsl(119, 34%, 47%)"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">kind: Cluster</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">apiVersion: kind.x-k8s.io/v1alpha4</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">containerdConfigPatches:</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">  - |-</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">    [plugins."io.containerd.grpc.v1.cri".registry]</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">      config_path = "/etc/containerd/certs.d"</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">nodes:</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">  - role: control-plane</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">  - role: worker</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">  - role: worker</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">EOF</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># 3. Point each node at the registry</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">REGISTRY_DIR</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string" style="color:hsl(119, 34%, 47%)">"/etc/containerd/certs.d/localhost:</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">${reg_port}</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> </span><span class="token for-or-select variable" style="color:hsl(221, 87%, 60%)">node</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> </span><span class="token variable" style="color:hsl(221, 87%, 60%)">$(</span><span class="token variable" style="color:hsl(221, 87%, 60%)">kind get nodes </span><span class="token variable parameter variable" style="color:hsl(221, 87%, 60%)">--name</span><span class="token variable" style="color:hsl(221, 87%, 60%)"> nativehub</span><span class="token variable" style="color:hsl(221, 87%, 60%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">do</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">${node}</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">mkdir</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-p</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">${REGISTRY_DIR}</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token function" style="color:hsl(221, 87%, 60%)">cat</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;&lt;</span><span class="token string" style="color:hsl(119, 34%, 47%)">EOF</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)"> </span><span class="token string bash punctuation operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)"> </span><span class="token string bash punctuation function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)"> </span><span class="token string bash punctuation builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)"> </span><span class="token string bash punctuation parameter variable" style="color:hsl(221, 87%, 60%)">-i</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)"> </span><span class="token string bash punctuation string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string bash punctuation string variable" style="color:hsl(221, 87%, 60%)">${node}</span><span class="token string bash punctuation string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)"> </span><span class="token string bash punctuation function" style="color:hsl(221, 87%, 60%)">cp</span><span class="token string bash punctuation" style="color:hsl(119, 34%, 47%)"> /dev/stdin </span><span class="token string bash punctuation string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string bash punctuation string variable" style="color:hsl(221, 87%, 60%)">${REGISTRY_DIR}</span><span class="token string bash punctuation string" style="color:hsl(119, 34%, 47%)">/hosts.toml"</span><span class="token string" style="color:hsl(119, 34%, 47%)"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">[host."http://</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">${reg_name}</span><span class="token string" style="color:hsl(119, 34%, 47%)">:5000"]</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token string" style="color:hsl(119, 34%, 47%)">EOF</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">done</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># 4. Join the registry to kind's network so the nodes can reach it by name</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> network connect </span><span class="token string" style="color:hsl(119, 34%, 47%)">"kind"</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">${reg_name}</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"> </span><span class="token operator file-descriptor important" style="color:hsl(230, 8%, 24%);font-weight:bold">2</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;</span><span class="token plain">/dev/null </span><span class="token operator" style="color:hsl(221, 87%, 60%)">||</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(35, 99%, 36%)">true</span><br></div></code></pre></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">chmod</span><span class="token plain"> +x setup-registry.sh </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;&amp;</span><span class="token plain"> ./setup-registry.sh</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> build </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-t</span><span class="token plain"> localhost:5001/myapp:dev </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> push localhost:5001/myapp:dev</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Reference it in your manifests as localhost:5001/myapp:dev</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="simulate-a-node-failure">Simulate a node failure<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#simulate-a-node-failure" class="hash-link" aria-label="Direct link to Simulate a node failure" title="Direct link to Simulate a node failure" translate="no">​</a></h2>
<p>This is the best reason to run multiple nodes locally.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Watch in one terminal</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">app</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> wide </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--watch</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Kill a node in another</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> stop nativehub-worker2</span><br></div></code></pre></div></div>
<p>Within about 40 seconds the node controller marks the node <code>NotReady</code>; after the eviction timeout
(five minutes by default) its Pods are marked for deletion and the ReplicaSet schedules replacements
on the surviving worker. Bring it back:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> start nativehub-worker2</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get nodes</span><br></div></code></pre></div></div>
<p>You can also practise a graceful drain, which is what a real node upgrade does:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl drain nativehub-worker --ignore-daemonsets --delete-emptydir-data</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> wide          </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># everything moved off</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl uncordon nativehub-worker</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="everyday-kind-commands">Everyday kind commands<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#everyday-kind-commands" class="hash-link" aria-label="Direct link to Everyday kind commands" title="Direct link to Everyday kind commands" translate="no">​</a></h2>
<table><thead><tr><th>Command</th><th>What it does</th></tr></thead><tbody><tr><td><code>kind get clusters</code></td><td>List clusters</td></tr><tr><td><code>kind get nodes --name X</code></td><td>List a cluster's node containers</td></tr><tr><td><code>kind load docker-image IMG --name X</code></td><td>Copy a local image into the nodes</td></tr><tr><td><code>kind export logs ./logs --name X</code></td><td>Dump all node and control-plane logs</td></tr><tr><td><code>kind delete cluster --name X</code></td><td>Tear it all down</td></tr><tr><td><code>docker exec -it X-worker bash</code></td><td>Shell into a node</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-kind-is-not-the-right-tool">When kind is not the right tool<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#when-kind-is-not-the-right-tool" class="hash-link" aria-label="Direct link to When kind is not the right tool" title="Direct link to When kind is not the right tool" translate="no">​</a></h2>
<p>kind is excellent for CI, controller development, and learning. Its limits are real:</p>
<ul>
<li class=""><strong>No cloud LoadBalancer.</strong> <code>type: LoadBalancer</code> Services stay <code>&lt;pending&gt;</code> unless you install
MetalLB or run <code>cloud-provider-kind</code>.</li>
<li class=""><strong>No persistent storage beyond the local-path provisioner</strong>, which is <code>ReadWriteOnce</code> and
node-local — you cannot exercise real CSI behaviour.</li>
<li class=""><strong>Nodes share the host kernel</strong>, so kernel-level differences from your production nodes will not
show up.</li>
<li class=""><strong>Everything is ephemeral by design.</strong> Deleting the cluster deletes the data.</li>
</ul>
<p>For a persistent single-node environment, minikube or k3d suit better. For anything involving cloud
integrations, nothing substitutes for a real cluster.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="clean-up">Clean up<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#clean-up" class="hash-link" aria-label="Direct link to Clean up" title="Direct link to Clean up" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kind delete cluster </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--name</span><span class="token plain"> nativehub</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> stop kind-registry </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">rm</span><span class="token plain"> kind-registry</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://nativehub-chi.vercel.app/blog/multi-node-cluster-kind#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/docs/guides/deploy-first-app">Deploy your first app to Kubernetes</a> — the natural next step.</li>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/docs/learn/kubernetes-networking">Kubernetes networking</a> — what the Ingress above is doing.</li>
<li class="">The <a href="https://kind.sigs.k8s.io/" target="_blank" rel="noopener noreferrer" class="">official kind documentation</a>.</li>
</ul>]]></content>
        <author>
            <name>Md Raiyan</name>
            <uri>https://github.com/mdryaaan</uri>
        </author>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="Local development" term="Local development"/>
        <category label="Tooling" term="Tooling"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[A practical guide to Kubernetes networking basics]]></title>
        <id>https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics</id>
        <link href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics"/>
        <updated>2026-04-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Services, ClusterIP vs NodePort vs LoadBalancer, how pod-to-pod traffic actually flows, and how DNS resolution works inside a cluster.]]></summary>
        <content type="html"><![CDATA[<p>Kubernetes networking has a reputation for being impenetrable. It mostly is not — there are about
five ideas, and the confusion comes from the fact that ClusterIPs are virtual addresses that no
machine actually owns. Once that clicks, the rest follows.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-rule-everything-is-built-on">The rule everything is built on<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#the-rule-everything-is-built-on" class="hash-link" aria-label="Direct link to The rule everything is built on" title="Direct link to The rule everything is built on" translate="no">​</a></h2>
<p>A conforming Kubernetes network must satisfy three requirements:</p>
<ol>
<li class="">Every Pod has its own unique IP address.</li>
<li class=""><strong>Any Pod can reach any other Pod by IP, across nodes, without NAT.</strong></li>
<li class="">Agents on a node can reach every Pod on that node.</li>
</ol>
<p>There is no port mapping between Pods. If your container listens on <code>:8080</code>, another Pod connects to
<code>&lt;pod-ip&gt;:8080</code> directly. This is deliberately unlike Docker's default bridge networking, where you
publish ports to the host and everything talks through NAT.</p>
<p>Kubernetes itself does not implement this. A <strong>CNI plugin</strong> — Calico, Cilium, Flannel, or your cloud
provider's VPC-native plugin — does. This is why a fresh cluster with no CNI installed leaves every
Pod <code>Pending</code> and every node reporting <code>NetworkReady=false</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pod-ips-are-worthless-to-you">Pod IPs are worthless to you<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#pod-ips-are-worthless-to-you" class="hash-link" aria-label="Direct link to Pod IPs are worthless to you" title="Direct link to Pod IPs are worthless to you" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> wide</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">NAME                   READY   STATUS    IP            NODE</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">web-7d4b9c6f85-2xk4l   1/1     Running   10.244.1.14   worker-1</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">web-7d4b9c6f85-9mfqz   1/1     Running   10.244.2.7    worker-2</span><br></div></code></pre></div></div>
<p>Those addresses are real and reachable — and completely disposable. Delete a Pod and its IP is gone
forever; the replacement gets a new one. Any configuration containing a Pod IP is already wrong.</p>
<p>This impermanence is the entire reason Services exist.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="services-a-stable-name-for-a-moving-target">Services: a stable name for a moving target<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#services-a-stable-name-for-a-moving-target" class="hash-link" aria-label="Direct link to Services: a stable name for a moving target" title="Direct link to Services: a stable name for a moving target" translate="no">​</a></h2>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockTitle_OeMC">service.yaml</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token key atrule" style="color:hsl(35, 99%, 36%)">apiVersion</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">kind</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> Service</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">metadata</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">spec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> ClusterIP</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">selector</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">app</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># matches POD labels</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">ports</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> http</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">port</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">80</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># the port the Service answers on</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">targetPort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8080</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># the port on the Pod</span><br></div></code></pre></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain"> service.yaml</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get svc web</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">NAME   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">web    ClusterIP   10.96.171.42   &lt;none&gt;        80/TCP</span><br></div></code></pre></div></div>
<p><code>10.96.171.42</code> is stable for the Service's whole lifetime. Behind it, the <strong>EndpointSlice
controller</strong> watches for Pods matching the selector and keeps a list of the <strong>ready</strong> ones:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get endpointslices </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> kubernetes.io/service-name</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> yaml </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-A2</span><span class="token plain"> addresses</span><br></div></code></pre></div></div>
<div style="margin-top:1.25rem"></div>
<p>Two consequences worth internalising:</p>
<ul>
<li class="">The selector matches <strong>Pod</strong> labels, not the Deployment's labels. They are often different, and
this is the number one cause of a Service that resolves but connects to nothing.</li>
<li class="">Only <strong>ready</strong> Pods are listed. If your readiness probe is failing, the endpoint list is empty and
connections are refused — the Service is working exactly as designed.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-four-service-types">The four Service types<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#the-four-service-types" class="hash-link" aria-label="Direct link to The four Service types" title="Direct link to The four Service types" translate="no">​</a></h2>
<table><thead><tr><th>Type</th><th>What it adds</th><th>Reachable from</th></tr></thead><tbody><tr><td><strong>ClusterIP</strong></td><td>A virtual IP inside the cluster</td><td>Inside the cluster only</td></tr><tr><td><strong>NodePort</strong></td><td>ClusterIP + a port on every node (30000–32767)</td><td>Outside, via <code>&lt;node-ip&gt;:&lt;nodePort&gt;</code></td></tr><tr><td><strong>LoadBalancer</strong></td><td>NodePort + a cloud load balancer</td><td>The internet</td></tr><tr><td><strong>ExternalName</strong></td><td>A CNAME record only, no proxying</td><td>Inside the cluster, resolving elsewhere</td></tr></tbody></table>
<p>They are <strong>cumulative</strong>. A LoadBalancer Service still has a NodePort and still has a ClusterIP; the
cloud load balancer simply forwards to that NodePort on each node.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="clusterip--the-default">ClusterIP — the default<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#clusterip--the-default" class="hash-link" aria-label="Direct link to ClusterIP — the default" title="Direct link to ClusterIP — the default" translate="no">​</a></h3>
<p>Internal only. Use it for everything that is not deliberately exposed: databases, internal APIs,
caches. Practically every Service in a cluster should be this type.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="nodeport--mostly-for-development">NodePort — mostly for development<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#nodeport--mostly-for-development" class="hash-link" aria-label="Direct link to NodePort — mostly for development" title="Direct link to NodePort — mostly for development" translate="no">​</a></h3>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token key atrule" style="color:hsl(35, 99%, 36%)">spec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> NodePort</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">ports</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">port</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">80</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">targetPort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">nodePort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">30080</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># optional; auto-assigned from 30000-32767 if omitted</span><br></div></code></pre></div></div>
<p>Every node now listens on 30080 and forwards to the Service, whether or not that node runs a
backing Pod. It is useful with kind or minikube; in production it means high, non-standard ports and
no TLS termination.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="loadbalancer--the-production-door">LoadBalancer — the production door<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#loadbalancer--the-production-door" class="hash-link" aria-label="Direct link to LoadBalancer — the production door" title="Direct link to LoadBalancer — the production door" translate="no">​</a></h3>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token key atrule" style="color:hsl(35, 99%, 36%)">spec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> LoadBalancer</span><br></div></code></pre></div></div>
<p>The cloud-controller-manager provisions a real load balancer and writes its address into
<code>status.loadBalancer</code>. The catch is cost and count: <strong>one cloud load balancer per Service</strong>. Ten
HTTP services means ten load balancers and ten bills.</p>
<p>That is what <strong>Ingress</strong> and the <strong>Gateway API</strong> exist to solve — a single load balancer fronting an
in-cluster proxy that routes by hostname and path.</p>
<div style="margin-top:1.25rem"></div>
<p>There is one setting on NodePort and LoadBalancer Services worth knowing:
<code>externalTrafficPolicy</code>. The default, <code>Cluster</code>, lets any node forward to a Pod on any other node —
even balancing, but the extra hop SNATs the packet and your application sees the node's IP instead
of the real client's. Setting it to <code>Local</code> forwards only to Pods on the receiving node, preserving
the client IP at the cost of uneven balancing when Pods are unevenly spread.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-a-clusterip-actually-works">How a ClusterIP actually works<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#how-a-clusterip-actually-works" class="hash-link" aria-label="Direct link to How a ClusterIP actually works" title="Direct link to How a ClusterIP actually works" translate="no">​</a></h2>
<p>This is the part that surprises people: <strong>nothing is listening on the ClusterIP.</strong> No interface has
that address. Nothing answers ARP for it. You cannot ping it meaningfully.</p>
<p>It exists only as a set of kernel rules:</p>
<ol>
<li class=""><code>kube-proxy</code> runs on every node and watches Services and EndpointSlices from the API server.</li>
<li class="">In <strong>iptables mode</strong> (the default) it writes NAT rules: packets destined for <code>10.96.171.42:80</code>
are DNAT'd to one of the ready backing Pod IPs, chosen at random with equal probability.</li>
<li class="">In <strong>IPVS mode</strong> it programs kernel IPVS virtual servers instead — better scaling past a few
thousand Services, and real balancing algorithms.</li>
</ol>
<p>The rewrite happens in the kernel on the <strong>sending</strong> node, before the packet ever leaves. kube-proxy
is not in the data path; it only maintains rules. That is why kube-proxy can be restarted without
dropping connections.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># On a node: the rules kube-proxy installed</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> iptables </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-t</span><span class="token plain"> nat </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-L</span><span class="token plain"> KUBE-SERVICES </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-n</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">head</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-20</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pod-to-pod-step-by-step">Pod-to-pod, step by step<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#pod-to-pod-step-by-step" class="hash-link" aria-label="Direct link to Pod-to-pod, step by step" title="Direct link to Pod-to-pod, step by step" translate="no">​</a></h2>
<p>A Pod in namespace <code>frontend</code> calls <code>http://web.backend.svc.cluster.local</code>:</p>
<ol>
<li class=""><strong>DNS.</strong> The request goes to CoreDNS, which returns the Service's ClusterIP — say
<code>10.96.171.42</code>.</li>
<li class=""><strong>Connect.</strong> The Pod opens a TCP connection to <code>10.96.171.42:80</code>.</li>
<li class=""><strong>DNAT.</strong> As the packet leaves the Pod's network namespace it hits the node's NAT table.
kube-proxy's rules rewrite the destination to a ready Pod, <code>10.244.2.7:8080</code>.</li>
<li class=""><strong>Route.</strong> The CNI plugin delivers it — over the local bridge if that Pod is on this node, or
across the node network (VXLAN tunnel, BGP route, or native VPC routing) if it is not.</li>
<li class=""><strong>Reply.</strong> conntrack un-NATs the response, so the client sees a reply from the address it dialled.</li>
</ol>
<p>The Pod never knew it was load balanced. It dialled one address and got an answer.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dns-inside-the-cluster">DNS inside the cluster<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#dns-inside-the-cluster" class="hash-link" aria-label="Direct link to DNS inside the cluster" title="Direct link to DNS inside the cluster" translate="no">​</a></h2>
<p>CoreDNS runs as a Deployment in <code>kube-system</code>, exposed by its own ClusterIP Service. The kubelet
writes every Pod's <code>/etc/resolv.conf</code> to point at it:</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockTitle_OeMC">/etc/resolv.conf in a Pod in namespace 'frontend'</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">nameserver 10.96.0.10</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">search frontend.svc.cluster.local svc.cluster.local cluster.local</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">options ndots:5</span><br></div></code></pre></div></div>
<p>The canonical record is <code>&lt;service&gt;.&lt;namespace&gt;.svc.cluster.local</code>, and the search path lets you
abbreviate:</p>
<table><thead><tr><th>From a Pod in <code>frontend</code>, this query…</th><th>resolves to</th></tr></thead><tbody><tr><td><code>web</code></td><td>the <code>web</code> Service in <code>frontend</code></td></tr><tr><td><code>web.backend</code></td><td>the <code>web</code> Service in <code>backend</code></td></tr><tr><td><code>web.backend.svc.cluster.local</code></td><td>the same, fully qualified — no search expansion</td></tr></tbody></table>
<p>Cross-namespace calls need at least <code>&lt;service&gt;.&lt;namespace&gt;</code>. A bare <code>web</code> will only ever find a
Service in the caller's own namespace.</p>
<div style="margin-top:1.25rem"></div>
<p><strong>The <code>ndots:5</code> gotcha.</strong> Any name with fewer than five dots is tried against every search suffix
<em>before</em> being tried as written. Looking up <code>api.github.com</code> (two dots) therefore issues
<code>api.github.com.frontend.svc.cluster.local</code>, then <code>...svc.cluster.local</code>, then <code>...cluster.local</code>,
and only then the real query — four wasted round trips per lookup. For hot external calls, use a
trailing dot (<code>api.github.com.</code>) to force an absolute lookup, or set a lower <code>ndots</code> in the Pod's
<code>dnsConfig</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="headless-services">Headless Services<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#headless-services" class="hash-link" aria-label="Direct link to Headless Services" title="Direct link to Headless Services" translate="no">​</a></h2>
<p>Setting <code>clusterIP: None</code> allocates no virtual IP and installs no proxy rules. DNS then returns the
A records of the individual Pods:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">$ </span><span class="token function" style="color:hsl(221, 87%, 60%)">nslookup</span><span class="token plain"> db.default.svc.cluster.local</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Address: </span><span class="token number" style="color:hsl(35, 99%, 36%)">10.244</span><span class="token plain">.1.21</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Address: </span><span class="token number" style="color:hsl(35, 99%, 36%)">10.244</span><span class="token plain">.2.33</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Address: </span><span class="token number" style="color:hsl(35, 99%, 36%)">10.244</span><span class="token plain">.3.9</span><br></div></code></pre></div></div>
<p>This is what StatefulSets use. Combined with a StatefulSet's stable names, each replica gets its own
resolvable record — <code>db-0.db.default.svc.cluster.local</code> — which is exactly what a database client
needs to distinguish a primary from a replica.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="debugging-three-commands-in-order">Debugging: three commands in order<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#debugging-three-commands-in-order" class="hash-link" aria-label="Direct link to Debugging: three commands in order" title="Direct link to Debugging: three commands in order" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># 1. Does the Service have any endpoints?</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get endpointslices </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> kubernetes.io/service-name</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Empty =&gt; selector mismatch or failing readiness probe. Stop here and fix it.</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># 2. Does DNS resolve?</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl run netshoot </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-it</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--restart</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">Never </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--image</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">nicolaka/netshoot -- </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token function" style="color:hsl(221, 87%, 60%)">nslookup</span><span class="token plain"> web.default.svc.cluster.local</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># 3. Does the Pod itself answer, bypassing the Service?</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">exec</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-it</span><span class="token plain"> netshoot -- </span><span class="token function" style="color:hsl(221, 87%, 60%)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-sv</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">10.244</span><span class="token plain">.2.7:8080</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Works =&gt; Service/kube-proxy problem. Fails =&gt; application or CNI problem.</span><br></div></code></pre></div></div>
<p>That third step is the one that saves the most time: it splits "the Service is misconfigured" from
"the application is not listening" in a single command.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-five-ideas">The five ideas<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#the-five-ideas" class="hash-link" aria-label="Direct link to The five ideas" title="Direct link to The five ideas" translate="no">​</a></h2>
<ol>
<li class="">Every Pod gets a real, routable IP — and it is disposable.</li>
<li class="">A <strong>Service</strong> is a stable virtual IP over a label-selected set of <strong>ready</strong> Pods.</li>
<li class="">That virtual IP is only kernel NAT rules, maintained by <strong>kube-proxy</strong>. Nothing listens on it.</li>
<li class=""><strong>CoreDNS</strong> maps <code>service.namespace.svc.cluster.local</code> to that virtual IP, and <code>ndots:5</code> makes
short names cheap and external names expensive.</li>
<li class="">Service types are cumulative: LoadBalancer contains NodePort contains ClusterIP.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://nativehub-chi.vercel.app/blog/kubernetes-networking-basics#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/docs/learn/kubernetes-networking">Kubernetes networking</a> — Ingress, Gateway API, and
NetworkPolicy in more depth.</li>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/docs/guides/debugging-pod-failures">Debugging pod failures</a> — when it is not the network.</li>
<li class="">The official <a href="https://kubernetes.io/docs/concepts/services-networking/" target="_blank" rel="noopener noreferrer" class="">Services, Load Balancing, and Networking</a>
documentation.</li>
</ul>]]></content>
        <author>
            <name>Md Raiyan</name>
            <uri>https://github.com/mdryaaan</uri>
        </author>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="Networking" term="Networking"/>
        <category label="Fundamentals" term="Fundamentals"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Docker vs containerd vs runc — what's actually running your containers]]></title>
        <id>https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc</id>
        <link href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc"/>
        <updated>2026-03-21T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Docker is a toolkit, containerd is the daemon that manages container lifecycle, and runc is the binary that actually asks the kernel for a container. Here is the real layering.]]></summary>
        <content type="html"><![CDATA[<p>"Kubernetes removed Docker support" caused a lot of confusion in 2021, and the confusion persists
because most people never had a reason to learn what sits underneath <code>docker run</code>. The stack is
layered, each layer has a specification, and once you see the boundaries the whole thing is
straightforward.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-stack-top-to-bottom">The stack, top to bottom<a href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc#the-stack-top-to-bottom" class="hash-link" aria-label="Direct link to The stack, top to bottom" title="Direct link to The stack, top to bottom" translate="no">​</a></h2>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">docker CLI                    what you type</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    │  REST over a Unix socket</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    ▼</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">dockerd                       image build, networking, volumes, Compose</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    │  gRPC</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    ▼</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">containerd                    image pull/store, container lifecycle, snapshots</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    │  spawns one shim per container</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    ▼</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">containerd-shim-runc-v2       keeps the container alive independently of containerd</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    │  exec</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    ▼</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">runc                          sets up namespaces + cgroups, then execs your process</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    │  syscalls: clone(), unshare(), setns(), pivot_root(), write to cgroupfs</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    ▼</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Linux kernel                  the only thing that actually "creates" a container</span><br></div></code></pre></div></div>
<p>Each arrow is a real, documented interface, not an implementation detail.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="runc-the-low-level-runtime">runc: the low-level runtime<a href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc#runc-the-low-level-runtime" class="hash-link" aria-label="Direct link to runc: the low-level runtime" title="Direct link to runc: the low-level runtime" translate="no">​</a></h2>
<p><strong>runc</strong> is a single static binary that implements the <a href="https://github.com/opencontainers/runtime-spec" target="_blank" rel="noopener noreferrer" class="">OCI Runtime
Specification</a>. Its entire job is: given a directory
on disk containing a root filesystem and a <code>config.json</code>, create the container the config describes
and run the process inside it.</p>
<p>It does not know what an image is. It cannot pull from a registry. It has no notion of tags,
networks, or volumes. It performs, roughly:</p>
<ol>
<li class=""><code>clone()</code> / <code>unshare()</code> with the requested namespace flags — new PID, mount, network, UTS, IPC,
and optionally user namespace.</li>
<li class="">Writes the resource limits into the cgroup filesystem.</li>
<li class="">Sets up mounts: <code>/proc</code>, <code>/sys</code>, <code>/dev</code>, and anything the config lists.</li>
<li class=""><code>pivot_root()</code> into the bundle's <code>rootfs</code>.</li>
<li class="">Drops capabilities, applies the seccomp filter, applies the AppArmor or SELinux label.</li>
<li class=""><code>execve()</code> the process from <code>process.args</code>.</li>
</ol>
<p>You can drive it by hand, which is the fastest way to make the abstraction concrete:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">mkdir</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-p</span><span class="token plain"> /tmp/mycontainer/rootfs </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&amp;&amp;</span><span class="token plain"> </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">cd</span><span class="token plain"> /tmp/mycontainer</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Borrow a root filesystem from an existing image</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">export</span><span class="token plain"> </span><span class="token variable" style="color:hsl(221, 87%, 60%)">$(</span><span class="token variable function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token variable" style="color:hsl(221, 87%, 60%)"> create alpine:3.21</span><span class="token variable" style="color:hsl(221, 87%, 60%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">tar</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-C</span><span class="token plain"> rootfs </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-xf</span><span class="token plain"> -</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Generate a default config.json</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">runc spec</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Run it — no Docker, no containerd, no daemon</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> runc run demo</span><br></div></code></pre></div></div>
<p>You are now in a shell inside a container that no container manager knows about. That is all a
container fundamentally is.</p>
<div style="margin-top:1.25rem"></div>
<p>Alternative low-level runtimes implement the same spec and slot into the same position: <strong>crun</strong>
(written in C, faster startup, lower memory), <strong>gVisor/runsc</strong> (a user-space kernel that intercepts
syscalls), and <strong>Kata Containers</strong> (each container in a lightweight VM). Because the interface is
specified, swapping them is a configuration change, not a migration.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="containerd-the-daemon">containerd: the daemon<a href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc#containerd-the-daemon" class="hash-link" aria-label="Direct link to containerd: the daemon" title="Direct link to containerd: the daemon" translate="no">​</a></h2>
<p><strong>containerd</strong> is a long-running daemon and a CNCF graduated project. It handles everything runc
deliberately does not:</p>
<ul>
<li class="">Pulling images from registries and verifying their digests</li>
<li class="">Unpacking image layers into snapshots (overlayfs, btrfs, devmapper)</li>
<li class="">Managing the container lifecycle: create, start, stop, delete, and exec</li>
<li class="">Attaching stdio, collecting exit codes, and reporting events</li>
<li class="">Namespacing its own state, so Docker and Kubernetes can share one containerd without collisions</li>
</ul>
<p>When containerd starts a container it does not fork runc as a child. It launches a <strong>shim</strong>
(<code>containerd-shim-runc-v2</code>), one per container, and the shim invokes runc. This indirection is the
reason containerd can be restarted or upgraded without killing running containers: the shim is the
container's parent and keeps holding its stdio and exit status, so containerd can reconnect
afterwards.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># ctr is containerd's low-level debug CLI — not a Docker replacement</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> ctr namespaces list</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> ctr </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-n</span><span class="token plain"> k8s.io images list </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">head</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> ctr </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-n</span><span class="token plain"> k8s.io containers list</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># nerdctl is the Docker-compatible CLI for containerd</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">nerdctl run </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-d</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-p</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8080</span><span class="token plain">:80 nginx:1.27-alpine</span><br></div></code></pre></div></div>
<p>Note the <code>k8s.io</code> namespace. On a Kubernetes node, that is where the kubelet's containers live —
which is exactly why <code>docker ps</code> on such a node shows nothing.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="docker-the-developer-toolkit">Docker: the developer toolkit<a href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc#docker-the-developer-toolkit" class="hash-link" aria-label="Direct link to Docker: the developer toolkit" title="Direct link to Docker: the developer toolkit" translate="no">​</a></h2>
<p><strong>Docker</strong> is the layer above containerd, and it is where the things developers care about actually
live:</p>
<ul>
<li class=""><code>docker build</code> and BuildKit — Dockerfiles, layer caching, multi-stage builds</li>
<li class="">Networking: bridge networks, port publishing, embedded DNS</li>
<li class="">Volume management</li>
<li class="">Docker Compose</li>
<li class="">The user-facing CLI and REST API</li>
</ul>
<p>Docker donated containerd to the CNCF in 2017 and then adopted it internally. Since Docker 18.09,
<code>docker run</code> ends up as a gRPC call to containerd, which spawns a shim, which execs runc.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># The chain, visible in the process tree</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-d</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--name</span><span class="token plain"> demo nginx:1.27-alpine</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">ps</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-ef</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--forest</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-E</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'containerd|nginx'</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">head</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-the-cri-fits">Where the CRI fits<a href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc#where-the-cri-fits" class="hash-link" aria-label="Direct link to Where the CRI fits" title="Direct link to Where the CRI fits" translate="no">​</a></h2>
<p>Kubernetes never wanted to talk to a specific vendor's daemon, so it defines the <strong>Container Runtime
Interface</strong> — a gRPC API the kubelet uses for image and container operations. Any runtime
implementing CRI can back a Kubernetes node.</p>
<ul>
<li class=""><strong>containerd</strong> implements CRI natively via its built-in CRI plugin.</li>
<li class=""><strong>CRI-O</strong> is a runtime built solely for Kubernetes: CRI in, OCI runtime out, nothing else.</li>
<li class=""><strong>Docker</strong> never implemented CRI. The kubelet used a built-in adapter called <strong>dockershim</strong> to
translate.</li>
</ul>
<p>That adapter is what was removed in Kubernetes 1.24. Nothing about "Docker images" was deprecated —
they are OCI images, and every CRI runtime runs them unchanged. What went away was the kubelet's
special-case translation layer for talking to <code>dockerd</code>. Since Docker already sat <em>on top of</em>
containerd, removing it from the node path simply deleted a hop:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Before 1.24:  kubelet → dockershim → dockerd → containerd → shim → runc</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">After  1.24:  kubelet → CRI ───────────────→ containerd → shim → runc</span><br></div></code></pre></div></div>
<div style="margin-top:1.25rem"></div>
<p><code>crictl</code> is the debugging CLI for whatever CRI runtime a node uses:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> crictl </span><span class="token function" style="color:hsl(221, 87%, 60%)">ps</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> crictl images</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> crictl logs </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token plain">container-id</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">sudo</span><span class="token plain"> crictl inspect </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token plain">container-id</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-three-specifications">The three specifications<a href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc#the-three-specifications" class="hash-link" aria-label="Direct link to The three specifications" title="Direct link to The three specifications" translate="no">​</a></h2>
<p>The reason all of this interoperates is that the Open Container Initiative standardised the
boundaries:</p>
<table><thead><tr><th>Specification</th><th>Defines</th><th>Consumed by</th></tr></thead><tbody><tr><td><strong>Image spec</strong></td><td>The layout of an image: layers, config, manifest, index</td><td>containerd, CRI-O, Podman, BuildKit</td></tr><tr><td><strong>Runtime spec</strong></td><td>A <em>bundle</em>: a <code>rootfs</code> directory plus <code>config.json</code></td><td>runc, crun, runsc, Kata</td></tr><tr><td><strong>Distribution spec</strong></td><td>The registry HTTP API for push and pull</td><td>Docker Hub, GHCR, ECR, Harbor, Zot</td></tr></tbody></table>
<p>An image built by <code>docker build</code>, pushed to GHCR, pulled by containerd, and run by crun crosses four
different implementations without anyone negotiating anything, because each hand-off is specified.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="so-which-one-do-i-use">So which one do I use?<a href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc#so-which-one-do-i-use" class="hash-link" aria-label="Direct link to So which one do I use?" title="Direct link to So which one do I use?" translate="no">​</a></h2>
<table><thead><tr><th>You are…</th><th>Use</th></tr></thead><tbody><tr><td>Developing on a laptop</td><td><strong>Docker Desktop</strong> or <strong>Podman Desktop</strong> — you want builds, Compose, and volumes</td></tr><tr><td>Running a Kubernetes node</td><td><strong>containerd</strong> (the default nearly everywhere) or <strong>CRI-O</strong></td></tr><tr><td>Debugging a Kubernetes node</td><td><strong>crictl</strong>, not <code>docker</code> — the kubelet's containers are in containerd's <code>k8s.io</code> namespace</td></tr><tr><td>Building images in CI</td><td><strong>BuildKit</strong> (via <code>docker buildx</code>), or <strong>Buildah</strong>/<strong>Kaniko</strong> for daemonless builds</td></tr><tr><td>Needing stronger isolation</td><td><strong>gVisor</strong> or <strong>Kata Containers</strong>, dropped in as the OCI runtime</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-one-sentence-summary">The one-sentence summary<a href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc#the-one-sentence-summary" class="hash-link" aria-label="Direct link to The one-sentence summary" title="Direct link to The one-sentence summary" translate="no">​</a></h2>
<p><strong>Docker</strong> is a developer toolkit that delegates to <strong>containerd</strong>, a daemon that manages images and
container lifecycle and delegates to <strong>runc</strong>, a binary that asks the <strong>kernel</strong> for namespaces and
cgroups and then execs your process. Kubernetes talks to containerd (or CRI-O) through the CRI and
skips Docker on the node entirely.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://nativehub-chi.vercel.app/blog/docker-vs-containerd-vs-runc#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/blog/what-is-oci-bundle">What is an OCI bundle?</a> — a close look at <code>config.json</code>.</li>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/docs/learn/docker-fundamentals">Docker fundamentals</a> — the layer model and Dockerfile practice.</li>
<li class="">The <a href="https://github.com/opencontainers/runtime-spec" target="_blank" rel="noopener noreferrer" class="">OCI runtime spec</a> and
<a href="https://github.com/containerd/containerd/blob/main/docs/README.md" target="_blank" rel="noopener noreferrer" class="">containerd architecture docs</a>.</li>
</ul>]]></content>
        <author>
            <name>Md Raiyan</name>
            <uri>https://github.com/mdryaaan</uri>
        </author>
        <category label="Containers" term="Containers"/>
        <category label="Runtimes" term="Runtimes"/>
        <category label="OCI" term="OCI"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Understanding Pods vs Deployments in Kubernetes]]></title>
        <id>https://nativehub-chi.vercel.app/blog/pods-vs-deployments</id>
        <link href="https://nativehub-chi.vercel.app/blog/pods-vs-deployments"/>
        <updated>2026-03-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A Pod is the smallest deployable unit. A Deployment manages ReplicaSets, which manage Pods. Understanding that three-level chain explains rollouts, rollbacks, and self-healing.]]></summary>
        <content type="html"><![CDATA[<p>Newcomers to Kubernetes almost always ask the same question in the same order: <em>what is a Pod, why
would I not just create one, and what does a Deployment add?</em> The answer is a three-level chain of
ownership, and once you can see it, most of Kubernetes' behaviour stops being surprising.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-pod-is-the-smallest-deployable-unit">A Pod is the smallest deployable unit<a href="https://nativehub-chi.vercel.app/blog/pods-vs-deployments#a-pod-is-the-smallest-deployable-unit" class="hash-link" aria-label="Direct link to A Pod is the smallest deployable unit" title="Direct link to A Pod is the smallest deployable unit" translate="no">​</a></h2>
<p>You cannot schedule a container. The smallest object Kubernetes will place on a node is a <strong>Pod</strong>:
one or more containers that share a network namespace and can share volumes.</p>
<p>Sharing the network namespace has a concrete consequence. Every container in a Pod sees the same
<code>localhost</code> and the same IP address, and they cannot bind the same port — two containers both
listening on <code>:8080</code> in one Pod is a port conflict, exactly as it would be on a single host.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockTitle_OeMC">pod.yaml</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token key atrule" style="color:hsl(35, 99%, 36%)">apiVersion</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">kind</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> Pod</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">metadata</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">labels</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">app</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">spec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">containers</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> nginx</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">image</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> nginxinc/nginx</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain">unprivileged</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain">1.27</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain">alpine</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">ports</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">containerPort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">resources</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">requests</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">cpu</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> 50m</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">memory</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> 64Mi</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">limits</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">memory</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> 128Mi</span><br></div></code></pre></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain"> pod.yaml</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pod web </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> wide</span><br></div></code></pre></div></div>
<p>This works. It is also a trap.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-a-bare-pod-is-not-enough">Why a bare Pod is not enough<a href="https://nativehub-chi.vercel.app/blog/pods-vs-deployments#why-a-bare-pod-is-not-enough" class="hash-link" aria-label="Direct link to Why a bare Pod is not enough" title="Direct link to Why a bare Pod is not enough" translate="no">​</a></h2>
<p>Delete it and see what happens:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl delete pod web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># No resources found in default namespace.</span><br></div></code></pre></div></div>
<p>Nothing brought it back, because nothing <em>owns</em> it. A Pod is a record of "this container should run
on this node." When the Pod goes away — you deleted it, the node was drained, the node caught fire
— that record is simply gone.</p>
<p>A bare Pod gives you:</p>
<ul>
<li class="">❌ No rescheduling after a node failure</li>
<li class="">❌ No way to run more than one copy without copy-pasting YAML</li>
<li class="">❌ No rolling update — changing the image means deleting and recreating, with downtime</li>
<li class="">❌ No rollback</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-chain-deployment--replicaset--pod">The chain: Deployment → ReplicaSet → Pod<a href="https://nativehub-chi.vercel.app/blog/pods-vs-deployments#the-chain-deployment--replicaset--pod" class="hash-link" aria-label="Direct link to The chain: Deployment → ReplicaSet → Pod" title="Direct link to The chain: Deployment → ReplicaSet → Pod" translate="no">​</a></h2>
<p>The fix is a controller. The most common one is a <strong>Deployment</strong>, and the crucial detail is that a
Deployment does not manage Pods directly:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Deployment  "I want 3 replicas of this Pod template"</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    │  owns</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    ▼</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">ReplicaSet  "I own exactly 3 Pods matching this exact template"</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    │  owns</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    ▼</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Pod  Pod  Pod</span><br></div></code></pre></div></div>
<p>Each level has one job:</p>
<table><thead><tr><th>Level</th><th>Responsibility</th></tr></thead><tbody><tr><td><strong>Deployment</strong></td><td>Manages <em>versions</em>. Creates a new ReplicaSet per Pod template, and orchestrates the shift of replicas between them.</td></tr><tr><td><strong>ReplicaSet</strong></td><td>Manages <em>count</em>. Keeps exactly N Pods matching one specific template alive.</td></tr><tr><td><strong>Pod</strong></td><td>Runs the containers.</td></tr></tbody></table>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockTitle_OeMC">deployment.yaml</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token key atrule" style="color:hsl(35, 99%, 36%)">apiVersion</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> apps/v1</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">kind</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> Deployment</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">metadata</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">spec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">replicas</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">3</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">revisionHistoryLimit</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">5</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">selector</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">matchLabels</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">app</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># immutable after creation</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">strategy</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> RollingUpdate</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">rollingUpdate</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">maxSurge</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># at most 4 Pods during a rollout</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">maxUnavailable</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># never fewer than 3 ready</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">template</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">metadata</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">labels</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">app</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> web </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># must satisfy spec.selector</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">spec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">      </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">containers</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> nginx</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">image</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> nginxinc/nginx</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain">unprivileged</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain">1.27</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain">alpine</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">ports</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">            </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">containerPort</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">          </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">readinessProbe</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">            </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">httpGet</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">              </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">path</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> /</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">              </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">port</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">            </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">initialDelaySeconds</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">            </span><span class="token key atrule" style="color:hsl(35, 99%, 36%)">periodSeconds</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">5</span><br></div></code></pre></div></div>
<p>Now the ownership is visible in the cluster:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-f</span><span class="token plain"> deployment.yaml</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get deploy,rs,pod </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">app</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">NAME                  READY   UP-TO-DATE   AVAILABLE</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">deployment.apps/web   3/3     3            3</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">NAME                             DESIRED   CURRENT   READY</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">replicaset.apps/web-7d4b9c6f85   3         3         3</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">NAME                       READY   STATUS    RESTARTS</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">pod/web-7d4b9c6f85-2xk4l   1/1     Running   0</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">pod/web-7d4b9c6f85-9mfqz   1/1     Running   0</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">pod/web-7d4b9c6f85-hd7vw   1/1     Running   0</span><br></div></code></pre></div></div>
<p>The Pod name is not random: <code>web-7d4b9c6f85-2xk4l</code> is <code>&lt;deployment&gt;-&lt;template-hash&gt;-&lt;random&gt;</code>. That
middle segment is a hash of the Pod template, and the ReplicaSet carries the same one. It is also
injected as a label, <code>pod-template-hash</code>, which is how each ReplicaSet claims only <em>its</em> Pods
without the templates' selectors colliding.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Ownership is recorded explicitly on the child object</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pod </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">app</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">jsonpath</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string" style="color:hsl(119, 34%, 47%)">'{.items[0].metadata.ownerReferences[0]}'</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">|</span><span class="token plain"> jq</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># { "apiVersion": "apps/v1", "kind": "ReplicaSet", "name": "web-7d4b9c6f85", ... }</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="self-healing-demonstrated">Self-healing, demonstrated<a href="https://nativehub-chi.vercel.app/blog/pods-vs-deployments#self-healing-demonstrated" class="hash-link" aria-label="Direct link to Self-healing, demonstrated" title="Direct link to Self-healing, demonstrated" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl delete pod </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">app</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web --field-selector</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">status.phase</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">Running </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--wait</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">false</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get pods </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">app</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web</span><br></div></code></pre></div></div>
<p>A replacement appears within seconds. Nothing special-cased "a Pod died". The ReplicaSet controller
runs the same loop it always runs: <em>desired 3, observed 2, create 1.</em> The identical loop is what
recovers from a node failure — the node controller marks the Pods on a dead node as terminating, the
count drops, and replacements are scheduled elsewhere.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-the-extra-replicaset-layer-earns-its-keep">Why the extra ReplicaSet layer earns its keep<a href="https://nativehub-chi.vercel.app/blog/pods-vs-deployments#why-the-extra-replicaset-layer-earns-its-keep" class="hash-link" aria-label="Direct link to Why the extra ReplicaSet layer earns its keep" title="Direct link to Why the extra ReplicaSet layer earns its keep" translate="no">​</a></h2>
<p>Change the image:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">set</span><span class="token plain"> image deployment/web </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">nginx</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">nginxinc/nginx-unprivileged:1.27.3-alpine</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl rollout status deployment/web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl get rs </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:hsl(221, 87%, 60%)">app</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">web</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">NAME             DESIRED   CURRENT   READY</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">web-7d4b9c6f85   0         0         0      &lt;- old template, scaled to zero</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">web-5f8c2d9b47   3         3         3      &lt;- new template</span><br></div></code></pre></div></div>
<p>The Deployment created a <strong>second</strong> ReplicaSet for the new template and moved replicas across one at
a time, respecting <code>maxSurge</code> and <code>maxUnavailable</code>, and waiting for each new Pod to pass its
readiness probe before retiring an old one.</p>
<p>The old ReplicaSet was kept at zero rather than deleted. That is the entire rollback mechanism:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl rollout </span><span class="token function" style="color:hsl(221, 87%, 60%)">history</span><span class="token plain"> deployment/web</span><br></div><div class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">kubectl rollout undo deployment/web</span><br></div></code></pre></div></div>
<p>Rolling back scales the previous ReplicaSet back up and the current one down. No image rebuild, no
registry pull of something new, no YAML archaeology — the previous desired state is still sitting
in the cluster. <code>revisionHistoryLimit</code> controls how many of these zero-scaled ReplicaSets are kept;
set it to <code>0</code> and you have nothing to roll back to.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-two-mistakes-everyone-makes-once">The two mistakes everyone makes once<a href="https://nativehub-chi.vercel.app/blog/pods-vs-deployments#the-two-mistakes-everyone-makes-once" class="hash-link" aria-label="Direct link to The two mistakes everyone makes once" title="Direct link to The two mistakes everyone makes once" translate="no">​</a></h2>
<p><strong>The selector must match the template labels.</strong> <code>spec.selector.matchLabels</code> and
<code>spec.template.metadata.labels</code> are separate fields and it is entirely possible to write a
Deployment where they disagree. The API server rejects it — <code>selector</code> does not match template
<code>labels</code> — but the error is easy to misread as a YAML problem.</p>
<p><strong>The selector is immutable.</strong> You cannot change <code>spec.selector</code> after creation. If you need
different labels, create a new Deployment and delete the old one. This is why version information
must never appear in the selector: the first upgrade that changes it will fail with <code>field is immutable</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-a-deployment-is-the-wrong-choice">When a Deployment is the wrong choice<a href="https://nativehub-chi.vercel.app/blog/pods-vs-deployments#when-a-deployment-is-the-wrong-choice" class="hash-link" aria-label="Direct link to When a Deployment is the wrong choice" title="Direct link to When a Deployment is the wrong choice" translate="no">​</a></h2>
<table><thead><tr><th>Controller</th><th>Use it when</th></tr></thead><tbody><tr><td><strong>Deployment</strong></td><td>Stateless, interchangeable replicas. Web servers, APIs, workers.</td></tr><tr><td><strong>StatefulSet</strong></td><td>Replicas need stable identity and their own storage. Databases, brokers, anything with a quorum.</td></tr><tr><td><strong>DaemonSet</strong></td><td>Exactly one Pod per node. Log shippers, CNI agents, node exporters.</td></tr><tr><td><strong>Job</strong> / <strong>CronJob</strong></td><td>Run to completion, once or on a schedule. Migrations, batch imports.</td></tr></tbody></table>
<p>A Deployment's Pods are deliberately anonymous — <code>web-7d4b9c6f85-2xk4l</code> means nothing, and Pod 2 is
not distinguishable from Pod 3. When identity matters (<code>db-0</code> must always reattach the same disk),
you want a StatefulSet instead.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-takeaway">The takeaway<a href="https://nativehub-chi.vercel.app/blog/pods-vs-deployments#the-takeaway" class="hash-link" aria-label="Direct link to The takeaway" title="Direct link to The takeaway" translate="no">​</a></h2>
<ul>
<li class="">A <strong>Pod</strong> is the unit of scheduling. Alone, it is unmanaged and disappears for good.</li>
<li class="">A <strong>ReplicaSet</strong> keeps N copies of one exact Pod template alive.</li>
<li class="">A <strong>Deployment</strong> manages ReplicaSets, giving you versioned rollouts and one-command rollback.</li>
</ul>
<p>Create Pods directly only for throwaway debugging (<code>kubectl run --rm -it</code>). For anything that should
survive the night, describe the desired state and let a controller converge on it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://nativehub-chi.vercel.app/blog/pods-vs-deployments#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/docs/learn/kubernetes-fundamentals">Kubernetes fundamentals</a> — the wider object model.</li>
<li class=""><a class="" href="https://nativehub-chi.vercel.app/docs/guides/deploy-first-app">Deploy your first app to Kubernetes</a> — this post, hands on.</li>
<li class=""><a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" target="_blank" rel="noopener noreferrer" class="">Deployments</a> in the
official documentation.</li>
</ul>]]></content>
        <author>
            <name>Md Raiyan</name>
            <uri>https://github.com/mdryaaan</uri>
        </author>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="Fundamentals" term="Fundamentals"/>
    </entry>
</feed>