<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Vsphere-Supervisor on The Nested Lab</title>
    <link>https://thenestedlab.com/tags/vsphere-supervisor/</link>
    <description>Recent content in Vsphere-Supervisor on The Nested Lab</description>
    <generator>Hugo</generator>
    <language>en-gb</language>
    <lastBuildDate>Wed, 16 Sep 2026 08:20:00 +0100</lastBuildDate>
    <atom:link href="https://thenestedlab.com/tags/vsphere-supervisor/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Nested ESXi inside an NSX VPC: the trunk-subnet design</title>
      <link>https://thenestedlab.com/posts/nested-esxi-nsx-vpc/</link>
      <pubDate>Wed, 16 Sep 2026 08:20:00 +0100</pubDate>
      <guid>https://thenestedlab.com/posts/nested-esxi-nsx-vpc/</guid>
      <description>Plain VPC subnets silently blackhole a nested ESXi host. Here&amp;rsquo;s why — and the trunk subnet + binding map design that makes nested labs work as an ordinary NSX VPC tenant, verified end to end.</description>
      <content:encoded><![CDATA[<p>The host booted clean. Management IP configured, services up, DCUI happy.
And every single packet it sent — ARP included — died silently.</p>
<p>That&rsquo;s how my first attempt at running nested ESXi inside an NSX VPC ended,
and the failure mode is nasty precisely because nothing <em>looks</em> wrong. If
you&rsquo;re trying to build nested vSphere labs on VCF 9 with VPC networking,
this post is the map of the minefield — and the design that gets you across
it, verified live.</p>
<h2 id="the-setup">The setup</h2>
<p>VCF 9.1, vSphere Supervisor with NSX VPC networking. The goal: deploy nested
ESXi hosts as ordinary VM Service VMs inside a tenant&rsquo;s VPC — no physical
fabric changes, no provider tickets, no special treatment. The kind of thing
you want for training pods, cert-study labs, or reproducing customer issues.</p>
<p>Nested ESXi needs what physical ESXi needs: a management network, vMotion,
vSAN — traditionally VLANs trunked to every host. But a VPC is an overlay
world. There are no VLANs to trunk. So what happens if you just attach the
nested host&rsquo;s vNIC to a normal VPC subnet?</p>
<h2 id="failure-1-the-silent-blackhole">Failure #1: the silent blackhole</h2>
<p>Here&rsquo;s the trap. A standard VPC subnet port gets <strong>address bindings</strong>: NSX
pins the exact IP + MAC it allocated to that vNIC, and SpoofGuard drops
everything else.</p>
<p>ESXi&rsquo;s vmk0 doesn&rsquo;t use the vNIC&rsquo;s MAC. It synthesises its own:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vmk0
</span></span><span class="line"><span class="cl">   MAC Address: 00:50:ac:1e:00:8c     &lt;- NOT the vNIC MAC (04:50:56:...)
</span></span></code></pre></div><p>So every frame the management interface sends carries a MAC the port doesn&rsquo;t
own. NSX drops it all — ARP, ping, everything — while the host itself boots
green and reports healthy. There is no error anywhere. You just can&rsquo;t reach
it, ever.</p>
<p><img alt="Standard VPC subnet port: SpoofGuard pins one IP+MAC; vmk0&rsquo;s synthesised MAC loses, silently" loading="lazy" src="/images/post1-blackhole.svg"></p>
<p>(There&rsquo;s a second trap stacked on top: VPC subnets run with DHCP deactivated,
so the appliance also sits at &ldquo;waiting for DHCP&rdquo; unless you inject static
addressing via OVF <code>guestinfo.*</code> properties. More on that below.)</p>
<h2 id="the-design-that-works-a-trunk-subnet--binding-maps">The design that works: a trunk subnet + binding maps</h2>
<p>The fix isn&rsquo;t a hack — it&rsquo;s a first-class NSX VPC construct that&rsquo;s barely
documented in the wild: <strong><code>SubnetConnectionBindingMap</code></strong>.</p>
<p>The idea:</p>
<ol>
<li>Create one ordinary VPC subnet to act as a <strong>trunk</strong> (<code>sn-trunk</code>). The
nested host&rsquo;s vNICs attach <em>only</em> here.</li>
<li>Create a normal VPC subnet per traditional network — <code>sn-mgmt</code>,
<code>sn-vmotion</code>, <code>sn-vsan</code>.</li>
<li>Bind each of those to the trunk with a <strong>binding map carrying a VLAN tag</strong>.
The nested host&rsquo;s vSwitch tags frames exactly as it would on metal; the
binding map strips the tag and delivers the frame into the right subnet.</li>
</ol>
<p>Pure L2 demultiplexing. One vNIC carries N VLANs, the VPC never routes on a
tag, and the physical fabric never sees any of it (the 802.1Q header rides
inside the Geneve overlay).</p>
<p>All of it is tenant-creatable through the supervisor as Kubernetes objects:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># sn-trunk and sn-mgmt are ordinary Private Subnets; the interesting object:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">crd.nsx.vmware.com/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">SubnetConnectionBindingMap</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">bm-mgmt}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">subnetName</span><span class="p">:</span><span class="w"> </span><span class="l">sn-mgmt         </span><span class="w"> </span><span class="c"># the map is a child of the VLAN subnet...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">targetSubnetName</span><span class="p">:</span><span class="w"> </span><span class="l">sn-trunk  </span><span class="w"> </span><span class="c"># ...and points AT the trunk</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vlanTrafficTag</span><span class="p">:</span><span class="w"> </span><span class="m">1610</span><span class="w">
</span></span></span></code></pre></div><p>That direction is easy to invert, so it&rsquo;s worth saying twice: <strong>the binding
map belongs to the VLAN subnet and points at the trunk</strong>, not the other way
round.</p>
<p><img alt="NSX: sn-trunk realized once per VPC, binding maps hanging off the VLAN subnets" loading="lazy" src="/images/ui/u11b-nsx-sntrunk-per-vpc.jpg"></p>
<p>On the nested host, nothing exotic — plain VST, like physical:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Name                Virtual Switch  Active Clients  VLAN ID
</span></span><span class="line"><span class="cl">------------------  --------------  --------------  -------
</span></span><span class="line"><span class="cl">Management Network  vSwitch0                     1     1610
</span></span><span class="line"><span class="cl">vMotion             vSwitch0                     1     1611
</span></span><span class="line"><span class="cl">vSAN                vSwitch0                     1     1612
</span></span></code></pre></div><p><img alt="Host Client: port groups on VLANs 1610 / 1611 / 1612" loading="lazy" src="/images/ui/u12a-hostclient-portgroups-vlans.jpg">
<em>The same three VLANs as the nested host sees them.</em></p>
<p>And because there&rsquo;s no DHCP in a VPC subnet, the nested-ESXi appliance gets
its identity through OVF properties in the VM Service spec:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">bootstrap</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vAppConfig</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- {<span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="nt">guestinfo.ipaddress, value</span><span class="p">:</span><span class="w"> </span>{<span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;172.30.0.40&#34;</span>}}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- {<span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="nt">guestinfo.netmask,   value</span><span class="p">:</span><span class="w"> </span>{<span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;255.255.255.224&#34;</span>}}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- {<span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="nt">guestinfo.gateway,   value</span><span class="p">:</span><span class="w"> </span>{<span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;172.30.0.33&#34;</span>}}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- {<span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="nt">guestinfo.vlan,     value</span><span class="p">:</span><span class="w"> </span>{<span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;1610&#34;</span>}}<span class="w">
</span></span></span></code></pre></div><h2 id="does-it-actually-work-the-receipts">Does it actually work? The receipts</h2>
<p>Two nested hosts, vNICs on <code>sn-trunk</code>, three VLANs. From host one:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[root@esx01:~] vmkping -c2 172.30.0.41            # mgmt, VLAN 1610
</span></span><span class="line"><span class="cl">3 packets transmitted, 3 packets received, 0% packet loss
</span></span><span class="line"><span class="cl">[root@esx01:~] vmkping -I vmk1 -c3 172.30.0.71    # vMotion, VLAN 1611
</span></span><span class="line"><span class="cl">3 packets transmitted, 3 packets received, 0% packet loss
</span></span><span class="line"><span class="cl">[root@esx01:~] vmkping -I vmk2 -c3 172.30.0.101   # vSAN, VLAN 1612
</span></span><span class="line"><span class="cl">3 packets transmitted, 3 packets received, 0% packet loss
</span></span></code></pre></div><p><img alt="Live capture: vmnic0 down, vMotion and vSAN VLANs still passing at 0% loss" loading="lazy" src="/images/demo-c6-nic-failover.jpg">
<em>The transcript that matters: fail the first NIC, and every VLAN keeps flowing on the second — captured live.</em></p>
<p>Two more results worth knowing before you design around this:</p>
<p><strong>Untagged frames are dropped.</strong> I put a probe vmk on the untagged
portgroup using the address NSX itself had allocated to the trunk port:
100% loss, empty ARP table, while tagged traffic flowed happily beside it.
Every network your nested host uses needs a VLAN and a binding map — there
is no untagged fallback.</p>
<p><strong>Failover behaves like real hardware.</strong> With two vNICs on the trunk teamed
active/active, <code>esxcli network nic down -n vmnic0</code> moved every VLAN onto
vmnic1 with zero loss — and the SSH session I was watching from never
dropped. The vmk MAC migrating between trunk ports mid-flow is exactly the
scenario that MAC-pinned standard ports would blackhole; the trunk carries
it fine.</p>
<h2 id="why-this-matters-outside-the-lab">Why this matters outside the lab</h2>
<p>Running whole vSphere environments <em>inside</em> a VPC turns the platform into
something most customers never had: a way to stand up complete, isolated
copies of infrastructure on demand, without a physical fabric change and
without waiting for anyone. That&rsquo;s what makes it commercially interesting:</p>
<ul>
<li><strong>Training and certification labs</strong> where every learner gets a real
vSphere environment, not a shared one.</li>
<li><strong>Reproducing a customer problem</strong> on a like-for-like copy instead of on
the customer&rsquo;s estate.</li>
<li><strong>Rehearsing upgrades and migrations</strong> end to end before the change
window, then throwing the copy away.</li>
<li><strong>Vendor and feature evaluations</strong> with real behaviour, at zero risk to
production.</li>
</ul>
<p>This is the design Comms-care uses to give every consultant a dedicated
environment, and the same pattern scales to a classroom or a proof-of-concept
factory.</p>
<h2 id="rules-learned">Rules learned</h2>
<ul>
<li>A nested ESXi vNIC on a <strong>standard</strong> VPC subnet is dead on arrival:
vmk0&rsquo;s synthesised MAC loses to SpoofGuard, silently.</li>
<li>Attach nested-host vNICs <strong>only to a trunk subnet</strong>; one binding map per
VLAN; the map lives under the VLAN subnet and points at the trunk.</li>
<li><strong>No DHCP in VPC subnets</strong> — bootstrap addressing via <code>guestinfo.*</code>
(appliances) or cloud-init (Linux). Static IP plans are a feature in a
lab anyway.</li>
<li>ESXi&rsquo;s default TCP/IP stack has <strong>one</strong> gateway — set per-vmk override
gateways (<code>esxcli ... ipv4 set -g</code>) so vMotion/vSAN carry their own
subnet&rsquo;s gateway.</li>
<li>Recreating a VM <strong>reallocates</strong> its NSX addresses. Pin what you depend on.</li>
<li>MTU: everything here ran at 1500. Raise the trunk and the nested vDS
before you do vSAN at any real scale.</li>
</ul>
<p>Next in this series: what happens when you want <em>ten</em> of these labs — with
byte-identical IP plans, firewalled from each other by construction. That&rsquo;s
where NSX VPCs go from &ldquo;workaround&rdquo; to genuinely better than physical.</p>
<hr>
<p><em>Lab environment; opinions my own. Everything above was captured from a live
VCF 9.1 environment — output trimmed for length, never edited for outcome.</em></p>
]]></content:encoded>
    </item>
  </channel>
</rss>
