{"id":312,"date":"2025-03-12T17:01:51","date_gmt":"2025-03-12T16:01:51","guid":{"rendered":"https:\/\/blog.openshift.one\/?p=312"},"modified":"2025-05-20T15:55:38","modified_gmt":"2025-05-20T13:55:38","slug":"running-a-lightweight-openshift-virtualization-lab-with-truenas-core","status":"publish","type":"post","link":"https:\/\/blog.openshift.one\/index.php\/2025\/03\/12\/running-a-lightweight-openshift-virtualization-lab-with-truenas-core\/","title":{"rendered":"Running a Lightweight OpenShift Virtualization Lab with TrueNAS CORE"},"content":{"rendered":"\n<p>In my lab, I maintain a small, fully virtualized OpenShift environment to practice and demonstrate its capabilities &#8211; especially OpenShift Virtualization. A critical component of this setup is the storage backend. While Ceph-based OpenShift Data Foundation (ODF) is a great choice for OpenShift and OpenShift Virtualization, its resource requirements make it impractical for my ultra-small environment.<\/p>\n\n\n\n<p>To address this, I sought a lightweight and simple storage solution that would still allow me to showcase most of OpenShift Virtualization\u2019s advanced features. After discussing with colleagues (thanks Thibaut!), I realized that <strong>TrueNAS CORE<\/strong> &#8211; which I already use at home &#8211; could be a perfect fit! Even better, <strong>TrueNAS CORE can be integrated with Kubernetes and OpenShift<\/strong> using the <strong>CSI drivers<\/strong> from the democratic-csi project (<a href=\"https:\/\/github.com\/democratic-csi\/democratic-csi\">https:\/\/github.com\/democratic-csi\/democratic-csi<\/a>) and its easy-to-deploy Helm Charts (<a href=\"https:\/\/democratic-csi.github.io\/charts\/\">https:\/\/democratic-csi.github.io\/charts\/<\/a>).<\/p>\n\n\n\n<p>CSI (Container Storage Interface) drivers are used to integrate external storage solutions with the platform. They provide a standardized way for OpenShift to manage persistent storage across different storage backends. They allow to dynamically provision and manage persistent volumes (PVs), support native storage functions such like snapshots, expansions and cloning and work with various storage backends such like Ceph, NFS, iSCSI, FC, etc. <\/p>\n\n\n\n<p>The benefit of using<strong> iSCSI and NFS<\/strong> in this lab is their familiarity to those experienced with traditional virtualization environments. This makes them especially valuable when showcasing OpenShift Virtualization to those exploring alternatives following the VMware\/Broadcom changes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Important Considerations<\/h3>\n\n\n\n<p>Before you jump in, keep these two things in mind:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>This setup is purely for learning and experimentation.<\/strong> It is not suitable for any production-like use cases, as it lacks essential security measures such as encryption and authentication. Many shortcuts were taken to get it up and running quickly.<\/li>\n\n\n\n<li><strong>Neither TrueNAS CORE nor democratic-csi are officially certified or supported by Red Hat<\/strong> according to the <a href=\"https:\/\/catalog.redhat.com\/platform\/red-hat-openshift\/virtualization\">Red Hat Ecosystem Catalog<\/a>. So you&#8217;re at your own here.<\/li>\n<\/ol>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"has-text-align-center has-x-large-font-size\"><strong>You\u2019ve been warned!<\/strong> <\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Understanding my setup &#8211; a simplified(?) environment diagram<\/h3>\n\n\n\n<p>To provide a clearer picture of my lab setup, let\u2019s start with a simplified environment diagram. <strong>All nodes in this setup are fully virtualized<\/strong>, even though, as of writing, <strong>Red Hat does not officially support nested virtualization<\/strong>. While it works, it does so without official endorsement.<\/p>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"879\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Untitled-2025-03-05-1206-1024x879.png\" alt=\"\" class=\"wp-image-382\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Untitled-2025-03-05-1206-1024x879.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Untitled-2025-03-05-1206-300x257.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Untitled-2025-03-05-1206-768x659.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Untitled-2025-03-05-1206-1536x1318.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Untitled-2025-03-05-1206-2048x1758.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>The environment consists of:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>A compact OpenShift cluster with three control plane nodes<\/strong>\n<ul class=\"wp-block-list\">\n<li>These nodes serve a dual purpose: they host both OpenShift\u2019s control plane components and workloads.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>A separate TrueNAS CORE virtual machine<\/strong>\n<ul class=\"wp-block-list\">\n<li>This VM acts as the storage backend for the OpenShift cluster.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Networking configuration<\/strong>\n<ul class=\"wp-block-list\">\n<li>Each OpenShift node is equipped with <strong>four virtual network interfaces (vNICs)<\/strong>, forming two independent bonds:\n<ul class=\"wp-block-list\">\n<li><strong>bond0<\/strong>: Assigned to the <strong>Machine Network (192.168.232.0\/24)<\/strong>, which serves as the default cluster network where the default PodNetwork is configured.<\/li>\n\n\n\n<li><strong>bond1<\/strong>: Dedicated to <strong>Storage VLAN10 (10.0.0.0\/24)<\/strong>, ensuring storage traffic remains separate from regular cluster operations.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>The TrueNAS CORE VM has <strong>two vNICs<\/strong> connected to both networks:\n<ul class=\"wp-block-list\">\n<li>The <strong>Machine Network<\/strong> interface is used for WebUI management access.<\/li>\n\n\n\n<li>The <strong>Storage VLAN10<\/strong> interface is used to provide storage services to the OpenShift cluster.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Installed OpenShift Operators<\/strong>:\n<ul class=\"wp-block-list\">\n<li>OpenShift Virtualization<\/li>\n\n\n\n<li>Kubernetes NMState Operator<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>With this setup in place, let\u2019s explore how everything integrates and functions together.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">OpenShift Cluster &#8211; storage network configuration<\/h2>\n\n\n\n<p>I need to configure <strong>VLAN 10<\/strong> on <strong>bond1<\/strong> for OpenShift nodes to ensure that storage traffic runs on a dedicated network, just as it would in a real-world scenario, preventing interference between OpenShift workloads and storage traffic. <\/p>\n\n\n\n<p>I assume that <strong>bond1<\/strong>, <strong>VLAN 10<\/strong>, and the configuration for the <strong>enp3s0<\/strong> and <strong>enp4s0<\/strong> interfaces are not present on the nodes, allowing me to configure them directly using <em>NodeNetworkConfigurationPolicy<\/em>. Additionally, since <strong>VLAN 10<\/strong> lacks a DHCP server, I must assign unique IP addresses to each node manually. The <em>NNCP<\/em> configuration files are as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>extra-net.master-0.nncp.yml:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code has-foreground-color has-tertiary-background-color has-text-color has-background\"><code>apiVersion: nmstate.io\/v1\nkind: NodeNetworkConfigurationPolicy\nmetadata:\n<strong>  name: master-0-bond1-vlan10\n<\/strong>spec:\n  nodeSelector:\n<strong>    kubernetes.io\/hostname: \"master-0\"\n<\/strong>  desiredState:\n    interfaces:\n      - name: bond1\n        type: bond\n        state: up\n        link-aggregation:\n          mode: active-backup\n          options:\n            primary: enp3s0\n          port:\n            - enp3s0\n            - enp4s0\n        ipv4:\n          dhcp: false\n          enabled: false\n      - name: bond1.10\n        type: vlan\n        state: up\n        vlan:\n          base-iface: bond1\n          id: 10\n        ipv4:\n          dhcp: false\n          enabled: true\n          address:\n<strong>            - ip: 10.0.0.100\n<\/strong>              prefix-length: 24<\/code><\/pre>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>extra-net.master-1.nncp.yml:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code has-foreground-color has-tertiary-background-color has-text-color has-background\"><code>apiVersion: nmstate.io\/v1\nkind: NodeNetworkConfigurationPolicy\nmetadata:\n<strong>  name: master-1-bond1-vlan10\n<\/strong>spec:\n  nodeSelector:\n<strong>    kubernetes.io\/hostname: \"master-1\"\n<\/strong>  desiredState:\n    interfaces:\n      - name: bond1\n        type: bond\n        state: up\n        link-aggregation:\n          mode: active-backup\n          options:\n            primary: enp3s0\n          port:\n            - enp3s0\n            - enp4s0\n        ipv4:\n          dhcp: false\n          enabled: false\n      - name: bond1.10\n        type: vlan\n        state: up\n        vlan:\n          base-iface: bond1\n          id: 10\n        ipv4:\n          dhcp: false\n          enabled: true\n          address:\n<strong>            - ip: 10.0.0.101\n<\/strong>              prefix-length: 24<\/code><\/pre>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>extra-net.master-2.nncp.yml:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code has-foreground-color has-tertiary-background-color has-text-color has-background\"><code>apiVersion: nmstate.io\/v1\nkind: NodeNetworkConfigurationPolicy\nmetadata:\n<strong>  name: master-2-bond1-vlan10\n<\/strong>spec:\n  nodeSelector:\n<strong>    kubernetes.io\/hostname: \"master-2\"\n<\/strong>  desiredState:\n    interfaces:\n      - name: bond1\n        type: bond\n        state: up\n        link-aggregation:\n          mode: active-backup\n          options:\n            primary: enp3s0\n          port:\n            - enp3s0\n            - enp4s0\n        ipv4:\n          dhcp: false\n          enabled: false\n      - name: bond1.10\n        type: vlan\n        state: up\n        vlan:\n          base-iface: bond1\n          id: 10\n        ipv4:\n          dhcp: false\n          enabled: true\n          address:\n<strong>            - ip: 10.0.0.102\n<\/strong>              prefix-length: 24<\/code><\/pre>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Once applied I verified if it was successful (spoiler warning: it was successful \ud83d\ude09 )<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># oc get nnce\nNAME                             STATUS      STATUS AGE   REASON\nmaster-0.master-0-bond1-vlan10   Available   20s          SuccessfullyConfigured\nmaster-1.master-1-bond1-vlan10   Available   20s          SuccessfullyConfigured\nmaster-2.master-2-bond1-vlan10   Available   20s          SuccessfullyConfigured\n\n\n# oc debug node\/master-0\nTemporary namespace openshift-debug-28lnr is created for debugging node...\nStarting pod\/master-0-debug-s6v8z ...\nTo use host binaries, run `chroot \/host`\nPod IP: 192.168.232.100\nIf you don't see a command prompt, try pressing enter.\n\n\nsh-5.1# ip -o link | grep bond1 ; ip -o addr | grep bond1.10\n4: enp3s0: &lt;BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP&gt; mtu 1450 qdisc fq_codel master bond1 state UP mode DEFAULT group default qlen 1000\\    link\/ether 52:54:00:c8:cb:00 brd ff:ff:ff:ff:ff:ff\n5: enp4s0: &lt;BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP&gt; mtu 1450 qdisc fq_codel master bond1 state UP mode DEFAULT group default qlen 1000\\    link\/ether 52:54:00:c8:cb:00 brd ff:ff:ff:ff:ff:ff permaddr 52:54:00:f7:27:97\n544: bond1: &lt;BROADCAST,MULTICAST,MASTER,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000\\    link\/ether 52:54:00:c8:cb:00 brd ff:ff:ff:ff:ff:ff\n545: bond1.10@bond1: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000\\    link\/ether 52:54:00:c8:cb:00 brd ff:ff:ff:ff:ff:ff\n545: bond1.10    inet 10.0.0.100\/24 brd 10.0.0.255 scope global noprefixroute bond1.10\\       valid_lft forever preferred_lft forever<\/code><\/pre>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>At this stage my OpenShift cluster is ready from the network configuration perspective so I can move to TrueNAS installation and configuration.<\/p>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">TrueNAS CORE installation and configuration<\/h2>\n\n\n\n<p>Installation of TrueNAS CORE is described in detail in the relevant documentation available here: <a href=\"https:\/\/www.truenas.com\/docs\/core\/13.3\/gettingstarted\/install\/\">https:\/\/www.truenas.com\/docs\/core\/13.3\/gettingstarted\/install\/<\/a>. Just please note that for the sake of saving resources I&#8217;ve configured only single disk for data which is suboptimal configuration from the data redundancy point of view. TrueNAS will warn you about it during pool configuration process.<\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Getting ISO file with TrueNAS CORE installator<\/h3>\n\n\n\n<p>I have downloaded the ISO file with TrueNAS installator from <a href=\"https:\/\/www.truenas.com\/download-truenas-core\/\">https:\/\/www.truenas.com\/download-truenas-core\/<\/a> and saved it in \/var\/lib\/libvirt\/images\/ folder on my host system where all virtual machines are running.<\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Creating virtual machine and installing TrueNAS CORE<\/h3>\n\n\n\n<p>I have created VM for TrueNAS using the following command. Please note that some of the parameters have to be modified accordingly to your environment, especially paths to qcow2 files, iso file and network configuration which in my case is based on OpenVSwitch.<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># virt-install --name truenas \\\n  --vcpus 2 \\\n  --memory 8192 \\\n  --memorybacking hugepages=on \\\n  --disk size=16,bus=scsi,path=\/home\/VirtualMachines\/truenas.qcow2 \\\n  --disk size=256,bus=scsi,path=\/home\/VirtualMachines\/truenas-data-0.qcow2 \\\n  --cdrom \/var\/lib\/libvirt\/images\/TrueNAS-13.3-U1.1.iso \\\n  --network model=e1000,bridge=br-ovs-frontend,virtualport_type=openvswitch \\\n  --network model=e1000,bridge=br-ovs-ctlplane,virtualport_type=openvswitch \\\n  --os-variant freebsd13.1 \\\n  --sound none \\\n  --import \\\n  --boot=hd,cdrom,network,menu=on \\\n  --noreboot \\\n  --noautoconsole<\/code><\/pre>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Once created the VM should boot up and enter the installator &#8211; at this stage it can be only accessed through the VM console:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"860\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.31.01-1024x860.png\" alt=\"\" class=\"wp-image-319\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.31.01-1024x860.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.31.01-300x252.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.31.01-768x645.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.31.01-1536x1291.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.31.01-2048x1721.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>The installation process is pretty straightforward, just ensure the system is installed on the smaller disk as bellow since the big one will remain for data:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"860\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.32.02-1024x860.png\" alt=\"\" class=\"wp-image-320\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.32.02-1024x860.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.32.02-300x252.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.32.02-768x645.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.32.02-1536x1291.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-13.32.02-2048x1721.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Since my <em>MachineNetwork<\/em> has DHCP configured to provide IP configuration, it was automatically picked up by TrueNAS:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"860\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.18.04-1024x860.png\" alt=\"\" class=\"wp-image-321\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.18.04-1024x860.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.18.04-300x252.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.18.04-768x645.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.18.04-1536x1291.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.18.04-2048x1721.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>With that IP address I could immediately access TrueNAS CORE WebUI using credentials configured during installation:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"874\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.23.36-1024x874.png\" alt=\"\" class=\"wp-image-322\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.23.36-1024x874.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.23.36-300x256.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.23.36-768x656.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.23.36-1536x1311.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.23.36.png 1619w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">TrueNAS CORE post installation configuration<\/h3>\n\n\n\n<p>Once I got TrueNAS CORE up and running I need to configure it further:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ensure storage <strong>VLAN 10<\/strong> access and IP configuration<\/li>\n\n\n\n<li>Creation of storage pool shared with OpenShift cluster<\/li>\n\n\n\n<li>Configuration of storage sharing services: iSCSI, NFS<\/li>\n\n\n\n<li>Configuration of SSH and API access to TrueNAS CORE<\/li>\n<\/ul>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Storage VLAN configuration<\/h4>\n\n\n\n<p>This is not really necessary as I could use MachineNetwork for storage configuration, however I do believe it is more realistic approach to get the dedicated network for this purpose. For that reason I need to configure TrueNAS to tag VLAN 10 over em1 interface. To do so I have to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Navigate to <strong>Network &gt; Interfaces<\/strong> from the left hand side menu<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"687\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.32.06-1024x687.png\" alt=\"\" class=\"wp-image-326\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.32.06-1024x687.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.32.06-300x201.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.32.06-768x515.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.32.06-1536x1030.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.32.06.png 1619w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>press <strong>ADD<\/strong> to create new interface<\/li>\n\n\n\n<li>specify interface type as <strong>VLAN<\/strong><\/li>\n\n\n\n<li>provide name of the interface (<strong>vlan10<\/strong> in my case)<\/li>\n\n\n\n<li>specify parent interface (<strong>em1<\/strong>)<\/li>\n\n\n\n<li>specify <strong>VLAN<\/strong> tag (10)<\/li>\n\n\n\n<li>provide manually IP configuration (<strong>10.0.0.254<\/strong>\/24)<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"686\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.33.35-1024x686.png\" alt=\"\" class=\"wp-image-327\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.33.35-1024x686.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.33.35-300x201.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.33.35-768x514.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.33.35-1536x1028.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.33.35.png 1619w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Test applied changes &#8211; <strong>TrueNAS will ensure you can maintain connectivity<\/strong> to it before making changes persistent. If not the changes will be automatically reverted<\/li>\n\n\n\n<li>Save the network configuration changes to ensure they will persist between reboots<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"686\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.34.43-1024x686.png\" alt=\"\" class=\"wp-image-328\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.34.43-1024x686.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.34.43-300x201.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.34.43-768x514.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.34.43-1536x1028.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-06-at-13.34.43.png 1619w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Just in case &#8211; confirming that my OpenShift node can reach TrueNAS over VLAN 10 (spoiler alert: it does)<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># oc debug node\/<strong>master-1<\/strong>\nTemporary namespace openshift-debug-xp5rn is created for debugging node...\nStarting pod\/master-1-debug-rrp4r ...\nTo use host binaries, run `chroot \/host`\nwarning: Container container-00 is unable to start due to an error: Back-off pulling image \"quay.io\/openshift-release-dev\/ocp-v4.0-art-dev@sha256:6ab858aed98e4fe57e6b144da8e90ad5d6698bb4cc5521206f5c05809f0f9296\"\nPod IP: 192.168.232.101\nIf you don't see a command prompt, try pressing enter.\n\n\nsh-5.1# ping -c 4 <strong>10.0.0.254<\/strong>\nPING 10.0.0.254 (10.0.0.254) 56(84) bytes of data.\n64 bytes from 10.0.0.254: icmp_seq=1 ttl=64 time=10.3 ms\n64 bytes from 10.0.0.254: icmp_seq=2 ttl=64 time=1.86 ms\n64 bytes from 10.0.0.254: icmp_seq=3 ttl=64 time=9.98 ms\n64 bytes from 10.0.0.254: icmp_seq=4 ttl=64 time=0.450 ms\n\n--- 10.0.0.254 ping statistics ---\n4 packets transmitted, 4 received, 0% packet loss, time 3006ms\nrtt min\/avg\/max\/mdev = 0.450\/5.643\/10.277\/4.515 ms<\/code><\/pre>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Storage pool configuration<\/h4>\n\n\n\n<p>In TrueNAS, storage pools are groups of physical disks combined into a single logical storage unit using ZFS. They provide redundancy, performance, and scalability by distributing data across multiple drives. In my case I have single drive only but the pool is still necessary to be created.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>To create a new pool, I got to <strong>Storage &gt; Pools<\/strong> from the left hand side menu and clicked <strong>ADD<\/strong>. Selected <strong>Create new pool <\/strong>and clicked <strong>CREATE POOL<\/strong> to open the Pool Manager. Ignore the error and select &#8220;<strong>Show disks with non-unique serial numbers<\/strong>&#8220;<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"726\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.26.05-1024x726.png\" alt=\"\" class=\"wp-image-334\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.26.05-1024x726.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.26.05-300x213.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.26.05-768x545.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.26.05-1536x1090.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.26.05.png 1617w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Selected da1 disk which just occurred above and move it from Avilable Disks to Data VDevs column<\/li>\n\n\n\n<li>Selected box \u201cForce\u201d and acknowledged warning about stripe data<\/li>\n\n\n\n<li>Filled the name field for the pool (&#8220;openshift&#8221;) and clicked create<\/li>\n\n\n\n<li>Confirmed \u201cThe contents of all added disks will be erased.\u201d warning<\/li>\n\n\n\n<li>Observed the pool being created.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"715\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.29.05-1024x715.png\" alt=\"\" class=\"wp-image-336\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.29.05-1024x715.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.29.05-300x210.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.29.05-768x536.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.29.05-1536x1073.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.29.05.png 1621w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Optionally click three dots on the right, go to edit options and disable the default lz4 compression &#8211; this should save some CPU resources<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"717\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.39.45-1024x717.png\" alt=\"\" class=\"wp-image-338\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.39.45-1024x717.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.39.45-300x210.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.39.45-768x538.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.39.45-1536x1076.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.39.45.png 1617w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Configuring iSCSI and NFS services on TrueNAS CORE<\/h4>\n\n\n\n<p>iSCSI (Internet Small Computer Systems Interface) is a <strong>block-level storage protocol<\/strong> that allows clients (initiators) to connect to storage devices (targets) over a network. On the other hand NFS (Network File System) is a <strong>file-level storage protocol<\/strong> that allows multiple clients to access shared files over a network. Among these two TrueNAS CORE can also support Apple Filing Protocol (AFP), Web-based Distributed Authoring and Versioning (WebDAV) and Server Message Block (SMB) but they&#8217;re out of the scope for this exercise. <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>To enable iSCSI and NFS I have to go to <strong>Services<\/strong> on the left hand side menu, <strong>make them running and started automatically<\/strong>. I also <strong>enabled SSH service<\/strong> as it will be needed later to provide management access for OpenShift.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"866\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.40.27-1024x866.png\" alt=\"\" class=\"wp-image-339\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.40.27-1024x866.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.40.27-300x254.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.40.27-768x649.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.40.27-1536x1298.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/Screenshot-2025-03-05-at-14.40.27.png 1622w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">iSCSI configuration<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>To make OpenShift being able to connect to iSCSI I need to configure it a bit, therefore I can use either <strong>Actions \/ Pen<\/strong> symbol from this screen or navigate to <strong>Sharing &gt; Block Shares (iSCSI)<\/strong> from the main menu. Both ways will take me to the same place where iSCSI protocol options are:<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"719\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-1024x719.png\" alt=\"\" class=\"wp-image-342\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-1024x719.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-300x211.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-768x539.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-1536x1078.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image.png 1619w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>I leave the defaults here and move to <strong>Portals<\/strong> tab where I add new<strong> <\/strong>endpoint that OpenShift can connect to, specyfing explicitly the <strong>Storage VLAN address to listen on (10.0.0.254)<\/strong>. I don&#8217;t use any authentication method which probably would not be the best idea in a production environment.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"719\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-1-1024x719.png\" alt=\"\" class=\"wp-image-343\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-1-1024x719.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-1-300x211.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-1-768x539.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-1-1536x1079.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-1.png 1619w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Next I move to <strong>Initiators Groups<\/strong> tab where I can specify who can connect to iSCSI service. I could either allow all Initiators (clients) or specify them by name (IQN) or IP address. I&#8217;ve chosen the second option and allowed all 10.0.0.0\/24 IPs to do connect:<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"714\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-2-1024x714.png\" alt=\"\" class=\"wp-image-344\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-2-1024x714.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-2-300x209.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-2-768x535.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-2-1536x1071.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-2.png 1621w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">NFS configuration<\/h4>\n\n\n\n<p>No specific NFS configuration is needed on the TrueNAS CORE side\u2014it just needs to be enabled. The CSI drivers will automatically create DataSets as required, following the settings defined in the freenas-nfs.yaml configuration file mentioned later in this post. Below is a screenshot showing the openshift storage pool along with the nfs-vols and vols DataSets, which were created automatically during storage usage:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"717\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-6-1024x717.png\" alt=\"\" class=\"wp-image-375\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-6-1024x717.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-6-300x210.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-6-768x538.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-6-1536x1075.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-6.png 1621w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">SSH access<\/h4>\n\n\n\n<p>Democratic-csi drivers needs both <strong>SSH and API access<\/strong> to manage storage resources provided by TrueNAS CORE. This probably isn&#8217;t the most elegant solution but for demo purposes it just works. Just as a side note, TrueNAS SCALE which is more modern version of TrueNAS CORE can be managed only using API, without a need to configure SSH access.<\/p>\n\n\n\n<p>So I can configure SSH access either with <strong>login\/password<\/strong> or <strong>login\/ssh-key<\/strong>, the second is more appealing to me so I will generate new SSH key pair just for that purpose:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code><strong># ssh-keygen -f .ssh\/ocp-truenas-csi\n<\/strong>Generating public\/private rsa key pair.\nEnter passphrase (empty for no passphrase):\nEnter same passphrase again:\nYour identification has been saved in .ssh\/ocp-truenas-csi\nYour public key has been saved in .ssh\/ocp-truenas-csi.pub\nThe key fingerprint is:\nSHA256:xyz rafal@zyx\nThe key's randomart image is:\n+---&#91;RSA 3072]----+\n|    -.-||-.-     |\n+----&#91;SHA256]-----+<\/code><\/pre>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>I paste content of the public key (in my case stored as .ssh\/ocp-truenas-csi.pub) to TrueNAS CORE root user by edditing it in <strong>Accounts &gt; Users &gt; root<\/strong>:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"719\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-3-1024x719.png\" alt=\"\" class=\"wp-image-353\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-3-1024x719.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-3-300x211.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-3-768x539.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-3-1536x1079.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-3.png 1619w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>and confirming whether it work properly, just to safe some troubleshooting time later:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code><strong># ssh -i .ssh\/ocp-truenas-csi root@192.168.232.120\n<\/strong>FreeBSD 13.3-RELEASE-p4 n257491-41f6a830f8e TRUENAS\n\n        TrueNAS (c) 2009-2025, iXsystems, Inc.\n        All rights reserved.\n        TrueNAS code is released under the modified BSD license with some\n        files copyrighted by (c) iXsystems, Inc.\n\n        For more information, documentation, help or support, go here:\n        http:&#47;&#47;truenas.com\nWelcome to TrueNAS<\/code><\/pre>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">API access<\/h4>\n\n\n\n<p>To <strong>obtain API key<\/strong> from TrueNAS CORE to configure it with democratic-csi drivers I have to go to <strong>Settings<\/strong> by clicking <strong>the cog icon in the upper right screen corner<\/strong>, then selecting <strong>API Keys<\/strong> from the menu, pressing <strong>ADD<\/strong> and providing the name for the key. Please note that the key will be shown only once and I won&#8217;t be able to retrieve it again, so it is better to save it in safe place for the future use when configuring CSI drivers.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"623\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-5-1024x623.png\" alt=\"\" class=\"wp-image-356\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-5-1024x623.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-5-300x183.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-5-768x468.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-5-1536x935.png 1536w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2025\/03\/image-5.png 1621w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">OpenShift CSI driver installation and configuration<\/h2>\n\n\n\n<p>In order to make OpenShift being able to automatically provision and manage storage resources from TrueNAS I need to install and configure CSI drivers. Fortunately it is quite easy as they&#8217;re provided as Helm Charts available from <a href=\"https:\/\/democratic-csi.github.io\/charts\/\">https:\/\/democratic-csi.github.io\/charts\/<\/a>. Following instructions I have added them and upgraded my Helm repository:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># helm repo add democratic-csi https:\/\/democratic-csi.github.io\/charts\/\n\"democratic-csi\" has been added to your repositories\n\n# helm repo update\nHang tight while we grab the latest from your chart repositories...\n...Successfully got an update from the \"democratic-csi\" chart repository\nUpdate Complete. \u2388Happy Helming!\u2388\n<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">iSCSI<\/h3>\n\n\n\n<p>To install the driver, I need to provide configuration files tailored to my environment. Fortunately, the Helm charts include several example files, available here: <a href=\"https:\/\/github.com\/democratic-csi\/charts\/tree\/master\/stable\/democratic-csi\/examples\">https:\/\/github.com\/democratic-csi\/charts\/tree\/master\/stable\/democratic-csi\/examples<\/a>. In my case, the most relevant example is <strong><a href=\"https:\/\/github.com\/democratic-csi\/charts\/blob\/master\/stable\/democratic-csi\/examples\/freenas-iscsi.yaml\">freenas-iscsi.yaml<\/a><\/strong>. However, it&#8217;s important to note that the <strong><em>driver:<\/em><\/strong> section in this file is just a placeholder and lacks the necessary details for proper configuration.<\/p>\n\n\n\n<p>To get the full set of options, I need to refer to the <strong>democratic-csi repository:<\/strong> <a href=\"https:\/\/github.com\/democratic-csi\/democratic-csi\/tree\/master\/examples\">https:\/\/github.com\/democratic-csi\/democratic-csi\/tree\/master\/examples<\/a>, where another <strong><a href=\"https:\/\/github.com\/democratic-csi\/democratic-csi\/blob\/master\/examples\/freenas-iscsi.yaml\">freenas-iscsi.yaml<\/a><\/strong> file contains the required settings.<\/p>\n\n\n\n<p>This part can be a bit confusing because the final configuration requires <strong>merging the contents of the second file into the <em>driver:<\/em> section of the first one<\/strong> to ensure everything is set up correctly. For my environment the following freenas-iscsi.yaml values file has been used:<\/p>\n\n\n\n<pre class=\"wp-block-code has-foreground-color has-tertiary-background-color has-text-color has-background\"><code>csiDriver:\n  name: \"org.democratic-csi.iscsi\"\n\nstorageClasses:\n  - name: freenas-iscsi-csi\n    defaultClass: true\n    reclaimPolicy: Delete\n    volumeBindingMode: Immediate\n    allowVolumeExpansion: true\n    parameters:\n      fsType: xfs\n    mountOptions: &#91;]\n    secrets:\n      provisioner-secret:\n      controller-publish-secret:\n      node-stage-secret:\n      node-publish-secret:\n      controller-expand-secret:\n\nvolumeSnapshotClasses:\n  - name: freenas-iscsi-csi\n    parameters:\n    secrets:\n      snapshotter-secret:\n\ndriver:\n  config:\n    driver: freenas-iscsi\n    instance_id:\n    httpConnection:\n      protocol: http\n      host: 10.0.0.254\n      port: 80\n      apiKey: \"1-d ***SNIP*** aS2\"\n      allowInsecure: true\n    sshConnection:\n      host: 10.0.0.254\n      port: 22\n      username: root\n      # use either password or key\n      password: \"\"\n      privateKey: |\n        -----BEGIN OPENSSH PRIVATE KEY-----\n        bAABBCCDDEEFFGGGHHIIJJKKLLMMNNOOPPQQQQRRRRSSSTTTUUVVXXXYYZZZZZZZZn\n        *** SNIP ***\n        qAABBCCDDEEFFGGGHHIIJJKKLLMMNNOOPPQQQQRRRRSSSTTTUUVVXXXYYZZZZZZZZ=\n        -----END OPENSSH PRIVATE KEY-----\n    zfs:\n      datasetParentName: openshift\/vols\n      detachedSnapshotsDatasetParentName: openshift\/snaps\n      zvolCompression:\n      zvolDedup:\n      zvolEnableReservation: false\n      zvolBlocksize:\n    iscsi:\n      targetPortal: \"10.0.0.254:3260\"\n      targetPortals: &#91;]\n      interface:\n      namePrefix: csi-\n      nameSuffix: \"-clustera\"\n\n      targetGroups:\n        - targetGroupPortalGroup: 1\n          targetGroupInitiatorGroup: 1\n          targetGroupAuthType: None\n          targetGroupAuthGroup:\n\n      extentInsecureTpc: true\n      extentXenCompat: false\n      extentDisablePhysicalBlocksize: true\n      extentBlocksize: 512\n      extentRpm: \"SSD\"\n      extentAvailThreshold: 0\n\ncontroller:\n  hostNetwork: true\n  enabled: true\n  rbac:\n    enabled: true\n    openshift:\n      # set to true if running on openshift *and* you have need\n      # ie: hostNetwork, hostIPC, etc are turned on\n      privileged: true\n\nnode:\n  hostNetwork: true\n  driver:\n    localtimeHostPath: false\n  rbac:\n    enabled: true\n    openshift:\n      # set to true if running on openshift\n      privileged: true<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>For detailed information on specific options, please refer to the example configuration files, which contain comments with explanations.<\/p>\n\n\n\n<p>Now since I have all necessary bits I can run helm install to get democratic-csi drivers installed and configured to manage my TrueNAS CORE storage backend:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># helm upgrade --install --values freenas-iscsi.yaml --create-namespace --namespace democratic-csi zfs-iscsi democratic-csi\/democratic-csi\nRelease \"zfs-iscsi\" does not exist. Installing it now.\nNAME: zfs-iscsi\nNAMESPACE: democratic-csi\nSTATUS: deployed\nREVISION: 1\nTEST SUITE: None<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Just to verify that all containers are up and running and I got expected <em>StorageClass<\/em> and <em>VolumeSnapshotClass<\/em> created:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># oc -n democratic-csi get pods\nNAME                                                   READY   STATUS    RESTARTS      AGE\nzfs-iscsi-democratic-csi-controller-75bb6756d9-6ckpk   6\/6     Running   3 (65s ago)   81s\nzfs-iscsi-democratic-csi-node-cn9k6                    4\/4     Running   0             81s\nzfs-iscsi-democratic-csi-node-gq4fw                    4\/4     Running   0             81s\nzfs-iscsi-democratic-csi-node-xzggk                    4\/4     Running   0             81s\n\n# oc get sc\nNAME                          PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE\nfreenas-iscsi-csi (default)   org.democratic-csi.iscsi       Delete          Immediate              true                   102s\n\n# oc get volumesnapshotclasses.snapshot.storage.k8s.io\nNAME                DRIVER                     DELETIONPOLICY   AGE\nfreenas-iscsi-csi   org.democratic-csi.iscsi   Delete           107s<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>It all seems good, even <strong>freenas-iscsi-csi<\/strong> <em>StorageClass<\/em> has been annotated as <strong>default<\/strong> one as requested (see <strong>defaultClass: true<\/strong> option in freenas-iscsi.yaml value file). This however won&#8217;t make it automatically working for OpenShift Virtualization aka CNV aka KubeVirt. It requires few additional tweaks.<\/p>\n\n\n\n<p>First, I need to designate it as the default <em>StorageClass<\/em> for virtualization. To do this, I run the following commands &#8211; the first checks that no other <em>StorageClass<\/em> is already set as the default for virtualization, and the second applies the annotation:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># oc get sc -o json| jq '.items&#91;].metadata|select(.annotations.\"<strong>storageclass.kubevirt.io\/is-default-virt-class<\/strong>\"==\"<strong>true<\/strong>\")|.name'\n\n# oc annotate sc freenas-iscsi-csi <strong><strong>storageclass.kubevirt.io<\/strong>\/is-default<strong>-virt-class<\/strong>=true<\/strong>\nstorageclass.storage.k8s.io\/freenas-iscsi-csi annotated<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Second, I have to update <em>StorageProfiles<\/em> from <em>cdi.kubevirt.io<\/em> API as the default one does not contain information about access and volume modes and clone strategy:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># oc get storageprofiles.cdi.kubevirt.io freenas-iscsi-csi -o yaml\napiVersion: cdi.kubevirt.io\/v1beta1\nkind: StorageProfile\nmetadata:\n  generation: 1\n  labels:\n    app: containerized-data-importer\n    app.kubernetes.io\/component: storage\n    app.kubernetes.io\/managed-by: cdi-controller\n    app.kubernetes.io\/part-of: hyperconverged-cluster\n    app.kubernetes.io\/version: 4.18.0\n    cdi.kubevirt.io: \"\"\n  name: freenas-iscsi-csi\n  ownerReferences:\n  - apiVersion: cdi.kubevirt.io\/v1beta1\n    blockOwnerDeletion: true\n    controller: true\n    kind: CDI\n    name: cdi-kubevirt-hyperconverged\n    uid: f5d44cad-c0dd-4c28-9e91-ba7bda1aba85\n  resourceVersion: \"56730175\"\n  uid: d56cada5-c5d2-47df-ab7e-00acb843e2f4\n<strong>spec: {}<\/strong>\nstatus:\n  cloneStrategy: snapshot\n  dataImportCronSourceFormat: pvc\n  provisioner: org.democratic-csi.iscsi\n  snapshotClass: freenas-iscsi-csi\n  storageClass: freenas-iscsi-csi\n\n\n# oc patch storageprofiles.cdi.kubevirt.io freenas-iscsi-csi --type=merge -p '{\"spec\":{\"<strong>claimPropertySets<\/strong>\":&#91;{\"<strong>accessModes<\/strong>\":&#91;\"<strong>ReadWriteMany<\/strong>\",\"<strong>ReadWriteOnce<\/strong>\"],\"<strong>volumeMode<\/strong>\":\"<strong>Block<\/strong>\"}]}}'\nstorageprofile.cdi.kubevirt.io\/freenas-iscsi-csi patched\n\n# oc get storageprofiles.cdi.kubevirt.io freenas-iscsi-csi -o yaml\napiVersion: cdi.kubevirt.io\/v1beta1\nkind: StorageProfile\nmetadata:\n  generation: 3\n  labels:\n    app: containerized-data-importer\n    app.kubernetes.io\/component: storage\n    app.kubernetes.io\/managed-by: cdi-controller\n    app.kubernetes.io\/part-of: hyperconverged-cluster\n    app.kubernetes.io\/version: 4.18.0\n    cdi.kubevirt.io: \"\"\n  name: freenas-iscsi-csi\n  ownerReferences:\n  - apiVersion: cdi.kubevirt.io\/v1beta1\n    blockOwnerDeletion: true\n    controller: true\n    kind: CDI\n    name: cdi-kubevirt-hyperconverged\n    uid: f5d44cad-c0dd-4c28-9e91-ba7bda1aba85\n  resourceVersion: \"56793834\"\n  uid: d56cada5-c5d2-47df-ab7e-00acb843e2f4\n<strong>spec:<\/strong>\n<strong>  claimPropertySets:\n  - accessModes:\n    - ReadWriteMany\n    - ReadWriteOnce\n    volumeMode: Block<\/strong>\nstatus:\n<strong>  claimPropertySets:\n  - accessModes:\n    - ReadWriteMany\n    - ReadWriteOnce\n    volumeMode: Block\n<\/strong>  cloneStrategy: snapshot\n  dataImportCronSourceFormat: pvc\n  provisioner: org.democratic-csi.iscsi\n  snapshotClass: freenas-iscsi-csi\n  storageClass: freenas-iscsi-csi<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Shortly after I can observe that OpenShift Virtualization Operator is capable to request and allocate new PVCs to host the default VM images. This confirms that iSCSI based storage backend is configured and function properly.<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background has-small-font-size\"><code># oc -n openshift-virtualization-os-images get pvc\nNAME                                         STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        VOLUMEATTRIBUTESCLASS   AGE\ncentos-stream10-52d45ea2052b                 Pending                                                                        freenas-iscsi-csi   &lt;unset&gt;                 53s\ncentos-stream9-a6374a5bf9f0                  Pending                                                                        freenas-iscsi-csi   &lt;unset&gt;                 53s\nfedora-171f94e28cc8                          Bound     pvc-81879410-1c18-4e58-bf38-f22da8904c45   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 53s\nprime-33d88fa7-89a0-4743-9d92-ed4a6d081197   Bound     pvc-8379f1df-1eda-42a6-882b-708fc2e191fe   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 52s\nprime-4f58f2d3-5c0d-43ee-97dc-b0422fe70093   Bound     pvc-00e8277b-cf7f-4f03-a17c-676387aaa0e4   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 53s\nprime-8aa74bbe-7755-4ddf-b152-9c928ff54a4f   Bound     pvc-0b77ad50-35da-436d-8060-2a4a5d133bf0   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 52s\nprime-b70fad6d-3668-4aee-b652-8d761bd9a93f   Bound     pvc-af64a72c-9592-44a9-af0e-dbe00b3fd29e   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 52s\nprime-bb2b9f06-2f06-46e4-bca5-fe26636c37c7   Bound     pvc-0b18e43a-2332-4f3f-ae51-ec76135ca1c6   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 53s\nrhel10-beta-8a0eb850f419                     Pending                                                                        freenas-iscsi-csi   &lt;unset&gt;                 52s\nrhel8-257b1af2a7f6                           Pending                                                                        freenas-iscsi-csi   &lt;unset&gt;                 52s\nrhel9-dd6a5c9fb09e                           Pending                                                                        freenas-iscsi-csi   &lt;unset&gt;                 52s\n\n\n&#91;root@bastion ~]# oc -n openshift-virtualization-os-images get pvc\nNAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        VOLUMEATTRIBUTESCLASS   AGE\ncentos-stream10-52d45ea2052b   Bound    pvc-00e8277b-cf7f-4f03-a17c-676387aaa0e4   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 5m\ncentos-stream9-a6374a5bf9f0    Bound    pvc-0b18e43a-2332-4f3f-ae51-ec76135ca1c6   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 5m\nfedora-171f94e28cc8            Bound    pvc-81879410-1c18-4e58-bf38-f22da8904c45   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 6m\nrhel10-beta-8a0eb850f419       Bound    pvc-af64a72c-9592-44a9-af0e-dbe00b3fd29e   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 7m\nrhel8-257b1af2a7f6             Bound    pvc-0b77ad50-35da-436d-8060-2a4a5d133bf0   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 9m\nrhel9-dd6a5c9fb09e             Bound    pvc-8379f1df-1eda-42a6-882b-708fc2e191fe   30Gi       RWO,RWX        freenas-iscsi-csi   &lt;unset&gt;                 12m<\/code><\/pre>\n\n\n\n<div style=\"height:21px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">NFS<\/h3>\n\n\n\n<p>Configuration of NFS protocol with democratic-csi and TrueNAS CORE is very similar to what I&#8217;ve done with iSCSI. First of all I need to create values file &#8211; freenas-nfs.yaml &#8211; with proper configuration. In my case it looks as follow:<\/p>\n\n\n\n<pre class=\"wp-block-code has-foreground-color has-tertiary-background-color has-text-color has-background\"><code>csiDriver:\n  name: \"org.democratic-csi.nfs\"\n  fsGroupPolicy: File\n\nstorageClasses:\n  - name: freenas-nfs-csi\n<strong>    defaultClass: false\n<\/strong>    reclaimPolicy: Delete\n    volumeBindingMode: Immediate\n    allowVolumeExpansion: true\n    parameters:\n      fsType: nfs\n    mountOptions:\n      - noatime\n      - nfsvers=3\n    secrets:\n      provisioner-secret:\n      controller-publish-secret:\n      node-stage-secret:\n      node-publish-secret:\n      controller-expand-secret:\n\nvolumeSnapshotClasses:\n  - name: freenas-nfs-csi\n    parameters:\n    secrets:\n      snapshotter-secret:\n\ndriver:\n  config:\n    driver: freenas-nfs\n    instance_id:\n    httpConnection:\n      protocol: http\n      host: 10.0.0.254\n      port: 80\n      apiKey: \"1-d ***SNIP*** aS2\"\n      username: root\n      password: \"\"\n      allowInsecure: true\n    sshConnection:\n      host: 10.0.0.254\n      port: 22\n      username: root\n      password: \"\"\n      privateKey: |\n        -----BEGIN OPENSSH PRIVATE KEY-----\n        bAABBCCDDEEFFGGGHHIIJJKKLLMMNNOOPPQQQQRRRRSSSTTTUUVVXXXYYZZZZZZZZn\n        *** SNIP ***\n        qAABBCCDDEEFFGGGHHIIJJKKLLMMNNOOPPQQQQRRRRSSSTTTUUVVXXXYYZZZZZZZZ=\n        -----END OPENSSH PRIVATE KEY-----\n    zfs:\n      datasetParentName: openshift\/nfs-vols\n      detachedSnapshotsDatasetParentName: openshift\/nfs-snaps\n      datasetEnableQuotas: true\n      datasetEnableReservation: false\n      datasetPermissionsMode: \"0777\"\n      datasetPermissionsUser: 0\n      datasetPermissionsGroup: 0\n    nfs:\n      shareHost: 10.0.0.254\n      shareAlldirs: false\n      shareAllowedHosts: &#91;]\n      shareAllowedNetworks: &#91;]\n      shareMaprootUser: root\n      shareMaprootGroup: wheel\n      shareMapallUser: \"\"\n      shareMapallGroup: \"\"\n\ncontroller:\n  hostNetwork: true\n  enabled: true\n  rbac:\n    enabled: true\n    openshift:\n      # set to true if running on openshift *and* you have need\n      # ie: hostNetwork, hostIPC, etc are turned on\n      privileged: true\n\nnode:\n  hostNetwork: true\n  driver:\n    localtimeHostPath: false\n  rbac:\n    enabled: true\n    openshift:\n      # set to true if running on openshift\n      privileged: true<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Once file is ready I can run helm install, please note I <strong>must<\/strong> use different deployment name &#8211; zfs-nfs:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># helm upgrade --install --values freenas-nfs.yaml --create-namespace --namespace democratic-csi <strong>zfs-nfs<\/strong> democratic-csi\/democratic-csi\nRelease \"zfs-nfs\" does not exist. Installing it now.\n<strong>NAME: zfs-nfs\n<\/strong>NAMESPACE: democratic-csi\nSTATUS: deployed\nREVISION: 1\nTEST SUITE: None<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Just to quickly verify if the new pods for NFS have been created:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># oc get pods -n democratic-csi\nNAME                                                   READY   STATUS    RESTARTS        AGE\nzfs-iscsi-democratic-csi-controller-75bb6756d9-6ckpk   6\/6     Running   3 (18h ago)     18h\nzfs-iscsi-democratic-csi-node-cn9k6                    4\/4     Running   0               18h\nzfs-iscsi-democratic-csi-node-gq4fw                    4\/4     Running   0               18h\nzfs-iscsi-democratic-csi-node-xzggk                    4\/4     Running   0               18h\n<strong>zfs-nfs-democratic-csi-controller-684dfc4d9-4d22h      6\/6     Running   3 (18m ago)     18m\nzfs-nfs-democratic-csi-node-47cvn                      4\/4     Running   0                6m\nzfs-nfs-democratic-csi-node-9cnmm                      4\/4     Running   0                6m\nzfs-nfs-democratic-csi-node-xh5jf                      4\/4     Running   0                6m<\/strong><\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>And similarly to what I did for iSCSI <em>StorageProfile<\/em>, I need to patch freenas-nfs-csi <em>StorageProfile<\/em> as well and set accessModes and volumeMode:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code># oc patch storageprofiles.cdi.kubevirt.io freenas-nfs-csi --type=merge -p '{\"spec\":{\"claimPropertySets\":&#91;{\"accessModes\":&#91;\"ReadWriteMany\",\"ReadWriteOnce\"],\"volumeMode\":\"Filesystem\"}]}}'\nstorageprofile.cdi.kubevirt.io\/freenas-nfs-csi patched<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>From this moment I can use NFS based volumes provided by TrueNAS CORE for OpenShift workloads, including virtual machines \ud83d\ude42<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<p>In case something isn&#8217;t right or I want to dig deeper into what&#8217;s underneath, the very first steps for troubleshooting are:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Check logs of pods in democratic-csi project, especially *-democratic-csi-controller-* pod<\/li>\n\n\n\n<li>Check events in openshift-virtualization-os-images project, to see why images are not being downloaded:<br><code># oc -n openshift-virtualization-os-images get events -w<\/code><\/li>\n\n\n\n<li>Check events in the project where resources were supposed to be created. Below example of events list which were thrown due to lack of <em>accessMode<\/em> and <em>volumeMode<\/em> configuration in <em>StorageProfile<\/em> freenas-nfs-csi<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code has-background-color has-foreground-background-color has-text-color has-background\"><code><strong># oc -n default get events\n<\/strong>LAST SEEN   TYPE      REASON                       OBJECT                                   MESSAGE\n10m         Normal    Modified                     networkaddonsconfig\/cluster              Config spec was modified\n107s        Warning   ErrClaimNotValid             datavolume\/fedora-beige-loon-39-volume   <strong>Spec is missing accessMode and volumeMode, cannot get access mode from StorageProfile freenas-nfs-csi<\/strong>\n3m39s       Normal    ErrClaimNotValid             datavolume\/fedora-beige-loon-39-volume   no accessMode specified in StorageProfile freenas-nfs-csi\n3m39s       Normal    SuccessfulDataVolumeCreate   virtualmachine\/fedora-beige-loon-39      Created DataVolume fedora-beige-loon-39-volume<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>In this blog post I&#8217;ve outlined a method for setting up a compact OpenShift environment using TrueNAS CORE as the storage backend. This approach offers a resource-efficient alternative to more demanding storage solutions like Ceph-based OpenShift Data Foundation (ODF), making it suitable for small-scale labs and experimentation.<\/p>\n\n\n\n<p>By integrating TrueNAS CORE with OpenShift using the democratic-csi project&#8217;s CSI drivers and Helm Charts, this lab setup provides a lightweight and straightforward storage solution. It enables users to explore and demonstrate OpenShift Virtualization&#8217;s advanced features without the overhead of more resource-intensive storage systems.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my lab, I maintain a small, fully virtualized OpenShift environment to practice and demonstrate its capabilities &#8211; especially OpenShift Virtualization. A critical component of this setup is the storage backend. While Ceph-based OpenShift Data Foundation (ODF) is a great choice for OpenShift and OpenShift Virtualization, its resource requirements make it impractical for my ultra-small [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-312","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/posts\/312","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/comments?post=312"}],"version-history":[{"count":50,"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/posts\/312\/revisions"}],"predecessor-version":[{"id":389,"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/posts\/312\/revisions\/389"}],"wp:attachment":[{"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/media?parent=312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/categories?post=312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/tags?post=312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}