<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: jindy zhao</title>
    <description>The latest articles on DEV Community by jindy zhao (@jindy_zhao_51a38a396d8054).</description>
    <link>https://dev.to/jindy_zhao_51a38a396d8054</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3945473%2F2fd8465d-89fa-4cdb-a8bc-00ceb6475194.png</url>
      <title>DEV Community: jindy zhao</title>
      <link>https://dev.to/jindy_zhao_51a38a396d8054</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jindy_zhao_51a38a396d8054"/>
    <language>en</language>
    <item>
      <title>Why KubeVirt Needs a Governance Layer — and How We Built One</title>
      <dc:creator>jindy zhao</dc:creator>
      <pubDate>Fri, 22 May 2026 07:04:05 +0000</pubDate>
      <link>https://dev.to/jindy_zhao_51a38a396d8054/why-kubevirt-needs-a-governance-layer-and-how-we-built-one-4bf9</link>
      <guid>https://dev.to/jindy_zhao_51a38a396d8054/why-kubevirt-needs-a-governance-layer-and-how-we-built-one-4bf9</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmuft34d75jrgvagahh6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmuft34d75jrgvagahh6.png" alt=" "&gt;&lt;/a&gt;&lt;br&gt;
KubeVirt puts VMs on Kubernetes. But it leaves a different set of questions&lt;br&gt;
open: who can request a VM, who approves it, where are the quotas enforced,&lt;br&gt;
and where is the audit trail?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kv-shepherd/shepherd" rel="noopener noreferrer"&gt;KubeVirt Shepherd&lt;/a&gt; is an open-source&lt;br&gt;
governance platform for KubeVirt, designed from the start around approval&lt;br&gt;
workflows, RBAC, and audit logging as foundational architecture. The project&lt;br&gt;
grew out of internal use in a financial-services Kubernetes environment and is&lt;br&gt;
Apache 2.0 licensed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://www.kv-shepherd.io" rel="noopener noreferrer"&gt;kv-shepherd.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Live demo: &lt;a href="https://demo.kv-shepherd.io" rel="noopener noreferrer"&gt;demo.kv-shepherd.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/kv-shepherd/shepherd" rel="noopener noreferrer"&gt;kv-shepherd/shepherd&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Discord: &lt;a href="https://discord.gg/9P2wtpPMUe" rel="noopener noreferrer"&gt;Join&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;In most KubeVirt environments, the VM lifecycle looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer wants a VM → kubectl apply → done.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works for dev clusters. In production, harder questions surface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Who approved this VM?&lt;/strong&gt; KubeVirt has no built-in approval flow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which team owns it?&lt;/strong&gt; No resource-to-team mapping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A VM has been idle for three months — who cleans it up?&lt;/strong&gt; No lifecycle governance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security incident — where are the operation records?&lt;/strong&gt; No platform-level audit trail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple clusters — how do you enforce policy consistently?&lt;/strong&gt; No unified governance plane.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The existing options each come with trade-offs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Trade-off&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OpenShift Virtualization&lt;/td&gt;
&lt;td&gt;Full-featured, but tightly coupled to the OpenShift ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Raw kubectl + K8s RBAC&lt;/td&gt;
&lt;td&gt;Too low-level — no approval flow, no self-service UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build your own portal&lt;/td&gt;
&lt;td&gt;Ongoing development and maintenance cost&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What Shepherd Does
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Approval workflows&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every VM operation — create, modify, start, stop, delete — goes through a structured request → approve → deliver flow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dual-layer RBAC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Platform-level roles plus System → Service → VM membership inheritance, with environment scoping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audit trail&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every resource change records the actor, timestamp, and payload&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-cluster&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manage VMs across multiple Kubernetes/KubeVirt clusters from one control plane&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Console access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Browser-based VNC and serial console with approval-aware entrypoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;i18n&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Chinese and English UI included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auth provider plugins&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SDK for LDAP, OIDC, and custom identity source integrations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Architecture Choices
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few decisions that shaped the project:&lt;/p&gt;

&lt;h3&gt;
  
  
  PostgreSQL-only runtime
&lt;/h3&gt;

