<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Why KubeVirt Needs a Governance Layer — and How We Built One]]></title><description><![CDATA[Why KubeVirt Needs a Governance Layer — and How We Built One]]></description><link>https://kubevirt-shepherd.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>Why KubeVirt Needs a Governance Layer — and How We Built One</title><link>https://kubevirt-shepherd.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 25 Sep 2026 09:18:56 GMT</lastBuildDate><atom:link href="https://kubevirt-shepherd.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Why KubeVirt Needs a Governance Layer — and How We Built One]]></title><description><![CDATA[KubeVirt puts VMs on Kubernetes. But it leaves a different set of questions open: who can request a VM, who approves it, where are the quotas enforced, and where is the audit trail?
KubeVirt Shepherd ]]></description><link>https://kubevirt-shepherd.hashnode.dev/why-kubevirt-needs-a-governance-layer-and-how-we-built-one</link><guid isPermaLink="true">https://kubevirt-shepherd.hashnode.dev/why-kubevirt-needs-a-governance-layer-and-how-we-built-one</guid><category><![CDATA[#kubevirt]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[open source]]></category><dc:creator><![CDATA[jindy zhao]]></dc:creator><pubDate>Fri, 22 May 2026 07:41:58 GMT</pubDate><content:encoded><![CDATA[<p>KubeVirt puts VMs on Kubernetes. But it leaves a different set of questions open: who can request a VM, who approves it, where are the quotas enforced, and where is the audit trail?</p>
<p><a href="https://github.com/kv-shepherd/shepherd">KubeVirt Shepherd</a> is an open-source governance platform for KubeVirt, designed from the start around approval workflows, RBAC, and audit logging as foundational architecture. The project grew out of internal use in a financial-services Kubernetes environment and is Apache 2.0 licensed.</p>
<ul>
<li><p>Website: <a href="https://www.kv-shepherd.io">kv-shepherd.io</a></p>
</li>
<li><p>Live demo: <a href="https://demo.kv-shepherd.io">demo.kv-shepherd.io</a></p>
</li>
<li><p>GitHub: <a href="https://github.com/kv-shepherd/shepherd">kv-shepherd/shepherd</a></p>
</li>
<li><p>Discord: <a href="https://discord.gg/9P2wtpPMUe">Join</a></p>
</li>
</ul>
<img src="https://www.kv-shepherd.io/screenshot.png" alt="屏幕截图" style="display:block;margin:0 auto" />

<hr />
<h2>The Problem</h2>
<p>In most KubeVirt environments, the VM lifecycle looks like this:</p>
<pre><code class="language-plaintext">Developer wants a VM → kubectl apply → done.
</code></pre>
<p>This works for dev clusters. In production, harder questions surface:</p>
<ul>
<li><p><strong>Who approved this VM?</strong> KubeVirt has no built-in approval flow.</p>
</li>
<li><p><strong>Which team owns it?</strong> No resource-to-team mapping.</p>
</li>
<li><p><strong>A VM has been idle for three months — who cleans it up?</strong> No lifecycle governance.</p>
</li>
<li><p><strong>Security incident — where are the operation records?</strong> No platform-level audit trail.</p>
</li>
<li><p><strong>Multiple clusters — how do you enforce policy consistently?</strong> No unified governance plane.</p>
</li>
</ul>
<p>The existing options each come with trade-offs:</p>
<table>
<thead>
<tr>
<th>Approach</th>
<th>Trade-off</th>
</tr>
</thead>
<tbody><tr>
<td>OpenShift Virtualization</td>
<td>Full-featured, but tightly coupled to the OpenShift ecosystem</td>
</tr>
<tr>
<td>Raw kubectl + K8s RBAC</td>
<td>Too low-level — no approval flow, no self-service UI</td>
</tr>
<tr>
<td>Build your own portal</td>
<td>Ongoing development and maintenance cost</td>
</tr>
</tbody></table>
<hr />
<h2>What Shepherd Does</h2>
<table>
<thead>
<tr>
<th>Capability</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Approval workflows</strong></td>
<td>Every VM operation — create, modify, start, stop, delete — goes through a structured request → approve → deliver flow</td>
</tr>
<tr>
<td><strong>Dual-layer RBAC</strong></td>
<td>Platform-level roles plus System → Service → VM membership inheritance, with environment scoping</td>
</tr>
<tr>
<td><strong>Audit trail</strong></td>
<td>Every resource change records the actor, timestamp, and payload</td>
</tr>
<tr>
<td><strong>Multi-cluster</strong></td>
<td>Manage VMs across multiple Kubernetes/KubeVirt clusters from one control plane</td>
</tr>
<tr>
<td><strong>Console access</strong></td>
<td>Browser-based VNC and serial console with approval-aware entrypoints</td>
</tr>
<tr>
<td><strong>i18n</strong></td>
<td>Chinese and English UI included</td>
</tr>
<tr>
<td><strong>Auth provider plugins</strong></td>
<td>SDK for LDAP, OIDC, and custom identity source integrations</td>
</tr>
</tbody></table>
<hr />
<h2>Architecture Choices</h2>
<pre><code class="language-text">Web UI (React 19 · Next.js 16)
  ↓ REST / WebSocket
