<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"><channel><title>blog.epheo.eu</title><link>https://blog.epheo.eu</link><description>Technical articles on OpenShift, Kubernetes, OpenStack, and Linux</description><language>en</language><copyright>2025, Thibaut Lapierre</copyright><item><title>Debugging PostgreSQL Crash Loop in OpenShift</title><link>https://blog.epheo.eu/debug/postgresql_openshift.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;April 20, 2024&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;3 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;section id="introduction"&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;This article describes how to fix a common PostgreSQL issue in OpenShift when the database enters a crash loop
with a “tuple concurrently updated” error. This problem typically occurs due to an unclean shutdown of the
PostgreSQL server, leaving the database in an inconsistent state.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="understanding-the-error"&gt;
&lt;h2&gt;Understanding the Error&lt;/h2&gt;
&lt;p&gt;When starting a PostgreSQL pod in OpenShift, you might encounter the following error:&lt;/p&gt;
&lt;div class="highlight-none notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;pg_ctl: another server might be running; trying to start server anyway
waiting for server to start....LOG:  redirecting log output to logging
collector process
HINT:  Future log output will appear in directory "pg_log".
..... done
server started
=&amp;gt; sourcing /usr/share/container-scripts/postgresql/start/set_passwords.sh ...
ERROR:  tuple concurrently updated
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This error indicates that PostgreSQL has detected an issue with its internal data consistency.
The “tuple concurrently updated” message suggests that a database tuple (row) was modified by multiple processes
simultaneously, leaving the database in an inconsistent state.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="step-by-step-solution"&gt;
&lt;h2&gt;Step-by-Step Solution&lt;/h2&gt;
&lt;p&gt;Follow these steps to resolve the issue:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Find the problematic PostgreSQL pod&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First, locate the PostgreSQL pod that is stuck in the crash loop.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start a debug session&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Use the OpenShift command-line tool to start a debug session with the pod:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;debug&lt;span class="w"&gt; &lt;/span&gt;pod/&amp;lt;postgres-pod-name&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scale down the deployment&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In another terminal, scale the associated PostgreSQL deployment to zero pods:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;scale&lt;span class="w"&gt; &lt;/span&gt;deployment/&amp;lt;postgres-deployment-name&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--replicas&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run the PostgreSQL startup script&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From the debug session terminal, run the PostgreSQL startup script:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;run-postgresql
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This creates necessary configuration files that will allow you to manage the PostgreSQL server.
You should see the same error output described above.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stop PostgreSQL cleanly&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Stop the PostgreSQL server with the following command:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;pg_ctl&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;-D&lt;span class="w"&gt; &lt;/span&gt;/var/lib/pgsql/data/userdata
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Expected output:&lt;/p&gt;
&lt;div class="highlight-none notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;waiting for server to shut down.... done
server stopped
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start PostgreSQL manually&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Start the PostgreSQL server manually to check if it initializes correctly:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;pg_ctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;-D&lt;span class="w"&gt; &lt;/span&gt;/var/lib/pgsql/data/userdata
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Expected output:&lt;/p&gt;
&lt;div class="highlight-none notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;server starting
LOG:  redirecting log output to logging collector process
HINT:  Future log output will appear in directory "pg_log".
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The server should remain running without errors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stop PostgreSQL cleanly again&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ensure a clean shutdown by stopping PostgreSQL:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;pg_ctl&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;-D&lt;span class="w"&gt; &lt;/span&gt;/var/lib/pgsql/data/userdata
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Expected output:&lt;/p&gt;
&lt;div class="highlight-none notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;waiting for server to shut down.... done
server stopped
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exit the debug session&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Type &lt;cite&gt;exit&lt;/cite&gt; to leave the debug session.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scale up the deployment&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Finally, scale the PostgreSQL deployment back up:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;scale&lt;span class="w"&gt; &lt;/span&gt;deployment/&amp;lt;postgres-deployment-name&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--replicas&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The PostgreSQL pod should now start normally without crashing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="why-this-works"&gt;
&lt;h2&gt;Why This Works&lt;/h2&gt;
&lt;p&gt;This procedure works because it:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Allows PostgreSQL to perform a clean shutdown, ensuring all data is properly written&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clears any potentially corrupted transaction logs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creates the necessary configuration files needed for proper operation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Eliminates race conditions that might occur during the container’s normal startup process&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you encounter this issue frequently with a particular PostgreSQL deployment, consider investigating:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Storage performance issues&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Abrupt pod terminations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resource constraints causing timeouts during shutdown&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improper backup procedures&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Sun, 15 Feb 2026 00:00:00 </pubDate></item><item><title>Running vLLM on Strix Halo</title><link>https://blog.epheo.eu/notes/strix-halo/index.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Feb 15, 2026&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;5 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;So I bought this machine, AMD RYZEN AI MAX+ 395 w/ Radeon 8060S and 128GB GTT RAM,
and I knew that the ecosystem was still… ongoing.
But it really felt like going back to the OpenStack early days, struggling with nightly builds,
unreleased patches, vendor forks, etc. Maybe the issue is just Python in the end.&lt;/p&gt;
&lt;p&gt;In short, AMD Strix Halo (gfx1151) isn’t in upstream vLLM’s supported GPU list yet, so
this note walks through building vLLM against ROCm nightly (TheRock) on Fedora 43,
including the patches needed to work around missing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amdsmi&lt;/span&gt;&lt;/code&gt; support.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference download internal" download="" href="../../_downloads/33f9b0d62ba821d9e4123d893a457560/vllm.sh"&gt;&lt;code class="xref download docutils literal notranslate"&gt;&lt;span class="pre"&gt;Download&lt;/span&gt; &lt;span class="pre"&gt;the&lt;/span&gt; &lt;span class="pre"&gt;full&lt;/span&gt; &lt;span class="pre"&gt;build&lt;/span&gt; &lt;span class="pre"&gt;script&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;section id="prerequisites"&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;python3.13&lt;span class="w"&gt; &lt;/span&gt;python3.13-devel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;libatomic&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;gcc&lt;span class="w"&gt; &lt;/span&gt;gcc-c++&lt;span class="w"&gt; &lt;/span&gt;make&lt;span class="w"&gt; &lt;/span&gt;ffmpeg-free&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;aria2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;libdrm-devel&lt;span class="w"&gt; &lt;/span&gt;zlib-devel&lt;span class="w"&gt; &lt;/span&gt;openssl-devel&lt;span class="w"&gt; &lt;/span&gt;procps-ng&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;numactl-devel&lt;span class="w"&gt; &lt;/span&gt;gperftools-libs&lt;span class="w"&gt; &lt;/span&gt;libibverbs-utils
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="installing-rocm-via-therock-nightly"&gt;
&lt;h2&gt;Installing ROCm via TheRock nightly&lt;/h2&gt;
&lt;p&gt;AMD’s &lt;a class="reference external" href="https://github.com/ROCm/TheRock"&gt;TheRock&lt;/a&gt; project publishes nightly
tarballs to an S3 bucket, indexed by GFX target. We grab the latest one for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gfx1151&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nv"&gt;GFX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gfx1151
&lt;span class="nv"&gt;ROCM_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/rocm

&lt;span class="nv"&gt;S3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://therock-nightly-tarball.s3.amazonaws.com"&lt;/span&gt;
&lt;span class="nv"&gt;PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"therock-dist-linux-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GFX&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-7"&lt;/span&gt;

&lt;span class="nv"&gt;KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;S3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?list-type=2&amp;amp;prefix=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PREFIX&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-oP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'(?&amp;lt;=&amp;lt;Key&amp;gt;)[^&amp;lt;]+'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sort&lt;span class="w"&gt; &lt;/span&gt;-V&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tail&lt;span class="w"&gt; &lt;/span&gt;-n1&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

aria2c&lt;span class="w"&gt; &lt;/span&gt;-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--file-allocation&lt;span class="o"&gt;=&lt;/span&gt;none&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;S3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;KEY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;therock.tar.gz

mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROCM_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
tar&lt;span class="w"&gt; &lt;/span&gt;xzf&lt;span class="w"&gt; &lt;/span&gt;therock.tar.gz&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROCM_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--strip-components&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
rm&lt;span class="w"&gt; &lt;/span&gt;therock.tar.gz
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="environment-setup"&gt;
&lt;h2&gt;Environment setup&lt;/h2&gt;
&lt;p&gt;TheRock nightlies don’t ship a stable bitcode path, so we locate it dynamically:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nv"&gt;BITCODE_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROCM_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-type&lt;span class="w"&gt; &lt;/span&gt;d&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;bitcode&lt;span class="w"&gt; &lt;/span&gt;-print&lt;span class="w"&gt; &lt;/span&gt;-quit&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then create a profile script so the environment is set for every shell:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/profile.d/rocm-sdk.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class="s"&gt;export ROCM_PATH=$ROCM_PATH&lt;/span&gt;
&lt;span class="s"&gt;export HIP_PLATFORM=amd&lt;/span&gt;
&lt;span class="s"&gt;export HIP_PATH=$ROCM_PATH&lt;/span&gt;
&lt;span class="s"&gt;export HIP_CLANG_PATH=$ROCM_PATH/llvm/bin&lt;/span&gt;
&lt;span class="s"&gt;export HIP_DEVICE_LIB_PATH=$BITCODE_PATH&lt;/span&gt;
&lt;span class="s"&gt;export PATH=$ROCM_PATH/bin:$ROCM_PATH/llvm/bin:\$PATH&lt;/span&gt;
&lt;span class="s"&gt;export LD_LIBRARY_PATH=$ROCM_PATH/lib:$ROCM_PATH/lib64:$ROCM_PATH/llvm/lib:\$LD_LIBRARY_PATH&lt;/span&gt;
&lt;span class="s"&gt;export ROCBLAS_USE_HIPBLASLT=1&lt;/span&gt;
&lt;span class="s"&gt;export TORCH_ROCM_AOTRITON_ENABLE_EXPERIMENTAL=1&lt;/span&gt;
&lt;span class="s"&gt;export VLLM_TARGET_DEVICE=rocm&lt;/span&gt;
&lt;span class="s"&gt;export HIP_FORCE_DEV_KERNARG=1&lt;/span&gt;
&lt;span class="s"&gt;export RAY_EXPERIMENTAL_NOSET_ROCR_VISIBLE_DEVICES=1&lt;/span&gt;
&lt;span class="s"&gt;export LD_PRELOAD=/usr/lib64/libtcmalloc_minimal.so.4&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/profile.d/rocm-sdk.sh
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Notable variables:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TORCH_ROCM_AOTRITON_ENABLE_EXPERIMENTAL&lt;/span&gt;&lt;/code&gt;: enables experimental Triton
kernels needed for gfx1151&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HIP_FORCE_DEV_KERNARG&lt;/span&gt;&lt;/code&gt;: required for Strix Halo’s memory model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LD_PRELOAD=libtcmalloc_minimal&lt;/span&gt;&lt;/code&gt;: significant inference throughput gain&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="installing-pytorch-from-rocm-nightly"&gt;
&lt;h2&gt;Installing PyTorch from ROCm nightly&lt;/h2&gt;
&lt;p&gt;AMD publishes per-target nightly wheels. The index URL must match the GFX
target:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;python&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--index-url&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://rocm.nightlies.amd.com/v2-staging/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GFX&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--pre&lt;span class="w"&gt; &lt;/span&gt;torch&lt;span class="w"&gt; &lt;/span&gt;torchaudio&lt;span class="w"&gt; &lt;/span&gt;torchvision
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="building-flash-attention-rocm-fork"&gt;
&lt;h2&gt;Building flash-attention (ROCm fork)&lt;/h2&gt;
&lt;p&gt;ROCm’s fork of flash-attention includes AMD-specific Triton optimizations:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;FLASH_ATTENTION_TRITON_AMD_ENABLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"TRUE"&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/ROCm/flash-attention.git&lt;span class="w"&gt; &lt;/span&gt;/opt/flash-attention
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/opt/flash-attention&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;checkout&lt;span class="w"&gt; &lt;/span&gt;main_perf
python&lt;span class="w"&gt; &lt;/span&gt;setup.py&lt;span class="w"&gt; &lt;/span&gt;install
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="patching-building-vllm"&gt;
&lt;h2&gt;Patching &amp;amp; building vLLM&lt;/h2&gt;
&lt;p&gt;vLLM probes &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amdsmi&lt;/span&gt;&lt;/code&gt; at import time to detect AMD GPUs,
but &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amdsmi&lt;/span&gt;&lt;/code&gt; doesn’t know about Strix Halo yet. The patches:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stub out amdsmi in&lt;/strong&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vllm/platforms/__init__.py&lt;/span&gt;&lt;/code&gt;: disable the import,
force &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_rocm&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;, and no-op the init/shutdown calls.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mock amdsmi in&lt;/strong&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vllm/platforms/rocm.py&lt;/span&gt;&lt;/code&gt;: inject a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MagicMock&lt;/span&gt;&lt;/code&gt; module
and hardcode &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_name&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;"gfx1151"&lt;/span&gt;&lt;/code&gt; so vLLM sees a known ROCm device.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set the GPU target in&lt;/strong&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CMakeLists.txt&lt;/span&gt;&lt;/code&gt;: replace the default RDNA4
targets with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gfx1151&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The build script applies these patches via an inline Python script, see
&lt;a class="reference download internal" download="" href="../../_downloads/33f9b0d62ba821d9e4123d893a457560/vllm.sh"&gt;&lt;code class="xref download docutils literal notranslate"&gt;&lt;span class="pre"&gt;vllm.sh&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; for the full patch.&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/vllm-project/vllm.git&lt;span class="w"&gt; &lt;/span&gt;/opt/vllm
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/opt/vllm

&lt;span class="c1"&gt;# Apply the amdsmi patches (see vllm.sh for details)&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;

&lt;span class="c1"&gt;# Replace default GPU targets&lt;/span&gt;
sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s/gfx1200;gfx1201/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GFX&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;CMakeLists.txt

&lt;span class="c1"&gt;# Fedora's GCC produces ABI-incompatible extensions — use ROCm's clang&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROCM_PATH&lt;/span&gt;&lt;span class="s2"&gt;/llvm/bin/clang"&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CXX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROCM_PATH&lt;/span&gt;&lt;span class="s2"&gt;/llvm/bin/clang++"&lt;/span&gt;

&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ROCM_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROCM_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PYTORCH_ROCM_ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GFX&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;HIP_ARCHITECTURES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GFX&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;AMDGPU_TARGETS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GFX&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MAX_JOBS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"4"&lt;/span&gt;

&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CMAKE_ARGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-DROCM_PATH=&lt;/span&gt;&lt;span class="nv"&gt;$ROCM_PATH&lt;/span&gt;&lt;span class="s2"&gt; -DHIP_PATH=&lt;/span&gt;&lt;span class="nv"&gt;$ROCM_PATH&lt;/span&gt;&lt;span class="s2"&gt; \&lt;/span&gt;
&lt;span class="s2"&gt;  -DAMDGPU_TARGETS=&lt;/span&gt;&lt;span class="nv"&gt;$GFX&lt;/span&gt;&lt;span class="s2"&gt; -DHIP_ARCHITECTURES=&lt;/span&gt;&lt;span class="nv"&gt;$GFX&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