&lt;p&gt;Shepherd deliberately avoids Redis and external message queues. PostgreSQL&lt;br&gt;
handles business state, audit data, encrypted credentials, and background jobs&lt;br&gt;
(via &lt;a href="https://github.com/riverqueue/river" rel="noopener noreferrer"&gt;River&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The practical benefit: async tasks and business data commit in the same&lt;br&gt;
database transaction — either both succeed or both roll back. This avoids the&lt;br&gt;
partial-failure scenarios that are common when a separate message queue is&lt;br&gt;
involved (e.g., a quota is deducted but the VM never gets created).&lt;/p&gt;

&lt;p&gt;The operational benefit: one database to back up, monitor, and scale. Deployment&lt;br&gt;
complexity drops significantly compared to a stack with Redis + RabbitMQ +&lt;br&gt;
PostgreSQL.&lt;/p&gt;
&lt;h3&gt;
  
  
  Contract-first API
&lt;/h3&gt;

&lt;p&gt;The OpenAPI spec is the single source of truth for both the Go backend and the&lt;br&gt;
TypeScript frontend. Server types and client types are generated from the spec.&lt;br&gt;
A CI gate blocks merges if the generated code drifts from the spec.&lt;/p&gt;
&lt;h3&gt;
  
  
  Architecture Decision Records
&lt;/h3&gt;

&lt;p&gt;The project maintains 53 ADRs that document key decisions — ORM selection,&lt;br&gt;
async model, transaction strategy, concurrency patterns, and more. ADRs are&lt;br&gt;
immutable once accepted; changes require a new ADR that supersedes the old one.&lt;br&gt;
CI gates enforce compliance with active ADRs.&lt;/p&gt;

&lt;p&gt;This matters because governance decisions tend to erode over time as a codebase&lt;br&gt;
grows. Making them explicit and enforceable keeps the architecture consistent&lt;br&gt;
as the project evolves.&lt;/p&gt;


&lt;h2&gt;
  
  
  How Shepherd Compares to OpenShift Virtualization
&lt;/h2&gt;

&lt;p&gt;Shepherd and OpenShift Virtualization operate at different levels:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;OpenShift Virtualization&lt;/th&gt;
&lt;th&gt;Shepherd&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scope&lt;/td&gt;
&lt;td&gt;Full enterprise virtualization platform&lt;/td&gt;
&lt;td&gt;Governance layer for KubeVirt VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-cluster&lt;/td&gt;
&lt;td&gt;Requires RHACM&lt;/td&gt;
&lt;td&gt;Built in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approval workflows&lt;/td&gt;
&lt;td&gt;Available&lt;/td&gt;
&lt;td&gt;Core architecture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-service model&lt;/td&gt;
&lt;td&gt;Operator-driven&lt;/td&gt;
&lt;td&gt;Request → approve → deliver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vendor dependency&lt;/td&gt;
&lt;td&gt;OpenShift ecosystem&lt;/td&gt;
&lt;td&gt;Any Kubernetes distribution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;Commercial&lt;/td&gt;
&lt;td&gt;Apache 2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If your team is already on OpenShift and satisfied with its VM governance,&lt;br&gt;
that stack likely covers your needs. If you run vanilla KubeVirt and want a&lt;br&gt;
governance layer without platform lock-in, Shepherd may be worth a look.&lt;/p&gt;


&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Online demo (no setup)
&lt;/h3&gt;

&lt;p&gt;Open &lt;a href="https://demo.kv-shepherd.io" rel="noopener noreferrer"&gt;demo.kv-shepherd.io&lt;/a&gt; in your browser. The&lt;br&gt;
instance is pre-seeded with sample data. You can walk through the full flow:&lt;br&gt;
log in, browse VMs, submit a request, approve it, and check the audit log.&lt;/p&gt;
&lt;h3&gt;
  
  
  Self-hosted (Docker Compose)
&lt;/h3&gt;

&lt;p&gt;One command to deploy on a VPS or local machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; shepherd-deploy &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;shepherd-deploy
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/kv-shepherd/shepherd/main/deploy/prod/deploy-prod.sh | &lt;span class="se"&gt;\&lt;/span&gt;
  bash &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--release-images&lt;/span&gt; &lt;span class="nt"&gt;--with-seed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Helm charts are also available for Kubernetes-native installs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add shepherd https://kv-shepherd.github.io/helm-charts
helm repo update
helm upgrade &lt;span class="nt"&gt;--install&lt;/span&gt; shepherd shepherd/shepherd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; shepherd &lt;span class="nt"&gt;--create-namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://github.com/kv-shepherd/shepherd/blob/main/docs/DEPLOYMENT.md" rel="noopener noreferrer"&gt;docs/DEPLOYMENT.md&lt;/a&gt;&lt;br&gt;
for external PostgreSQL, domain/TLS configuration, and the security checklist.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current Status
&lt;/h2&gt;

&lt;p&gt;Shepherd is in &lt;strong&gt;Alpha&lt;/strong&gt;. The core governance paths — approval workflows, RBAC,&lt;br&gt;
audit trails, VM lifecycle management — have been validated through internal&lt;br&gt;
production use. The Alpha label reflects deliberate caution while broader&lt;br&gt;
external feedback is gathered.&lt;/p&gt;

&lt;p&gt;What is planned next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finish live E2E validation across all major paths&lt;/li&gt;
&lt;li&gt;Harden deployment documentation and upgrade guidance&lt;/li&gt;
&lt;li&gt;Keep the PostgreSQL-only runtime baseline through V1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Features tracked as RFCs for future versions include VM snapshots, clone&lt;br&gt;
workflows, external approval system adapters, and event archiving. See&lt;br&gt;
&lt;a href="https://github.com/kv-shepherd/shepherd/blob/main/ROADMAP.md" rel="noopener noreferrer"&gt;ROADMAP.md&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Get Involved
&lt;/h2&gt;

&lt;p&gt;Shepherd is a solo-maintained project at this stage. All forms of participation&lt;br&gt;
are welcome — code, bug reports, documentation, or simply sharing your&lt;br&gt;
experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Try the demo&lt;/strong&gt; and share your impressions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Report bugs&lt;/strong&gt; or request features via &lt;a href="https://github.com/kv-shepherd/shepherd/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Join the conversation&lt;/strong&gt; on &lt;a href="https://discord.gg/9P2wtpPMUe" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Star the repo&lt;/strong&gt; if you find it useful — it helps with visibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is Apache 2.0 licensed. Contributions follow the&lt;br&gt;
&lt;a href="https://github.com/kv-shepherd/shepherd/blob/main/DCO.md" rel="noopener noreferrer"&gt;DCO sign-off&lt;/a&gt; model.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://www.kv-shepherd.io" rel="noopener noreferrer"&gt;https://www.kv-shepherd.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Live demo: &lt;a href="https://demo.kv-shepherd.io" rel="noopener noreferrer"&gt;https://demo.kv-shepherd.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/kv-shepherd/shepherd" rel="noopener noreferrer"&gt;https://github.com/kv-shepherd/shepherd&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Discord: &lt;a href="https://discord.gg/9P2wtpPMUe" rel="noopener noreferrer"&gt;https://discord.gg/9P2wtpPMUe&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubevirt</category>
      <category>kubernetes</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