Go Backend (Gin · Ent ORM · River Queue)
  ↓
PostgreSQL 18 (single data store)
  ↓
Kubernetes / KubeVirt Clusters (client-go · multi-cluster)
</code></pre>
<p>A few decisions that shaped the project:</p>
<h3>PostgreSQL-only runtime</h3>
<p>Shepherd deliberately avoids Redis and external message queues. PostgreSQL handles business state, audit data, encrypted credentials, and background jobs (via <a href="https://github.com/riverqueue/river">River</a>).</p>
<p>The practical benefit: async tasks and business data commit in the same database transaction — either both succeed or both roll back. This avoids the partial-failure scenarios that are common when a separate message queue is involved (e.g., a quota is deducted but the VM never gets created).</p>
<p>The operational benefit: one database to back up, monitor, and scale. Deployment complexity drops significantly compared to a stack with Redis + RabbitMQ + PostgreSQL.</p>
<h3>Contract-first API</h3>
<p>The OpenAPI spec is the single source of truth for both the Go backend and the TypeScript frontend. Server types and client types are generated from the spec. A CI gate blocks merges if the generated code drifts from the spec.</p>
<h3>Architecture Decision Records</h3>
<p>The project maintains 53 ADRs that document key decisions — ORM selection, async model, transaction strategy, concurrency patterns, and more. ADRs are immutable once accepted; changes require a new ADR that supersedes the old one. CI gates enforce compliance with active ADRs.</p>
<p>This matters because governance decisions tend to erode over time as a codebase grows. Making them explicit and enforceable keeps the architecture consistent as the project evolves.</p>
<hr />
<h2>How Shepherd Compares to OpenShift Virtualization</h2>
<p>Shepherd and OpenShift Virtualization operate at different levels:</p>
<table>
<thead>
<tr>
<th>Dimension</th>
<th>OpenShift Virtualization</th>
<th>Shepherd</th>
</tr>
</thead>
<tbody><tr>
<td>Scope</td>
<td>Full enterprise virtualization platform</td>
<td>Governance layer for KubeVirt VMs</td>
</tr>
<tr>
<td>Multi-cluster</td>
<td>Requires RHACM</td>
<td>Built in</td>
</tr>
<tr>
<td>Approval workflows</td>
<td>Available</td>
<td>Core architecture</td>
</tr>
<tr>
<td>Self-service model</td>
<td>Operator-driven</td>
<td>Request → approve → deliver</td>
</tr>
<tr>
<td>Vendor dependency</td>
<td>OpenShift ecosystem</td>
<td>Any Kubernetes distribution</td>
</tr>
<tr>
<td>License</td>
<td>Commercial</td>
<td>Apache 2.0</td>
</tr>
</tbody></table>
<p>If your team is already on OpenShift and satisfied with its VM governance, that stack likely covers your needs. If you run vanilla KubeVirt and want a governance layer without platform lock-in, Shepherd may be worth a look.</p>
<hr />
<h2>Try It</h2>
<h3>Online demo (no setup)</h3>
<p>Open <a href="https://demo.kv-shepherd.io">demo.kv-shepherd.io</a> in your browser. The instance is pre-seeded with sample data. You can walk through the full flow: log in, browse VMs, submit a request, approve it, and check the audit log.</p>
<h3>Self-hosted (Docker Compose)</h3>
<p>One command to deploy on a VPS or local machine:</p>
<pre><code class="language-bash">mkdir -p shepherd-deploy &amp;&amp; cd shepherd-deploy
curl -fsSL https://raw.githubusercontent.com/kv-shepherd/shepherd/main/deploy/prod/deploy-prod.sh | \
  bash -s -- --release-images --with-seed