python&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;wheel&lt;span class="w"&gt; &lt;/span&gt;--no-build-isolation&lt;span class="w"&gt; &lt;/span&gt;--no-deps&lt;span class="w"&gt; &lt;/span&gt;-w&lt;span class="w"&gt; &lt;/span&gt;/tmp/dist&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;.
python&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;/tmp/dist/*.whl
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="bitsandbytes-rocm-fork"&gt;
&lt;h2&gt;bitsandbytes (ROCm fork)&lt;/h2&gt;
&lt;p&gt;For quantized model support, build the ROCm-enabled bitsandbytes fork:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CMAKE_PREFIX_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROCM_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;rocm_enabled_multi_backend&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;https://github.com/ROCm/bitsandbytes.git&lt;span class="w"&gt; &lt;/span&gt;/opt/bitsandbytes
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/opt/bitsandbytes

cmake&lt;span class="w"&gt; &lt;/span&gt;-S&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-DGPU_TARGETS&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GFX&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-DBNB_ROCM_ARCH&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GFX&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-DCOMPUTE_BACKEND&lt;span class="o"&gt;=&lt;/span&gt;hip

make&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;nproc&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
python&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;--no-build-isolation&lt;span class="w"&gt; &lt;/span&gt;--no-deps
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Sun, 15 Feb 2026 00:00:00 </pubDate></item><item><title>How this blog is served to you</title><link>https://blog.epheo.eu/articles/kiss-rust-server/index.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Aug 16, 2025&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;5 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This blog is just static files, served from a container, behind a Kubernetes Ingress Controller.&lt;/p&gt;
&lt;p&gt;So a container image containing a whole userland and a fullfledged webserver with all
bells and whistle behind yet another fullfledged proxy.&lt;/p&gt;
&lt;p&gt;Now I thought, we’re in 2025 and disk space is expensive (Yes, I wrote that before it actually became true).
An Nginx container image is at least 80MiB, If I would write my very own static web server and run it from a scratch
container image I could go down to a few hundred KiB and save…
Let’s do the maths: a 1TB NVMe is around 70Euros on Amazon (yes it was) so that’s around 0.00007€
per MiB, assuming my container image will be around 500KiB that’s a whooping 0.005 Euro
difference, bargain !&lt;/p&gt;
&lt;p&gt;So I decided to spend a few days of my summer holidays and go save those 0.005 Euro.&lt;/p&gt;
&lt;p&gt;Who need logic when you have a goal.&lt;/p&gt;
&lt;p&gt;Anyhow, I started working on it with my friend Claude, got a functionnal prototype, and
finaly came back to reason: this is useless.&lt;/p&gt;
&lt;p&gt;Unless… unless my 20 monthly visitors were too much for Nginx to handle and I needed
a much more performant web server. Let’s set a 1 Million Request per seconds target so
if those 20 monthly visitors suddenly decided to connect at the exact same time and all
refresh my blog page 50 000 times every seconds, they’d be safe.&lt;/p&gt;
&lt;p&gt;So I started working again, and got to a 454KiB container image, that serves around 700K
requests per seconds from my laptop’s Intel Gen12 and 1M+ RPS on my server !&lt;/p&gt;
&lt;p&gt;I now host my blog with it, and you, who read, are safe to refresh this page if you want.
Unless… unless the ingress controler is now the bottleneck ! Let’s work on a new
K8S Ingress Controller (or Gateway API) that implements io_uring and use eBPF.&lt;/p&gt;
&lt;section id="details"&gt;
&lt;h2&gt;Details&lt;/h2&gt;
&lt;p&gt;KISS (that’s its name) for “Kubernetes Instant Static Server” is taking some shortcuts
to achieve its goals.&lt;/p&gt;
&lt;p&gt;The first and more important one is &lt;strong&gt;no disk I/O&lt;/strong&gt;, all content is pre-loaded in RAM
and all requests are pre-generated at startup time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Traditional Static Servers&lt;/strong&gt; (nginx, Apache):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Read files from disk per request&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate HTTP headers per request&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiple system calls per response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Filesystem caching complexity&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;KISS Approach&lt;/strong&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;All files loaded into memory at startup&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP responses pre-generated once&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Single write() system call per request&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zero runtime filesystem operations&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are also mindfull of saving some disk space and serving a ridiculous amount of
request per seconds without any guaranty, you can also try KISS.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/epheo/kiss"&gt;GitHub project&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://quay.io/repository/epheo/kiss"&gt;Container image on Quay.io&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Sat, 16 Aug 2025 00:00:00 </pubDate></item><item><title>Merging kubeconfig Files</title><link>https://blog.epheo.eu/notes/merge-kubeconfig.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Apr 25, 2025&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;3 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When working with multiple Kubernetes or OpenShift clusters, you’ll often have multiple kubeconfig files.
Kubernetes provides tools to merge these configurations into a single file.&lt;/p&gt;
&lt;section id="prerequisites"&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Access to the Kubernetes or OpenShift clusters you want to manage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Existing kubeconfig files for each cluster&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kubectl or oc command-line tools installed&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="step-by-step-merge-process"&gt;
&lt;h2&gt;Step-by-Step Merge Process&lt;/h2&gt;
&lt;section id="backup-existing-configuration"&gt;
&lt;h3&gt;1. Backup Existing Configuration&lt;/h3&gt;
&lt;p&gt;Before merging, create a backup of your existing kubeconfig file to ensure you can revert to the original configuration if needed.&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;cp&lt;span class="w"&gt; &lt;/span&gt;~/.kube/config&lt;span class="w"&gt; &lt;/span&gt;~/.kube/config.backup
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="set-the-kubeconfig-environment-variable"&gt;
&lt;h3&gt;2. Set the KUBECONFIG Environment Variable&lt;/h3&gt;
&lt;p&gt;The KUBECONFIG environment variable allows you to specify multiple kubeconfig files. These files will be merged automatically by kubectl.&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;KUBECONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.kube/config:/path/to/second-kubeconfig
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You can add as many kubeconfig files as needed, separating them with colons (on Linux/macOS) or semicolons (on Windows).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="merge-the-files"&gt;
&lt;h3&gt;3. Merge the Files&lt;/h3&gt;
&lt;p&gt;Use the kubectl config view command with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--merge&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--flatten&lt;/span&gt;&lt;/code&gt; options to merge the configurations into a single file.&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;view&lt;span class="w"&gt; &lt;/span&gt;--merge&lt;span class="w"&gt; &lt;/span&gt;--flatten&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;~/.kube/merged_kubeconfig
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="replace-the-original-configuration"&gt;
&lt;h3&gt;4. Replace the Original Configuration&lt;/h3&gt;
&lt;p&gt;Move the merged configuration to the default location.&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;mv&lt;span class="w"&gt; &lt;/span&gt;~/.kube/merged_kubeconfig&lt;span class="w"&gt; &lt;/span&gt;~/.kube/config
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="verify-the-merged-configuration"&gt;
&lt;h3&gt;5. Verify the Merged Configuration&lt;/h3&gt;
&lt;p&gt;Ensure that the merged configuration works correctly by exploring and managing your contexts:&lt;/p&gt;
&lt;section id="listing-available-contexts"&gt;
&lt;h4&gt;Listing Available Contexts&lt;/h4&gt;
&lt;p&gt;To view all available contexts in your merged configuration:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;get-contexts
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This command displays a table with all contexts in your kubeconfig file, including:
- The current active context (marked with an asterisk *)
- Context names
- Cluster names
- Authentication users
- Namespaces (if specified)&lt;/p&gt;
&lt;p&gt;For a more detailed view of your entire kubeconfig:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;view
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="checking-the-current-context"&gt;
&lt;h4&gt;Checking the Current Context&lt;/h4&gt;
&lt;p&gt;To see which context is currently active:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;current-context
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="switching-between-contexts"&gt;
&lt;h4&gt;Switching Between Contexts&lt;/h4&gt;
&lt;p&gt;To switch to a different context:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;use-context&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;context-name&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Sun, 27 Apr 2025 00:00:00 </pubDate></item><item><title>OpenShift Virtualization Sidecar Implementation Guide</title><link>https://blog.epheo.eu/notes/kubevirt-sidecar.html</link><description>
&lt;span id="kubevirt-sidecar-section"/&gt;
&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;April 25, 2025&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;8 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;section id="overview"&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;The Sidecar feature in Kubevirt enables the attachment of additional containers to virtual machine pods. These sidecar containers run alongside the VM container, allowing for enhanced functionality such as monitoring, logging, debugging, and custom modifications to the VM environment without modifying the core VM itself.&lt;/p&gt;
&lt;p&gt;This document provides instructions for enabling and implementing the Sidecar feature in an OpenShift Container Native Virtualization (CNV) environment.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="enabling-the-sidecar-feature-gate"&gt;
&lt;h2&gt;Enabling the Sidecar Feature Gate&lt;/h2&gt;
&lt;p&gt;The Sidecar feature is controlled by a feature gate which must be explicitly enabled:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;annotate&lt;span class="w"&gt; &lt;/span&gt;--overwrite&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openshift-cnv&lt;span class="w"&gt; &lt;/span&gt;hco&lt;span class="w"&gt; &lt;/span&gt;kubevirt-hyperconverged&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;kubevirt.kubevirt.io/jsonpatch&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'[{"op": "add", "path": "/spec/configuration/developerConfiguration/featureGates/-", "value": "Sidecar"}]'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="verify-feature-gate-is-enabled"&gt;
&lt;h3&gt;Verify Feature Gate is Enabled&lt;/h3&gt;
&lt;p&gt;To confirm the feature gate has been successfully added:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;kubevirt&lt;span class="w"&gt; &lt;/span&gt;kubevirt-kubevirt-hyperconverged&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openshift-cnv&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.configuration.developerConfiguration.featureGates}'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The output should include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Sidecar&lt;/span&gt;&lt;/code&gt; in the list of enabled feature gates.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementing-a-sidecar-container"&gt;
&lt;h2&gt;Implementing a Sidecar Container&lt;/h2&gt;
&lt;section id="kubevirt-hook-types"&gt;
&lt;h3&gt;KubeVirt Hook Types&lt;/h3&gt;
&lt;p&gt;KubeVirt sidecars support different hook types for various modification purposes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;onDefineDomain&lt;/strong&gt;: Modifies the libvirt XML domain definition before VM creation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;preCloudInitIso&lt;/strong&gt;: Modifies cloud-init data before the ISO is generated&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="sidecar-script-arguments"&gt;
&lt;h3&gt;Sidecar Script Arguments&lt;/h3&gt;
&lt;p&gt;When writing sidecar scripts, it’s important to understand how arguments are passed to your script:&lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;onDefineDomain&lt;/strong&gt; hook:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Argument 1&lt;/strong&gt;: The hook name (onDefineDomain)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Argument 2&lt;/strong&gt;: The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--version&lt;/span&gt;&lt;/code&gt; parameter (e.g., v1alpha2)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Argument 3&lt;/strong&gt;: The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--vmi&lt;/span&gt;&lt;/code&gt; parameter with VMI information as JSON string&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Argument 4&lt;/strong&gt;: The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--domain&lt;/span&gt;&lt;/code&gt; parameter with the current domain XML&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For &lt;strong&gt;preCloudInitIso&lt;/strong&gt; hook:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Argument 1&lt;/strong&gt;: The hook name (preCloudInitIso)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Argument 2&lt;/strong&gt;: The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--version&lt;/span&gt;&lt;/code&gt; parameter (e.g., v1alpha2)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Argument 3&lt;/strong&gt;: The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--vmi&lt;/span&gt;&lt;/code&gt; parameter with VMI information as JSON string&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Argument 4&lt;/strong&gt;: The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--cloud-init&lt;/span&gt;&lt;/code&gt; parameter with CloudInitData as JSON&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Your script should read the input XML/JSON from the appropriate argument (usually the 4th argument).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It must output the modified content to standard output (stdout).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The script must preserve any XML/JSON structure while making targeted modifications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any errors should be directed to standard error (stderr).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="example-hook-configmap"&gt;
&lt;h3&gt;Example Hook ConfigMap&lt;/h3&gt;
&lt;p&gt;The following ConfigMap provides a script that modifies VM configurations by adding custom metadata to the VM’s libvirt XML definition using the &lt;strong&gt;onDefineDomain&lt;/strong&gt; hook:&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ConfigMap&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;xmleditscript&lt;/span&gt;
&lt;span class="nt"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;script.sh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;tempFile=`mktemp --dry-run`&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;echo $4 &amp;gt; $tempFile&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;sed -i "s|&amp;lt;baseBoard&amp;gt;&amp;lt;/baseBoard&amp;gt;|&amp;lt;baseBoard&amp;gt;&amp;lt;entry name='manufacturer'&amp;gt;Radical Edward&amp;lt;/entry&amp;gt;&amp;lt;/baseBoard&amp;gt;|" $tempFile&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;cat $tempFile&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The libvirt domain XML is received as the 4th argument (&lt;cite&gt;$4&lt;/cite&gt;), and the script’s standard output is used as the new domain definition to apply. This allows for dynamic modifications to the VM configuration.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="using-sidecars-with-vms"&gt;
&lt;h3&gt;Using Sidecars with VMs&lt;/h3&gt;
&lt;p&gt;To add a hook sidecar to a VM, modify the VM manifest to include the required annotations that specify the hook configuration. The ConfigMap containing your script must be referenced in the annotations:&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubevirt.io/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;VirtualMachine&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;example-vm&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;hooks.kubevirt.io/hookSidecars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'[{"args":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;["--version",&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"v1alpha2"],&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s"&gt;"configMap":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{"name":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"xmleditscript",&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"key":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"script.sh",&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"hookPath":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"/usr/bin/onDefineDomain"}}]'&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# VM configuration...&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;config-volume&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;configMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;xmleditscript&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="validating-the-sidecar-modifications"&gt;
&lt;h2&gt;Validating the Sidecar Modifications&lt;/h2&gt;
&lt;p&gt;After applying the sidecar configuration, you can verify that the changes have been successfully applied using several methods:&lt;/p&gt;
&lt;section id="method-1-check-vm-xml-from-virt-launcher-pod"&gt;
&lt;h3&gt;Method 1: Check VM XML from virt-launcher Pod&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Get the virt-launcher pod for your VM:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pods&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;namespace&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;virt-launcher-&amp;lt;vm-name&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Examine the libvirt XML directly from the virt-launcher pod:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;virt-launcher-&amp;lt;vm-name&amp;gt;-&amp;lt;random-id&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;namespace&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;virsh&lt;span class="w"&gt; &lt;/span&gt;dumpxml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-A3&lt;span class="w"&gt; &lt;/span&gt;manufacturer
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;The output should include the modified XML with the custom manufacturer entry:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-xml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;&amp;lt;entry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'manufacturer'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Radical&lt;span class="w"&gt; &lt;/span&gt;Edward&lt;span class="nt"&gt;&amp;lt;/entry&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="method-2-from-inside-the-vm"&gt;
&lt;h3&gt;Method 2: From Inside the VM&lt;/h3&gt;
&lt;p&gt;If your modification affects data visible to the guest OS (like SMBIOS data), you can also verify from inside the VM using tools like dmidecode:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Connect to the VM console or SSH into the VM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run dmidecode to check the baseboard manufacturer:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;dmidecode&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;baseboard-manufacturer
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;The output should show:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Radical Edward
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple" id="kubevirt-docs"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://kubevirt.io/user-guide/"&gt;KubeVirt Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openshift.com/container-platform/latest/virt/about-virt.html"&gt;OpenShift CNV Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://kubernetes.io/docs/concepts/workloads/pods/#how-pods-manage-multiple-containers"&gt;Kubernetes Sidecar Patterns&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Sat, 26 Apr 2025 00:00:00 </pubDate></item><item><title>OpenShift Console Banner</title><link>https://blog.epheo.eu/notes/openshift-banner.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Apr 25, 2025&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;2 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Adding visual indicators to your OpenShift clusters can help users quickly identify which environment they’re working in, potentially preventing accidental changes in production environments.&lt;/p&gt;
&lt;p&gt;This article demonstrates how to set a console banner in OpenShift to display important information like the cluster name or environment type.&lt;/p&gt;
&lt;section id="setting-up-a-console-banner"&gt;
&lt;h2&gt;Setting up a Console Banner&lt;/h2&gt;
&lt;p&gt;You can create a banner on the OpenShift web console by creating a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsoleNotification&lt;/span&gt;&lt;/code&gt; custom resource:&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;console.openshift.io/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ConsoleNotification&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;banner&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'#0f4414'&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Dark red&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'#ffffff'&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# White text&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;BannerTop&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;If it ain't broke, don't fix it&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="banner-customization"&gt;
&lt;h2&gt;Banner Customization&lt;/h2&gt;
&lt;p&gt;You can customize the following aspects of the banner:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;backgroundColor&lt;/strong&gt;: The background color of the banner (hex color code)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;color&lt;/strong&gt;: The text color (hex color code)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;location&lt;/strong&gt;: Where the banner appears. Options include:
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BannerTop&lt;/span&gt;&lt;/code&gt;: Displays at the very top of the console (most common)
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BannerBottom&lt;/span&gt;&lt;/code&gt;: Displays at the bottom of the console
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BannerTopBottom&lt;/span&gt;&lt;/code&gt;: Displays at both top and bottom of the console
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AlertBanner&lt;/span&gt;&lt;/code&gt;: Displays as a more prominent alert banner&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;text&lt;/strong&gt;: The message to display to users&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="example-colors"&gt;
&lt;h3&gt;Example Colors&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Production: &lt;span class="color-prod"&gt;Red (#880808)&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Development: &lt;span class="color-dev"&gt;Blue (#0066CC)&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing: &lt;span class="color-test"&gt;Green (#2E8B57)&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Staging: &lt;span class="color-staging"&gt;Orange (#FF8C00)&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="common-use-cases"&gt;
&lt;h2&gt;Common Use Cases&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Identifying different clusters (prod, dev, test)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Warning users about scheduled maintenance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Highlighting important information about the environment&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Using distinct colors for different environments helps users visually identify which cluster they’re working with, reducing the risk of mistakes.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="applying-the-configuration"&gt;
&lt;h2&gt;Applying the Configuration&lt;/h2&gt;
&lt;p&gt;Apply the configuration using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oc&lt;/span&gt;&lt;/code&gt; command:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;banner.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To remove the banner:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;delete&lt;span class="w"&gt; &lt;/span&gt;consolennotification&lt;span class="w"&gt; &lt;/span&gt;banner
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Sat, 26 Apr 2025 00:00:00 </pubDate></item><item><title>Simple Block Device Backup for OpenShift Lab Environments</title><link>https://blog.epheo.eu/articles/openshift-borg/index.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;April 25, 2025&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;8 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;section id="introduction"&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Like the Borg collective from Star Trek assimilates technology, BorgBackup assimilates your data.&lt;/p&gt;
&lt;p&gt;This article shows how to back up and restore LVM Logical Volumes from local storage to FreeNAS using BorgBackup.
While not for enterprise production workloads, this method works well for lab environments.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="overview-prerequisites"&gt;
&lt;h2&gt;Overview &amp;amp; Prerequisites&lt;/h2&gt;
&lt;p&gt;This backup solution backs up LVM Logical Volumes from Single Node OpenShift local storage to FreeNAS servers using:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BorgBackup&lt;/strong&gt;: For efficient, deduplicated, encrypted backups&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Container Image&lt;/strong&gt;: Minimal image with BorgBackup and required tools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Kubernetes CronJobs&lt;/strong&gt;: For scheduled backups of local LVM volumes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Kubernetes Pods&lt;/strong&gt;: For restores to FreeNAS storage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Volume/Device Mounts&lt;/strong&gt;: Direct access to LVM block devices on the SNO node&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;All resources in this article are available in the &lt;a class="reference external" href="https://github.com/epheo/blog"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="step-1-prepare-your-environment"&gt;
&lt;h2&gt;Step 1: Prepare Your Environment&lt;/h2&gt;
&lt;section id="container-image"&gt;
&lt;h3&gt;Container Image&lt;/h3&gt;
&lt;p&gt;Create a container image with BorgBackup:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id1"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Container image definition&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-dockerfile notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt;1&lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;fedora:latest&lt;/span&gt;
&lt;span class="linenos"&gt;2&lt;/span&gt;
&lt;span class="linenos"&gt;3&lt;/span&gt;&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;borgbackup
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Build and push the image:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;borg-container
podman&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;registry.example.com/borgbackup:latest&lt;span class="w"&gt; &lt;/span&gt;.
podman&lt;span class="w"&gt; &lt;/span&gt;push&lt;span class="w"&gt; &lt;/span&gt;registry.example.com/borgbackup:latest
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="resource-planning"&gt;
&lt;h3&gt;Resource Planning&lt;/h3&gt;
&lt;p&gt;Allocate resources for backup and restore pods:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memory&lt;/strong&gt;: 4Gi limit (1Gi request)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CPU&lt;/strong&gt;: 2 cores limit (500m request)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These values balance performance with efficient resource usage.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="storage-architecture"&gt;
&lt;h3&gt;Storage Architecture&lt;/h3&gt;
&lt;p&gt;The backup system uses two storage mechanisms:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Source LVM Storage&lt;/strong&gt;: Direct access to LVM Logical Volumes on the SNO node&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;FreeNAS Repository Storage&lt;/strong&gt;: iSCSI-based persistent volumes for BorgBackup repositories&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach enables efficient backup of LVM volumes to FreeNAS while maintaining block-level operations.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="step-2-configure-and-run-backups"&gt;
&lt;h2&gt;Step 2: Configure and Run Backups&lt;/h2&gt;
&lt;p&gt;Create a CronJob for regular backups:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id2"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Example backup cronjob configuration&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;batch/v1&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;CronJob&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-backup-cronjob&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;31&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# A non-recurring time (e.g., Feb 31st)&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Prevents the job from running automatically&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;jobTemplate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;backup-container&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;registry.desku.be/epheo/borgbackup:latest&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;BORG_CONFIG_DIR&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/tmp/borg_config&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;BORG_CACHE_DIR&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/tmp/borg_cache&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"yes"&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"/bin/bash"&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-c"&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="no"&gt;echo "Starting Windows Backup pod with two mounted PVCs"&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="no"&gt;mkdir -p $BORG_CONFIG_DIR $BORG_CACHE_DIR&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="no"&gt;borg init --encryption=none /backup/&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="no"&gt;borg create --read-special /backup::"backup-$(date +%Y-%m-%d_%H-%M-%S)" /dev/windows-block&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;volumeDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;devicePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/windows-block&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-block&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;volumeMounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;33&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mountPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/backup&lt;/span&gt;
&lt;span class="linenos"&gt;34&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-backup&lt;/span&gt;
&lt;span class="linenos"&gt;35&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;36&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;37&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1Gi"&lt;/span&gt;
&lt;span class="linenos"&gt;38&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"500m"&lt;/span&gt;
&lt;span class="linenos"&gt;39&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;40&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"4Gi"&lt;/span&gt;
&lt;span class="linenos"&gt;41&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;
&lt;span class="linenos"&gt;42&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;restartPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OnFailure&lt;/span&gt;
&lt;span class="linenos"&gt;43&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;44&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-block&lt;/span&gt;
&lt;span class="linenos"&gt;45&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;46&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows&lt;/span&gt;
&lt;span class="linenos"&gt;47&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-backup&lt;/span&gt;
&lt;span class="linenos"&gt;48&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;49&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-backup&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply the configuration:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;backup-cronjob.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Run an immediate backup:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;job&lt;span class="w"&gt; &lt;/span&gt;--from&lt;span class="o"&gt;=&lt;/span&gt;cronjob/&amp;lt;backup-cronjob-name&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;manual-backup
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;Ensure source block devices are accessible to the backup pod.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="step-3-monitor-and-manage-your-backups"&gt;
&lt;h2&gt;Step 3: Monitor and Manage Your Backups&lt;/h2&gt;
&lt;section id="checking-backup-status"&gt;
&lt;h3&gt;Checking Backup Status&lt;/h3&gt;
&lt;p&gt;Monitor backup job status:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;jobs&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example output:&lt;/p&gt;
&lt;div class="highlight-none notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;NAME                   COMPLETIONS   DURATION   AGE
block-backup-manual    1/1           2m15s      10m
vm-backup-1682456400   1/1           1m32s      2h
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="examining-backup-logs"&gt;
&lt;h3&gt;Examining Backup Logs&lt;/h3&gt;
&lt;p&gt;View logs to confirm success or troubleshoot:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pod-name&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="admonition-title"&gt;Tip&lt;/p&gt;
&lt;p&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;kubectl&lt;/span&gt; &lt;span class="pre"&gt;logs&lt;/span&gt; &lt;span class="pre"&gt;-f&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;pod-name&amp;gt;&lt;/span&gt;&lt;/code&gt; to follow logs in real-time.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="managing-backup-archives"&gt;
&lt;h3&gt;Managing Backup Archives&lt;/h3&gt;
&lt;p&gt;List available backups:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Create a temporary pod with the backup volume&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; EOF | kubectl apply -f -&lt;/span&gt;
&lt;span class="s"&gt;apiVersion: v1&lt;/span&gt;
&lt;span class="s"&gt;kind: Pod&lt;/span&gt;
&lt;span class="s"&gt;metadata:&lt;/span&gt;
&lt;span class="s"&gt;  name: borg-inspector&lt;/span&gt;
&lt;span class="s"&gt;spec:&lt;/span&gt;
&lt;span class="s"&gt;  containers:&lt;/span&gt;
&lt;span class="s"&gt;  - name: borg-inspector&lt;/span&gt;
&lt;span class="s"&gt;    image: registry.desku.be/epheo/borgbackup:latest&lt;/span&gt;
&lt;span class="s"&gt;    command: ["sleep", "3600"]&lt;/span&gt;
&lt;span class="s"&gt;    env:&lt;/span&gt;
&lt;span class="s"&gt;    - name: BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK&lt;/span&gt;
&lt;span class="s"&gt;      value: "yes"&lt;/span&gt;
&lt;span class="s"&gt;    volumeMounts:&lt;/span&gt;
&lt;span class="s"&gt;    - mountPath: /backup&lt;/span&gt;
&lt;span class="s"&gt;      name: backup-volume&lt;/span&gt;
&lt;span class="s"&gt;  volumes:&lt;/span&gt;
&lt;span class="s"&gt;  - name: backup-volume&lt;/span&gt;
&lt;span class="s"&gt;    persistentVolumeClaim:&lt;/span&gt;
&lt;span class="s"&gt;      claimName: windowsdata-backup&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

&lt;span class="c1"&gt;# Wait for the pod to start&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;wait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--for&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ready&lt;span class="w"&gt; &lt;/span&gt;pod/borg-inspector

&lt;span class="c1"&gt;# List backups&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;borg-inspector&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;borg&lt;span class="w"&gt; &lt;/span&gt;list&lt;span class="w"&gt; &lt;/span&gt;/backup

&lt;span class="c1"&gt;# Break a lock if needed:&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;borg-inspector&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;borg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;-lock&lt;span class="w"&gt; &lt;/span&gt;/backup

&lt;span class="c1"&gt;# Additional commands:&lt;/span&gt;
&lt;span class="c1"&gt;# Check repository&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;borg-inspector&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;borg&lt;span class="w"&gt; &lt;/span&gt;check&lt;span class="w"&gt; &lt;/span&gt;/backup

&lt;span class="c1"&gt;# Show repository info&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;borg-inspector&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;borg&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;/backup

&lt;span class="c1"&gt;# List archive contents&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;borg-inspector&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;borg&lt;span class="w"&gt; &lt;/span&gt;list&lt;span class="w"&gt; &lt;/span&gt;/backup::archivename

&lt;span class="c1"&gt;# Extract files&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;borg-inspector&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;borg&lt;span class="w"&gt; &lt;/span&gt;extract&lt;span class="w"&gt; &lt;/span&gt;/backup::archivename&lt;span class="w"&gt; &lt;/span&gt;path/to/file

&lt;span class="c1"&gt;# Prune old archives&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;borg-inspector&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;borg&lt;span class="w"&gt; &lt;/span&gt;prune&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;--list&lt;span class="w"&gt; &lt;/span&gt;--keep-within&lt;span class="o"&gt;=&lt;/span&gt;30d&lt;span class="w"&gt; &lt;/span&gt;/backup

&lt;span class="c1"&gt;# Remove the temporary pod&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;delete&lt;span class="w"&gt; &lt;/span&gt;pod&lt;span class="w"&gt; &lt;/span&gt;borg-inspector
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="step-4-restore-to-a-local-volume"&gt;
&lt;h2&gt;Step 4: Restore to a Local Volume&lt;/h2&gt;
&lt;p&gt;Restore a backup to a local volume:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id3"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Example restore pod configuration&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Pod&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-restore&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;epheo&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;restore-container&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;registry.desku.be/epheo/borgbackup:latest&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;BORG_CONFIG_DIR&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/tmp/borg_config&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;BORG_CACHE_DIR&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/tmp/borg_cache&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"yes"&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"/bin/bash"&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-c"&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;echo "Starting Windows Backup pod with two mounted PVCs"&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;mkdir -p $BORG_CONFIG_DIR $BORG_CACHE_DIR&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;borg extract --progress --stdout /backup::$(borg list /backup --last 1 --format "{archive}") |dd of=/dev/windows-block&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumeDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;devicePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/windows-block&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-block&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumeMounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mountPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/backup&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-backup&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1Gi"&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"500m"&lt;/span&gt;
&lt;span class="linenos"&gt;33&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;34&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"4Gi"&lt;/span&gt;
&lt;span class="linenos"&gt;35&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;
&lt;span class="linenos"&gt;36&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;37&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-block&lt;/span&gt;
&lt;span class="linenos"&gt;38&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;39&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows&lt;/span&gt;
&lt;span class="linenos"&gt;40&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-backup&lt;/span&gt;
&lt;span class="linenos"&gt;41&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;42&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-backup&lt;/span&gt;
&lt;span class="linenos"&gt;43&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;restartPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OnFailure&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply the configuration:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;restore-pod.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;Ensure target block devices are not in use during restore.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="step-5-cross-platform-restoration-process"&gt;
&lt;h2&gt;Step 5: Cross-Platform Restoration Process&lt;/h2&gt;
&lt;p&gt;This section explains how to restore backups from FreeNAS to LVM Logical Volumes on Single Node OpenShift.&lt;/p&gt;
&lt;section id="prerequisites"&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;p&gt;Before starting:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Install Democratic-CSI backend on your SNO cluster&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure access to FreeNAS storage with the backup repositories&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify permissions to create storage resources in the target namespace&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The process involves three steps:&lt;/p&gt;
&lt;section id="step-5-1-create-a-reference-to-the-existing-backup-volume"&gt;
&lt;h4&gt;Step 5.1: Create a Reference to the Existing Backup Volume&lt;/h4&gt;
&lt;p&gt;Create a PersistentVolume referencing your FreeNAS volume:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id4"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;existing-backup-pv.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PersistentVolume&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-backup-pv&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;500Gi&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;volumeMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Filesystem&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;accessModes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ReadWriteOnce&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeReclaimPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Retain&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;storageClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;freenas-iscsi-csi&lt;/span&gt;
&lt;/span&gt;&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;csi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;org.democratic-csi.iscsi&lt;/span&gt;
&lt;/span&gt;&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumeHandle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-backup-volume-id&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# ID of your existing volume on FreeNAS&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumeAttributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;fs_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ext4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply it:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;existing-backup-pv.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="step-5-2-create-a-claim-for-the-backup-volume"&gt;
&lt;h4&gt;Step 5.2: Create a Claim for the Backup Volume&lt;/h4&gt;
&lt;p&gt;Create a PersistentVolumeClaim:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id5"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;existing-backup-pvc.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PersistentVolumeClaim&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-backup-pvc&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;accessModes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ReadWriteOnce&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;500Gi&lt;/span&gt;
&lt;/span&gt;&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;storageClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;freenas-iscsi-csi&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;volumeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-backup-pv&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply it:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;existing-backup-pvc.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="step-5-3-create-a-restore-pod"&gt;
&lt;h4&gt;Step 5.3: Create a Restore Pod&lt;/h4&gt;
&lt;p&gt;Create a restoration pod:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id6"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;restore-from-backup-pod.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Pod&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;restore-from-existing-backup&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;restore-container&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;registry.desku.be/epheo/borgbackup:latest&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;BORG_CONFIG_DIR&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/tmp/borg_config&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;BORG_CACHE_DIR&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/tmp/borg_cache&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"yes"&lt;/span&gt;
&lt;/span&gt;&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"/bin/bash"&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-c"&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;mkdir -p $BORG_CONFIG_DIR $BORG_CACHE_DIR&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;borg extract --progress --stdout /existing-backup::$(borg list /existing-backup --last 1 --format "{archive}") | dd of=/dev/target-block bs=4M status=progress&lt;/span&gt;
&lt;/span&gt;&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumeDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;devicePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/target-block&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;target-block-device&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumeMounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mountPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/existing-backup&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-backup-volume&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-backup-volume&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-backup-pvc&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;target-block-device&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;33&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;target-device-pvc&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply it:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;restore-from-backup-pod.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="step-6-verify-the-restoration"&gt;
&lt;h2&gt;Step 6: Verify the Restoration&lt;/h2&gt;
&lt;p&gt;Verify restored data:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id7"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Verification commands&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Create verification directory&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;restore-from-existing-backup&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/mnt/verify

&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Mount the restored device&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;restore-from-existing-backup&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;/dev/target-block&lt;span class="w"&gt; &lt;/span&gt;/mnt/verify

&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Check contents&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;restore-from-existing-backup&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-la&lt;span class="w"&gt; &lt;/span&gt;/mnt/verify
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="admonition-title"&gt;Tip&lt;/p&gt;
&lt;p&gt;For block devices with partition tables, use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fdisk&lt;/span&gt; &lt;span class="pre"&gt;-l&lt;/span&gt; &lt;span class="pre"&gt;/dev/target-block&lt;/span&gt;&lt;/code&gt;
before mounting.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="step-7-directly-using-existing-block-devices-with-kubernetes"&gt;
&lt;h2&gt;Step 7: Directly Using Existing Block Devices with Kubernetes&lt;/h2&gt;
&lt;p&gt;Recent OpenShift versions can reinstall without wiping disks, preserving LVM Logical Volumes for recovery after reinstallation.&lt;/p&gt;
&lt;section id="identifying-available-block-devices"&gt;
&lt;h3&gt;Identifying Available Block Devices&lt;/h3&gt;
&lt;p&gt;Identify block devices:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# From a debug pod&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;debug&lt;span class="w"&gt; &lt;/span&gt;node/&amp;lt;node-name&amp;gt;
chroot&lt;span class="w"&gt; &lt;/span&gt;/host

&lt;span class="c1"&gt;# List devices&lt;/span&gt;
lsblk

&lt;span class="c1"&gt;# Get device info&lt;/span&gt;
blkid&lt;span class="w"&gt; &lt;/span&gt;/dev/sdX
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="direct-persistentvolume-approach"&gt;
&lt;h3&gt;Direct PersistentVolume Approach&lt;/h3&gt;
&lt;p&gt;Create a PersistentVolume referencing the block device:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id8"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;local-pv.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PersistentVolume&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-block-pv&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;50Gi&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;volumeMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Block&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Use Block for raw device or Filesystem for formatted&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;accessModes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ReadWriteOnce&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeReclaimPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Retain&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;storageClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;local-storage&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;local&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/sdX&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Replace with your device path&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nodeAffinity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;nodeSelectorTerms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchExpressions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubernetes.io/hostname&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;In&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sno-node-01&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Replace with your node name&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply it:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;local-pv.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="creating-a-persistentvolumeclaim"&gt;
&lt;h3&gt;Creating a PersistentVolumeClaim&lt;/h3&gt;
&lt;p&gt;Create a PersistentVolumeClaim:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id9"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;local-pvc.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PersistentVolumeClaim&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-block-pvc&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;my-namespace&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;volumeMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Block&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Must match the PV's volumeMode&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;accessModes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ReadWriteOnce&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;50Gi&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;volumeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-block-pv&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Reference the PV by name&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;storageClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;local-storage&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply it:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;local-pvc.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="using-the-block-device-in-a-pod"&gt;
&lt;h3&gt;Using the Block Device in a Pod&lt;/h3&gt;
&lt;p&gt;Use the block device in a pod:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id10"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;block-device-pod.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Pod&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;block-device-pod&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;my-namespace&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;block-user&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;registry.access.redhat.com/ubi8/ubi-minimal:latest&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"sleep"&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"infinity"&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumeDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Use volumeDevices for Block mode&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;block-vol&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;devicePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/xvda&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Device path in container&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;block-vol&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;existing-block-pvc&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply it:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;block-device-pod.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="verification"&gt;
&lt;h3&gt;Verification&lt;/h3&gt;
&lt;p&gt;Verify access to the block device:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Check pod status&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pod&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;my-namespace&lt;span class="w"&gt; &lt;/span&gt;block-device-pod

&lt;span class="c1"&gt;# Verify block device&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;my-namespace&lt;span class="w"&gt; &lt;/span&gt;block-device-pod&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;lsblk

&lt;span class="c1"&gt;# Format and mount if needed&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;my-namespace&lt;span class="w"&gt; &lt;/span&gt;block-device-pod&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;mkfs.ext4&lt;span class="w"&gt; &lt;/span&gt;/dev/xvda
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;my-namespace&lt;span class="w"&gt; &lt;/span&gt;block-device-pod&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/mnt/data
kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;my-namespace&lt;span class="w"&gt; &lt;/span&gt;block-device-pod&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;/dev/xvda&lt;span class="w"&gt; &lt;/span&gt;/mnt/data
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="admonition-title"&gt;Tip&lt;/p&gt;
&lt;p&gt;Skip formatting for existing formatted devices.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This approach gives direct access to block devices while managing them through Kubernetes.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="resources-and-references"&gt;
&lt;h2&gt;Resources and References&lt;/h2&gt;
&lt;p&gt;Additional resources:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://borgbackup.readthedocs.io/en/stable/deployment/image-backup.html"&gt;BorgBackup Image Backup Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/"&gt;Kubernetes CronJob Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/"&gt;Kubernetes Persistent Volumes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Fri, 25 Apr 2025 00:00:00 </pubDate></item><item><title>OpenStack OVN Networking - Deep Dive and Debugging</title><link>https://blog.epheo.eu/debug/openstack-ovn.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Aug 22, 2025&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;12 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;OVN (Open Virtual Network) provides advanced networking capabilities for OpenStack environments.
This article explores how to debug, analyze and understand OVN’s networking components within an OpenStack
deployment, helping you troubleshoot and gain deeper insights into the networking layer.&lt;/p&gt;
&lt;section id="locating-ovn-services"&gt;
&lt;h2&gt;Locating OVN Services&lt;/h2&gt;
&lt;p&gt;OVN in OpenStack typically runs as a clustered service. First, we need to identify where these services
are running in our environment.&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# pcs status&lt;/span&gt;
Container&lt;span class="w"&gt; &lt;/span&gt;bundle&lt;span class="w"&gt; &lt;/span&gt;set:&lt;span class="w"&gt; &lt;/span&gt;ovn-dbs-bundle&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;undercloud-0.ctlplane.redhat.local:8787/rh-osbs/rhosp16-openstack-ovn-northd:pcmklatest&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;ovn-dbs-bundle-0&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ocf::ovn:ovndb-servers&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt;       &lt;/span&gt;Master&lt;span class="w"&gt; &lt;/span&gt;controller-3
&lt;span class="w"&gt;   &lt;/span&gt;ovn-dbs-bundle-1&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ocf::ovn:ovndb-servers&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt;       &lt;/span&gt;Slave&lt;span class="w"&gt; &lt;/span&gt;controller-0
&lt;span class="w"&gt;   &lt;/span&gt;ovn-dbs-bundle-2&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ocf::ovn:ovndb-servers&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt;       &lt;/span&gt;Slave&lt;span class="w"&gt; &lt;/span&gt;controller-2
&lt;span class="w"&gt; &lt;/span&gt;ip-172.17.1.200&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ocf::heartbeat:IPaddr2&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt;       &lt;/span&gt;Started&lt;span class="w"&gt; &lt;/span&gt;controller-1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can also inspect the detailed properties of the OVN database service:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# pcs resource show ovn-dbs-bundle&lt;/span&gt;
Resource:&lt;span class="w"&gt; &lt;/span&gt;ovndb_servers&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ocf&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ovn&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ovndb-servers&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;Attributes:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;inactive_probe_interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;180000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;manage_northd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;yes&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;master_ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;172&lt;/span&gt;.17.1.179&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;nb_master_port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6641&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;sb_master_port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6642&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;Meta&lt;span class="w"&gt; &lt;/span&gt;Attrs:&lt;span class="w"&gt; &lt;/span&gt;container-attribute-target&lt;span class="o"&gt;=&lt;/span&gt;host&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;notify&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;Operations:&lt;span class="w"&gt; &lt;/span&gt;demote&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ovndb_servers-demote-interval-0s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;monitor&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Master&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ovndb_servers-monitor-interval-10s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;monitor&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Slave&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ovndb_servers-monitor-interval-30s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;notify&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ovndb_servers-notify-interval-0s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;promote&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ovndb_servers-promote-interval-0s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;200s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ovndb_servers-start-interval-0s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;200s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ovndb_servers-stop-interval-0s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="executing-ovn-commands-in-the-cluster"&gt;
&lt;h2&gt;Executing OVN Commands in the Cluster&lt;/h2&gt;
&lt;p&gt;Before executing OVN commands, we need to identify which node is running the OVN databases as the master:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;ansible&lt;span class="w"&gt; &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;/usr/bin/tripleo-ansible-inventory&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pcs status | grep ovn-dbs-bundle | grep Master"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;controller-2
controller-3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;CHANGED&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class="w"&gt;   &lt;/span&gt;ovn-dbs-bundle-0&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ocf::ovn:ovndb-servers&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt;       &lt;/span&gt;Master&lt;span class="w"&gt; &lt;/span&gt;controller-0
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now that we’ve identified the master node, we can execute read/write operations directly against the OVN Northbound (NB) and Southbound (SB) databases from the corresponding container:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# On the master controller node (controller-2)&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;root@controller-0&lt;span class="w"&gt; &lt;/span&gt;~&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# podman exec -it ovn-dbs-bundle-podman-0 bash&lt;/span&gt;

&lt;span class="c1"&gt;# Creating a test logical switch&lt;/span&gt;
&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-1&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-nbctl ls-add ovn_test_lswitch&lt;/span&gt;

&lt;span class="c1"&gt;# Verifying the switch was created&lt;/span&gt;
&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-3&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-nbctl ls-list | grep ovn_test_lswitch&lt;/span&gt;
9905fd23-1ed2-4f57-b220-77b008b2116e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ovn_test_lswitch&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Deleting the test switch&lt;/span&gt;
&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-1&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-nbctl ls-del ovn_test_lswitch&lt;/span&gt;

&lt;span class="c1"&gt;# Confirming the switch was deleted&lt;/span&gt;
&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-2&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-nbctl ls-list | grep -c ovn_test_lswitch&lt;/span&gt;
&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="remote-ovn-database-access"&gt;
&lt;h2&gt;Remote OVN Database Access&lt;/h2&gt;
&lt;p&gt;We can also run commands from non-master nodes, but we need the Virtual IP (VIP) of the OVN database service:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;[&lt;/span&gt;root@controller-2&lt;span class="w"&gt; &lt;/span&gt;~&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovs-vsctl get Open_Vswitch . external_ids:ovn-remote | cut -d':' -f 2&lt;/span&gt;
&lt;span class="m"&gt;172&lt;/span&gt;.17.1.213
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Using the IP address obtained above, we can execute commands against the OVN databases from any node:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Creating a test logical switch in the NB database&lt;/span&gt;
&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-1&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-nbctl --db="tcp:172.17.1.59:6641" ls-add ovn_test_lswitch&lt;/span&gt;

&lt;span class="c1"&gt;# Removing the test logical switch&lt;/span&gt;
&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-3&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-nbctl --db="tcp:172.17.1.156:6641" ls-del ovn_test_lswitch&lt;/span&gt;

&lt;span class="c1"&gt;# Creating a test chassis in the SB database&lt;/span&gt;
&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-0&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-sbctl --db="tcp:172.17.1.49:6642" chassis-add ovn_test_chassis geneve 127.0.0.1&lt;/span&gt;

&lt;span class="c1"&gt;# Removing the test chassis&lt;/span&gt;
&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-1&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-sbctl --db="tcp:172.17.1.170:6642" chassis-del ovn_test_chassis&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note: By default, TCP port 6641 is used for the OVN Northbound database and 6642 for the OVN Southbound database.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="understanding-ovn-database-structure"&gt;
&lt;h2&gt;Understanding OVN Database Structure&lt;/h2&gt;
&lt;p&gt;OVN uses two databases to manage the network: the Northbound (NB) and Southbound (SB) databases. Let’s explore their contents to understand how the logical and physical elements relate.&lt;/p&gt;
&lt;section id="northbound-database-logical-network-elements"&gt;
&lt;h3&gt;Northbound Database - Logical Network Elements&lt;/h3&gt;
&lt;p&gt;The Northbound database defines all the logical networking elements configured through Neutron. By examining this database, we can see the logical routers, ports, and NAT rules:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-1&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-nbctl show&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
router&lt;span class="w"&gt; &lt;/span&gt;a6b22fb8-6d75-4849-9650-5e255d023591&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;neutron-a929f25e-e00f-4857-9e35-e0db72c396f2&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;aka&lt;span class="w"&gt; &lt;/span&gt;router1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;port&lt;span class="w"&gt; &lt;/span&gt;lrp-36ba33f2-31fc-4f41-a86d-7a8dc6a6bcb6&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;private1&lt;span class="w"&gt; &lt;/span&gt;subnet&lt;span class="w"&gt; &lt;/span&gt;interface
&lt;span class="w"&gt;        &lt;/span&gt;mac:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fa:16:3e:09:9a:bf"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;networks:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"192.168.30.1/24"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;port&lt;span class="w"&gt; &lt;/span&gt;lrp-5c3d686a-1918-4663-88c3-cdd9faa1d3b2&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;public&lt;span class="w"&gt; &lt;/span&gt;subnet&lt;span class="w"&gt; &lt;/span&gt;interface
&lt;span class="w"&gt;        &lt;/span&gt;mac:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fa:16:3e:40:f8:46"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;networks:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.0.0.36/24"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;gateway&lt;span class="w"&gt; &lt;/span&gt;chassis:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;21347b99-e853-4aa8-b7da-82aee8aa972a&lt;span class="w"&gt; &lt;/span&gt;50cf1414-5c00-4aa9-a1d7-8a45de1a72ae&lt;span class="w"&gt; &lt;/span&gt;956d66be-6c1a-437f-88ae-247045816147&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;port&lt;span class="w"&gt; &lt;/span&gt;lrp-b139f4e9-01b9-4642-8835-5790ba8b1142&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;private2&lt;span class="w"&gt; &lt;/span&gt;subnet&lt;span class="w"&gt; &lt;/span&gt;interface
&lt;span class="w"&gt;        &lt;/span&gt;mac:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fa:16:3e:b4:08:73"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;networks:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"192.168.40.1/24"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;6401e181-0479-4a70-bd9e-06b8ecd83d21&lt;span class="w"&gt;       &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;Floating&lt;span class="w"&gt; &lt;/span&gt;IP
&lt;span class="w"&gt;        &lt;/span&gt;external&lt;span class="w"&gt; &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10.0.0.130"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;logical&lt;span class="w"&gt; &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"192.168.40.66"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;type:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dnat_and_snat"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;24adb45d-d48a-4c33-84e2-f9642d1a66ae&lt;span class="w"&gt;       &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;SNAT&lt;span class="w"&gt; &lt;/span&gt;rule&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;private1&lt;span class="w"&gt; &lt;/span&gt;subnet
&lt;span class="w"&gt;        &lt;/span&gt;external&lt;span class="w"&gt; &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10.0.0.182"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;logical&lt;span class="w"&gt; &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"192.168.30.0/24"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;type:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"snat"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;f1d6bb14-0f2e-4682-85a8-7b2a92b994bf&lt;span class="w"&gt;       &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;Floating&lt;span class="w"&gt; &lt;/span&gt;IP
&lt;span class="w"&gt;        &lt;/span&gt;external&lt;span class="w"&gt; &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10.0.0.6"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;logical&lt;span class="w"&gt; &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"192.168.40.25"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;type:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dnat_and_snat"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;182b12fd-e2aa-46c4-adcb-71e6d8276c04&lt;span class="w"&gt;       &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;Floating&lt;span class="w"&gt; &lt;/span&gt;IP
&lt;span class="w"&gt;        &lt;/span&gt;external&lt;span class="w"&gt; &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10.0.0.146"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;logical&lt;span class="w"&gt; &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"192.168.30.108"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;type:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dnat_and_snat"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;22a78989-5a46-4590-9532-9f31fa783b5a&lt;span class="w"&gt;      &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;SNAT&lt;span class="w"&gt; &lt;/span&gt;rule&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;private2&lt;span class="w"&gt; &lt;/span&gt;subnet
&lt;span class="w"&gt;        &lt;/span&gt;external&lt;span class="w"&gt; &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10.0.0.194"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;logical&lt;span class="w"&gt; &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"192.168.40.0/24"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;type:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"snat"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="southbound-database-physical-mapping"&gt;
&lt;h3&gt;Southbound Database - Physical Mapping&lt;/h3&gt;
&lt;p&gt;The Southbound database maps the logical elements to physical locations in the infrastructure. By examining this database, we can see where instances and network elements are actually running:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-3&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-sbctl show&lt;/span&gt;

Chassis&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0140f271-2811-47f5-8174-5ca281aaeb41"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;hostname:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compute-2.redhat.local"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Encap&lt;span class="w"&gt; &lt;/span&gt;geneve
&lt;span class="w"&gt;        &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"172.17.2.86"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;options:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;csum&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Port_Binding&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a2ff1c60-c074-47c4-9c1e-c768ade269cb"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;private2_vm1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;compute-1
&lt;span class="w"&gt;    &lt;/span&gt;Port_Binding&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"b631ec31-d634-430c-b50e-1b7819ce7dbd"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;private1_vm1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;compute-0
Chassis&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"554f96ab-2f35-40c6-a5eb-764067db3188"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;hostname:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compute-0.redhat.local"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Encap&lt;span class="w"&gt; &lt;/span&gt;geneve
&lt;span class="w"&gt;        &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"172.17.2.36"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;options:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;csum&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Port_Binding&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2d6249e2-d05c-48fd-81c6-7831cfe107b3"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;private1_vm2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;compute-3
&lt;span class="w"&gt;    &lt;/span&gt;Port_Binding&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4b0b7e46-9217-4267-a090-418873a8b6f0"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;private2_vm2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;compute-3
Chassis&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"21347b99-e853-4aa8-b7da-82aee8aa972a"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;hostname:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"controller-2.redhat.local"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Encap&lt;span class="w"&gt; &lt;/span&gt;geneve
&lt;span class="w"&gt;        &lt;/span&gt;ip:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"172.17.2.83"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;options:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;csum&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Port_Binding&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cr-lrp-5c3d686a-1918-4663-88c3-cdd9faa1d3b2"&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&amp;lt;-&lt;span class="w"&gt; &lt;/span&gt;Gateway&lt;span class="w"&gt; &lt;/span&gt;port&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;controller-2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;SNAT&lt;span class="w"&gt; &lt;/span&gt;traffic&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="tracing-security-group-rules-through-ovn"&gt;
&lt;h2&gt;Tracing Security Group Rules Through OVN&lt;/h2&gt;
&lt;p&gt;One of the most powerful aspects of OVN is being able to trace how a Neutron Security Group Rule (SGR) is translated through the networking stack. We can follow the path from:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Neutron Security Group Rule&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OVN Access Control List (ACL)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Logical Flow in the Southbound DB&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OpenFlow rules on compute nodes&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let’s start by examining a security group rule in Neutron:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;(&lt;/span&gt;overcloud&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;stack@undercloud-0&lt;span class="w"&gt; &lt;/span&gt;~&lt;span class="o"&gt;]&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;security&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;rule&lt;span class="w"&gt; &lt;/span&gt;list
+--------------------------------------+-------------+-----------+-------------------+------------+--------------------------------------+--------------------------------------+
&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ID&lt;span class="w"&gt;                                   &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;Protocol&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Ethertype&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;Range&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Port&lt;span class="w"&gt; &lt;/span&gt;Range&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Remote&lt;span class="w"&gt; &lt;/span&gt;Security&lt;span class="w"&gt; &lt;/span&gt;Group&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Security&lt;span class="w"&gt; &lt;/span&gt;Group&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
+--------------------------------------+-------------+-----------+-------------------+------------+--------------------------------------+--------------------------------------+
&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;0a6cfa3d-9291-4331-8e52-82b7e3800200&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tcp&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;IPv4&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.13.116/30&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9999&lt;/span&gt;:9999&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;None&lt;span class="w"&gt;                                 &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;3e484201-4fba-4d47-b18c-a515b6a1b8f3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
+--------------------------------------+-------------+-----------+-------------------+------------+--------------------------------------+--------------------------------------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Next, we can find the corresponding ACL entry in the OVN Northbound database by searching for the security group rule ID:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-2&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-nbctl find ACL external_ids:"neutron\:security_group_rule_id"=0a6cfa3d-9291-4331-8e52-82b7e3800200&lt;/span&gt;
_uuid&lt;span class="w"&gt;               &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;fc662a6a-1228-4c04-b1bf-3cb6f6e61c91
action&lt;span class="w"&gt;              &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;allow-related
direction&lt;span class="w"&gt;           &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;to-lport
external_ids&lt;span class="w"&gt;        &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"neutron:security_group_rule_id"&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0a6cfa3d-9291-4331-8e52-82b7e3800200"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
label&lt;span class="w"&gt;               &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
log&lt;span class="w"&gt;                 &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
match&lt;span class="w"&gt;               &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"outport == @pg_3e484201_4fba_4d47_b18c_a515b6a1b8f3 &amp;amp;&amp;amp; ip4 &amp;amp;&amp;amp; ip4.src == 192.168.13.20/30 &amp;amp;&amp;amp; tcp &amp;amp;&amp;amp; tcp.dst == 9999"&lt;/span&gt;
priority&lt;span class="w"&gt;            &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1002&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then, we can search for the corresponding logical flows in the Southbound database using the ACL’s UUID prefix:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-2&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-sbctl find Logical_Flow external_ids:stage-hint=59ec7790&lt;/span&gt;
_uuid&lt;span class="w"&gt;               &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;0e465ba7-2a0d-45c8-9401-4446d8776c71
actions&lt;span class="w"&gt;             &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next;"&lt;/span&gt;
external_ids&lt;span class="w"&gt;        &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"northd.c:6108"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;stage-hint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"59ec7790"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;stage-name&lt;span class="o"&gt;=&lt;/span&gt;ls_out_acl&lt;span class="o"&gt;}&lt;/span&gt;
logical_datapath&lt;span class="w"&gt;    &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;334f6950-34fc-474d-8897-84a2d13846a0
match&lt;span class="w"&gt;               &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reg0[8] == 1 &amp;amp;&amp;amp; (outport == @pg_3e484201_4fba_4d47_b18c_a515b6a1b8f3 &amp;amp;&amp;amp; ip4 &amp;amp;&amp;amp; ip4.src == 192.168.13.186/30 &amp;amp;&amp;amp; tcp &amp;amp;&amp;amp; tcp.dst == 9999)"&lt;/span&gt;
pipeline&lt;span class="w"&gt;            &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;egress
priority&lt;span class="w"&gt;            &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2002&lt;/span&gt;
table_id&lt;span class="w"&gt;            &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;

_uuid&lt;span class="w"&gt;               &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;48213015&lt;/span&gt;-8c4e-4383-a564-83d5ca516695
actions&lt;span class="w"&gt;             &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reg0[1] = 1; next;"&lt;/span&gt;
external_ids&lt;span class="w"&gt;        &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"northd.c:6084"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;stage-hint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"59ec7790"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;stage-name&lt;span class="o"&gt;=&lt;/span&gt;ls_out_acl&lt;span class="o"&gt;}&lt;/span&gt;
logical_datapath&lt;span class="w"&gt;    &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;334f6950-34fc-474d-8897-84a2d13846a0
match&lt;span class="w"&gt;               &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reg0[7] == 1 &amp;amp;&amp;amp; (outport == @pg_3e484201_4fba_4d47_b18c_a515b6a1b8f3 &amp;amp;&amp;amp; ip4 &amp;amp;&amp;amp; ip4.src == 192.168.13.17/30 &amp;amp;&amp;amp; tcp &amp;amp;&amp;amp; tcp.dst == 9999)"&lt;/span&gt;
pipeline&lt;span class="w"&gt;            &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;egress
priority&lt;span class="w"&gt;            &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2002&lt;/span&gt;
table_id&lt;span class="w"&gt;            &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Finally, we can verify the actual OpenFlow rules installed on the compute nodes that implement these logical flows:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;[&lt;/span&gt;root@compute-0&lt;span class="w"&gt; &lt;/span&gt;~&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# for i in 1c09a74f 4663ae1f; do ovs-ofctl dump-flows br-int | grep $i; done&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cookie&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x58a831c2,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;134139&lt;/span&gt;.172s,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_packets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;idle_age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;18910&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;hard_age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4013&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2002&lt;/span&gt;,tcp,reg0&lt;span class="o"&gt;=&lt;/span&gt;0x100/0x100,reg15&lt;span class="o"&gt;=&lt;/span&gt;0x3,metadata&lt;span class="o"&gt;=&lt;/span&gt;0x8,nw_src&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.13.144/30,tp_dst&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;9999&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;resubmit&lt;span class="o"&gt;(&lt;/span&gt;,45&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cookie&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xf2e670b7,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;128550&lt;/span&gt;.798s,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_packets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;idle_age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;9762&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;hard_age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8793&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2002&lt;/span&gt;,tcp,reg0&lt;span class="o"&gt;=&lt;/span&gt;0x80/0x80,reg15&lt;span class="o"&gt;=&lt;/span&gt;0x3,metadata&lt;span class="o"&gt;=&lt;/span&gt;0x8,nw_src&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.13.31/30,tp_dst&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;9999&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;load:0x1-&amp;gt;NXM_NX_XXREG0&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;97&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,resubmit&lt;span class="o"&gt;(&lt;/span&gt;,45&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# We can also check specific flows for specific ports&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;root@compute-0&lt;span class="w"&gt; &lt;/span&gt;~&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovs-ofctl dump-flows br-int table=65 | grep 'reg15=0x3,metadata=0x8'&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;root@compute-2&lt;span class="w"&gt; &lt;/span&gt;~&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovs-ofctl show br-int&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The values &lt;cite&gt;reg15=0x3,metadata=0x8&lt;/cite&gt; identify a particular VM - in this case, csl-log-redhat-0 (192.168.13.92) on compute-0.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="packet-tracing-with-ovn-trace"&gt;
&lt;h2&gt;Packet Tracing with ovn-trace&lt;/h2&gt;
&lt;p&gt;One of the most powerful debugging tools in OVN is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ovn-trace&lt;/span&gt;&lt;/code&gt;, which allows us to simulate packet flows through the logical network. This tool helps identify issues in packet processing before they reach the physical network.&lt;/p&gt;
&lt;p&gt;How ovn-trace Works:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Reads the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Logical_Flow&lt;/span&gt;&lt;/code&gt; and other tables from the OVN Southbound database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simulates a packet’s path through logical networks by following the entire tree of possibilities&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shows how logical flows would process specific types of packets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only simulates the OVN logical network (not the physical elements)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When used with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--ovs&lt;/span&gt;&lt;/code&gt; option, it will also show the OpenFlow rules installed in the bridge&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This tool is invaluable for debugging connectivity issues, as it helps isolate whether the problem is in the logical configuration or the physical implementation.&lt;/p&gt;
&lt;section id="example-tracing-icmp-traffic-between-vms"&gt;
&lt;h3&gt;Example: Tracing ICMP Traffic Between VMs&lt;/h3&gt;
&lt;p&gt;Let’s use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ovn-trace&lt;/span&gt;&lt;/code&gt; to explore how an ICMP packet would travel between two guest instances:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;()[&lt;/span&gt;root@compute-0&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-trace --db="tcp:172.17.1.203:6642" --ovs --friendly-names --ct=new private2  'inport == "4b0b7e46-9217-4267-a090-418873a8b6f0" &amp;amp;&amp;amp; eth.src == fa:16:3e:fe:90:9a &amp;amp;&amp;amp; eth.dst == fa:16:3e:e3:e2:c8 &amp;amp;&amp;amp; ip4.src == 192.168.40.158 &amp;amp;&amp;amp; ip4.dst == 192.168.40.12 &amp;amp;&amp;amp; ip.ttl == 64 &amp;amp;&amp;amp; icmp4.type == 8'&lt;/span&gt;

&lt;span class="c1"&gt;#icmp,reg14=0x3,vlan_tci=0x0000,dl_src=fa:16:3e:ce:02:65,dl_dst=fa:16:3e:5b:01:ec,nw_src=192.168.30.229,nw_dst=192.168.30.48,nw_tos=0,nw_ecn=0,nw_ttl=64,icmp_type=8,icmp_code=0&lt;/span&gt;

ingress&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;dp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"private2"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;inport&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"private2_vm2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
---------------------------------------------
&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;ls_out_acl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ovn-northd.c:4549&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;!ct.new&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ct.est&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!ct.rpl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ct_label.blocked&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;outport&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;@pg_1576d8a3_7db2_40e9_942f_90f7c37a355e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip4&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip4.src&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.0.0.0/0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;icmp4&lt;span class="o"&gt;)&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;priority&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2002&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;uuid&lt;span class="w"&gt; &lt;/span&gt;eda37d0e
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;cookie&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xeda37d0e,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;677279&lt;/span&gt;.297s,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_packets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;14905&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2002&lt;/span&gt;,ct_state&lt;span class="o"&gt;=&lt;/span&gt;-new+est-rpl+trk,ct_label&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;/0x1,icmp,reg15&lt;span class="o"&gt;=&lt;/span&gt;0x3,metadata&lt;span class="o"&gt;=&lt;/span&gt;0x3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;resubmit&lt;span class="o"&gt;(&lt;/span&gt;,45&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;next&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;ls_out_port_sec_l2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ovn-northd.c:4081&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;outport&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private2_vm1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;eth.dst&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;fa:16:3e:25:26:50&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;priority&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;uuid&lt;span class="w"&gt; &lt;/span&gt;060cf739
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;cookie&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x60cf739,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;670224&lt;/span&gt;.080s,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;49&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_packets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4626&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;372616&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;,reg15&lt;span class="o"&gt;=&lt;/span&gt;0x3,metadata&lt;span class="o"&gt;=&lt;/span&gt;0x3,dl_dst&lt;span class="o"&gt;=&lt;/span&gt;fa:16:3e:68:c6:ee&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;resubmit&lt;span class="o"&gt;(&lt;/span&gt;,64&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;output&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;/*&lt;span class="w"&gt; &lt;/span&gt;output&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private2_vm1"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;*/
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this trace example, we can see how an ICMP packet from private2_vm2 to private2_vm1 is processed through the logical pipeline. The trace shows several stages including ACL processing (step 4) and port security checks (step 9) before the packet is finally output to the destination VM.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="verifying-physical-network-flows"&gt;
&lt;h2&gt;Verifying Physical Network Flows&lt;/h2&gt;
&lt;p&gt;While ovn-trace is extremely helpful for debugging logical flows, sometimes we need to verify how packets are flowing through the physical network infrastructure:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Let’s explore an ICMP packet delivered to a VM on its compute node&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We’ll ping between two guests and expect the packet to be delivered on the correct tap interface&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By monitoring the flow’s n_packets field in table 65, we can confirm packet delivery&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;According to the ovn-architecture manual, table 65 performs the final translation between logical ports and physical ports, with the actual packet output happening in this table.&lt;/p&gt;
&lt;p&gt;First, identify the OpenFlow port number for the VM’s tap interface:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;[&lt;/span&gt;root@compute-2&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovs-ofctl show br-int|grep tapf4ada4a0&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;113&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;tap11d54329--3&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;addr:63:75:6e:e0:9f:a8
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then, monitor the OpenFlow rules to see if packets are being delivered:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;[&lt;/span&gt;root@compute-0&lt;span class="w"&gt; &lt;/span&gt;~&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# watch -d -n1 "ovs-ofctl dump-flows br-int table=65 | grep 'output:113'"&lt;/span&gt;
&lt;span class="nv"&gt;cookie&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x0,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;819057&lt;/span&gt;.906s,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;65&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_packets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4727&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;412655&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;idle_age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;25642&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;hard_age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;11420&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;,reg15&lt;span class="o"&gt;=&lt;/span&gt;0x3,metadata&lt;span class="o"&gt;=&lt;/span&gt;0x3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;output:113
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When the &lt;cite&gt;n_packets&lt;/cite&gt; counter increases, it confirms that packets are successfully reaching the destination VM’s interface.&lt;/p&gt;
&lt;p&gt;Note: OpenFlow table numbers in OVN correspond to logical tables as follows:
- Ingress pipeline tables: Logical table ID + 8
- Egress pipeline tables: Logical table ID + 40&lt;/p&gt;
&lt;p&gt;For a detailed explanation of the OVN logical tables, refer to the ovn-northd manual page.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dhcp-in-ovn"&gt;
&lt;h2&gt;DHCP in OVN&lt;/h2&gt;
&lt;p&gt;Unlike in ML2/OVS, OVN serves DHCP locally in the compute nodes. The DHCP requests are sent to ovn-controller and replied according to the database contents. When a VM starts on a hypervisor, ovn-controller will install flows in table 20 with a controller action.&lt;/p&gt;
&lt;p&gt;We can find the right DHCP_Options row in the NB database (Neutron inserts this every time a subnet is created):&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-3&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-nbctl find DHCP_Options external_ids:subnet_id=ce6193c4-80ef-448c-8153-4b8282eef0f3&lt;/span&gt;

_uuid&lt;span class="w"&gt;               &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;c95ccc99-e50f-471c-978e-bf68dafef362
cidr&lt;span class="w"&gt;                &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"192.168.30.0/24"&lt;/span&gt;
external_ids&lt;span class="w"&gt;        &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"neutron:revision_number"&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;subnet_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ce6193c4-80ef-448c-8153-4b8282eef0f3"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
options&lt;span class="w"&gt;             &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;classless_static_route&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{169.254.169.254/32,192.168.30.2, 0.0.0.0/0,192.168.30.1}"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dns_server&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{172.16.0.1, 10.0.0.1}"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lease_time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"43200"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;mtu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1442"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;router&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"192.168.30.1"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;server_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"192.168.30.1"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;server_mac&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"fa:16:3e:8c:0e:f5"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The options include:
* 169.254.169.254/32,192.168.30.2 -&amp;gt; Static route for the metadata service
* 0.0.0.0/0,192.168.30.1 -&amp;gt; Default gateway route&lt;/p&gt;
&lt;p&gt;We can also find the corresponding logical flow in the SB database:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;()[&lt;/span&gt;root@controller-2&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovn-sbctl find logical_flow external_ids:stage-name=ls_in_dhcp_options&lt;/span&gt;
_uuid&lt;span class="w"&gt;               &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;6b422d1e-0a41-4422-9390-e4cc67352e12
actions&lt;span class="w"&gt;             &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reg0[3] = put_dhcp_opts(offerip = 192.168.30.182, classless_static_route = {169.254.169.254/32,192.168.30.2, 0.0.0.0/0,192.168.30.1}, dns_server = {172.16.0.1, 10.0.0.1}, lease_time = 43200, mtu = 1442, netmask = 255.255.255.0, router = 192.168.30.1, server_id = 192.168.30.1); next;"&lt;/span&gt;
external_ids&lt;span class="w"&gt;        &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ovn-northd.c:5413"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;stage-name&lt;span class="o"&gt;=&lt;/span&gt;ls_in_dhcp_options&lt;span class="o"&gt;}&lt;/span&gt;
logical_datapath&lt;span class="w"&gt;    &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;3b7964f9-d315-4a93-85fb-c5d485ffeefd
match&lt;span class="w"&gt;               &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"inport == \"b631ec31-d634-430c-b50e-1b7819ce7dbd\" &amp;amp;&amp;amp; eth.src == fa:16:3e:40:31:2c &amp;amp;&amp;amp; ip4.src == 0.0.0.0 &amp;amp;&amp;amp; ip4.dst == 255.255.255.255 &amp;amp;&amp;amp; udp.src == 68 &amp;amp;&amp;amp; udp.dst == 67"&lt;/span&gt;
pipeline&lt;span class="w"&gt;            &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;ingress
priority&lt;span class="w"&gt;            &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
table_id&lt;span class="w"&gt;            &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In compute-1 we should be able to see the flow in table 20 (12+8):&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;()[&lt;/span&gt;root@compute-3&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;# ovs-ofctl dump-flows br-int |grep bbe8861b&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cookie&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xbbe8861b,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;780275&lt;/span&gt;.467s,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_packets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n_bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;idle_age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;25685&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;hard_age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;29126&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;,udp,reg14&lt;span class="o"&gt;=&lt;/span&gt;0x3,metadata&lt;span class="o"&gt;=&lt;/span&gt;0x2,dl_src&lt;span class="o"&gt;=&lt;/span&gt;fa:16:3e:c8:4a:a8,nw_src&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.0.0.0,nw_dst&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;.255.255.255,tp_src&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;68&lt;/span&gt;,tp_dst&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;67&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;controller&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;userdata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;.00.00.20.00.00.00.240.00.01.de.10.00.00.98.63.c0.a8.1e.54.79.0e.20.a9.fe.a9.fe.c0.a8.1e.02.00.c0.a8.1e.01.06.08.ac.10.00.01.0a.00.00.01.83.04.00.00.a8.c0.1a.02.05.a2.01.04.ff.ff.ff.00.03.04.c0.a8.1e.01.36.04.c0.a8.1e.01,pause&lt;span class="o"&gt;)&lt;/span&gt;,resubmit&lt;span class="o"&gt;(&lt;/span&gt;,21&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;cite&gt;controller&lt;/cite&gt; action indicates that DHCP requests will be processed by the local ovn-controller process, which generates responses based on the configuration in the OVN databases.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 23 Apr 2025 00:00:00 </pubDate></item><item><title>DEFMS: Distributed, Encrypted and Free Mail System</title><link>https://blog.epheo.eu/notes/defms/index.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Feb 24, 2018&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;2 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Let’s have a closer look at the current implementation of our global email delivery
system.&lt;/p&gt;
&lt;p&gt;It scaled out from the very early stage of our network while all mail addresses was
summed up in a paper book to our current multi-billion addresses directory quite
impressively, the workload and delivery effort is mostly shared across the few biggest
current IT and telecom companies and the required bandwidth and data effort is
duplicated between all sender, receivers and intermediates of the transmission.
Content encryption or signature is still a marginal practice and while normally not
accessible by a random tiers, the relevant intermediates and providers do not hesitate
to monitor and analyze our day to day exchanges. Content is easily reversible, which
so prevent (or at least should prevent) them to have any juridical value.&lt;/p&gt;
&lt;p&gt;As of today, we used the available technologies and paradigms to scale from an
inter-lab experiment to a multi-billion connection delivery network, but as new
paradigms and technologies arrived, we now have all the tools to create a new email
delivery network, compatible with the current protocols, that better suits our
everyday needs.&lt;/p&gt;
&lt;p&gt;Regarding how fast the importance of this media grew up those past two decades, one
would now want to be able to rely on multiple sources for the storage and transport of
his messages without having to necessarily trust those third-parties, one would also
like to guaranty the integrity, the consistency and the immutability in time of his
exchanges with someone. An entirely distributed, partly encrypted and free mail
exchange system would allow us to communicate directly with the concerned receivers
without restrictions of size, number, consistency or availability of the exchanged
messages. Applications are numerous but more importantly this will help us reducing the
total amount of storage and bandwith required by mail exchanges.&lt;/p&gt;
&lt;p&gt;As encryption, peer to peer and data immutability are already widespread principles one
remaining pain-point is in the compatibility with our existing systems and protocols.
Such a compatibility with actual mail protocols will be achieved by non-ditributed
gateway servers, this long-term temporary solution will encrypt and forward all email
from standard MX systems to and from DEFMS.&lt;/p&gt;
</description><pubDate>Wed, 23 Apr 2025 00:00:00 </pubDate></item><item><title>Advanced File Permissions with ACL on Linux</title><link>https://blog.epheo.eu/notes/linux/droits-multiples-et-acl/index.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Aug 06, 2010&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;10 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Traditional Unix file permissions have a significant limitation: they don’t allow us to grant different
access levels to multiple users or groups simultaneously - such as read/write access for some groups
while restricting others to read-only access.&lt;/p&gt;
&lt;p&gt;This is where Access Control Lists (ACLs) come in. ACLs provide a more flexible permission system
by allowing multiple access rules per file or directory. Although ACLs come pre-installed on many
modern Linux distributions, knowing how to use them effectively remains essential, especially for
scenarios like file sharing with Samba or managing multi-user environments.&lt;/p&gt;
&lt;section id="understanding-the-difference-traditional-permissions-vs-acls"&gt;
&lt;h2&gt;Understanding the Difference: Traditional Permissions vs. ACLs&lt;/h2&gt;
&lt;p&gt;Before diving into ACLs, let’s compare them with traditional Unix permissions:&lt;/p&gt;
&lt;div class="table-wrapper colwidths-given docutils container"&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 30.0%"/&gt;
&lt;col style="width: 35.0%"/&gt;
&lt;col style="width: 35.0%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Feature&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Traditional Unix Permissions&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Access Control Lists (ACLs)&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Permission Structure&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Simple rwx for owner, group, others&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Multiple permission entries for different users/groups&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Permission Granularity&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Limited to three entities&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Unlimited entities with specific permissions&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Inheritance Control&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Limited (primarily through umask)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Explicit inheritance with default ACLs&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Management Complexity&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Simple to understand and manage&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;More complex but much more flexible&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Command Tools&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;chmod, chown, chgrp&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;getfacl, setfacl&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Windows Compatibility&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Limited&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Advanced support for Samba/CIFS sharing&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;By understanding these differences, you can make informed decisions about when to use traditional permissions versus ACLs for your file security needs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="practical-use-case"&gt;
&lt;h2&gt;Practical Use Case&lt;/h2&gt;
&lt;p&gt;Let’s consider a Samba file sharing setup in a small business with a directory called “ProjectDocs”.
In this scenario:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The manager needs full control over ProjectDocs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The developers need read and execute permissions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The clients should only have read-only access&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a perfect case where we need to manage the directory permissions with ACLs, as standard Unix
permissions would not allow this level of granular control.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementing-our-use-case"&gt;
&lt;h2&gt;Implementing Our Use Case&lt;/h2&gt;
&lt;p&gt;Let’s implement the scenario described above with specific commands. Assuming you’ve already created a directory called “ProjectDocs”:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Create the directory and test files&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs
touch&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs/report.doc
touch&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs/specs.pdf

&lt;span class="c1"&gt;# Set basic permissions first&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;manager:managers&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs
sudo&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;750&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs

&lt;span class="c1"&gt;# Grant full access to the manager&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;u:manager:rwx&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs

&lt;span class="c1"&gt;# Set read and execute permissions for the developers group&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;g:developers:rx&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs

&lt;span class="c1"&gt;# Set read-only permissions for the clients group&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;g:clients:r&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs

&lt;span class="c1"&gt;# Set default ACLs so new files inherit these permissions&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;d:u:manager:rwx&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs
sudo&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;d:g:developers:rx&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs
sudo&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;d:g:clients:r&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs

&lt;span class="c1"&gt;# Apply ACLs recursively to existing files&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;u:manager:rwx&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs
sudo&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;g:developers:rx&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs
sudo&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;g:clients:r&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After executing these commands, the directory structure will have the exact permissions needed for our scenario:
- Manager has full control (read, write, execute)
- Developers can read and execute files, but not modify them
- Clients can only read the files
- All new files created in the directory will automatically inherit these permissions&lt;/p&gt;
&lt;p&gt;You can verify the configuration with:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;getfacl&lt;span class="w"&gt; &lt;/span&gt;/data/ProjectDocs
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="installation"&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;On most modern Linux distributions, ACL support is pre-installed. If not, you can install it using your package manager:&lt;/p&gt;
&lt;p&gt;For Red Hat-based systems:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;acl
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For Debian-based systems:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;acl
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="enabling-acl-support"&gt;
&lt;h2&gt;Enabling ACL Support&lt;/h2&gt;
&lt;p&gt;Most modern Linux filesystems (ext4, XFS, Btrfs) have ACL support enabled by default. However, if you need to explicitly enable it, you’ll need to modify the filesystem mount options.&lt;/p&gt;
&lt;p&gt;First, identify the partition you want to modify. You can use the following command to list your mounted filesystems:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;df&lt;span class="w"&gt; &lt;/span&gt;-h
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Let’s say we need to enable ACLs on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/dev/nvme0n1p3&lt;/span&gt;&lt;/code&gt; mounted at &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/data&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Edit the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/etc/fstab&lt;/span&gt;&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;nano&lt;span class="w"&gt; &lt;/span&gt;/etc/fstab
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;acl&lt;/span&gt;&lt;/code&gt; option to your partition’s mount options:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;/dev/nvme0n1p3&lt;span class="w"&gt;    &lt;/span&gt;/data&lt;span class="w"&gt;    &lt;/span&gt;ext4&lt;span class="w"&gt;    &lt;/span&gt;defaults,acl&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To apply the changes without rebooting:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;remount,acl&lt;span class="w"&gt; &lt;/span&gt;/data
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note: On most modern Linux systems with ext4, XFS, or Btrfs filesystems, ACL support is enabled by default, so this step may not be necessary.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="verifying-acl-support"&gt;
&lt;h2&gt;Verifying ACL Support&lt;/h2&gt;
&lt;p&gt;To confirm that your filesystem supports ACLs, you can use one of these methods:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Method 1: Check filesystem capabilities&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;tune2fs&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;/dev/nvme0n1p3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Default mount options"&lt;/span&gt;

&lt;span class="c1"&gt;# Method 2: Check if the current mount has ACL support&lt;/span&gt;
mount&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/data"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acl"&lt;/span&gt;

&lt;span class="c1"&gt;# Method 3: Test if you can set an ACL (if this succeeds, ACLs are supported)&lt;/span&gt;
touch&lt;span class="w"&gt; &lt;/span&gt;/data/test_acl
setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;u:nobody:r&lt;span class="w"&gt; &lt;/span&gt;/data/test_acl
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="configuring-acls-for-files-and-directories"&gt;
&lt;h2&gt;Configuring ACLs for Files and Directories&lt;/h2&gt;
&lt;p&gt;There are two main commands for working with ACLs: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;getfacl&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;setfacl&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;getfacl&lt;/span&gt;&lt;/code&gt; command lists ACL permissions:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;getfacl&lt;span class="w"&gt; &lt;/span&gt;filename
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;It works similar to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ls&lt;/span&gt; &lt;span class="pre"&gt;-l&lt;/span&gt;&lt;/code&gt; but provides more detailed information specific to ACLs. For example, to check permissions on a file named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project-report.pdf&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;getfacl&lt;span class="w"&gt; &lt;/span&gt;project-report.pdf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;setfacl&lt;/span&gt;&lt;/code&gt; command configures ACL permissions for a file or directory. Its basic syntax is:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="o"&gt;[&lt;/span&gt;option&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;specification&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;filename
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The command can be broken down into these components:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Options&lt;/strong&gt;:
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-m&lt;/span&gt;&lt;/code&gt; to add or modify a rule
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-b&lt;/span&gt;&lt;/code&gt; to remove all ACL entries
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-x&lt;/span&gt;&lt;/code&gt; to remove specific ACL entries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Specification&lt;/strong&gt;: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[d:]type:name:permissions&lt;/span&gt;&lt;/code&gt;
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;d:&lt;/span&gt;&lt;/code&gt; (optional) - if present, applies to default ACLs (used for directories)
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt; - can be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;u&lt;/span&gt;&lt;/code&gt; (user), &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;g&lt;/span&gt;&lt;/code&gt; (group), or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;o&lt;/span&gt;&lt;/code&gt; (other)
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt; - username or group name (not needed for “other”)
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;permissions&lt;/span&gt;&lt;/code&gt; - any combination of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;r&lt;/span&gt;&lt;/code&gt; (read), &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;w&lt;/span&gt;&lt;/code&gt; (write), and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x&lt;/span&gt;&lt;/code&gt; (execute)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="understanding-acl-masks"&gt;
&lt;h2&gt;Understanding ACL Masks&lt;/h2&gt;
&lt;p&gt;One of the most important concepts in Linux ACLs is the “mask”. The mask defines the maximum permissions that can be granted by any ACL entry for a file or directory. Think of it as an upper bound for permissions.&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;# Example ACL with mask
user::rw-        # Owner has read-write
user:alex:rwx    # User alex has read-write-execute, but...
group::r--       # Group owner has read-only
mask::r--        # The mask restricts to read-only!
other::---       # Others have no permissions
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this example, despite giving alex rwx permissions, the effective permissions will be r–, because the mask restricts the maximum permissions to read-only.&lt;/p&gt;
&lt;p&gt;To explicitly set the mask value:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Set the mask to allow read and execute&lt;/span&gt;
setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;m::rx&lt;span class="w"&gt; &lt;/span&gt;project-report.pdf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The mask is automatically recalculated when you add or modify ACL entries, unless you use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--no-mask&lt;/span&gt;&lt;/code&gt; option with setfacl.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="examples-of-acl-usage"&gt;
&lt;h2&gt;Examples of ACL Usage&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Give write permission to user “alex” on a file:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;u:alex:w&lt;span class="w"&gt; &lt;/span&gt;project-report.pdf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Give read and execute permissions to the “developers” group:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;g:developers:rx&lt;span class="w"&gt; &lt;/span&gt;project-report.pdf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;Remove all ACL entries from a file:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;project-report.pdf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="4"&gt;
&lt;li&gt;&lt;p&gt;Apply ACLs recursively to a directory and all its contents:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;g:developers:rx&lt;span class="w"&gt; &lt;/span&gt;ProjectDocs/
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="5"&gt;
&lt;li&gt;&lt;p&gt;Set default ACLs on a directory (new files created in this directory will inherit these ACLs):&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;d:g:developers:rx&lt;span class="w"&gt; &lt;/span&gt;ProjectDocs/
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="6"&gt;
&lt;li&gt;&lt;p&gt;Give read permission to others (all users not specifically mentioned):&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;o::r&lt;span class="w"&gt; &lt;/span&gt;project-report.pdf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="7"&gt;
&lt;li&gt;&lt;p&gt;View current ACL settings:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;getfacl&lt;span class="w"&gt; &lt;/span&gt;project-report.pdf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="8"&gt;
&lt;li&gt;&lt;p&gt;Remove a specific ACL entry (remove just alex’s permissions):&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-x&lt;span class="w"&gt; &lt;/span&gt;u:alex&lt;span class="w"&gt; &lt;/span&gt;project-report.pdf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="9"&gt;
&lt;li&gt;&lt;p&gt;Copy ACLs from one file to another:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;getfacl&lt;span class="w"&gt; &lt;/span&gt;source_file.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;--set-file&lt;span class="o"&gt;=&lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;destination_file.txt
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The output might look like:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;# file: project-report.pdf
# owner: manager
# group: admin
user::rw-
user:alex:rw-
group::r--
group:developers:r-x
mask::rwx
other::r--
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="troubleshooting-acls"&gt;
&lt;h2&gt;Troubleshooting ACLs&lt;/h2&gt;
&lt;p&gt;When working with ACLs, you might encounter some common issues. Here are solutions for the most frequent problems:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ACL Commands Not Working&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Verify your filesystem supports and has ACLs enabled:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;tune2fs&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;/dev/nvme0n1p3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Default mount options"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Check if the ACL package is installed:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;which&lt;span class="w"&gt; &lt;/span&gt;getfacl
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Permission Denied Errors&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ensure you have sufficient permissions (usually requires root or ownership):&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Check your permissions on the file/directory&lt;/span&gt;
ls&lt;span class="w"&gt; &lt;/span&gt;-la&lt;span class="w"&gt; &lt;/span&gt;/path/to/file

&lt;span class="c1"&gt;# Use sudo if needed&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;u:user:rw&lt;span class="w"&gt; &lt;/span&gt;/path/to/file
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ACLs Not Being Applied&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Check if there’s a restrictive mask:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;getfacl&lt;span class="w"&gt; &lt;/span&gt;/path/to/file&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;mask

&lt;span class="c1"&gt;# Set a more permissive mask if needed&lt;/span&gt;
setfacl&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;m::rwx&lt;span class="w"&gt; &lt;/span&gt;/path/to/file
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ACLs Lost After Copying Files&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Use the correct copy command to preserve ACLs:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Use cp with the -a (archive) option&lt;/span&gt;
cp&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;source_file&lt;span class="w"&gt; &lt;/span&gt;destination_file

&lt;span class="c1"&gt;# Or use rsync&lt;/span&gt;
rsync&lt;span class="w"&gt; &lt;/span&gt;-av&lt;span class="w"&gt; &lt;/span&gt;--acls&lt;span class="w"&gt; &lt;/span&gt;source_file&lt;span class="w"&gt; &lt;/span&gt;destination_file
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging Complex ACL Issues&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For more complex issues, use verbose mode with ACL commands:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;setfacl&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;u:user:rw&lt;span class="w"&gt; &lt;/span&gt;/path/to/file
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="working-with-acls-in-samba-shares"&gt;
&lt;h2&gt;Working with ACLs in Samba Shares&lt;/h2&gt;
&lt;p&gt;When using Samba to share files with Windows systems, you can manage ACLs through Windows File Explorer. This provides a familiar graphical interface for Windows users while maintaining the security controls you’ve established.&lt;/p&gt;
&lt;p&gt;To enable this functionality in your Samba configuration, edit &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/etc/samba/smb.conf&lt;/span&gt;&lt;/code&gt; and ensure these options are set:&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[global]&lt;/span&gt;
&lt;span class="na"&gt;map acl inherit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;store dos attributes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;

&lt;span class="k"&gt;[ProjectDocs]&lt;/span&gt;
&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/data/ProjectDocs&lt;/span&gt;
&lt;span class="na"&gt;read only&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;span class="na"&gt;acl_xattr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s"&gt;ignore system acls = yes&lt;/span&gt;
&lt;span class="na"&gt;inherit acls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This configuration allows Windows clients to modify the ACLs through the familiar Windows security dialog, providing a seamless experience across platforms.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Access Control Lists provide a powerful way to manage complex permission requirements that go beyond the traditional Unix permission model. By understanding how to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;getfacl&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;setfacl&lt;/span&gt;&lt;/code&gt;, you can create sophisticated permission structures that meet the needs of multi-user environments while maintaining proper security controls.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 23 Apr 2025 00:00:00 </pubDate></item><item><title>Useful Podman Commands</title><link>https://blog.epheo.eu/notes/podman.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;April 22, 2025&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;5 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;section id="introduction"&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;This article provides a collection of useful Podman commands and techniques for common container operations.
Podman is a daemonless container engine that provides a Docker-compatible command line interface.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="squashing-container-images"&gt;
&lt;h2&gt;Squashing Container Images&lt;/h2&gt;
&lt;p&gt;Squashing container images reduces their size by combining multiple layers into one, making distribution more efficient.&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;podman&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;--layers&lt;span class="w"&gt; &lt;/span&gt;--force-rm&lt;span class="w"&gt; &lt;/span&gt;--squash-all&lt;span class="w"&gt; &lt;/span&gt;--tag&lt;span class="w"&gt; &lt;/span&gt;squashedimage&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FROM regsitry/imagetosquash"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="container-run-commands"&gt;
&lt;h2&gt;Container Run Commands&lt;/h2&gt;
&lt;p&gt;Here are several useful patterns for running containers with Podman:&lt;/p&gt;
&lt;p&gt;Running a Gollum wiki server:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;podman&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--detach&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;gollum&lt;span class="w"&gt; &lt;/span&gt;--security-opt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;disable&lt;span class="w"&gt; &lt;/span&gt;--userns&lt;span class="o"&gt;=&lt;/span&gt;keep-id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/srv/wiki:/wiki&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4567&lt;/span&gt;:4567&lt;span class="w"&gt; &lt;/span&gt;gollumwiki/gollum:master&lt;span class="w"&gt; &lt;/span&gt;--default-keybind&lt;span class="w"&gt; &lt;/span&gt;vim
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Running a container with host networking:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;podman&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--network&lt;span class="w"&gt; &lt;/span&gt;host&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/var/log/sshoney/:/root/logs/&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;sshoney&lt;span class="w"&gt; &lt;/span&gt;97f3876877e2
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Running a MariaDB container in a pod:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;podman&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--detach&lt;span class="w"&gt; &lt;/span&gt;--pod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$POD_NAME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DB_PASS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DB_PASS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DB_NAME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DB_USER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_NAME_DB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;/database"&lt;/span&gt;:/var/lib/mysql&lt;span class="w"&gt; &lt;/span&gt;docker.io/mariadb:latest
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Running a WordPress container in a pod:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;podman&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--detach&lt;span class="w"&gt; &lt;/span&gt;--pod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$POD_NAME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;WORDPRESS_DB_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.1:3306&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;WORDPRESS_DB_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DB_NAME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;WORDPRESS_DB_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DB_USER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;WORDPRESS_DB_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DB_PASS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_NAME_WP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;/html"&lt;/span&gt;:/var/www/html&lt;span class="w"&gt; &lt;/span&gt;docker.io/wordpress
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="image-transfer-between-systems"&gt;
&lt;h2&gt;Image Transfer Between Systems&lt;/h2&gt;
&lt;p&gt;When direct registry access is unavailable, you can save and load images for transfer:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;podman&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;save&lt;span class="w"&gt; &lt;/span&gt;97f3876877e2&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;97f3876877e2.tgz
podman&lt;span class="w"&gt; &lt;/span&gt;load&lt;span class="w"&gt; &lt;/span&gt;--input&lt;span class="w"&gt; &lt;/span&gt;97f3876877e2.tgz
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="systemd-integration"&gt;
&lt;h2&gt;Systemd Integration&lt;/h2&gt;
&lt;p&gt;Running containers as systemd services allows them to persist even when the user is logged out:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Enable executing processes with logged out shell&lt;/span&gt;
loginctl&lt;span class="w"&gt; &lt;/span&gt;enable-linger&lt;span class="w"&gt; &lt;/span&gt;user

&lt;span class="c1"&gt;# Move to user systemd directory&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/.config/systemd/user/

&lt;span class="c1"&gt;# Generate systemd files for container&lt;/span&gt;
podman&lt;span class="w"&gt; &lt;/span&gt;generate&lt;span class="w"&gt; &lt;/span&gt;systemd&lt;span class="w"&gt; &lt;/span&gt;--restart-policy&lt;span class="o"&gt;=&lt;/span&gt;always&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;container_name&lt;span class="w"&gt; &lt;/span&gt;--files

&lt;span class="c1"&gt;# Enable and start the service&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;container-container_name.service
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Wed, 23 Apr 2025 00:00:00 </pubDate></item><item><title>Layer 2 User Defined Networks for OpenShift Virtualization</title><link>https://blog.epheo.eu/articles/openshift-layer2-udn/index.html</link><description>
&lt;span id="openshift-layer2-udn"/&gt;
&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;April 22, 2025&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;20 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Learn how to set up Layer 2 User Defined Networks (UDN) for VMs in OpenShift Virtualization for isolated tenant networks with multi-node connectivity.&lt;/p&gt;
&lt;p&gt;This guide shows how to implement UDNs in OpenShift Virtualization for network isolation between VMs within or across namespaces. UDNs create isolated tenant networks separate from the default pod network, enabling complex network layouts and better security.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;Learn more about OpenShift Virtualization networking in the official &lt;a class="reference external" href="https://docs.openshift.com/container-platform/latest/virt/virtual_machines/vm_networking/"&gt;OpenShift Virtualization Documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is compatible with OpenShift 4.18 and newer versions.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="implementation-steps"&gt;
&lt;h2&gt;Implementation Steps&lt;/h2&gt;
&lt;section id="understand-user-defined-networks"&gt;
&lt;h3&gt;1. Understand User Defined Networks&lt;/h3&gt;
&lt;p&gt;OpenShift Virtualization offers two UDN types:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UserDefinedNetwork (UDN)&lt;/strong&gt;: Creates network isolation within a single namespace.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ClusterUserDefinedNetwork (Cluster UDN)&lt;/strong&gt;: Spans multiple namespaces, allowing VMs in different namespaces to communicate while staying isolated from other networks.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="layer-2-vs-layer-3-user-defined-networks"&gt;
&lt;h4&gt;Layer 2 vs Layer 3 User Defined Networks&lt;/h4&gt;
&lt;p&gt;UDNs can use either Layer 2 or Layer 3 topology:&lt;/p&gt;
&lt;div class="note admonition"&gt;
&lt;p class="admonition-title"&gt;Layer 2 UDN&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Creates a virtual switch across all cluster nodes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All VMs connect to the same subnet regardless of node location&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provides a single broadcast domain&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports VM live migration between nodes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Best for apps needing Layer 2 adjacency&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simpler to configure&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="note admonition"&gt;
&lt;p class="admonition-title"&gt;Layer 3 UDN&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Creates unique Layer 2 segments per node with Layer 3 routing between them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each node has its own subnet&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Controls broadcast traffic within node-specific segments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better scalability for large deployments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports NetworkPolicy for security control&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better for environments with many VMs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="tip admonition"&gt;
&lt;p class="admonition-title"&gt;Primary vs Secondary Networks&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Primary networks handle default traffic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secondary networks add interfaces for specific traffic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A VM can have one primary but multiple secondary networks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UDNs work as either primary or secondary networks&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Compatibility Note:&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Only Layer 2 UDNs work as primary networks for VMs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Layer 3 UDNs only work with regular pods, not VMs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;This guide focuses on Layer 2 UDNs for VM workloads that need simplicity and migration support.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="create-a-namespace-for-user-defined-network"&gt;
&lt;h3&gt;2. Create a Namespace for User Defined Network&lt;/h3&gt;
&lt;p&gt;Create a namespace with the UDN label:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id1"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;udn-namespace.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Namespace&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;udn-example&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;k8s.ovn.org/primary-user-defined-network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;Add this label when creating the namespace. You cannot add it to existing namespaces.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Apply the namespace:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;udn-namespace.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="create-a-user-defined-network"&gt;
&lt;h3&gt;3. Create a User Defined Network&lt;/h3&gt;
&lt;p&gt;Create a UDN in your namespace:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id2"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;udn-example.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;k8s.ovn.org/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;UserDefinedNetwork&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;udn-example&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;udn-example&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;layer2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ipam&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;lifecycle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Persistent&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Primary&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;subnets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10.200.0.0/16&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;topology&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Layer2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply the UDN:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;udn-example.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Verify creation:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;userdefinednetwork&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;udn-example
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="create-a-vm-on-the-user-defined-network"&gt;
&lt;h3&gt;4. Create a VM on the User Defined Network&lt;/h3&gt;
&lt;p&gt;VMs in a namespace with a UDN automatically use the UDN as their primary network:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id3"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;example-vm.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubevirt.io/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;VirtualMachine&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;example-vm&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;udn-example&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;runStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Always&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;disks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;rootdisk&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;virtio&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;l2bridge&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;2Gi&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;pod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;rootdisk&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;containerDisk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;quay.io/containerdisks/fedora:latest&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Don’t modify the VM’s network config. The UDN system handles it automatically.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;Restart or live migrate the VM after network changes:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Restart the VM:&lt;/span&gt;
virtctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;example-vm

&lt;span class="c1"&gt;# Or live migrate (no downtime):&lt;/span&gt;
virtctl&lt;span class="w"&gt; &lt;/span&gt;migrate&lt;span class="w"&gt; &lt;/span&gt;example-vm
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="create-a-cluster-user-defined-network"&gt;
&lt;h3&gt;5. Create a Cluster User Defined Network&lt;/h3&gt;
&lt;p&gt;For cross-namespace communication, create a Cluster UDN:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Create namespaces with the proper labels:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id4"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;udn-namespaces.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Namespace&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;udn-prod&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;k8s.ovn.org/primary-user-defined-network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cluster-udn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prod&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Namespace&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;udn-preprod&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;k8s.ovn.org/primary-user-defined-network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cluster-udn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prod&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the Cluster UDN:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id5"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;cluster-udn-prod.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;k8s.ovn.org/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ClusterUserDefinedNetwork&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cluster-udn-prod&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespaceSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;cluster-udn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prod&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;layer2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;ipam&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;lifecycle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Persistent&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Primary&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;subnets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10.100.0.0/16&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;topology&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Layer2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apply the config:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;cluster-udn-prod.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify creation:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;clusteruserdefinednetwork
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="testing-and-validation"&gt;
&lt;h2&gt;Testing and Validation&lt;/h2&gt;
&lt;section id="test-vm-connectivity-within-udn"&gt;
&lt;h3&gt;1. Test VM Connectivity within UDN&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Create multiple VMs in the same namespace with a UDN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connect to the VM:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Use console&lt;/span&gt;
virtctl&lt;span class="w"&gt; &lt;/span&gt;console&lt;span class="w"&gt; &lt;/span&gt;example-vm

&lt;span class="c1"&gt;# Or SSH if available&lt;/span&gt;
virtctl&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;example-vm
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check network config:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;ip&lt;span class="w"&gt; &lt;/span&gt;addr&lt;span class="w"&gt; &lt;/span&gt;show
ip&lt;span class="w"&gt; &lt;/span&gt;route
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test connectivity between VMs:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;ping&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;other-vm-ip-address&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify VMs got IP addresses from the UDN subnet&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="test-vm-connectivity-across-cluster-udn"&gt;
&lt;h3&gt;2. Test VM Connectivity across Cluster UDN&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Create VMs in different namespaces connected by a Cluster UDN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check network config in each VM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test connectivity:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# From VM in namespace 1&lt;/span&gt;
ping&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;vm-ip-in-namespace-2&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="test-north-south-network-access"&gt;
&lt;h3&gt;3. Test North/South Network Access&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Test external network access:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# From inside the VM&lt;/span&gt;
ping&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.1.1.1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;Don’t manually configure IP addresses. The UDN controller manages IP allocation through IPAM.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;For direct north/south connectivity using the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;br-ex&lt;/span&gt;&lt;/code&gt; bridge, see &lt;a class="reference internal" href="../openshift-localnet/index.html#openshift-localnet"&gt;&lt;span class="std std-ref"&gt;OpenShift Virtualization with Localnet Configuration&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Tue, 22 Apr 2025 00:00:00 </pubDate></item><item><title>OpenShift Virtualization with Localnet Configuration</title><link>https://blog.epheo.eu/articles/openshift-localnet/index.html</link><description>
&lt;span id="openshift-localnet"/&gt;
&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;April 22, 2025&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;15 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This use case demonstrates how to configure OpenShift Virtualization to leverage the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;br-ex&lt;/span&gt;&lt;/code&gt; OVS bridge for direct north/south connectivity of virtual machines. Instead of using a dedicated interface, this approach reuses the main OpenShift interface to provide IP addresses from your baremetal network to your KubeVirt virtual machines.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;For more information about OpenShift Virtualization networking, check out the official &lt;a class="reference external" href="https://docs.openshift.com/container-platform/4.18/virt/virtual_machines/vm_networking/"&gt;OpenShift Virtualization Documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is compatible with OpenShift 4.18 and newer versions.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="implementation-steps"&gt;
&lt;h2&gt;Implementation Steps&lt;/h2&gt;
&lt;section id="understanding-localnet-and-br-ex-bridge"&gt;
&lt;h3&gt;1. Understanding Localnet and br-ex Bridge&lt;/h3&gt;
&lt;p&gt;The OpenShift &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;br-ex&lt;/span&gt;&lt;/code&gt; bridge is typically used for external connectivity for the OpenShift cluster. By configuring a localnet mapping to this bridge, we can:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Allow virtual machines to obtain IP addresses directly from the baremetal network&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable direct north/south connectivity without network translation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simplify network architecture by reusing existing resources&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;br-ex&lt;/span&gt;&lt;/code&gt; bridge is part of OVN-Kubernetes networking in OpenShift. This approach eliminates the need for dedicated physical interfaces for VM connectivity.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="configure-nodenetworkconfigurationpolicy"&gt;
&lt;h3&gt;2. Configure NodeNetworkConfigurationPolicy&lt;/h3&gt;
&lt;p&gt;Create a NodeNetworkConfigurationPolicy (NNCP) to add a localnet mapping to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;br-ex&lt;/span&gt;&lt;/code&gt; bridge:&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nmstate.io/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NodeNetworkConfigurationPolicy&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;br-ex-network&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nodeSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;node-role.kubernetes.io/worker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;desiredState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ovn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;bridge-mappings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;localnet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;br-ex-network&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;bridge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;br-ex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;present&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply the policy:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;br-ex-nncp.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="verify-nodenetworkconfigurationpolicy-status"&gt;
&lt;h3&gt;3. Verify NodeNetworkConfigurationPolicy Status&lt;/h3&gt;
&lt;p&gt;Check that the policy has been applied correctly:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;nncp
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Expected output:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;NAME            STATUS      REASON
br-ex-network   Available   SuccessfullyConfigured
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Verify the node network configuration enactments:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;nnce
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Expected output:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;NAME                         STATUS      STATUS AGE   REASON
&amp;lt;node-name&amp;gt;.br-ex-network   Available   &amp;lt;age&amp;gt;         SuccessfullyConfigured
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="create-networkattachmentdefinition"&gt;
&lt;h3&gt;4. Create NetworkAttachmentDefinition&lt;/h3&gt;
&lt;p&gt;Create a NetworkAttachmentDefinition (NAD) that will use the localnet:&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;k8s.cni.cncf.io/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NetworkAttachmentDefinition&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;br-ex-network&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;"name":"br-ex-network",&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;"type":"ovn-k8s-cni-overlay",&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;"cniVersion":"0.4.0",&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;"topology":"localnet",&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;"netAttachDefName":"default/br-ex-network"&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s"&gt;}'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply the NetworkAttachmentDefinition:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;br-ex-network-nad.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="vlan-configuration-example"&gt;
&lt;h4&gt;VLAN Configuration Example&lt;/h4&gt;
&lt;p&gt;To configure a NetworkAttachmentDefinition with a specific VLAN ID, use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vlanID&lt;/span&gt;&lt;/code&gt; property in the config. This is particularly useful for environments where network segmentation is required:&lt;/p&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="admonition-title"&gt;Tip&lt;/p&gt;
&lt;p&gt;Using VLANs with localnet can help maintain network isolation while still leveraging the existing physical infrastructure.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;k8s.cni.cncf.io/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NetworkAttachmentDefinition&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vlan-network&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="no"&gt;"cniVersion": "0.3.1",&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="no"&gt;"name": "vlan-network",&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="no"&gt;"type": "ovn-k8s-cni-overlay",&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="no"&gt;"topology": "localnet",&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="no"&gt;"vlanID": 200,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="no"&gt;"netAttachDefName": "default/vlan-network"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply the VLAN NetworkAttachmentDefinition:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;vlan-network-nad.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this example, the virtual machines connected to this network will receive VLAN tagged traffic with VLAN ID 200.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adding-network-interface-to-virtual-machines"&gt;
&lt;h3&gt;5. Adding Network Interface to Virtual Machines&lt;/h3&gt;
&lt;p&gt;To attach a VM to the localnet bridge, modify your VM definition to include an additional network interface:&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubevirt.io/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;VirtualMachine&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;example-vm&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;runStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Always&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;disks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;rootdisk&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;virtio&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;masquerade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;br-ex-interface&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;bridge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;2Gi&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;pod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;br-ex-interface&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;multus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;networkName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default/br-ex-network&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;rootdisk&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;containerDisk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;quay.io/containerdisks/fedora:latest&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="testing-and-validation"&gt;
&lt;h2&gt;Testing and Validation&lt;/h2&gt;
&lt;section id="verify-vm-network-configuration"&gt;
&lt;h3&gt;1. Verify VM Network Configuration&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Connect to the VM console or SSH:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;virtctl&lt;span class="w"&gt; &lt;/span&gt;console&lt;span class="w"&gt; &lt;/span&gt;example-vm
&lt;span class="c1"&gt;# or&lt;/span&gt;
virtctl&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;example-vm
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check network interfaces:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;ip&lt;span class="w"&gt; &lt;/span&gt;addr&lt;span class="w"&gt; &lt;/span&gt;show
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify you have two interfaces:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;First interface connected to the pod network (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;default&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second interface connected to the br-ex network with an IP from your baremetal network&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="test-external-network-connectivity"&gt;
&lt;h3&gt;2. Test External Network Connectivity&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Test network connectivity:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# From inside VM&lt;/span&gt;
ping&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.1.1.1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test that external hosts can directly reach the VM on its baremetal IP:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# From an external machine&lt;/span&gt;
ping&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;vm-ip-address&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;VMs using localnet networking will be directly exposed to your physical network, so ensure proper security measures are in place.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;For isolated tenant networks without physical network exposure, see &lt;a class="reference internal" href="../openshift-layer2-udn/index.html#openshift-layer2-udn"&gt;&lt;span class="std std-ref"&gt;Layer 2 User Defined Networks for OpenShift Virtualization&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Tue, 22 Apr 2025 00:00:00 </pubDate></item><item><title>BGP Implementation in Red Hat OpenStack Services on OpenShift</title><link>https://blog.epheo.eu/articles/openstack-bgp/index.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Nov 20, 2024&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;30 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Deprecation Notice&lt;/strong&gt;: The OVN BGP Agent was deprecated in RHOSO 18.0.10 (Feature Release 3).
This component will be removed and replaced in a future release. An alternative BGP integration
mechanism will be provided in a future release.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="key-components"&gt;
&lt;h2&gt;Key Components&lt;/h2&gt;
&lt;p&gt;RHOSO’s dynamic routing relies on four primary components working together in a distributed architecture that requires dedicated networking nodes:&lt;/p&gt;
&lt;section id="ovn-bgp-agent"&gt;
&lt;h3&gt;OVN BGP Agent&lt;/h3&gt;
&lt;p&gt;The OVN BGP agent is a Python-based daemon running in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ovn_bgp_agent&lt;/span&gt;&lt;/code&gt; container on Compute and Networker nodes. Its primary functions include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database monitoring&lt;/strong&gt;: Monitors the OVN northbound database for VM and floating IP events&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Route management&lt;/strong&gt;: Triggers FRR to advertise or withdraw routes based on workload lifecycle&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traffic redirection&lt;/strong&gt;: Configures Linux kernel networking for proper traffic flow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interface management&lt;/strong&gt;: Manages the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bgp-nic&lt;/span&gt;&lt;/code&gt; dummy interface for route advertisement&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The agent operates by detecting changes in the OVN database and translating these into BGP routing decisions.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In RHOSO 18.0, BGP is deployed through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OpenStackControlPlane&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OpenStackDataPlaneNodeSet&lt;/span&gt;&lt;/code&gt; custom resources managed by the RHOSO operators.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id1"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;OVN BGP Agent Configuration (ovn_bgp_agent.conf)&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[DEFAULT]&lt;/span&gt;
&lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;False&lt;/span&gt;
&lt;span class="na"&gt;reconcile_interval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;120&lt;/span&gt;
&lt;span class="na"&gt;expose_tenant_network&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;False&lt;/span&gt;
&lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;ovn_bgp_driver&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="frr-container-suite"&gt;
&lt;h3&gt;FRR Container Suite&lt;/h3&gt;
&lt;p&gt;Free Range Routing runs as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;frr&lt;/span&gt;&lt;/code&gt; container on all RHOSO nodes, providing enterprise-grade routing capabilities:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BGP Daemon (bgpd)&lt;/strong&gt;: Manages BGP peer relationships and route advertisements&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BFD Daemon (bfdd)&lt;/strong&gt;: Provides sub-second failure detection&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zebra Daemon&lt;/strong&gt;: Interfaces between FRR and the Linux kernel routing table&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;VTY Shell&lt;/strong&gt;: Command-line interface for configuration and monitoring&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="literal-block-wrapper docutils container" id="id2"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Sample FRR Configuration for RHOSO&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;frr version 8.5
frr defaults traditional
hostname rhoso-compute-0
log syslog informational
service integrated-vtysh-config
!
router bgp 64999
 bgp router-id 172.30.1.10
 neighbor 172.30.1.254 remote-as 65000
 neighbor 172.30.1.254 bfd
 !
 address-family ipv4 unicast
  redistribute connected
  maximum-paths 8
 exit-address-family
!
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="kernel-networking-integration"&gt;
&lt;h3&gt;Kernel Networking Integration&lt;/h3&gt;
&lt;p&gt;RHOSO leverages RHEL kernel networking features configured by the OVN BGP agent:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;VRF (Virtual Routing and Forwarding)&lt;/strong&gt;: Network isolation using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bgp_vrf&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;IP Rules&lt;/strong&gt;: Direct traffic to appropriate routing tables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dummy Interface&lt;/strong&gt;: The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bgp-nic&lt;/span&gt;&lt;/code&gt; interface for route advertisement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;OVS Integration&lt;/strong&gt;: Flow rules redirecting traffic to the OVN overlay&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="dedicated-networking-nodes"&gt;
&lt;h3&gt;Dedicated Networking Nodes&lt;/h3&gt;
&lt;p&gt;RHOSO BGP deployments &lt;strong&gt;require&lt;/strong&gt; dedicated networking nodes with specific architectural constraints:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mandatory Architecture&lt;/strong&gt;: BGP dynamic routing cannot function without dedicated networker nodes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DVR Integration&lt;/strong&gt;: Must be deployed with Distributed Virtual Routing (DVR) enabled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traffic Gateway Role&lt;/strong&gt;: Networker nodes host neutron router gateways and CR-LRP (Chassis Redirect Logical Router Ports)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;North-South Traffic&lt;/strong&gt;: All external traffic to tenant networks flows through networker nodes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BGP Advertisement&lt;/strong&gt;: Both compute and networker nodes run FRR and OVN BGP agent containers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="literal-block-wrapper docutils container" id="id3"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Networker Node Configuration Requirements&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# OpenShift node labels for dedicated networking&lt;/span&gt;
&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Node&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;rhoso-networker-0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;node-role.kubernetes.io/rhoso-networker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;feature.node.kubernetes.io/network-sriov.capable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Networker nodes require specific networking capabilities&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# and dedicated hardware for external connectivity&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Architecture Constraints&lt;/strong&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control Plane OVN Gateways&lt;/strong&gt;: Not supported with BGP (incompatible)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Octavia Load Balancer&lt;/strong&gt;: Cannot be used with BGP dynamic routing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BFD Limitations&lt;/strong&gt;: Bi-directional forwarding detection has known issues&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="network-architecture"&gt;
&lt;h2&gt;Network Architecture&lt;/h2&gt;
&lt;section id="rhoso-bgp-network-topology"&gt;
&lt;h3&gt;RHOSO BGP Network Topology&lt;/h3&gt;
&lt;object data="../../_images/mermaid-1f784973343563afc39307e72c054134f4642996.svg" type="image/svg+xml"&gt;
            &lt;p class="warning"&gt;---
config:
  theme: neutral
---
graph TB
    subgraph "External Network"
        TOR1[ToR Switch 1&amp;lt;br/&amp;gt;AS 65000]
        TOR2[ToR Switch 2&amp;lt;br/&amp;gt;AS 65000]
        EXT[External Networks&amp;lt;br/&amp;gt;192.0.2.0/24]
    end

    subgraph "OpenShift Cluster"
        subgraph "RHOSO Control Plane"
            CP1[Controller Pod 1&amp;lt;br/&amp;gt;172.30.1.1]
            CP2[Controller Pod 2&amp;lt;br/&amp;gt;172.30.1.2]
            CP3[Controller Pod 3&amp;lt;br/&amp;gt;172.30.1.3]
        end

        subgraph "RHOSO Compute Nodes"
            CN1[Compute Node 1&amp;lt;br/&amp;gt;FRR + OVN BGP Agent]
            CN2[Compute Node 2&amp;lt;br/&amp;gt;FRR + OVN BGP Agent]
            CN3[Compute Node 3&amp;lt;br/&amp;gt;FRR + OVN BGP Agent]
        end

        subgraph "OVN Overlay"
            VM1[VM 10.0.0.10&amp;lt;br/&amp;gt;Floating IP: 192.0.2.10]
            VM2[VM 10.0.0.20&amp;lt;br/&amp;gt;Floating IP: 192.0.2.20]
            LB[Load Balancer&amp;lt;br/&amp;gt;192.0.2.100]
        end
    end

    TOR1 -.-&amp;gt;|eBGP&amp;lt;br/&amp;gt;AS 64999| CN1
    TOR1 -.-&amp;gt;|eBGP&amp;lt;br/&amp;gt;AS 64999| CN2
    TOR2 -.-&amp;gt;|eBGP&amp;lt;br/&amp;gt;AS 64999| CN2
    TOR2 -.-&amp;gt;|eBGP&amp;lt;br/&amp;gt;AS 64999| CN3

    CN1 --&amp;gt; VM1
    CN2 --&amp;gt; VM2
    CN3 --&amp;gt; LB

    TOR1 &amp;lt;--&amp;gt; EXT
    TOR2 &amp;lt;--&amp;gt; EXT&lt;/p&gt;&lt;/object&gt;
&lt;/section&gt;
&lt;section id="bgp-component-interactions"&gt;
&lt;h3&gt;BGP Component Interactions&lt;/h3&gt;
&lt;p&gt;The following diagram shows detailed interactions between all RHOSO BGP components as they operate within the OpenShift container environment:&lt;/p&gt;
&lt;object data="../../_images/mermaid-0da1aed5a8fd807f5eb70c0ae52f5e314a90e3c4.svg" type="image/svg+xml"&gt;
            &lt;p class="warning"&gt;---
config:
  theme: neutral
---
graph TB
    subgraph "External Infrastructure"
        PEER1[BGP Peer 1&amp;lt;br/&amp;gt;ToR Switch&amp;lt;br/&amp;gt;AS 65000]
        PEER2[BGP Peer 2&amp;lt;br/&amp;gt;ToR Switch&amp;lt;br/&amp;gt;AS 65000]
    end

    subgraph "OpenShift Node (Compute/Networker)"
        subgraph "Container Runtime"
            subgraph "FRR Container"
                BGPD[BGP Daemon&amp;lt;br/&amp;gt;bgpd]
                ZEBRA[Zebra Daemon&amp;lt;br/&amp;gt;Route Manager]
                BFD[BFD Daemon&amp;lt;br/&amp;gt;bfdd]
                VTY[VTY Shell&amp;lt;br/&amp;gt;vtysh]
            end

            subgraph "OVN BGP Agent Container"
                AGENT[OVN BGP Agent&amp;lt;br/&amp;gt;Python Daemon]
                DRIVER[BGP Speaker Driver&amp;lt;br/&amp;gt;ovn_bgp_driver]
            end
        end

        subgraph "Host Kernel"
            KRTAB[Kernel Routing Table]
            BGPNIC[bgp-nic Interface&amp;lt;br/&amp;gt;Dummy Interface]
            BRVRF[bgp_vrf&amp;lt;br/&amp;gt;VRF Instance]
            IPRULES[IP Rules &amp;amp; Routes]
        end

        subgraph "OVS Integration"
            BREX[br-ex&amp;lt;br/&amp;gt;Provider Bridge]
            FLOWS[OVS Flow Rules]
        end

        subgraph "OVN Database"
            OVNNB[(OVN Northbound&amp;lt;br/&amp;gt;Database)]
            OVNSB[(OVN Southbound&amp;lt;br/&amp;gt;Database)]
        end
    end

    %% External BGP Sessions
    PEER1 &amp;lt;==&amp;gt;|TCP 179&amp;lt;br/&amp;gt;BGP Session| BGPD
    PEER2 &amp;lt;==&amp;gt;|TCP 179&amp;lt;br/&amp;gt;BGP Session| BGPD

    %% Internal Component Interactions
    BGPD &amp;lt;--&amp;gt; ZEBRA
    BGPD &amp;lt;--&amp;gt; BFD
    ZEBRA &amp;lt;--&amp;gt; KRTAB
    ZEBRA &amp;lt;--&amp;gt; BGPNIC

    %% OVN BGP Agent Monitoring
    AGENT --&amp;gt; OVNNB
    AGENT --&amp;gt; OVNSB
    AGENT --&amp;gt; BGPNIC
    AGENT --&amp;gt; IPRULES
    AGENT --&amp;gt; FLOWS

    %% Route Advertisement Flow
    BGPNIC --&amp;gt; KRTAB
    KRTAB --&amp;gt; ZEBRA
    ZEBRA --&amp;gt; BGPD
    BGPD --&amp;gt; PEER1
    BGPD --&amp;gt; PEER2

    %% Traffic Redirection
    IPRULES --&amp;gt; BREX
    FLOWS --&amp;gt; BREX
    BRVRF --&amp;gt; BREX

    %% Configuration Management
    VTY -.-&amp;gt; BGPD
    VTY -.-&amp;gt; ZEBRA
    VTY -.-&amp;gt; BFD

    DRIVER -.-&amp;gt; AGENT&lt;/p&gt;&lt;/object&gt;
&lt;/section&gt;
&lt;section id="traffic-flow-process"&gt;
&lt;h3&gt;Traffic Flow Process&lt;/h3&gt;
&lt;p&gt;When a VM is created or a floating IP is assigned, the following sequence occurs:&lt;/p&gt;
&lt;object data="../../_images/mermaid-7f60109a513012013de3bb667123cbe409eaa73e.svg" type="image/svg+xml"&gt;
            &lt;p class="warning"&gt;sequenceDiagram
    participant OVN as OVN Database
    participant Agent as OVN BGP Agent
    participant FRR as FRR BGP Daemon
    participant Kernel as Linux Kernel
    participant Peer as BGP Peer

    OVN-&amp;gt;&amp;gt;Agent: VM created with IP 192.0.2.10
    Agent-&amp;gt;&amp;gt;Agent: Add IP to bgp-nic interface
    Agent-&amp;gt;&amp;gt;Kernel: Configure IP rules and routes
    Agent-&amp;gt;&amp;gt;Kernel: Configure OVS flows
    Kernel-&amp;gt;&amp;gt;FRR: Route appears in kernel table
    FRR-&amp;gt;&amp;gt;Peer: Advertise route 192.0.2.10/32
    Peer-&amp;gt;&amp;gt;Peer: Update routing table

    Note over Agent,Kernel: Traffic redirection configured
    Note over FRR,Peer: Route convergence complete&lt;/p&gt;&lt;/object&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="private-network-advertising"&gt;
&lt;h2&gt;Private Network Advertising&lt;/h2&gt;
&lt;p&gt;RHOSO BGP supports advertising private tenant networks, though this feature is disabled by default due to security implications.&lt;/p&gt;
&lt;section id="tenant-network-exposure-configuration"&gt;
&lt;h3&gt;Tenant Network Exposure Configuration&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Default Behavior&lt;/strong&gt;: By default, only floating IPs and provider network IPs are advertised via BGP. Private tenant networks remain isolated within the OVN overlay.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enabling Tenant Network Advertisement&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id4"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;OVN BGP Agent Configuration with Tenant Network Exposure&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[DEFAULT]&lt;/span&gt;
&lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;False&lt;/span&gt;
&lt;span class="na"&gt;reconcile_interval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;120&lt;/span&gt;
&lt;span class="na"&gt;expose_tenant_network&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;True&lt;/span&gt;
&lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;ovn_bgp_driver&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Security Considerations&lt;/strong&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network Isolation&lt;/strong&gt;: Enabling tenant network exposure breaks traditional OpenStack network isolation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Routing Policies&lt;/strong&gt;: External routers must implement proper filtering to maintain security boundaries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Non-Overlapping CIDRs&lt;/strong&gt;: Tenant networks must use unique, non-overlapping IP ranges&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access Control&lt;/strong&gt;: External network infrastructure must enforce tenant access policies&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="traffic-flow-for-tenant-networks"&gt;
&lt;h3&gt;Traffic Flow for Tenant Networks&lt;/h3&gt;
&lt;p&gt;When tenant network advertising is enabled, traffic follows a specific path through dedicated networking nodes:&lt;/p&gt;
&lt;object data="../../_images/mermaid-c886ef295aa2214c41347733ae33c848b5a5b68d.svg" type="image/svg+xml"&gt;
            &lt;p class="warning"&gt;---
config:
  theme: neutral
---
graph TD
    CLIENT[External Client&amp;lt;br/&amp;gt;203.0.113.100]

    TOR[ToR Switch&amp;lt;br/&amp;gt;BGP AS 65000&amp;lt;br/&amp;gt;Routes: 10.1.0.0/24]

    subgraph NETWORKER ["Networker Node"]
        FRR1[FRR Container&amp;lt;br/&amp;gt;BGP: AS 64999&amp;lt;br/&amp;gt;Advertises: 10.1.0.0/24]
        AGENT1[OVN BGP Agent&amp;lt;br/&amp;gt;Monitors OVN DB&amp;lt;br/&amp;gt;Configures CR-LRP]
        KERNEL1[Host Kernel&amp;lt;br/&amp;gt;IP Rules &amp;amp; Routes]
        BREX1[br-ex Bridge&amp;lt;br/&amp;gt;Provider Bridge]
        CRLRP1[CR-LRP Gateway&amp;lt;br/&amp;gt;10.1.0.1]
    end

    subgraph COMPUTE ["Compute Node - OVN Overlay"]
        LROUTER[Logical Router&amp;lt;br/&amp;gt;tenant-router-1]
        LSWITCH[Logical Switch&amp;lt;br/&amp;gt;tenant-net-1&amp;lt;br/&amp;gt;10.1.0.0/24]
        VM[Tenant VM&amp;lt;br/&amp;gt;10.1.0.10]
    end

    %% Main Traffic Flow (Top to Bottom)
    CLIENT --&amp;gt;|1. Send packet&amp;lt;br/&amp;gt;dst: 10.1.0.10| TOR
    TOR --&amp;gt;|2. BGP route lookup&amp;lt;br/&amp;gt;forward to networker| KERNEL1
    KERNEL1 --&amp;gt;|3. Apply IP rules&amp;lt;br/&amp;gt;route to br-ex| BREX1
    BREX1 --&amp;gt;|4. Traffic injection&amp;lt;br/&amp;gt;enter OVN overlay| CRLRP1
    CRLRP1 --&amp;gt;|5. L3 gateway&amp;lt;br/&amp;gt;route to logical switch| LROUTER
    LROUTER --&amp;gt;|6. ARP resolution&amp;lt;br/&amp;gt;L3 to L2 forwarding| LSWITCH
    LSWITCH --&amp;gt;|7. MAC lookup&amp;lt;br/&amp;gt;deliver packet| VM

    %% BGP Advertisement Flow (Dashed)
    AGENT1 -.-&amp;gt;|Monitor tenant&amp;lt;br/&amp;gt;network events| LSWITCH
    AGENT1 -.-&amp;gt;|Configure gateway&amp;lt;br/&amp;gt;on networker node| CRLRP1
    AGENT1 -.-&amp;gt;|Add route to&amp;lt;br/&amp;gt;bgp-nic interface| FRR1
    FRR1 -.-&amp;gt;|BGP UPDATE&amp;lt;br/&amp;gt;advertise 10.1.0.0/24| TOR&lt;/p&gt;&lt;/object&gt;
&lt;p&gt;&lt;strong&gt;Key Technical Details&lt;/strong&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CR-LRP Role&lt;/strong&gt;: Chassis Redirect Logical Router Ports serve as the entry point for external traffic to tenant networks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Networker Node Gateway&lt;/strong&gt;: All north-south traffic to tenant networks must traverse the networker node hosting the neutron router gateway&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Route Advertisement&lt;/strong&gt;: The OVN BGP agent on networker nodes advertises neutron router gateway ports when tenant network exposure is enabled&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="implementation-requirements"&gt;
&lt;h3&gt;Implementation Requirements&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Network Planning&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id5"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Tenant Network BGP Advertisement Example&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;# Tenant network configuration
router bgp 64999
  # Advertise tenant network ranges
  address-family ipv4 unicast
    network 10.0.0.0/24    # Tenant network 1
    network 10.1.0.0/24    # Tenant network 2
    network 10.2.0.0/24    # Tenant network 3
  exit-address-family

# Route filtering for security
ip prefix-list TENANT-NETWORKS permit 10.0.0.0/8 le 24
route-map TENANT-FILTER permit 10
  match ip address prefix-list TENANT-NETWORKS
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Operational Considerations&lt;/strong&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network Overlap Detection&lt;/strong&gt;: Implement monitoring to detect and prevent CIDR overlaps&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Route Filtering&lt;/strong&gt;: Configure external routers with appropriate filters to prevent route leaks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Tenancy&lt;/strong&gt;: Consider impact on tenant isolation and implement additional security measures&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Troubleshooting Complexity&lt;/strong&gt;: Private network advertising increases troubleshooting complexity&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="real-world-deployment-scenarios"&gt;
&lt;h2&gt;Real-World Deployment Scenarios&lt;/h2&gt;
&lt;section id="enterprise-multi-zone-deployment"&gt;
&lt;h3&gt;Enterprise Multi-Zone Deployment&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Use Case&lt;/strong&gt;: Large enterprise with RHOSO deployed across multiple OpenShift clusters in different availability zones.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Multi-Zone Network Topology&lt;/strong&gt;:&lt;/p&gt;
&lt;object data="../../_images/mermaid-898baf3ab09f2979bd4b9b70ccb35378fc0015d7.svg" type="image/svg+xml"&gt;
            &lt;p class="warning"&gt;---
config:
  theme: neutral
---
graph TB
    subgraph "Enterprise WAN"
        WAN[Enterprise WAN&amp;lt;br/&amp;gt;Core Network&amp;lt;br/&amp;gt;AS 65000]
        MPLS[MPLS/VPN Backbone]
    end

    subgraph "Availability Zone 1 (East)"
        subgraph "Zone 1 Network Infrastructure"
            TOR1A[ToR Switch 1A&amp;lt;br/&amp;gt;AS 65001]
            TOR1B[ToR Switch 1B&amp;lt;br/&amp;gt;AS 65001]
            SPINE1[Spine Switch 1&amp;lt;br/&amp;gt;AS 65001]
        end

        subgraph "OpenShift Cluster 1"
            subgraph "RHOSO Control Plane 1"
                CP1A[Controller Pod 1A]
                CP1B[Controller Pod 1B]
            end

            subgraph "Networker Nodes Zone 1"
                NN1A[Networker 1A&amp;lt;br/&amp;gt;BGP AS 64999&amp;lt;br/&amp;gt;Router-ID: 10.1.1.1]
                NN1B[Networker 1B&amp;lt;br/&amp;gt;BGP AS 64999&amp;lt;br/&amp;gt;Router-ID: 10.1.1.2]
            end

            subgraph "Compute Nodes Zone 1"
                CN1A[Compute 1A]
                CN1B[Compute 1B]
                CN1C[Compute 1C]
            end
        end

        subgraph "Workloads Zone 1"
            VIP1[Control Plane VIP&amp;lt;br/&amp;gt;203.0.113.10]
            TENANT1[Tenant Networks&amp;lt;br/&amp;gt;10.1.0.0/16]
            FIP1[Floating IPs&amp;lt;br/&amp;gt;203.0.113.100~200]
        end
    end

    subgraph "Availability Zone 2 (West)"
        subgraph "Zone 2 Network Infrastructure"
            TOR2A[ToR Switch 2A&amp;lt;br/&amp;gt;AS 65002]
            TOR2B[ToR Switch 2B&amp;lt;br/&amp;gt;AS 65002]
            SPINE2[Spine Switch 2&amp;lt;br/&amp;gt;AS 65002]
        end

        subgraph "OpenShift Cluster 2"
            subgraph "RHOSO Control Plane 2"
                CP2A[Controller Pod 2A]
                CP2B[Controller Pod 2B]
            end

            subgraph "Networker Nodes Zone 2"
                NN2A[Networker 2A&amp;lt;br/&amp;gt;BGP AS 64998&amp;lt;br/&amp;gt;Router-ID: 10.2.1.1]
                NN2B[Networker 2B&amp;lt;br/&amp;gt;BGP AS 64998&amp;lt;br/&amp;gt;Router-ID: 10.2.1.2]
            end

            subgraph "Compute Nodes Zone 2"
                CN2A[Compute 2A]
                CN2B[Compute 2B]
                CN2C[Compute 2C]
            end
        end

        subgraph "Workloads Zone 2"
            VIP2[Control Plane VIP&amp;lt;br/&amp;gt;203.0.113.11]
            TENANT2[Tenant Networks&amp;lt;br/&amp;gt;10.2.0.0/16]
            FIP2[Floating IPs&amp;lt;br/&amp;gt;203.0.113.201~255]
        end
    end

    %% WAN Connectivity
    WAN &amp;lt;--&amp;gt; MPLS
    MPLS &amp;lt;--&amp;gt; SPINE1
    MPLS &amp;lt;--&amp;gt; SPINE2

    %% Zone 1 Internal BGP
    SPINE1 &amp;lt;--&amp;gt; TOR1A
    SPINE1 &amp;lt;--&amp;gt; TOR1B
    TOR1A -.-&amp;gt;|eBGP| NN1A
    TOR1A -.-&amp;gt;|eBGP| CN1A
    TOR1B -.-&amp;gt;|eBGP| NN1B
    TOR1B -.-&amp;gt;|eBGP| CN1B

    %% Zone 2 Internal BGP
    SPINE2 &amp;lt;--&amp;gt; TOR2A
    SPINE2 &amp;lt;--&amp;gt; TOR2B
    TOR2A -.-&amp;gt;|eBGP| NN2A
    TOR2A -.-&amp;gt;|eBGP| CN2A
    TOR2B -.-&amp;gt;|eBGP| NN2B
    TOR2B -.-&amp;gt;|eBGP| CN2B

    %% Inter-Zone BGP Peering
    NN1A -.-&amp;gt;|iBGP via WAN| NN2A
    NN1B -.-&amp;gt;|iBGP via WAN| NN2B

    %% Workload Distribution
    NN1A --&amp;gt; VIP1
    NN1A --&amp;gt; TENANT1
    NN1A --&amp;gt; FIP1

    NN2A --&amp;gt; VIP2
    NN2A --&amp;gt; TENANT2
    NN2A --&amp;gt; FIP2&lt;/p&gt;&lt;/object&gt;
&lt;p&gt;&lt;strong&gt;Technical Implementation&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id6"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Multi-Zone BGP Configuration&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;# Zone 1 Configuration (AS 64999)
router bgp 64999
  bgp router-id 10.1.1.1

  # Local zone ToR peering (eBGP)
  neighbor 10.1.1.254 remote-as 65001
  neighbor 10.1.1.253 remote-as 65001

  # Inter-zone peering (iBGP confederation or eBGP)
  neighbor 10.2.1.1 remote-as 64998
  neighbor 10.2.1.1 ebgp-multihop 3

  address-family ipv4 unicast
    # Advertise zone-specific networks
    network 203.0.113.10/32    # Control plane VIP
    network 203.0.113.100/28   # Zone 1 floating IPs
    network 10.1.0.0/16        # Zone 1 tenant networks (if enabled)

    # ECMP for load balancing
    maximum-paths 4
    maximum-paths ibgp 4

    # Route filtering between zones
    neighbor 10.2.1.1 route-map ZONE2-IN in
    neighbor 10.2.1.1 route-map ZONE1-OUT out
  exit-address-family

# Zone 2 Configuration (AS 64998)
router bgp 64998
  bgp router-id 10.2.1.1

  # Local zone ToR peering (eBGP)
  neighbor 10.2.1.254 remote-as 65002
  neighbor 10.2.1.253 remote-as 65002

  # Inter-zone peering
  neighbor 10.1.1.1 remote-as 64999
  neighbor 10.1.1.1 ebgp-multihop 3

  address-family ipv4 unicast
    # Advertise zone-specific networks
    network 203.0.113.11/32    # Control plane VIP
    network 203.0.113.201/28   # Zone 2 floating IPs
    network 10.2.0.0/16        # Zone 2 tenant networks (if enabled)

    maximum-paths 4
    maximum-paths ibgp 4
  exit-address-family
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:
- &lt;strong&gt;Geographic Distribution&lt;/strong&gt;: Workloads distributed across multiple data centers
- &lt;strong&gt;Fault Isolation&lt;/strong&gt;: Zone failures don’t impact other zones
- &lt;strong&gt;Load Distribution&lt;/strong&gt;: Traffic distributed based on BGP routing policies
- &lt;strong&gt;Disaster Recovery&lt;/strong&gt;: Automatic failover between zones via BGP route withdrawal
- &lt;strong&gt;Scalability&lt;/strong&gt;: Independent scaling of compute and network resources per zone&lt;/p&gt;
&lt;/section&gt;
&lt;section id="control-plane-high-availability"&gt;
&lt;h3&gt;Control Plane High Availability&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Use Case&lt;/strong&gt;: RHOSO control plane services distributed across OpenShift nodes with BGP-advertised VIPs.&lt;/p&gt;
&lt;object data="../../_images/mermaid-81c478a0c2dec8183f75386d00bbde2fb078a282.svg" type="image/svg+xml"&gt;
            &lt;p class="warning"&gt;---
config:
  theme: neutral
---
graph LR
    subgraph "OpenShift Cluster"
        CP1[Control Plane Pod 1&amp;lt;br/&amp;gt;Node: ocp-master-1]
        CP2[Control Plane Pod 2&amp;lt;br/&amp;gt;Node: ocp-master-2]
        CP3[Control Plane Pod 3&amp;lt;br/&amp;gt;Node: ocp-master-3]
        VIP[Control Plane VIP&amp;lt;br/&amp;gt;192.0.2.100]
    end

    subgraph "External Network"
        Client[API Clients]
        BGP[BGP Router]
    end

    CP1 -.-&amp;gt; VIP
    CP2 -.-&amp;gt; VIP
    CP3 -.-&amp;gt; VIP
    VIP --&amp;gt; BGP
    BGP --&amp;gt; Client&lt;/p&gt;&lt;/object&gt;
&lt;p&gt;&lt;strong&gt;Implementation Details&lt;/strong&gt;:
- Kubernetes-native HA manages VIP assignment
- OVN BGP agent advertises active VIP location
- Sub-second failover with BFD
- No single point of failure&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dedicated-networker-node-deployment"&gt;
&lt;h3&gt;Dedicated Networker Node Deployment&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Use Case&lt;/strong&gt;: Enterprise RHOSO deployment with dedicated networking infrastructure for BGP routing and tenant network isolation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Architecture Requirements&lt;/strong&gt;:&lt;/p&gt;
&lt;object data="../../_images/mermaid-820dad70607ac4dd50f61621c458f7289a6d4b99.svg" type="image/svg+xml"&gt;
            &lt;p class="warning"&gt;---
config:
  theme: neutral
---
graph TB
    subgraph "External Infrastructure"
        TOR1[ToR Switch 1&amp;lt;br/&amp;gt;AS 65000]
        TOR2[ToR Switch 2&amp;lt;br/&amp;gt;AS 65000]
        FW[Enterprise Firewall]
    end

    subgraph "OpenShift Cluster"
        subgraph "Control Plane Nodes"
            CP1[Master 1]
            CP2[Master 2]
            CP3[Master 3]
        end

        subgraph "Dedicated Networker Nodes"
            NN1[Networker 1&amp;lt;br/&amp;gt;FRR + OVN BGP Agent&amp;lt;br/&amp;gt;CR-LRP Host]
            NN2[Networker 2&amp;lt;br/&amp;gt;FRR + OVN BGP Agent&amp;lt;br/&amp;gt;CR-LRP Host]
        end

        subgraph "Compute Nodes"
            CN1[Compute 1&amp;lt;br/&amp;gt;FRR + OVN BGP Agent]
            CN2[Compute 2&amp;lt;br/&amp;gt;FRR + OVN BGP Agent]
            CN3[Compute 3&amp;lt;br/&amp;gt;FRR + OVN BGP Agent]
        end
    end

    subgraph "Tenant Networks"
        T1[Tenant A: 10.1.0.0/24]
        T2[Tenant B: 10.2.0.0/24]
        T3[Tenant C: 10.3.0.0/24]
    end

    TOR1 -.-&amp;gt;|eBGP| NN1
    TOR1 -.-&amp;gt;|eBGP| CN1
    TOR2 -.-&amp;gt;|eBGP| NN2
    TOR2 -.-&amp;gt;|eBGP| CN2

    NN1 --&amp;gt; T1
    NN1 --&amp;gt; T2
    NN2 --&amp;gt; T2
    NN2 --&amp;gt; T3

    FW &amp;lt;--&amp;gt; TOR1
    FW &amp;lt;--&amp;gt; TOR2&lt;/p&gt;&lt;/object&gt;
&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:
- &lt;strong&gt;Dedicated Traffic Path&lt;/strong&gt;: All north-south traffic controlled through networker nodes
- &lt;strong&gt;High Availability&lt;/strong&gt;: Multiple networker nodes provide redundancy for tenant network access
- &lt;strong&gt;Security Isolation&lt;/strong&gt;: Clear separation between compute and networking functions
- &lt;strong&gt;Scalability&lt;/strong&gt;: Independent scaling of compute and network infrastructure&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Deployment Considerations&lt;/strong&gt;:
- &lt;strong&gt;Hardware Requirements&lt;/strong&gt;: Networker nodes need enhanced networking capabilities
- &lt;strong&gt;Network Connectivity&lt;/strong&gt;: Direct physical connections to external infrastructure
- &lt;strong&gt;DVR Requirement&lt;/strong&gt;: Must be deployed with Distributed Virtual Routing enabled
- &lt;strong&gt;Monitoring&lt;/strong&gt;: Enhanced monitoring required for CR-LRP and gateway functions&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="configuration-and-deployment"&gt;
&lt;h2&gt;Configuration and Deployment&lt;/h2&gt;
&lt;section id="prerequisites"&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;p&gt;RHOSO dynamic routing requires:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RHOSO 18.0 or later&lt;/strong&gt; with ML2/OVN mechanism driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;OpenShift 4.18+&lt;/strong&gt; with appropriate node networking&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BGP-capable network infrastructure&lt;/strong&gt; (ToR switches, routers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dedicated networker nodes&lt;/strong&gt; (mandatory for BGP deployments)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distributed Virtual Routing (DVR)&lt;/strong&gt; enabled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Proper network planning&lt;/strong&gt; for ASN assignment and IP addressing&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Critical Architecture Requirements&lt;/strong&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Control Plane OVN Gateways&lt;/strong&gt;: BGP is incompatible with control plane OVN gateway deployments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Octavia Load Balancer&lt;/strong&gt;: Cannot be used simultaneously with BGP dynamic routing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Distributed Control Plane&lt;/strong&gt;: RHOSO dynamic routing does not support distributed control planes across datacenters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Non-overlapping CIDRs&lt;/strong&gt;: When using tenant network advertising, all networks must use unique IP ranges&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;External BGP Peers&lt;/strong&gt;: Network infrastructure must support BGP peering and route filtering&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cross-Datacenter Deployment Design Considerations&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;RHOSO BGP deployments across datacenters require additional planning and design considerations:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control Plane Design&lt;/strong&gt;: Consider the implications of control plane service communication patterns across WAN links&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network Latency Planning&lt;/strong&gt;: Evaluate network latency requirements for optimal OpenStack service performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database Architecture&lt;/strong&gt;: Plan for database replication, backup, and disaster recovery strategies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Storage Design&lt;/strong&gt;: Consider storage architecture options that balance performance, availability, and data locality&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Alternative Options&lt;/strong&gt;: Red Hat’s &lt;strong&gt;Distributed Compute Node (DCN)&lt;/strong&gt; architecture provides a proven approach for multi-site deployments with centralized control planes and distributed compute resources.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="openshift-integration"&gt;
&lt;h3&gt;OpenShift Integration&lt;/h3&gt;
&lt;p&gt;RHOSO BGP services integrate with OpenShift through:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pod Deployment&lt;/strong&gt;: BGP containers run as privileged pods with host networking
&lt;strong&gt;ConfigMaps&lt;/strong&gt;: Configuration stored as Kubernetes ConfigMaps
&lt;strong&gt;Monitoring&lt;/strong&gt;: Integration with OpenShift monitoring and alerting
&lt;strong&gt;Networking&lt;/strong&gt;: Uses OpenShift SDN or OVN-Kubernetes for pod networking&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="production-operations"&gt;
&lt;h2&gt;Production Operations&lt;/h2&gt;
&lt;section id="monitoring-and-observability"&gt;
&lt;h3&gt;Monitoring and Observability&lt;/h3&gt;
&lt;p&gt;RHOSO BGP monitoring leverages OpenShift’s native observability:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prometheus Metrics&lt;/strong&gt;: FRR and OVN BGP agent export metrics
&lt;strong&gt;Grafana Dashboards&lt;/strong&gt;: Pre-built dashboards for BGP performance
&lt;strong&gt;Alerting&lt;/strong&gt;: Automated alerts for BGP session failures
&lt;strong&gt;Logging&lt;/strong&gt;: Centralized logging through OpenShift logging stack&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id7"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;BGP Status Monitoring Commands&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Check BGP session status&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/frr-bgp&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;vtysh&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'show bgp summary'&lt;/span&gt;

&lt;span class="c1"&gt;# View route advertisements&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/frr-bgp&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;vtysh&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'show ip bgp neighbors advertised-routes'&lt;/span&gt;

&lt;span class="c1"&gt;# Check OVN BGP agent status&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ovn-bgp-agent&lt;span class="w"&gt; &lt;/span&gt;--tail&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="scaling-operations"&gt;
&lt;h3&gt;Scaling Operations&lt;/h3&gt;
&lt;p&gt;Adding new compute capacity with BGP requires:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;OpenShift node addition&lt;/strong&gt;: Standard OpenShift node scaling procedures&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic BGP configuration&lt;/strong&gt;: DaemonSets ensure BGP services on new nodes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network validation&lt;/strong&gt;: Verify BGP peering and route advertisement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Workload validation&lt;/strong&gt;: Test VM connectivity through new nodes&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="network-failure-and-recovery"&gt;
&lt;h3&gt;Network Failure and Recovery&lt;/h3&gt;
&lt;p&gt;RHOSO BGP deployments implement automated failure detection and recovery mechanisms:&lt;/p&gt;
&lt;object data="../../_images/mermaid-39cbce7ede9a99d07db65c7e65fff90bcd0dcf9b.svg" type="image/svg+xml"&gt;
            &lt;p class="warning"&gt;---
config:
  theme: neutral
---
flowchart TD
    START([Normal Operation&amp;lt;br/&amp;gt;BGP Sessions Active]) --&amp;gt; MONITOR{Monitoring&amp;lt;br/&amp;gt;Systems}

    MONITOR --&amp;gt;|BGP Session Failure| BGP_FAIL[BGP Session Down]
    MONITOR --&amp;gt;|Node Failure| NODE_FAIL[Networker Node Down]
    MONITOR --&amp;gt;|BFD Timeout| BFD_FAIL[BFD Session Timeout]

    BGP_FAIL --&amp;gt; BGP_DETECT{Failure Detection&amp;lt;br/&amp;gt;Method}
    BGP_DETECT --&amp;gt;|BFD Enabled| BFD_FAST[Sub-second Detection&amp;lt;br/&amp;gt;100~300ms]
    BGP_DETECT --&amp;gt;|BGP Keepalive Only| BGP_SLOW[Standard Detection&amp;lt;br/&amp;gt;30~90 seconds]

    BFD_FAST --&amp;gt; WITHDRAW_ROUTES[Withdraw BGP Routes&amp;lt;br/&amp;gt;from Failed Peer]
    BGP_SLOW --&amp;gt; WITHDRAW_ROUTES
    BFD_FAIL --&amp;gt; WITHDRAW_ROUTES

    NODE_FAIL --&amp;gt; CR_LRP_CHECK{CR-LRP Migration&amp;lt;br/&amp;gt;Available?}
    CR_LRP_CHECK --&amp;gt;|Yes| CR_LRP_MIGRATE[Migrate CR-LRP to&amp;lt;br/&amp;gt;Healthy Networker Node]
    CR_LRP_CHECK --&amp;gt;|No| TENANT_OUTAGE[Tenant Network&amp;lt;br/&amp;gt;Connectivity Lost]

    WITHDRAW_ROUTES --&amp;gt; REROUTE[Traffic Rerouted&amp;lt;br/&amp;gt;via Remaining Peers]
    CR_LRP_MIGRATE --&amp;gt; REROUTE

    REROUTE --&amp;gt; RECOVERY_CHECK{Service&amp;lt;br/&amp;gt;Recovery?}
    RECOVERY_CHECK --&amp;gt;|BGP Peer Recovery| PEER_RECOVERY[Re-establish&amp;lt;br/&amp;gt;BGP Session]
    RECOVERY_CHECK --&amp;gt;|Node Recovery| NODE_RECOVERY[Node Rejoins&amp;lt;br/&amp;gt;Cluster]

    PEER_RECOVERY --&amp;gt; READVERTISE[Re-advertise&amp;lt;br/&amp;gt;BGP Routes]
    NODE_RECOVERY --&amp;gt; POD_RESTART[Restart BGP&amp;lt;br/&amp;gt;Services]
    POD_RESTART --&amp;gt; READVERTISE

    READVERTISE --&amp;gt; CONVERGE[Network&amp;lt;br/&amp;gt;Convergence]
    CONVERGE --&amp;gt; START

    TENANT_OUTAGE --&amp;gt; MANUAL_INTERVENTION[Manual Intervention&amp;lt;br/&amp;gt;Required]
    MANUAL_INTERVENTION --&amp;gt;|Add Networker Node| NODE_RECOVERY&lt;/p&gt;&lt;/object&gt;
&lt;p&gt;&lt;strong&gt;Failure Scenarios and Recovery Times&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="table-wrapper colwidths-given docutils container" id="id8"&gt;
&lt;table class="docutils align-default" id="id8"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;RHOSO BGP Failure Recovery Matrix&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 30.0%"/&gt;
&lt;col style="width: 25.0%"/&gt;
&lt;col style="width: 25.0%"/&gt;
&lt;col style="width: 20.0%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Failure Type&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Detection Time&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Recovery Time&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Impact Level&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;BGP Session Failure (BFD enabled)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;100~300ms&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1~3 seconds&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Low (alternate paths)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;BGP Session Failure (no BFD)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;30~90 seconds&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;30~120 seconds&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Medium (delayed reroute)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Single Networker Node&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;5~15 seconds&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;10~30 seconds&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Medium (CR-LRP migration)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Multiple Networker Nodes&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;5~15 seconds&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Manual intervention&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;High (tenant isolation)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Compute Node&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;30~60 seconds&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;60~180 seconds&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Low (workload migration)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Automated Recovery Mechanisms&lt;/strong&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BGP Route Withdrawal&lt;/strong&gt;: Automatic route withdrawal upon session failure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BFD Fast Detection&lt;/strong&gt;: Sub-second failure detection with proper BFD configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CR-LRP Migration&lt;/strong&gt;: Automatic migration of Chassis Redirect Logical Router Ports&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traffic Rerouting&lt;/strong&gt;: ECMP and alternate path utilization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Session Re-establishment&lt;/strong&gt;: Automatic BGP session recovery&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="troubleshooting"&gt;
&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;section id="common-issues-and-solutions"&gt;
&lt;h3&gt;Common Issues and Solutions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;BGP Sessions Not Establishing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Symptoms: BGP peers show “Idle” or “Connect” state&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id9"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Diagnosis Commands&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Check BGP peer status&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/frr-bgp&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;vtysh&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'show bgp neighbors'&lt;/span&gt;

&lt;span class="c1"&gt;# Verify network connectivity&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/frr-bgp&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;ping&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;peer-ip&amp;gt;

&lt;span class="c1"&gt;# Check firewall rules&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/frr-bgp&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;ss&lt;span class="w"&gt; &lt;/span&gt;-tulpn&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;179&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Verify network connectivity, ASN configuration, and firewall rules allowing TCP port 179.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Routes Not Being Advertised&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Symptoms: External networks cannot reach RHOSO workloads&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id10"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Diagnosis and Resolution&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Check if IPs are on bgp-nic interface&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/ovn-bgp-agent&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;addr&lt;span class="w"&gt; &lt;/span&gt;show&lt;span class="w"&gt; &lt;/span&gt;bgp-nic

&lt;span class="c1"&gt;# Verify FRR is redistributing connected routes&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/frr-bgp&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;vtysh&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'show running-config'&lt;/span&gt;

&lt;span class="c1"&gt;# Check OVN BGP agent logs&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ovn-bgp-agent
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Ensure OVN BGP agent is running and FRR has “redistribute connected” configured.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tenant Networks Not Reachable&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Symptoms: External clients cannot reach VMs on tenant networks despite &lt;cite&gt;expose_tenant_network = True&lt;/cite&gt;&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id11"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Tenant Network Troubleshooting&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Check if tenant network exposure is enabled&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/ovn-bgp-agent&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;expose_tenant_network&lt;span class="w"&gt; &lt;/span&gt;/etc/ovn_bgp_agent/ovn_bgp_agent.conf

&lt;span class="c1"&gt;# Verify CR-LRP (Chassis Redirect Logical Router Ports) are active on networker nodes&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/ovn-bgp-agent&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;ovn-sbctl&lt;span class="w"&gt; &lt;/span&gt;show&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;cr-lrp

&lt;span class="c1"&gt;# Check neutron router gateway port advertisement&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/frr-bgp&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;vtysh&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'show ip bgp | grep 10.0.0'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Verify networker nodes are hosting CR-LRP and neutron router gateways are properly advertised.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Networker Node Failures&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Symptoms: Complete loss of external connectivity to tenant networks&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id12"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Networker Node Failure Diagnosis&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Check networker node health&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;nodes&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;node-role.kubernetes.io/rhoso-networker

&lt;span class="c1"&gt;# Verify networker pods are running&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pods&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rhoso-networker

&lt;span class="c1"&gt;# Check CR-LRP failover status&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/ovn-bgp-agent&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;ovn-sbctl&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;Chassis_Redirect_Port

&lt;span class="c1"&gt;# Verify BGP session status on remaining networker nodes&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;ds/frr-bgp&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;vtysh&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'show bgp summary'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Ensure multiple networker nodes are deployed for high availability and CR-LRP can migrate between nodes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Slow Convergence&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Symptoms: Long failover times during node or network failures&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id13"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;BFD Configuration for Fast Convergence&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;router bgp 64999
  neighbor 172.30.1.254 bfd
  neighbor 172.30.1.254 bfd profile fast-detect

bfd
  profile fast-detect
    detect-multiplier 3
    receive-interval 100
    transmit-interval 100
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="known-issues"&gt;
&lt;h3&gt;Known Issues&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Floating IP port forwarding&lt;/strong&gt;: Port forwarding with floating IPs fails when BGP dynamic routing is enabled (BZ 2160481)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multicast routing&lt;/strong&gt;: Multicast routing is not supported with BGP dynamic routing (BZ 2163477)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-tuning"&gt;
&lt;h3&gt;Performance Tuning&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;ECMP Configuration&lt;/strong&gt;&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id14"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Optimized ECMP Settings&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;router bgp 64999
  maximum-paths 8
  maximum-paths ibgp 8
  bestpath as-path multipath-relax
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;BGP Timers Optimization&lt;/strong&gt;&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id15"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Production BGP Timers&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;router bgp 64999
  neighbor 172.30.1.254 timers 10 30
  neighbor 172.30.1.254 capability extended-nexthop
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Wed, 20 Nov 2024 00:00:00 </pubDate></item><item><title>Dual Interface Routing with NGINX Ingress in Kubernetes</title><link>https://blog.epheo.eu/articles/k8s-nginx-ingress-sharding/index.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Aug 16, 2024&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;15 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;While I would consider this a basic requirement I never understood why Kubernetes Ingress
Routers didn’t natively provides a way to expose private endpoints on one interface and
public ones on a second interface (OpenShift does it quite well).&lt;/p&gt;
&lt;p&gt;The following describes how one would implement true network separation in Kubernetes
using dual interface routing with NGINX ingress controllers and externalIPs services and
enable isolation between public and private services.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://kubernetes.io/docs/concepts/services-networking/service/#externalips"&gt;https://kubernetes.io/docs/concepts/services-networking/service/#externalips&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;section id="architecture-overview"&gt;
&lt;h2&gt;Architecture Overview&lt;/h2&gt;
&lt;p&gt;Our dual interface implementation consists of:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Public Interface (eth0)&lt;/strong&gt;: Routes external traffic to public services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Private Interface (eth1)&lt;/strong&gt;: Routes internal traffic to private services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ExternalIPs Services&lt;/strong&gt;: Bind NGINX controllers to specific interface IPs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ingress Class Selection&lt;/strong&gt;: Applications choose routing via ingress class&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;External Clients
├── Public Interface (168.119.158.20:80/443)
│   └── nginx-public-external Service (externalIPs)
│       └── nginx-ingress-public Controller
│           ├── blog.epheo.eu (public blog)
│           └── epheo.eu (personal site)
│
└── Private Interface (172.16.0.11:80/443)
    └── nginx-private-external Service (externalIPs)
        └── nginx-ingress-private Controller
            ├── argocd (GitOps management)
            └── git (Git server)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="implementation-details"&gt;
&lt;h2&gt;Implementation Details&lt;/h2&gt;
&lt;section id="network-interface-configuration"&gt;
&lt;h3&gt;Network Interface Configuration&lt;/h3&gt;
&lt;p&gt;The implementation assumes two network interfaces on Kubernetes nodes:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;eth0: 168.119.158.20    # Public interface (firewall: 80/443 only)
eth1: 172.16.0.11     # Private interface (no firewall restrictions)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="externalips-services-setup"&gt;
&lt;h3&gt;ExternalIPs Services Setup&lt;/h3&gt;
&lt;p&gt;Create services that bind NGINX controllers to specific interface IPs:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id1"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;nginx-public-external.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Service&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-public-external&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-ingress-public&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-public-external&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;networking&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/instance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-external-services&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/part-of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;platform&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ClusterIP&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;externalIPs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;168.119.158.20&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# eth0 public interface&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;80&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;80&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TCP&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;443&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;443&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TCP&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;https&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ingress-nginx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/instance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-ingress-public&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;controller&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id2"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;nginx-private-external.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Service&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-private-external&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-ingress-private&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-private-external&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;networking&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/instance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-external-services&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/part-of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;platform&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ClusterIP&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;externalIPs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;172.16.0.11&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# eth1 private interface&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;80&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;80&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TCP&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;443&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;443&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TCP&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;https&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ingress-nginx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/instance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-ingress-private&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app.kubernetes.io/component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;controller&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="nginx-controller-configuration"&gt;
&lt;h3&gt;NGINX Controller Configuration&lt;/h3&gt;
&lt;p&gt;Configure separate NGINX ingress controllers for each interface:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id3"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;public-controller-values.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-public&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ingressClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-public&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ingressClassResource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-public&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;controllerValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"k8s.io/nginx-public"&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Minimal configuration for reliable operation&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;use-forwarded-headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;compute-full-forwarded-for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;use-proxy-protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Resource configuration&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;100m&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;90Mi&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;500m&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;256Mi&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The private controller uses an identical configuration with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nginx-private&lt;/span&gt;&lt;/code&gt; replacing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nginx-public&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;k8s.io/nginx-private&lt;/span&gt;&lt;/code&gt; as the controller value.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="application-configuration"&gt;
&lt;h2&gt;Application Configuration&lt;/h2&gt;
&lt;section id="public-service-example"&gt;
&lt;h3&gt;Public Service Example&lt;/h3&gt;
&lt;p&gt;Configure public-facing applications to use the public ingress class:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id4"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;public-app-ingress.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Ingress&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;epheo-eu&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;epheo-eu&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cert-manager.io/cluster-issuer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;letsencrypt-prod&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ingressClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-public&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;tls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;epheo.eu&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;secretName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;epheo-eu-tls&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;epheo.eu&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;pathType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Prefix&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;epheo-eu&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="nt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;80&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="private-service-example"&gt;
&lt;h3&gt;Private Service Example&lt;/h3&gt;
&lt;p&gt;Configure administrative and internal services to use the private ingress class:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id5"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;argocd-ingress.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Ingress&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;argocd-server&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;argocd&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cert-manager.io/cluster-issuer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;self-signed-issuer&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ingressClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-private&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;tls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;argocd.def.ms&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;secretName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;argocd-server-tls&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;argocd.def.ms&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;pathType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Prefix&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;argocd-server&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="nt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;80&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="verification"&gt;
&lt;h2&gt;Verification&lt;/h2&gt;
&lt;p&gt;Verify the ingress controllers are running and routing correctly:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Check both controllers are running&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pods&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;nginx-ingress-public
kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pods&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;nginx-ingress-private

&lt;span class="c1"&gt;# Verify services have correct externalIPs&lt;/span&gt;
kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;svc&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;nginx-ingress-public&lt;span class="w"&gt; &lt;/span&gt;nginx-public-external
kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;svc&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;nginx-ingress-private&lt;span class="w"&gt; &lt;/span&gt;nginx-private-external

&lt;span class="c1"&gt;# Test public routing&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Host: epheo.eu"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http://168.119.158.20

&lt;span class="c1"&gt;# Test private routing&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Host: argocd.def.ms"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http://172.16.0.11
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 16 Aug 2024 00:00:00 </pubDate></item><item><title>Kubernetes Secret Management with SOPS + Age + Git</title><link>https://blog.epheo.eu/articles/k8s-sops-secrets/index.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Aug 16, 2024&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;15 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I don’t like managing secrets in Kubernetes. Solutions like HashiCorp Vault are
complicated and resource-intensive. Kubeseal was actually great but now that Bitnami
got aquired by Broadcom, I’m concerned about the future of the apiVersion: bitnami.com/ API domain.&lt;/p&gt;
&lt;p&gt;I wanted something fully transparent, so I can work with normal secrets in my repo, git
commit, have the secrets provisioned on my k8s cluster and never have to care about
encryption and secret management.&lt;/p&gt;
&lt;p&gt;This repo boilerplate uses SOPS (Secrets OPerationS), AGE encryption and advanced
gitattributes filters in order to provide a transparent workflow for developers to
manage their secrets.&lt;/p&gt;
&lt;p&gt;While this may be enough by itself we can also use sops-secrets-operator when using
ArgoCD or Flux for GitOps.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/getsops/sops"&gt;https://github.com/getsops/sops&lt;/a&gt;
&lt;a class="reference external" href="https://github.com/FiloSottile/age"&gt;https://github.com/FiloSottile/age&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;All configurations and examples are available in the &lt;a class="reference external" href="https://github.com/epheo/k8s-sops-secrets-boilerplate"&gt;k8s-sops-secrets-boilerplate repository&lt;/a&gt;.&lt;/p&gt;
&lt;section id="why-sops-age-for-secret-management"&gt;
&lt;h2&gt;Why SOPS + Age for Secret Management?&lt;/h2&gt;
&lt;section id="advantages-of-this-approach"&gt;
&lt;h3&gt;Advantages of This Approach&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transparency&lt;/strong&gt;: Secrets appear as plain text in your working directory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplicity&lt;/strong&gt;: No external secret management infrastructure required&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Git Integration&lt;/strong&gt;: Automatic encryption when committing to Git&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer Friendly&lt;/strong&gt;: Works with existing tooling and workflows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secure&lt;/strong&gt;: Strong encryption with Age’s modern cryptographic design&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Selective&lt;/strong&gt;: Only encrypt what needs to be encrypted using annotations&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="architecture-overview"&gt;
&lt;h3&gt;Architecture Overview&lt;/h3&gt;
&lt;p&gt;The workflow is completely transparent:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Edit secrets in plain text locally&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git automatically encrypts them when staging changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secrets are stored encrypted in the upstream repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Working directory always shows decrypted content&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="setting-up-the-environment"&gt;
&lt;h2&gt;Setting Up the Environment&lt;/h2&gt;
&lt;section id="installing-required-tools"&gt;
&lt;h3&gt;Installing Required Tools&lt;/h3&gt;
&lt;p&gt;First, install the required dependencies and tools:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Install Python dependencies&lt;/span&gt;
pip3&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;PyYAML

&lt;span class="c1"&gt;# Install SOPS&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-LO&lt;span class="w"&gt; &lt;/span&gt;https://github.com/getsops/sops/releases/download/v3.9.1/sops-v3.9.1.linux.amd64
sudo&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;sops-v3.9.1.linux.amd64&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin/sops
sudo&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin/sops

&lt;span class="c1"&gt;# Install Age&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-LO&lt;span class="w"&gt; &lt;/span&gt;https://github.com/FiloSottile/age/releases/latest/download/age-v1.1.1-linux-amd64.tar.gz
tar&lt;span class="w"&gt; &lt;/span&gt;xf&lt;span class="w"&gt; &lt;/span&gt;age-v1.1.1-linux-amd64.tar.gz
sudo&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;age/age*&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin/
sudo&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin/age*
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Check the &lt;a class="reference external" href="https://github.com/getsops/sops/releases"&gt;SOPS releases&lt;/a&gt; and
&lt;a class="reference external" href="https://github.com/FiloSottile/age/releases"&gt;Age releases&lt;/a&gt; pages for latest versions.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="generating-age-keys"&gt;
&lt;h3&gt;Generating Age Keys&lt;/h3&gt;
&lt;p&gt;Create encryption keys for your project:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Create age directory and generate key pair&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;.age
age-keygen&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;.age/age.key

&lt;span class="c1"&gt;# Extract the public key for SOPS configuration&lt;/span&gt;
grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"public key:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.age/age.key

&lt;span class="c1"&gt;# Add age directory to gitignore&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".age/"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;.gitignore

&lt;span class="c1"&gt;# Secure the private key&lt;/span&gt;
chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.age/age.key
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Store the private key securely and share only the public key with team members who need to encrypt secrets.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="project-configuration"&gt;
&lt;h2&gt;Project Configuration&lt;/h2&gt;
&lt;section id="sops-configuration"&gt;
&lt;h3&gt;SOPS Configuration&lt;/h3&gt;
&lt;p&gt;Create a &lt;cite&gt;.sops.yaml&lt;/cite&gt; configuration file in your repository root:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id1"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;.sops.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;creation_rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;\.secrets\.ya?ml$&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;encrypted_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'^(data|stringData)$'&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;secrets/.*\.ya?ml$&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;encrypted_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'^(data|stringData)$'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Key configuration options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;path_regex&lt;/strong&gt;: Files matching this pattern will be encrypted&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;age&lt;/strong&gt;: Public key for encryption&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;encrypted_regex&lt;/strong&gt;: Only encrypt specified YAML keys (data, stringData for secrets)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="git-filter-setup"&gt;
&lt;h3&gt;Git Filter Setup&lt;/h3&gt;
&lt;p&gt;The repository includes Python scripts for Git filter integration. First, make them executable:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Make filter scripts executable&lt;/span&gt;
chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;sops-clean.py&lt;span class="w"&gt; &lt;/span&gt;sops-smudge.py
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Configure Git to automatically encrypt/decrypt files:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id2"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;.gitattributes&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;*.secrets.yaml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sops&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;diff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sops
*.secrets.yml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sops&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;diff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sops
secrets/*.yaml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sops&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;diff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sops
secrets/*.yml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sops&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;diff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sops
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Configure Git filters using the Python scripts:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Configure SOPS filters with Python scripts&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;filter.sops.clean&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'./sops-clean.py'&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;filter.sops.smudge&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'./sops-smudge.py'&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;filter.sops.required&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="environment-variables"&gt;
&lt;h3&gt;Environment Variables&lt;/h3&gt;
&lt;p&gt;Set required environment variables to point to your age key:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id3"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;.envrc (if using direnv)&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;SOPS_AGE_KEY_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.age/age.key
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Or add to your shell profile:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'export SOPS_AGE_KEY_FILE=.age/age.key'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;~/.bashrc
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="creating-encrypted-secrets"&gt;
&lt;h2&gt;Creating Encrypted Secrets&lt;/h2&gt;
&lt;section id="basic-secret-creation"&gt;
&lt;h3&gt;Basic Secret Creation&lt;/h3&gt;
&lt;p&gt;Create a Kubernetes secret with transparent encryption:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id4"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;app.secrets.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Secret&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;app-secrets&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;production&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# This annotation ensures the secret is managed by our system&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;secrets.k8s.io/managed-by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sops&lt;/span&gt;
&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Opaque&lt;/span&gt;
&lt;span class="nt"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;database-url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cG9zdGdyZXNxbDovL3VzZXI6cGFzc3dvcmRAZGIuZXhhbXBsZS5jb20vbXlkYg==&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;api-key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bG9sLCB5b3UgcmVhbGx5IHRob3VnaHQgSSBkaWQsIHJpZ2h0ID8K&lt;/span&gt;
&lt;span class="nt"&gt;stringData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;config.json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;"database": {&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;"host": "db.example.com",&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;"port": 5432,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;"username": "myuser",&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;"password": "mypassword"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;"api": {&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;"key": "super-secret-api-key",&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;"endpoint": "https://api.example.com"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When you edit this file locally, you see plain text. When committed to Git, only the &lt;cite&gt;data&lt;/cite&gt; and &lt;cite&gt;stringData&lt;/cite&gt; sections are encrypted.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="tls-certificate-secrets"&gt;
&lt;h3&gt;TLS Certificate Secrets&lt;/h3&gt;
&lt;p&gt;Manage TLS certificates securely:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id5"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;tls.secrets.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Secret&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;app-tls&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;production&lt;/span&gt;
&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubernetes.io/tls&lt;/span&gt;
&lt;span class="nt"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;tls.crt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;BAMMGnNlbGYtc2lnbmVkLWNlcnRpZmljYXRlLTAwHhcNMjEwMzEwMTYwNDAxWhcN&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;LS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;tls.key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0t&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;wxPBDkdPPDGBX8YXbMR7cGVOcLd9qnkL4Zx7gV7lY1P5zt8jRB9XvV4qS4A1z8PF&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;LS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQ==&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="working-with-encrypted-secrets"&gt;
&lt;h2&gt;Working with Encrypted Secrets&lt;/h2&gt;
&lt;section id="daily-workflow"&gt;
&lt;h3&gt;Daily Workflow&lt;/h3&gt;
&lt;p&gt;The beauty of this system is its transparency:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Edit secrets normally - they appear as plain text&lt;/span&gt;
vim&lt;span class="w"&gt; &lt;/span&gt;app.secrets.yaml

&lt;span class="c1"&gt;# Add the file to Git - it gets encrypted automatically&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;app.secrets.yaml

&lt;span class="c1"&gt;# Commit - the encrypted version is stored&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;commit&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Update database credentials"&lt;/span&gt;

&lt;span class="c1"&gt;# Other team members can clone and immediately see decrypted content&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;repository&amp;gt;
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;project&amp;gt;
cat&lt;span class="w"&gt; &lt;/span&gt;app.secrets.yaml&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Shows decrypted content&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="manual-encryption-decryption"&gt;
&lt;h3&gt;Manual Encryption/Decryption&lt;/h3&gt;
&lt;p&gt;For advanced use cases, use SOPS directly:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Encrypt a file manually&lt;/span&gt;
sops&lt;span class="w"&gt; &lt;/span&gt;--encrypt&lt;span class="w"&gt; &lt;/span&gt;--in-place&lt;span class="w"&gt; &lt;/span&gt;secrets/app.secrets.yaml

&lt;span class="c1"&gt;# Decrypt a file manually&lt;/span&gt;
sops&lt;span class="w"&gt; &lt;/span&gt;--decrypt&lt;span class="w"&gt; &lt;/span&gt;secrets/app.secrets.yaml

&lt;span class="c1"&gt;# Edit encrypted file directly&lt;/span&gt;
sops&lt;span class="w"&gt; &lt;/span&gt;secrets/app.secrets.yaml

&lt;span class="c1"&gt;# View decrypted content without modifying&lt;/span&gt;
sops&lt;span class="w"&gt; &lt;/span&gt;--decrypt&lt;span class="w"&gt; &lt;/span&gt;secrets/app.secrets.yaml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;less
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="key-rotation"&gt;
&lt;h3&gt;Key Rotation&lt;/h3&gt;
&lt;p&gt;Rotate encryption keys periodically:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Generate new Age key&lt;/span&gt;
age-keygen&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;new-key.txt

&lt;span class="c1"&gt;# Update .sops.yaml with new public key&lt;/span&gt;
&lt;span class="c1"&gt;# Re-encrypt all secrets with new key&lt;/span&gt;
find&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*.secrets.yaml"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;sops&lt;span class="w"&gt; &lt;/span&gt;updatekeys&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;

&lt;span class="c1"&gt;# Update team members' key files&lt;/span&gt;
cp&lt;span class="w"&gt; &lt;/span&gt;new-key.txt&lt;span class="w"&gt; &lt;/span&gt;.age/age.key
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="kubernetes-integration"&gt;
&lt;h2&gt;Kubernetes Integration&lt;/h2&gt;
&lt;section id="sops-secrets-operator"&gt;
&lt;h3&gt;SOPS Secrets Operator&lt;/h3&gt;
&lt;p&gt;For automated secret management, deploy the SOPS Secrets Operator:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id6"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;sops-secrets-operator.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Namespace&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sops-secrets-operator&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;apps/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Deployment&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sops-secrets-operator&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sops-secrets-operator&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sops-secrets-operator&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sops-secrets-operator&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;serviceAccountName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sops-secrets-operator&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;manager&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;isindir/sops-secrets-operator:0.12.0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WATCH_NAMESPACE&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;SOPS_AGE_KEY&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;valueFrom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;secretKeyRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sops-age-key&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;key.txt&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;100m&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;128Mi&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;500m&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;512Mi&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The operator automatically syncs encrypted secrets from Git to Kubernetes secrets.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="advanced-patterns"&gt;
&lt;h2&gt;Advanced Patterns&lt;/h2&gt;
&lt;section id="conditional-encryption"&gt;
&lt;h3&gt;Conditional Encryption&lt;/h3&gt;
&lt;p&gt;Use SOPS path-based rules for selective encryption:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id7"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;.sops.yaml (advanced)&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;creation_rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Production secrets - always encrypted&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prod/.*\.ya?ml$&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;agexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;encrypted_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'^(data|stringData|password|secret|key|token)$'&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Development secrets - only sensitive fields&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;dev/.*\.ya?ml$&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;agexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;encrypted_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'^(password|secret|key|token)$'&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Test secrets - minimal encryption&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;test/.*\.ya?ml$&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;agexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;encrypted_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'^(password)$'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="multi-key-management"&gt;
&lt;h3&gt;Multi-Key Management&lt;/h3&gt;
&lt;p&gt;Support multiple teams with different keys:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id8"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;.sops.yaml (multi-team)&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;creation_rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Platform team secrets&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;platform/.*\.ya?ml$&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;&amp;gt;-&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;agexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;age1xyz...platform-team-key&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;encrypted_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'^(data|stringData)$'&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Development team secrets&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;apps/.*\.ya?ml$&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;&amp;gt;-&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;age1abc...dev-team-key,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;agexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;encrypted_regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'^(data|stringData)$'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="audit-and-compliance"&gt;
&lt;h2&gt;Audit and Compliance&lt;/h2&gt;
&lt;p&gt;Track secret changes with Git history:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# View secret change history&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;--oneline&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;secrets/

&lt;span class="c1"&gt;# See who changed secrets&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;blame&lt;span class="w"&gt; &lt;/span&gt;secrets/production.secrets.yaml

&lt;span class="c1"&gt;# Diff encrypted secrets&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;diff&lt;span class="w"&gt; &lt;/span&gt;HEAD~1&lt;span class="w"&gt; &lt;/span&gt;secrets/production.secrets.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="testing-and-validation"&gt;
&lt;h2&gt;Testing and Validation&lt;/h2&gt;
&lt;section id="repository-testing-framework"&gt;
&lt;h3&gt;Repository Testing Framework&lt;/h3&gt;
&lt;p&gt;The repository includes comprehensive end-to-end testing scripts:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Quick filter testing - tests Git filters work correctly&lt;/span&gt;
./run-e2e-tests.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt;

&lt;span class="c1"&gt;# Complete GitOps workflow test - full end-to-end validation&lt;/span&gt;
./run-e2e-tests.sh&lt;span class="w"&gt; &lt;/span&gt;full
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;These tests validate:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Git filter encryption/decryption functionality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SOPS configuration correctness&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complete GitOps workflow with ArgoCD/Flux integration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secret operator deployment and management&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="manual-validation-scripts"&gt;
&lt;h3&gt;Manual Validation Scripts&lt;/h3&gt;
&lt;p&gt;Create additional validation scripts for your workflow:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id9"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;validate-secrets.sh&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c1"&gt;# Validate all secret files can be decrypted&lt;/span&gt;
find&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*.secrets.yaml"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Validating &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sops&lt;span class="w"&gt; &lt;/span&gt;--decrypt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/null&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"✓ &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt; is valid"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"✗ &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt; failed validation"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c1"&gt;# Check for unencrypted sensitive data&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"password:\|secret:\|key:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;--include&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.yaml"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--exclude&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.secrets.yaml"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"⚠ Found potential unencrypted secrets"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"All validations passed"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="debugging-commands"&gt;
&lt;h3&gt;Debugging Commands&lt;/h3&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Test SOPS configuration&lt;/span&gt;
sops&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;.sops.yaml&lt;span class="w"&gt; &lt;/span&gt;encrypt&lt;span class="w"&gt; &lt;/span&gt;/dev/null

&lt;span class="c1"&gt;# Verify Age key&lt;/span&gt;
age-keygen&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;.age/age.key

&lt;span class="c1"&gt;# Check Git filters&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;--list&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;sops

&lt;span class="c1"&gt;# Test encryption/decryption&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test: secret"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sops&lt;span class="w"&gt; &lt;/span&gt;--encrypt&lt;span class="w"&gt; &lt;/span&gt;/dev/stdin&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sops&lt;span class="w"&gt; &lt;/span&gt;--decrypt&lt;span class="w"&gt; &lt;/span&gt;/dev/stdin

&lt;span class="c1"&gt;# Test Git filter scripts&lt;/span&gt;
./sops-clean.py&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;test.secrets.yaml
./sops-smudge.py&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;encrypted-test.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Fri, 16 Aug 2024 00:00:00 </pubDate></item><item><title>Running Mistral:7b LLM on OpenShift</title><link>https://blog.epheo.eu/articles/openshift-ollama/index.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Feb 05, 2024&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;10 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Running your local LLM model with Ollama on your OpenShift cluster.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://ollama.ai/"&gt;Ollama&lt;/a&gt; is an open-source tool that simplifies running and managing Large Language Models (LLMs) locally. It provides a simple API for managing model lifecycles and making inference requests.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://mistral.ai/news/announcing-mistral-7b/"&gt;https://mistral.ai/news/announcing-mistral-7b/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Mistral is a powerful Large Language Model trained by a French start-up that currently
outperforms other models of the same size. By combining Mistral with Ollama on OpenShift, you can run a production-grade LLM environment within your own infrastructure.&lt;/p&gt;
&lt;p&gt;All the files and configurations referenced in this article are available in the &lt;a class="reference external" href="https://github.com/epheo/openshift-ollama"&gt;openshift-ollama GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;section id="running-mistral-7b-on-openshift"&gt;
&lt;h2&gt;Running Mistral:7B on OpenShift&lt;/h2&gt;
&lt;section id="architecture-overview"&gt;
&lt;h3&gt;Architecture Overview&lt;/h3&gt;
&lt;p&gt;Our deployment consists of the following components:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;An Ollama server pod with GPU access for model execution&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Persistent storage for model weights and cache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internal and external routes for API access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optional integration with client applications (Telegram bot, VSCode plugins, iOS app)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="deploying-ollama"&gt;
&lt;h3&gt;Deploying Ollama&lt;/h3&gt;
&lt;p&gt;First, we’ll create the required OpenShift namespace:&lt;/p&gt;
&lt;p&gt;Within an ollama namespace&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id1"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;openshift-ollama.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt;1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt;2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Namespace&lt;/span&gt;
&lt;span class="linenos"&gt;3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We create the PVC and Deployment using the ollama official container image:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://hub.docker.com/r/ollama/ollama"&gt;https://hub.docker.com/r/ollama/ollama&lt;/a&gt;&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id2"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;openshift-ollama.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PersistentVolumeClaim&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama-storage&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;accessModes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ReadWriteOnce&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;volumeMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Filesystem&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;100Gi&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;apps/v1&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Deployment&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama/ollama:latest&lt;/span&gt;
&lt;span class="linenos"&gt;33&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;34&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http&lt;/span&gt;
&lt;span class="linenos"&gt;35&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;containerPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;11434&lt;/span&gt;
&lt;span class="linenos"&gt;36&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TCP&lt;/span&gt;
&lt;span class="linenos"&gt;37&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;terminationMessagePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/termination-log&lt;/span&gt;
&lt;span class="linenos"&gt;38&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;terminationMessagePolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;File&lt;/span&gt;
&lt;span class="linenos"&gt;39&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;volumeMounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;40&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mountPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/.ollama&lt;/span&gt;
&lt;span class="linenos"&gt;41&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama-storage&lt;/span&gt;
&lt;span class="linenos"&gt;42&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;43&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;44&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;nvidia.com/gpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="linenos"&gt;45&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;restartPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Always&lt;/span&gt;
&lt;span class="linenos"&gt;46&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Always&lt;/span&gt;
&lt;span class="linenos"&gt;47&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;48&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama-storage&lt;/span&gt;
&lt;span class="linenos"&gt;49&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;50&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama-storage&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We notice the &lt;strong&gt;nvidia.com/gpu: 1&lt;/strong&gt; resources parameter.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="exposing-the-ollama-api-endpoint"&gt;
&lt;h3&gt;Exposing the Ollama API endpoint&lt;/h3&gt;
&lt;p&gt;We expose the Ollama API endpoint both internally (for other containers like our Telegram Bot) and externally (for services such as VSCode plugins or mobile apps).&lt;/p&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;Security note: The external endpoint in this setup is only exposed on a private network
accessed via VPN. Since we haven’t configured authentication for this endpoint, exposing it
to a public IP would create a significant security risk.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id3"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;openshift-ollama.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Service&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ClusterIP&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;80&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TCP&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Route&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;route.openshift.io/v1&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Service&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;tls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;null&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="running-mistral-llm-on-ollama"&gt;
&lt;h3&gt;Running Mistral LLM on Ollama&lt;/h3&gt;
&lt;p&gt;Now that our Ollama service is up and running, we can pull the Mistral:7b model using the exposed API endpoint:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;http://&lt;span class="k"&gt;$(&lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;route&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;-ojsonpath&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.host}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/api/pull&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{"name": "mistral:7b"}'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Depending on your network speed and GPU capabilities, this may take several minutes as it downloads and prepares the model.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;After the download is complete, we can validate that our model has been successfully loaded:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;http://&lt;span class="k"&gt;$(&lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;route&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;-ojsonpath&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.host}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/api/tags&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;jq&lt;span class="w"&gt; &lt;/span&gt;.
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"models"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mistral:7b"&lt;/span&gt;,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"model"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mistral:7b"&lt;/span&gt;,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"modified_at"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024-02-03T19:44:00.872177836Z"&lt;/span&gt;,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"size"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4109865159&lt;/span&gt;,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"digest"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"61e88e884507ba5e06c49b40e6226884b2a16e872382c2b44a42f2d119d804a5"&lt;/span&gt;,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"details"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"parent_model"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;,
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"format"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gguf"&lt;/span&gt;,
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"family"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"llama"&lt;/span&gt;,
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"families"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s2"&gt;"llama"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"parameter_size"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7B"&lt;/span&gt;,
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"quantization_level"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Q4_0"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response contains important information:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;format&lt;/strong&gt;: GGUF (GPT-Generated Unified Format) - optimized for inference&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;family&lt;/strong&gt;: llama - the base architecture family&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;parameter_size&lt;/strong&gt;: 7B - the model has 7 billion parameters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;quantization_level&lt;/strong&gt;: Q4_0 - the precision level of the model weights&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="creating-custom-models-with-specializations"&gt;
&lt;h4&gt;Creating Custom Models with Specializations&lt;/h4&gt;
&lt;p&gt;One of Ollama’s powerful features is the ability to create custom models with specialized behaviors without retraining. Let’s create a model specialized in OpenShift documentation:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;http://&lt;span class="k"&gt;$(&lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;route&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;-ojsonpath&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.host}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/api/create&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{&lt;/span&gt;
&lt;span class="s1"&gt;  "name": "ocplibrarian",&lt;/span&gt;
&lt;span class="s1"&gt;  "modelfile": "FROM mistral:7b\nSYSTEM You are a Librarian, specialized in retrieving content from the OpenShift documentation."&lt;/span&gt;
&lt;span class="s1"&gt;}'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This creates a new model called “ocplibrarian” that inherits all capabilities from Mistral:7b but has been given a specific persona and purpose through the SYSTEM instruction.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternative-models-openhermes-2-5"&gt;
&lt;h3&gt;Alternative Models: OpenHermes 2.5&lt;/h3&gt;
&lt;p&gt;Mistral is one of many models you can run on Ollama. Let’s also try OpenHermes 2.5, an instruction-tuned variant of Mistral that offers improved performance on many tasks:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;http://&lt;span class="k"&gt;$(&lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;route&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;-ojsonpath&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.host}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/api/pull&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{"name": "openhermes2.5-mistral:7b-q4_K_M"}'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After pulling the model, we can create a customized version with a specific personality:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;http://&lt;span class="k"&gt;$(&lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;route&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;-ojsonpath&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.host}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/api/create&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{&lt;/span&gt;
&lt;span class="s1"&gt;  "name": "hermes2",&lt;/span&gt;
&lt;span class="s1"&gt;  "modelfile": "FROM openhermes2.5-mistral:7b-q4_K_M\nSYSTEM You are \"Hermes 2\", a conversational AI assistant developed by Teknium. Your purpose is to assist users with helpful, accurate information and engaging conversation."&lt;/span&gt;
&lt;span class="s1"&gt;}'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The model is now available as “hermes2” and carries the specified system prompt that defines its behavior.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="interacting-with-the-llm"&gt;
&lt;h2&gt;Interacting with the LLM&lt;/h2&gt;
&lt;section id="building-a-telegram-bot-interface"&gt;
&lt;h3&gt;Building a Telegram Bot Interface&lt;/h3&gt;
&lt;p&gt;For a practical demonstration of the Ollama API, let’s create a simple Telegram bot that serves as an interface to our LLM. We’ll call it &lt;strong&gt;Tellama&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The core functionality retrieves user messages from Telegram, forwards them to the Ollama API, and returns the LLM’s responses:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id4"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;tellama.py&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ContextTypes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_TYPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;      &lt;span class="s2"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mistral:7b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;      &lt;span class="s2"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;          &lt;span class="s2"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;          &lt;span class="s2"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;      &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;      &lt;span class="s2"&gt;"stream"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OLLAMA_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;        &lt;span class="n"&gt;ollama_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reply_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ollama_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reply_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Sorry, there was an error processing your request.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This implementation is intentionally simple and has some limitations:
- No conversation history or context is maintained between messages
- No support for streaming responses
- Limited error handling&lt;/p&gt;
&lt;p&gt;These limitations could be addressed in a more robust implementation, but this serves as a good starting point for testing the API.&lt;/p&gt;
&lt;section id="deploying-the-telegram-bot-on-openshift"&gt;
&lt;h4&gt;Deploying the Telegram Bot on OpenShift&lt;/h4&gt;
&lt;p&gt;Now let’s containerize our Python script using a UBI (Universal Base Image) container and deploy it to our OpenShift cluster:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Build the container image&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tellama
podman&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;.

&lt;span class="c1"&gt;# Get the image ID and OpenShift registry URL&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;image_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;podman&lt;span class="w"&gt; &lt;/span&gt;images&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="w"&gt; &lt;/span&gt;json&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;jq&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;.Id&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cut&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;-13&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ocp_registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;route&lt;span class="w"&gt; &lt;/span&gt;default-route&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openshift-image-registry&lt;span class="w"&gt; &lt;/span&gt;-ojsonpath&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.host}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Push to the OpenShift internal registry&lt;/span&gt;
podman&lt;span class="w"&gt; &lt;/span&gt;login&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;user&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;whoami&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ocp_registry&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
podman&lt;span class="w"&gt; &lt;/span&gt;push&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$image_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker://&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ocp_registry&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/ollama/tellama:latest
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After creating a new Telegram bot messaging @botfather we create a new Secret
containing the Telegram Token.&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id5"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;ollama-secret.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt;1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt;2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Secret&lt;/span&gt;
&lt;span class="linenos"&gt;3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama-secret&lt;/span&gt;
&lt;span class="linenos"&gt;5&lt;/span&gt;&lt;span class="nt"&gt;stringData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;TELEGRAM_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;&amp;lt;your_telegram_token&amp;gt;&lt;/span&gt;
&lt;span class="linenos"&gt;7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;OLLAMA_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"http://ollama/api/chat"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can now deploy our created image within the OpenShift cluster.
Replacing the &lt;strong&gt;image:&lt;/strong&gt; with the value of &lt;strong&gt;$ocp_registry&lt;/strong&gt;&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id6"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;tellama.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;apps/v1&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Deployment&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tellama&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tellama&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default-route-openshift-image-registry.apps.da2.epheo.eu/ollama/tellama:latest&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;envFrom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;secretRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama-secret&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;restartPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Always&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Always&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="integrating-with-development-tools"&gt;
&lt;h3&gt;Integrating with Development Tools&lt;/h3&gt;
&lt;section id="developer-experience-with-vscode-extensions"&gt;
&lt;h4&gt;Developer Experience with VSCode Extensions&lt;/h4&gt;
&lt;p&gt;With our Ollama service running, we can integrate it with various development tools. Here are some VSCode extensions that work well with self-hosted LLMs:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Continue&lt;/strong&gt;: A VSCode extension similar to GitHub Copilot that can leverage your self-hosted LLM for code completion, explanation, and generation.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/continuedev/continue"&gt;https://github.com/continuedev/continue&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;figure class="align-center"&gt;
&lt;a class="reference internal image-reference" href="https://github.com/continuedev/continue/raw/main/media/readme.gif"&gt;&lt;img alt="https://github.com/continuedev/continue/raw/main/media/readme.gif" src="https://github.com/continuedev/continue/raw/main/media/readme.gif" style="width: 100%;"/&gt;
&lt;/a&gt;
&lt;/figure&gt;
&lt;p&gt;You can install Continue directly from the VSCode extension marketplace. After installation, you’ll need to configure it to use your self-hosted Ollama service:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Create or edit the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;~/.continue/config.json&lt;/span&gt;&lt;/code&gt; configuration file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add Ollama as your LLM provider with the appropriate endpoint&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Replace the example endpoint with your actual Ollama route:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oc&lt;/span&gt; &lt;span class="pre"&gt;get&lt;/span&gt; &lt;span class="pre"&gt;route&lt;/span&gt; &lt;span class="pre"&gt;ollama&lt;/span&gt; &lt;span class="pre"&gt;-n&lt;/span&gt; &lt;span class="pre"&gt;ollama&lt;/span&gt; &lt;span class="pre"&gt;-ojsonpath='{.spec.host}'&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"models"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mistral"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ollama"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mistral:7b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"apiBase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://ollama-ollama.apps.da2.epheo.eu"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;commitollama&lt;/strong&gt; is a specialized VSCode extension that generates meaningful Git commit messages using your self-hosted LLM.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/JepriCreations/commitollama"&gt;https://github.com/JepriCreations/commitollama&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Configuration is straightforward through your VSCode settings:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"commitollama.custom.endpoint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://ollama-ollama.apps.da2.epheo.eu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"commitollama.model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"custom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"commitollama.custom.model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mistral:7b"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;With this configuration, you can simply stage your changes and let commitollama analyze the diff to generate descriptive commit messages.&lt;/p&gt;
&lt;figure class="align-center"&gt;
&lt;a class="reference internal image-reference" href="https://raw.githubusercontent.com/jepricreations/commitollama/main/commitollama-demo.gif"&gt;&lt;img alt="https://raw.githubusercontent.com/jepricreations/commitollama/main/commitollama-demo.gif" src="https://raw.githubusercontent.com/jepricreations/commitollama/main/commitollama-demo.gif" style="width: 100%;"/&gt;
&lt;/a&gt;
&lt;/figure&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="mobile-integration-enchanted-for-ios"&gt;
&lt;h3&gt;Mobile Integration: Enchanted for iOS&lt;/h3&gt;
&lt;p&gt;For on-the-go access to your self-hosted LLM, you can use Enchanted, an open-source iOS application specifically designed for Ollama compatibility.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/AugustDev/enchanted"&gt;https://github.com/AugustDev/enchanted&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Enchanted offers a ChatGPT-like interface for interacting with your self-hosted models, providing a clean, intuitive mobile experience with features like:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Conversation history&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Different model selection&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conversation context management&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Share and export options&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Since our Ollama endpoint is exposed on a private network, your iOS device can connect
either through a local WiFi network or by configuring a VPN connection to your network.&lt;/p&gt;
&lt;/div&gt;
&lt;a class="reference internal image-reference" href="../../_images/ollama-enchanted-appstore.jpg"&gt;&lt;img alt="../../_images/ollama-enchanted-appstore.jpg" src="../../_images/ollama-enchanted-appstore.jpg" style="width: 49%;"/&gt;
&lt;/a&gt;
&lt;a class="reference internal image-reference" href="../../_images/ollama-enchanted-settings.jpg"&gt;&lt;img alt="../../_images/ollama-enchanted-settings.jpg" src="../../_images/ollama-enchanted-settings.jpg" style="width: 49%;"/&gt;
&lt;/a&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="performance-considerations"&gt;
&lt;h2&gt;Performance Considerations&lt;/h2&gt;
&lt;section id="gpu-selection"&gt;
&lt;h3&gt;GPU Selection&lt;/h3&gt;
&lt;p&gt;While any NVIDIA GPU can run these models, performance varies considerably:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RTX 3080/3090 or better&lt;/strong&gt;: Excellent for running multiple 7B models&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CPU-only&lt;/strong&gt;: Functional but with much slower inference speeds (5-10x slower)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="model-quantization"&gt;
&lt;h3&gt;Model Quantization&lt;/h3&gt;
&lt;p&gt;Quantization reduces model precision to improve performance at a small cost to accuracy:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Q4_0&lt;/strong&gt;: Fastest inference, lowest VRAM usage (4-bit quantization)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Q5_K_M&lt;/strong&gt;: Good balance between quality and performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Q8_0&lt;/strong&gt;: Higher quality results but requires more VRAM and slower inference&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="memory-requirements"&gt;
&lt;h3&gt;Memory Requirements&lt;/h3&gt;
&lt;p&gt;Typical memory requirements for a 7B parameter model:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Full precision (FP16): ~14GB VRAM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Q8_0 quantization: ~7GB VRAM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Q4_0 quantization: ~4GB VRAM&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="troubleshooting"&gt;
&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;p&gt;For common issues and their solutions, refer to the &lt;a class="reference external" href="https://github.com/epheo/openshift-ollama/blob/main/troubleshooting.md"&gt;troubleshooting guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Common challenges include:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;GPU detection issues&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memory limitations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Network connectivity problems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Model loading failures&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="security-considerations"&gt;
&lt;h2&gt;Security Considerations&lt;/h2&gt;
&lt;p&gt;When deploying LLM services like Ollama, consider these important security aspects:&lt;/p&gt;
&lt;section id="authentication"&gt;
&lt;h3&gt;Authentication&lt;/h3&gt;
&lt;p&gt;The default Ollama API has no built-in authentication. For production use, consider:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implementing a reverse proxy with authentication&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using OpenShift network policies to restrict access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating application-specific API keys&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-privacy"&gt;
&lt;h3&gt;Data Privacy&lt;/h3&gt;
&lt;p&gt;One of the main advantages of self-hosting LLMs is data privacy:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;All prompts and completions remain within your infrastructure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No data is sent to third-party services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sensitive information can be processed safely&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, remember that the model itself may contain biases or potentially generate problematic content. Implement appropriate guardrails for your specific use case.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="resource-isolation"&gt;
&lt;h3&gt;Resource Isolation&lt;/h3&gt;
&lt;p&gt;Use OpenShift’s resource management features to ensure your Ollama deployment:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Has appropriate resource limits to prevent cluster resource exhaustion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is isolated from other critical workloads&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Has priority classes set according to your needs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Mon, 05 Feb 2024 00:00:00 </pubDate></item><item><title>Setting up a Virtual Workstation in OpenShift with VFIO Passthrough</title><link>https://blog.epheo.eu/articles/openshift-workstation/index.html</link><description>

&lt;div class="sd-container-fluid sd-sphinx-override sd-p-0 sd-mt-2 sd-mb-4 docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-gx-2 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;div class="sd-container-fluid sd-sphinx-override docutils"&gt;
&lt;div class="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-3 sd-row-cols-md-3 sd-row-cols-lg-3 sd-gx-3 sd-gy-1 docutils"&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"/&gt;&lt;/svg&gt;&lt;/span&gt;Feb 27, 2023&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sd-col sd-col-auto sd-d-flex-row sd-align-minor-center docutils"&gt;
&lt;p class="sd-p-0 sd-m-0"&gt;&lt;span class="sd-pr-2"&gt;&lt;svg version="1.1" width="16.0px" height="16.0px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"&gt;&lt;path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/&gt;&lt;/svg&gt;&lt;/span&gt;25 min read&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This guide explains how to configure OpenShift as a workstation with GPU PCI passthrough
using Container Native Virtualization (CNV) on a single OpenShift node (SNO). This setup
delivers near-native performance for GPU-intensive applications while leveraging Kubernetes
orchestration capabilities.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Run containerized workloads and virtual machines on the same hardware&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use a single GPU for both Kubernetes pods and VMs by switching driver binding&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Achieve near-native performance for gaming and professional applications in VMs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain Kubernetes/OpenShift flexibility for other workloads&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In testing, this configuration successfully ran Microsoft Flight Simulator in a Windows VM
with performance comparable to a bare metal Windows installation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hardware Used:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="table-wrapper colwidths-given docutils container"&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 20.0%"/&gt;
&lt;col style="width: 80.0%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Component&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Specification&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;strong&gt;CPU&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;AMD Ryzen 9 3950X (16-Core, 32-Threads)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;&lt;strong&gt;Memory&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;64GB DDR4 3200MHz&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;strong&gt;GPU&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Nvidia RTX 3080 FE 10GB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;div class="line-block"&gt;
&lt;div class="line"&gt;2x 2TB NVMe Disks (VM storage)&lt;/div&gt;
&lt;div class="line"&gt;1x 500GB SSD Disk (OpenShift root system)&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;10Gbase-CX4 Mellanox Ethernet&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Similar configurations with Intel CPUs should work with minor adjustments noted throughout this guide.&lt;/p&gt;
&lt;section id="installing-openshift-sno"&gt;
&lt;h2&gt;Installing OpenShift SNO&lt;/h2&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;The OpenShift assisted installer formats the first 512 bytes of any disk with a bootable partition.
Back up and remove any existing partition tables you want to preserve. See the &lt;a class="reference external" href="https://github.com/openshift/assisted-service/blob/d37ac44051be76e95676f33b8361c04eae290357/internal/host/hostcommands/install_cmd.go#L232"&gt;assisted-service source code&lt;/a&gt; for details.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="openshift-installation"&gt;
&lt;h3&gt;OpenShift Installation&lt;/h3&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/installing_on_a_single_node/install-sno-installing-sno"&gt;https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/installing_on_a_single_node/install-sno-installing-sno&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;You can use the OpenShift web UI installer in Red Hat Hybrid Cloud Console.
This guides you through installation with the Assisted Installer service:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://console.redhat.com/openshift/assisted-installer/clusters"&gt;https://console.redhat.com/openshift/assisted-installer/clusters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This also provides an automated way to install multiple Operators from Day 0.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Relevant Operators for this setup:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Logical Volume Manager Storage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NMState&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node Feature Discovery&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NVIDIA GPU&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OpenShift Virtualization&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;p&gt;After backing up existing file systems and removing bootable partitions, proceed with the
OpenShift Single Node installation.&lt;/p&gt;
&lt;p&gt;CoreOS requires an entire disk for installation:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;500GB SSD for the OpenShift operating system&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Two 2TB NVMe disks for persistent volumes as LVM Physical volumes in the same Volume Group&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This setup enables flexible VM storage management while keeping the system installation separate&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nv"&gt;OCP_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;latest-4.10
&lt;span class="linenos"&gt; 4&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-k&lt;span class="w"&gt; &lt;/span&gt;https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/openshift-client-linux.tar.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;oc.tar.gz
&lt;span class="linenos"&gt; 6&lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;zxf&lt;span class="w"&gt; &lt;/span&gt;oc.tar.gz
&lt;span class="linenos"&gt; 7&lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;~/.local/bin/
&lt;span class="linenos"&gt; 8&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-k&lt;span class="w"&gt; &lt;/span&gt;https://mirror.openshift.com/pub/openshift-v4/clients/ocp/&lt;span class="nv"&gt;$OCP_VERSION&lt;/span&gt;/openshift-install-linux.tar.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;openshift-install-linux.tar.gz
&lt;span class="linenos"&gt;10&lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;zxvf&lt;span class="w"&gt; &lt;/span&gt;openshift-install-linux.tar.gz
&lt;span class="linenos"&gt;11&lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;openshift-install&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;openshift-install&lt;span class="w"&gt; &lt;/span&gt;~/.local/bin/
&lt;span class="linenos"&gt;12&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;openshift-install&lt;span class="w"&gt; &lt;/span&gt;coreos&lt;span class="w"&gt; &lt;/span&gt;print-stream-json&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;location&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;x86_64&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;iso&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cut&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f4&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;rhcos-live.x86_64.iso
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id1"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;install-config.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="c1"&gt;# This file contains the configuration for an OpenShift cluster installation.&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="c1"&gt;# The base domain for the cluster.&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="nt"&gt;baseDomain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;epheo.eu&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="c1"&gt;# Configuration for the compute nodes.&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="nt"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;worker&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="c1"&gt;# Configuration for the control plane nodes.&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="nt"&gt;controlPlane&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;master&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="c1"&gt;# Metadata for the cluster.&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;da2&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="c1"&gt;# Networking configuration for the cluster.&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="nt"&gt;networking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;networkType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OVNKubernetes&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;clusterNetwork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cidr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10.128.0.0/14&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;hostPrefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;23&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;serviceNetwork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;172.30.0.0/16&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="c1"&gt;# Platform configuration for the cluster.&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;&lt;span class="nt"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;33&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;none&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt;34&lt;/span&gt;
&lt;span class="linenos"&gt;35&lt;/span&gt;&lt;span class="c1"&gt;# Configuration for bootstrapping the cluster.&lt;/span&gt;
&lt;span class="linenos"&gt;36&lt;/span&gt;&lt;span class="nt"&gt;bootstrapInPlace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;37&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;installationDisk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/sda&lt;/span&gt;
&lt;span class="linenos"&gt;38&lt;/span&gt;
&lt;span class="linenos"&gt;39&lt;/span&gt;&lt;span class="c1"&gt;# Pull secret for accessing the OpenShift registry.&lt;/span&gt;
&lt;span class="linenos"&gt;40&lt;/span&gt;&lt;span class="nt"&gt;pullSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'{"auths":{"cloud.openshift.com":{"auth":"XXXXXXXX"}}}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="linenos"&gt;41&lt;/span&gt;
&lt;span class="linenos"&gt;42&lt;/span&gt;&lt;span class="c1"&gt;# SSH key for accessing the cluster nodes.&lt;/span&gt;
&lt;span class="linenos"&gt;43&lt;/span&gt;&lt;span class="nt"&gt;sshKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="linenos"&gt;44&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="no"&gt;ssh-rsa AAAAB3XXXXXXXXXXXXXXXXXXXXXXXXX&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id2"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Generate OpenShift Container Platform assets&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;ocp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;install-config.yaml&lt;span class="w"&gt; &lt;/span&gt;ocp
openshift-install&lt;span class="w"&gt; &lt;/span&gt;--dir&lt;span class="o"&gt;=&lt;/span&gt;ocp&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;single-node-ignition-config
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id3"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Embed the ignition data into the RHCOS ISO:&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;coreos-installer&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'podman run --privileged --rm \&lt;/span&gt;
&lt;span class="s1"&gt;      -v /dev:/dev -v /run/udev:/run/udev -v $PWD:/data \&lt;/span&gt;
&lt;span class="s1"&gt;      -w /data quay.io/coreos/coreos-installer:release'&lt;/span&gt;
cp&lt;span class="w"&gt; &lt;/span&gt;ocp/bootstrap-in-place-for-live-iso.ign&lt;span class="w"&gt; &lt;/span&gt;iso.ign
coreos-installer&lt;span class="w"&gt; &lt;/span&gt;iso&lt;span class="w"&gt; &lt;/span&gt;ignition&lt;span class="w"&gt; &lt;/span&gt;embed&lt;span class="w"&gt; &lt;/span&gt;-fi&lt;span class="w"&gt; &lt;/span&gt;iso.ign&lt;span class="w"&gt; &lt;/span&gt;rhcos-live.x86_64.iso
dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;discovery_image_sno.iso&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/usbkey&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After copying the ISO to a USB drive, boot your workstation from it to install OpenShift.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="installing-cnv-operator"&gt;
&lt;h3&gt;Installing CNV Operator&lt;/h3&gt;
&lt;p&gt;Enable Intel VT or AMD-V hardware virtualization extensions in your BIOS/UEFI settings.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/virtualization/installing"&gt;https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/virtualization/installing&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id4"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;cnv-resources.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="c1"&gt;# This YAML file contains Kubernetes resources for installing the KubeVirt Hyperconverged Operator (HCO) on the OpenShift Container Platform.&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="c1"&gt;# It creates a namespace named "openshift-cnv", an operator group named "kubevirt-hyperconverged-group" in the "openshift-cnv" namespace, and a subscription named "hco-operatorhub" in the "openshift-cnv" namespace.&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="c1"&gt;# The subscription specifies the source, source namespace, name, starting CSV, and channel for the KubeVirt Hyperconverged Operator.&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Namespace&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openshift-cnv&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;operators.coreos.com/v1&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OperatorGroup&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubevirt-hyperconverged-group&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openshift-cnv&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;targetNamespaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openshift-cnv&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;operators.coreos.com/v1alpha1&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Subscription&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;hco-operatorhub&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openshift-cnv&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redhat-operators&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;sourceNamespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openshift-marketplace&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubevirt-hyperconverged&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;startingCSV&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubevirt-hyperconverged-operator.v4.10.0&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"stable"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;cnv-resources.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id5"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Installing Virtctl client on your desktop&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;subscription-manager&lt;span class="w"&gt; &lt;/span&gt;repos&lt;span class="w"&gt; &lt;/span&gt;--enable&lt;span class="w"&gt; &lt;/span&gt;cnv-4.10-for-rhel-8-x86_64-rpms
dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;kubevirt-virtctl
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="configuring-openshift-for-gpu-passthrough"&gt;
&lt;h2&gt;Configuring OpenShift for GPU Passthrough&lt;/h2&gt;
&lt;p&gt;Since we’re working with a single GPU, additional configuration is required.&lt;/p&gt;
&lt;p&gt;We’ll use MachineConfig to configure our node. In a single-node OpenShift setup,
all MachineConfig changes apply to the master machineset. In multi-node clusters,
these would apply to workers instead.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openshift/machine-config-operator/blob/master/docs/SingleNodeOpenShift.md"&gt;https://github.com/openshift/machine-config-operator/blob/master/docs/SingleNodeOpenShift.md&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;section id="setting-kernel-boot-arguments"&gt;
&lt;h3&gt;Setting Kernel Boot Arguments&lt;/h3&gt;
&lt;p&gt;To enable GPU passthrough, we need to pass several kernel arguments at boot time via the MachineConfigOperator:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;amd_iommu=on&lt;/strong&gt;: Enables IOMMU support for AMD platforms (use intel_iommu=on for Intel CPUs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;vga=off&lt;/strong&gt;: Disables VGA console output during boot&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;rdblaclist=nouveau&lt;/strong&gt;: Blacklists the Nouveau open-source NVIDIA driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;video=efifb:off&lt;/strong&gt;: Disables EFI framebuffer console output&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.reddit.com/r/VFIO/comments/cktnhv/bar_0_cant_reserve/"&gt;https://www.reddit.com/r/VFIO/comments/cktnhv/bar_0_cant_reserve/&lt;/a&gt;
&lt;a class="reference external" href="https://www.reddit.com/r/VFIO/comments/mx5td8/bar_3_cant_reserve_mem_0xc00000000xc1ffffff_64bit/"&gt;https://www.reddit.com/r/VFIO/comments/mx5td8/bar_3_cant_reserve_mem_0xc00000000xc1ffffff_64bit/&lt;/a&gt;
&lt;a class="reference external" href="https://docs.kernel.org/fb/fbcon.html"&gt;https://docs.kernel.org/fb/fbcon.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id6"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;Setting Kernel Arguments at boot time.&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openshift&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;4.10.0&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;100-vfio&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;machineconfiguration.openshift.io/role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;master&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="nt"&gt;openshift&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;kernel_arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;amd_iommu=on&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vga=off&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;rdblaclist=nouveau&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'video=efifb:off'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt;1&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;articles/openshift-workstation/machineconfig/build
&lt;span class="linenos"&gt;2&lt;/span&gt;butane&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;vfio-prepare.bu&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;../vfio-prepare.yaml
&lt;span class="linenos"&gt;3&lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;patch&lt;span class="w"&gt; &lt;/span&gt;MachineConfig&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;-vfio&lt;span class="w"&gt; &lt;/span&gt;--type&lt;span class="o"&gt;=&lt;/span&gt;merge&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;../vfio-prepare.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Intel CPU users: use intel_iommu=on instead of amd_iommu=on.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="installing-the-nvidia-gpu-operator"&gt;
&lt;h3&gt;Installing the NVIDIA GPU Operator&lt;/h3&gt;
&lt;p&gt;The NVIDIA GPU Operator simplifies GPU management in Kubernetes environments.&lt;/p&gt;
&lt;section id="step-1-install-the-operator"&gt;
&lt;h4&gt;Step 1: Install the Operator&lt;/h4&gt;
&lt;p&gt;Via OpenShift web console:
1. Go to &lt;strong&gt;Operators&lt;/strong&gt; → &lt;strong&gt;OperatorHub&lt;/strong&gt;
2. Search for “NVIDIA GPU Operator”
3. Select the operator and click &lt;strong&gt;Install&lt;/strong&gt;
4. Keep default settings and click &lt;strong&gt;Install&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Or via CLI:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;https://raw.githubusercontent.com/NVIDIA/gpu-operator/master/deployments/git/operator-namespace.yaml
oc&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;https://raw.githubusercontent.com/NVIDIA/gpu-operator/master/deployments/git/operator-source.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="step-2-configure-the-clusterpolicy"&gt;
&lt;h4&gt;Step 2: Configure the ClusterPolicy&lt;/h4&gt;
&lt;p&gt;Set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sandboxWorkloads.enabled&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt; to enable the components needed for GPU passthrough:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id7"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;sandboxWorkloadsEnabled.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt;1&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ClusterPolicy&lt;/span&gt;
&lt;span class="linenos"&gt;2&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;gpu-cluster-policy&lt;/span&gt;
&lt;span class="linenos"&gt;4&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;sandboxWorkloads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;defaultWorkload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;container&lt;/span&gt;
&lt;span class="linenos"&gt;7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;patch&lt;span class="w"&gt; &lt;/span&gt;ClusterPolicy&lt;span class="w"&gt; &lt;/span&gt;gpu-cluster-policy&lt;span class="w"&gt; &lt;/span&gt;--type&lt;span class="o"&gt;=&lt;/span&gt;merge&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;sandboxWorkloadsEnabled.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The NVIDIA GPU Operator doesn’t officially support consumer-grade GPUs and won’t automatically
bind the GPU audio device to the vfio-pci driver. We’ll handle this manually with the following
machine config:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id8"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;vfio-prepare.bu&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openshift&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;4.10.0&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;100-vfio&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;machineconfiguration.openshift.io/role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;master&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/usr/local/bin/vfio-prepare&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;0755&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;overwrite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;local&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./vfio-prepare.sh&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/modules-load.d/vfio-pci.conf&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;0644&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;overwrite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vfio-pci&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="nt"&gt;systemd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vfioprepare.service&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;[Unit]&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;Description=Prepare vfio devices&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;After=ignition-firstboot-complete.service&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;Before=kubelet.service crio.service&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;[Service]&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;Type=oneshot&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;ExecStart=/usr/local/bin/vfio-prepare&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;
&lt;span class="linenos"&gt;33&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;[Install]&lt;/span&gt;
&lt;span class="linenos"&gt;34&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;WantedBy=kubelet.service&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id9"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;vfio-prepare.sh&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;vfio_attach&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/driver/unbind"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/driver/unbind
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vfio-pci&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/driver_override
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/bus/pci/drivers/vfio-pci/bind&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/bus/pci/drivers/vfio-pci/new_id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="c1"&gt;# 0a:00.1 Audio device [0403]: NVIDIA Corporation GA102 High Definition Audio Controller [10de:1aef] (rev a1)&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0000&lt;/span&gt;:0a:00.1
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/sys/bus/pci/devices/0000&lt;span class="se"&gt;\:&lt;/span&gt;0a&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;.1
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"10de 1467"&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;vfio_attach
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt;1&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;articles/openshift-workstation/machineconfig/build
&lt;span class="linenos"&gt;2&lt;/span&gt;butane&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;vfio-prepare.bu&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;../vfio-prepare.yaml
&lt;span class="linenos"&gt;3&lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;patch&lt;span class="w"&gt; &lt;/span&gt;MachineConfig&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;-vfio&lt;span class="w"&gt; &lt;/span&gt;--type&lt;span class="o"&gt;=&lt;/span&gt;merge&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;../vfio-prepare.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dynamically-switching-gpu-drivers"&gt;
&lt;h3&gt;Dynamically Switching GPU Drivers&lt;/h3&gt;
&lt;p&gt;A key advantage of this setup is using a single GPU for both container workloads and VMs
without rebooting.&lt;/p&gt;
&lt;section id="use-case-scenario"&gt;
&lt;h4&gt;Use Case Scenario&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Single NVIDIA GPU shared between container workloads and VMs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Container workloads require the NVIDIA kernel driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;VMs with GPU passthrough require the VFIO-PCI driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Switching between modes without rebooting&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="driver-switching-using-node-labels"&gt;
&lt;h4&gt;Driver Switching Using Node Labels&lt;/h4&gt;
&lt;p&gt;The NVIDIA GPU Operator with sandbox workloads enabled lets you switch driver bindings using node labels:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For container workloads (NVIDIA driver):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Replace 'da2' with your node name&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;label&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="w"&gt; &lt;/span&gt;da2&lt;span class="w"&gt; &lt;/span&gt;--overwrite&lt;span class="w"&gt; &lt;/span&gt;nvidia.com/gpu.workload.config&lt;span class="o"&gt;=&lt;/span&gt;container
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;For VM passthrough (VFIO-PCI driver):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Replace 'da2' with your node name&lt;/span&gt;
oc&lt;span class="w"&gt; &lt;/span&gt;label&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="w"&gt; &lt;/span&gt;da2&lt;span class="w"&gt; &lt;/span&gt;--overwrite&lt;span class="w"&gt; &lt;/span&gt;nvidia.com/gpu.workload.config&lt;span class="o"&gt;=&lt;/span&gt;vm-passthrough
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="notes-on-driver-switching"&gt;
&lt;h4&gt;Notes on Driver Switching&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Driver switching takes a few minutes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify current driver with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;lspci&lt;/span&gt; &lt;span class="pre"&gt;-nnk&lt;/span&gt; &lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;grep&lt;/span&gt; &lt;span class="pre"&gt;-A3&lt;/span&gt; &lt;span class="pre"&gt;NVIDIA&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stop all GPU workloads before switching drivers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No reboot is usually required&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can be occasionally unreliable and may require a reboot&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adding-gpu-as-a-hardware-device"&gt;
&lt;h3&gt;Adding GPU as a Hardware Device&lt;/h3&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/kubevirt/kubevirt/blob/main/docs/devel/host-devices-and-device-plugins.md"&gt;https://github.com/kubevirt/kubevirt/blob/main/docs/devel/host-devices-and-device-plugins.md&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;First, identify the GPU’s Vendor and Product ID:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;lspci&lt;span class="w"&gt; &lt;/span&gt;-nnk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;VGA
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then, identify the device name provided by gpu-feature-discovery:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;nodes&lt;span class="w"&gt; &lt;/span&gt;da2&lt;span class="w"&gt; &lt;/span&gt;-ojson&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;jq&lt;span class="w"&gt; &lt;/span&gt;.status.capacity&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;nvidia
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now, add the GPU to the permitted host devices:&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;HyperConverged&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubevirt-hyperconverged&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openshift-cnv&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;permittedHostDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;pciHostDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;externalResourceProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;pciDeviceSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10DE:2206&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;resourceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nvidia.com/GA102_GEFORCE_RTX_3080&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;patch&lt;span class="w"&gt; &lt;/span&gt;hyperconverged&lt;span class="w"&gt; &lt;/span&gt;kubevirt-hyperconverged&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openshift-cnv&lt;span class="w"&gt; &lt;/span&gt;--type&lt;span class="o"&gt;=&lt;/span&gt;merge&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;hyperconverged.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;cite&gt;pciDeviceSelector&lt;/cite&gt; specifies the vendor:device ID, while &lt;cite&gt;resourceName&lt;/cite&gt; specifies the resource
name in Kubernetes/OpenShift.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="passthrough-usb-controllers-to-vms"&gt;
&lt;h2&gt;Passthrough USB Controllers to VMs&lt;/h2&gt;
&lt;p&gt;For a complete desktop experience, you’ll want to pass through an entire USB controller to
your VM for better performance and flexibility.&lt;/p&gt;
&lt;section id="identifying-a-suitable-usb-controller"&gt;
&lt;h3&gt;Identifying a Suitable USB Controller&lt;/h3&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html-single/virtualization/index#virt-configuring-pci-passthrough"&gt;https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html-single/virtualization/index#virt-configuring-pci-passthrough&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;List all USB controllers:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;lspci&lt;span class="w"&gt; &lt;/span&gt;-nnk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;usb
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example output:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;0b:00.3 USB controller [0c03]: Advanced Micro Devices, Inc. [AMD] Matisse USB 3.0 Host Controller [1022:149c]
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Note the PCI address (e.g., &lt;cite&gt;0b:00.3&lt;/cite&gt;) and device ID (&lt;cite&gt;1022:149c&lt;/cite&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the IOMMU group:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;find&lt;span class="w"&gt; &lt;/span&gt;/sys/kernel/iommu_groups/&lt;span class="w"&gt; &lt;/span&gt;-iname&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*0b:00.3*"&lt;/span&gt;
&lt;span class="c1"&gt;# Shows which IOMMU group contains this device&lt;/span&gt;

ls&lt;span class="w"&gt; &lt;/span&gt;/sys/kernel/iommu_groups/27/devices/
&lt;span class="c1"&gt;# Lists all devices in the same IOMMU group&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: For clean passthrough, the USB controller should ideally be alone in its IOMMU group.
If other devices share the group, you’ll need to pass those through as well.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="adding-the-usb-controller-as-a-permitted-device"&gt;
&lt;h3&gt;Adding the USB Controller as a Permitted Device&lt;/h3&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://access.redhat.com/solutions/6250271"&gt;https://access.redhat.com/solutions/6250271&lt;/a&gt;
&lt;a class="reference external" href="https://kubevirt.io/user-guide/virtual_machines/host-devices/#listing-permitted-devices"&gt;https://kubevirt.io/user-guide/virtual_machines/host-devices/#listing-permitted-devices&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Add the controller’s Vendor and Product IDs to permitted host devices:&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;HyperConverged&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubevirt-hyperconverged&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openshift-cnv&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;permittedHostDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;pciHostDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pciDeviceSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1022:149C&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;resourceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;devices.kubevirt.io/USB3_Controller&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pciDeviceSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;8086:2723&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;resourceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;intel.com/WIFI_Controller&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;patch&lt;span class="w"&gt; &lt;/span&gt;hyperconverged&lt;span class="w"&gt; &lt;/span&gt;kubevirt-hyperconverged&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;openshift-cnv&lt;span class="w"&gt; &lt;/span&gt;--type&lt;span class="o"&gt;=&lt;/span&gt;merge&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;hyperconverged.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="binding-the-usb-controller-to-vfio-pci-driver"&gt;
&lt;h3&gt;Binding the USB Controller to VFIO-PCI Driver&lt;/h3&gt;
&lt;div class="literal-block-wrapper docutils container" id="id10"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;vfio-prepare.bu&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openshift&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;4.10.0&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;100-vfio&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;machineconfiguration.openshift.io/role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;master&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/usr/local/bin/vfio-prepare&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;0755&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;overwrite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;local&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./vfio-prepare.sh&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/modules-load.d/vfio-pci.conf&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;0644&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;overwrite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vfio-pci&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/modprobe.d/vfio.conf&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;0644&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;overwrite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;options vfio-pci ids=8086:2723,1022:149c&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="nt"&gt;systemd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vfioprepare.service&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;[Unit]&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;Description=Prepare vfio devices&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;After=ignition-firstboot-complete.service&lt;/span&gt;
&lt;span class="linenos"&gt;33&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;Before=kubelet.service crio.service&lt;/span&gt;
&lt;span class="linenos"&gt;34&lt;/span&gt;
&lt;span class="linenos"&gt;35&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;[Service]&lt;/span&gt;
&lt;span class="linenos"&gt;36&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;Type=oneshot&lt;/span&gt;
&lt;span class="linenos"&gt;37&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;ExecStart=/usr/local/bin/vfio-prepare&lt;/span&gt;
&lt;span class="linenos"&gt;38&lt;/span&gt;
&lt;span class="linenos"&gt;39&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;[Install]&lt;/span&gt;
&lt;span class="linenos"&gt;40&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="no"&gt;WantedBy=kubelet.service&lt;/span&gt;
&lt;span class="linenos"&gt;41&lt;/span&gt;&lt;span class="nt"&gt;openshift&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;42&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;kernel_arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;43&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;amd_iommu=on&lt;/span&gt;
&lt;span class="linenos"&gt;44&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vga=off&lt;/span&gt;
&lt;span class="linenos"&gt;45&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;rdblaclist=nouveau&lt;/span&gt;
&lt;span class="linenos"&gt;46&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'video=efifb:off'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Create a script to unbind the USB controller from its current driver and bind it to vfio-pci:&lt;/p&gt;
&lt;div class="literal-block-wrapper docutils container" id="id11"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;vfio-prepare.sh&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;vfio_attach&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/driver/unbind"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/driver/unbind
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vfio-pci&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/driver_override
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/bus/pci/drivers/vfio-pci/bind&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/bus/pci/drivers/vfio-pci/new_id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="c1"&gt;# 0a:00.1 Audio device [0403]: NVIDIA Corporation GA102 High Definition Audio Controller [10de:1aef] (rev a1)&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0000&lt;/span&gt;:0a:00.1
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/sys/bus/pci/devices/0000&lt;span class="se"&gt;\:&lt;/span&gt;0a&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;.1
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"10de 1467"&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;vfio_attach
&lt;span class="linenos"&gt;17&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="c1"&gt;# Bind "useless" device to vfio-pci to satisfy IOMMU group&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0000&lt;/span&gt;:07:00.0
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/sys/bus/pci/devices/0000&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="m"&gt;07&lt;/span&gt;&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;.0
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1043 87c0"&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;vfio_attach
&lt;span class="linenos"&gt;23&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="c1"&gt;# Unbind USB switch and handle via vfio-pci kernel driver&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0000&lt;/span&gt;:07:00.1
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/sys/bus/pci/devices/0000&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="m"&gt;07&lt;/span&gt;&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;.1
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1043 87c0"&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;vfio_attach
&lt;span class="linenos"&gt;29&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;&lt;span class="c1"&gt;# Unbind USB switch and handle via vfio-pci kernel driver&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0000&lt;/span&gt;:07:00.3
&lt;span class="linenos"&gt;32&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/sys/bus/pci/devices/0000&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="m"&gt;07&lt;/span&gt;&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;.3
&lt;span class="linenos"&gt;33&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1022 149c"&lt;/span&gt;
&lt;span class="linenos"&gt;34&lt;/span&gt;vfio_attach
&lt;span class="linenos"&gt;35&lt;/span&gt;
&lt;span class="linenos"&gt;36&lt;/span&gt;&lt;span class="c1"&gt;# Unbind USB switch and handle via vfio-pci kernel driver&lt;/span&gt;
&lt;span class="linenos"&gt;37&lt;/span&gt;&lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0000&lt;/span&gt;:0c:00.3
&lt;span class="linenos"&gt;38&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/sys/bus/pci/devices/0000&lt;span class="se"&gt;\:&lt;/span&gt;0c&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;.3
&lt;span class="linenos"&gt;39&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1022 148c"&lt;/span&gt;
&lt;span class="linenos"&gt;40&lt;/span&gt;vfio_attach
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt;1&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;articles/openshift-workstation/machineconfig/build
&lt;span class="linenos"&gt;2&lt;/span&gt;butane&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;vfio-prepare.bu&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;../vfio-prepare.yaml
&lt;span class="linenos"&gt;3&lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;patch&lt;span class="w"&gt; &lt;/span&gt;MachineConfig&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;-vfio&lt;span class="w"&gt; &lt;/span&gt;--type&lt;span class="o"&gt;=&lt;/span&gt;merge&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;../vfio-prepare.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="creating-vms-with-gpu-passthrough"&gt;
&lt;h2&gt;Creating VMs with GPU Passthrough&lt;/h2&gt;
&lt;p&gt;This section explains how to create VMs that can use GPU passthrough, using existing
LVM Logical Volumes with UEFI boot.&lt;/p&gt;
&lt;section id="creating-persistent-volumes-from-lvm-disks"&gt;
&lt;h3&gt;Creating Persistent Volumes from LVM Disks&lt;/h3&gt;
&lt;p&gt;First, make LVM volumes available to OpenShift via Persistent Volume Claims (PVCs).
This assumes you have the Local Storage Operator installed.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/storage/configuring-persistent-storage#lvms-installing-lvms-with-web-console_logical-volume-manager-storage"&gt;https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/storage/configuring-persistent-storage#lvms-installing-lvms-with-web-console_logical-volume-manager-storage&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Create a YAML file for each VM disk:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="literal-block-wrapper docutils container" id="id12"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;fedora_pvc.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PersistentVolumeClaim&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;fedora35&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;accessModes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ReadWriteOnce&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;volumeMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Block&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;100Gi&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;storageClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;lvms-vg1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Apply the YAML:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;fedora35.yaml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;Verify the PV and PVC are bound:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pv
oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pvc&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;your-namespace&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="defining-vms-with-gpu-passthrough"&gt;
&lt;h3&gt;Defining VMs with GPU Passthrough&lt;/h3&gt;
&lt;p&gt;Key configuration elements for desktop VMs with GPU passthrough:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GPU Passthrough&lt;/strong&gt;: Pass the entire physical GPU to the VM&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://kubevirt.io/user-guide/virtual_machines/host-devices/#pci-passthrough"&gt;https://kubevirt.io/user-guide/virtual_machines/host-devices/#pci-passthrough&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Disable Virtual VGA&lt;/strong&gt;: Remove the emulated VGA device&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://kubevirt.io/api-reference/master/definitions.html#_v1_devices"&gt;https://kubevirt.io/api-reference/master/definitions.html#_v1_devices&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;USB Controller Passthrough&lt;/strong&gt;: For connecting peripherals directly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UEFI Boot&lt;/strong&gt;: For compatibility with modern OSes and GPU drivers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CPU/Memory Configuration&lt;/strong&gt;: Based on workload requirements&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="literal-block-wrapper docutils container" id="id13"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;fedora.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubevirt.io/v1&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;VirtualMachine&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;fedora&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;epheo&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;runStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Halted&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;kubevirt.io/domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;fedora&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;architecture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;amd64&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;8&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;host-passthrough&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;sockets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;2&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;acpi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;smm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;firmware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;bootloader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;efi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;secureBoot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# For Nvidia Driver...&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;disks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bootOrder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;virtio&lt;/span&gt;
&lt;span class="linenos"&gt;33&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pvdisk&lt;/span&gt;
&lt;span class="linenos"&gt;34&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;35&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;virtio&lt;/span&gt;
&lt;span class="linenos"&gt;36&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cloudinitdisk&lt;/span&gt;
&lt;span class="linenos"&gt;37&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;autoattachGraphicsDevice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;
&lt;span class="linenos"&gt;38&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;gpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;39&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nvidia.com/GA102_GEFORCE_RTX_3080&lt;/span&gt;
&lt;span class="linenos"&gt;40&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;gpuvideo&lt;/span&gt;
&lt;span class="linenos"&gt;41&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;hostDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;42&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;devices.kubevirt.io/USB3_Controller&lt;/span&gt;
&lt;span class="linenos"&gt;43&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;usbcontroller&lt;/span&gt;
&lt;span class="linenos"&gt;44&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;devices.kubevirt.io/USB3_Controller&lt;/span&gt;
&lt;span class="linenos"&gt;45&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;usbcontroller2&lt;/span&gt;
&lt;span class="linenos"&gt;46&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;intel.com/WIFI_Controller&lt;/span&gt;
&lt;span class="linenos"&gt;47&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wificontroller&lt;/span&gt;
&lt;span class="linenos"&gt;48&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;49&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;masquerade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt;50&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default&lt;/span&gt;
&lt;span class="linenos"&gt;51&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bridge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt;52&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;virtio&lt;/span&gt;
&lt;span class="linenos"&gt;53&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nic-0&lt;/span&gt;
&lt;span class="linenos"&gt;54&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;networkInterfaceMultiqueue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt;55&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;rng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt;56&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;machine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;57&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;q35&lt;/span&gt;
&lt;span class="linenos"&gt;58&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;59&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;60&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;16G&lt;/span&gt;
&lt;span class="linenos"&gt;61&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;fedora&lt;/span&gt;
&lt;span class="linenos"&gt;62&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;63&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default&lt;/span&gt;
&lt;span class="linenos"&gt;64&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;pod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt;65&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;multus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;66&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;networkName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;br1&lt;/span&gt;
&lt;span class="linenos"&gt;67&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nic-0&lt;/span&gt;
&lt;span class="linenos"&gt;68&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;terminationGracePeriodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;0&lt;/span&gt;
&lt;span class="linenos"&gt;69&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;70&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;71&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'fedora35'&lt;/span&gt;
&lt;span class="linenos"&gt;72&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pvdisk&lt;/span&gt;
&lt;span class="linenos"&gt;73&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cloudInitNoCloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;74&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|-&lt;/span&gt;
&lt;span class="linenos"&gt;75&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="no"&gt;#cloud-config&lt;/span&gt;
&lt;span class="linenos"&gt;76&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="no"&gt;password: fedora&lt;/span&gt;
&lt;span class="linenos"&gt;77&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="no"&gt;chpasswd: { expire: False }&lt;/span&gt;
&lt;span class="linenos"&gt;78&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cloudinitdisk&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="literal-block-wrapper docutils container" id="id14"&gt;
&lt;div class="code-block-caption"&gt;&lt;span class="caption-text"&gt;windows.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt;  1&lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kubevirt.io/v1&lt;/span&gt;
&lt;span class="linenos"&gt;  2&lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;VirtualMachine&lt;/span&gt;
&lt;span class="linenos"&gt;  3&lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;  4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;  5&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;vm.kubevirt.io/os&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows10&lt;/span&gt;
&lt;span class="linenos"&gt;  6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;vm.kubevirt.io/workload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;desktop&lt;/span&gt;
&lt;span class="linenos"&gt;  7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows&lt;/span&gt;
&lt;span class="linenos"&gt;  8&lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;  9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;runStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Manual&lt;/span&gt;
&lt;span class="linenos"&gt; 10&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 11&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 12&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 13&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;kubevirt.io/domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows&lt;/span&gt;
&lt;span class="linenos"&gt; 14&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 15&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;architecture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;amd64&lt;/span&gt;
&lt;span class="linenos"&gt; 16&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 17&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;clock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 18&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 19&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;hpet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 20&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;present&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;
&lt;span class="linenos"&gt; 21&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;hyperv&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 22&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;pit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 23&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;tickPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;delay&lt;/span&gt;
&lt;span class="linenos"&gt; 24&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;rtc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 25&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;tickPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;catchup&lt;/span&gt;
&lt;span class="linenos"&gt; 26&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 27&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 28&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;8&lt;/span&gt;
&lt;span class="linenos"&gt; 29&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;dedicatedCpuPlacement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt; 30&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;sockets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;2&lt;/span&gt;
&lt;span class="linenos"&gt; 31&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="linenos"&gt; 32&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 33&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;autoattachGraphicsDevice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;
&lt;span class="linenos"&gt; 34&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;disks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 35&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cdrom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 36&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sata&lt;/span&gt;
&lt;span class="linenos"&gt; 37&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-guest-tools&lt;/span&gt;
&lt;span class="linenos"&gt; 38&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bootOrder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="linenos"&gt; 39&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 40&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;virtio&lt;/span&gt;
&lt;span class="linenos"&gt; 41&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pvdisk&lt;/span&gt;
&lt;span class="linenos"&gt; 42&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 43&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;virtio&lt;/span&gt;
&lt;span class="linenos"&gt; 44&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pvdisk1&lt;/span&gt;
&lt;span class="linenos"&gt; 45&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;gpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 46&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nvidia.com/GA102_GEFORCE_RTX_3080&lt;/span&gt;
&lt;span class="linenos"&gt; 47&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;gpuvideo&lt;/span&gt;
&lt;span class="linenos"&gt; 48&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;hostDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 49&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;devices.kubevirt.io/USB3_Controller&lt;/span&gt;
&lt;span class="linenos"&gt; 50&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;usbcontroller&lt;/span&gt;
&lt;span class="linenos"&gt; 51&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;devices.kubevirt.io/USB3_Controller&lt;/span&gt;
&lt;span class="linenos"&gt; 52&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;usbcontroller2&lt;/span&gt;
&lt;span class="linenos"&gt; 53&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;intel.com/WIFI_Controller&lt;/span&gt;
&lt;span class="linenos"&gt; 54&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wificontroller&lt;/span&gt;
&lt;span class="linenos"&gt; 55&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 56&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bridge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 57&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;virtio&lt;/span&gt;
&lt;span class="linenos"&gt; 58&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nic-0&lt;/span&gt;
&lt;span class="linenos"&gt; 59&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;networkInterfaceMultiqueue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt; 60&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;rng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 61&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;tpm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 62&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 63&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;acpi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 64&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;apic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 65&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;hyperv&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 66&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;frequencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 67&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;ipi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 68&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;reenlightenment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 69&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;relaxed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 70&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 71&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 72&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;spinlocks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 73&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;spinlocks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;8191&lt;/span&gt;
&lt;span class="linenos"&gt; 74&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;synic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 75&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;synictimer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 76&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;direct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 77&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;tlbflush&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 78&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;vapic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 79&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;vpindex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 80&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;smm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 81&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;firmware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 82&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;bootloader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 83&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;efi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 84&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;secureBoot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="linenos"&gt; 85&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;machine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 86&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;q35&lt;/span&gt;
&lt;span class="linenos"&gt; 87&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 88&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;hugepages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 89&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1Gi&lt;/span&gt;
&lt;span class="linenos"&gt; 90&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 91&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 92&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;32Gi&lt;/span&gt;
&lt;span class="linenos"&gt; 93&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;evictionStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;None&lt;/span&gt;
&lt;span class="linenos"&gt; 94&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows&lt;/span&gt;
&lt;span class="linenos"&gt; 95&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 96&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;multus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 97&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;networkName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;br1&lt;/span&gt;
&lt;span class="linenos"&gt; 98&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nic-0&lt;/span&gt;
&lt;span class="linenos"&gt; 99&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;terminationGracePeriodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;3600&lt;/span&gt;
&lt;span class="linenos"&gt;100&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;101&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containerDisk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;102&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;registry.redhat.io/container-native-virtualization/virtio-win-rhel9@sha256:0c536c7aba76eb9c1e75a8f2dc2bbfa017e90314d55b242599ea41f42ba4434f&lt;/span&gt;
&lt;span class="linenos"&gt;103&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows-guest-tools&lt;/span&gt;
&lt;span class="linenos"&gt;104&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pvdisk&lt;/span&gt;
&lt;span class="linenos"&gt;105&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;106&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows&lt;/span&gt;
&lt;span class="linenos"&gt;107&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pvdisk1&lt;/span&gt;
&lt;span class="linenos"&gt;108&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;109&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windowsdata&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="future-improvements"&gt;
&lt;h2&gt;Future Improvements&lt;/h2&gt;
&lt;p&gt;Some potential future improvements to this setup:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Using MicroShift instead of OpenShift to reduce Control Plane footprint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Running Linux Desktop in containers instead of VMs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementing more efficient resource allocation with CPU pinning and huge pages&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="troubleshooting"&gt;
&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;section id="iommu-group-issues"&gt;
&lt;h3&gt;IOMMU Group Issues&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt;
VM fails to start with:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"component"&lt;/span&gt;:&lt;span class="s2"&gt;"virt-launcher"&lt;/span&gt;,&lt;span class="s2"&gt;"level"&lt;/span&gt;:&lt;span class="s2"&gt;"error"&lt;/span&gt;,&lt;span class="s2"&gt;"msg"&lt;/span&gt;:&lt;span class="s2"&gt;"Failed to start VirtualMachineInstance"&lt;/span&gt;,
&lt;span class="s2"&gt;"reason"&lt;/span&gt;:&lt;span class="s2"&gt;"virError... vfio 0000:07:00.1: group 19 is not viable&lt;/span&gt;
&lt;span class="s2"&gt;Please ensure all devices within the iommu_group are bound to their vfio bus driver."&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Diagnosis:&lt;/strong&gt;
Not all devices in the IOMMU group are bound to vfio-pci. Check:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Check devices in the IOMMU group&lt;/span&gt;
ls&lt;span class="w"&gt; &lt;/span&gt;/sys/kernel/iommu_groups/19/devices/

&lt;span class="c1"&gt;# Check what these devices are&lt;/span&gt;
lspci&lt;span class="w"&gt; &lt;/span&gt;-nnks&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;07&lt;/span&gt;:00.0
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;
Bind all devices in the IOMMU group to vfio-pci:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Add to vfio-prepare.sh&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vfio-pci"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/bus/pci/devices/0000:03:08.0/driver_override
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vfio-pci"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/bus/pci/devices/0000:07:00.0/driver_override
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vfio-pci"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/bus/pci/devices/0000:07:00.1/driver_override
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vfio-pci"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/bus/pci/devices/0000:07:00.3/driver_override

&lt;span class="c1"&gt;# Unbind from current drivers, then bind to vfio-pci&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="common-issues-and-solutions"&gt;
&lt;h3&gt;Common Issues and Solutions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;No display output after GPU passthrough:&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Disable virtual VGA in VM spec&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass through both GPU and audio device&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install proper GPU drivers inside VM&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Performance issues in Windows VM:&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Configure CPU pinning correctly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable huge pages for better memory performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install latest NVIDIA drivers in VM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disable Windows Game Bar and overlay software&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;GPU driver switching fails:&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Stop all GPU workloads before switching&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check GPU operator logs: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oc&lt;/span&gt; &lt;span class="pre"&gt;logs&lt;/span&gt; &lt;span class="pre"&gt;-n&lt;/span&gt; &lt;span class="pre"&gt;nvidia-gpu-operator&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;pod-name&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify IOMMU is enabled in BIOS/UEFI&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For further troubleshooting, check logs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;virt-handler: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oc&lt;/span&gt; &lt;span class="pre"&gt;logs&lt;/span&gt; &lt;span class="pre"&gt;-n&lt;/span&gt; &lt;span class="pre"&gt;openshift-cnv&lt;/span&gt; &lt;span class="pre"&gt;virt-handler-&amp;lt;hash&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;virt-launcher: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oc&lt;/span&gt; &lt;span class="pre"&gt;logs&lt;/span&gt; &lt;span class="pre"&gt;-n&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;namespace&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;virt-launcher-&amp;lt;vm-name&amp;gt;-&amp;lt;hash&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nvidia-driver-daemonset: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oc&lt;/span&gt; &lt;span class="pre"&gt;logs&lt;/span&gt; &lt;span class="pre"&gt;-n&lt;/span&gt; &lt;span class="pre"&gt;nvidia-gpu-operator&lt;/span&gt; &lt;span class="pre"&gt;nvidia-driver-daemonset-&amp;lt;hash&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Mon, 27 Feb 2023 00:00:00 </pubDate></item></channel></rss>