</code></pre>
<p>Helm charts are also available for Kubernetes-native installs:</p>
<pre><code class="language-bash">helm repo add shepherd https://kv-shepherd.github.io/helm-charts
helm repo update
helm upgrade --install shepherd shepherd/shepherd \
  --namespace shepherd --create-namespace
</code></pre>
<p>See <a href="https://github.com/kv-shepherd/shepherd/blob/main/docs/DEPLOYMENT.md">docs/DEPLOYMENT.md</a> for external PostgreSQL, domain/TLS configuration, and the security checklist.</p>
<hr />
<h2>Current Status</h2>
<p>Shepherd is in <strong>Alpha</strong>. The core governance paths — approval workflows, RBAC, audit trails, VM lifecycle management — have been validated through internal production use. The Alpha label reflects deliberate caution while broader external feedback is gathered.</p>
<p>What is planned next:</p>
<ul>
<li><p>Finish live E2E validation across all major paths</p>
</li>
<li><p>Harden deployment documentation and upgrade guidance</p>
</li>
<li><p>Keep the PostgreSQL-only runtime baseline through V1</p>
</li>
</ul>
<p>Features tracked as RFCs for future versions include VM snapshots, clone workflows, external approval system adapters, and event archiving. See <a href="https://github.com/kv-shepherd/shepherd/blob/main/ROADMAP.md">ROADMAP.md</a>.</p>
<hr />
<h2>Get Involved</h2>
<p>Shepherd is a solo-maintained project at this stage. All forms of participation are welcome — code, bug reports, documentation, or simply sharing your experience:</p>
<ul>
<li><p><strong>Try the demo</strong> and share your impressions</p>
</li>
<li><p><strong>Report bugs</strong> or request features via <a href="https://github.com/kv-shepherd/shepherd/issues">GitHub Issues</a></p>
</li>
<li><p><strong>Join the conversation</strong> on <a href="https://discord.gg/9P2wtpPMUe">Discord</a></p>
</li>
<li><p><strong>Star the repo</strong> if you find it useful — it helps with visibility</p>
</li>
</ul>
<p>The project is Apache 2.0 licensed. Contributions follow the <a href="https://github.com/kv-shepherd/shepherd/blob/main/DCO.md">DCO sign-off</a> model.</p>
<hr />
<p><strong>Links:</strong></p>
<ul>
<li><p>Website: <a href="https://www.kv-shepherd.io">https://www.kv-shepherd.io</a></p>
</li>
<li><p>Live demo: <a href="https://demo.kv-shepherd.io">https://demo.kv-shepherd.io</a></p>
</li>
<li><p>GitHub: <a href="https://github.com/kv-shepherd/shepherd">https://github.com/kv-shepherd/shepherd</a></p>
</li>
<li><p>Discord: <a href="https://discord.gg/9P2wtpPMUe">https://discord.gg/9P2wtpPMUe</a></p>
</li>
</ul>
]]></content:encoded></item></channel></rss>