{"id":27,"date":"2023-03-10T16:57:20","date_gmt":"2023-03-10T15:57:20","guid":{"rendered":"https:\/\/blog.openshift.one\/?p=27"},"modified":"2023-03-13T12:52:27","modified_gmt":"2023-03-13T11:52:27","slug":"red-hat-openshift-virtualisation-rhel-for-edge-lab","status":"publish","type":"post","link":"https:\/\/blog.openshift.one\/index.php\/2023\/03\/10\/red-hat-openshift-virtualisation-rhel-for-edge-lab\/","title":{"rendered":"Red Hat OpenShift Virtualization &#038; RHEL for Edge lab"},"content":{"rendered":"\n<p>The purpose of this document is to explain how <strong>Red Hat OpenShift Container Platform<\/strong> with <strong>Virtualization<\/strong> could be used to practice and demo RHEL for Edge use-cases.<\/p>\n\n\n\n<p>This particular example is built on the top of <a href=\"https:\/\/docs.openshift.com\/container-platform\/4.12\/installing\/installing_sno\/install-sno-installing-sno.html\">Single Node OpenShift<\/a> deployment, however it should run on any regular OpenShift Container Platform with OpenShift Virtualization enabled as well.<\/p>\n\n\n\n<p>The setup consist of:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em><strong>podNetwork<\/strong><\/em> &#8211; this is the default network where pods running on OpenShift are connected to<\/li>\n\n\n\n<li><em><strong>br<\/strong>&#8211;<strong>edge<\/strong><\/em> &#8211; local bridge simulating edge network which edge devices are using to bootstrap from<\/li>\n\n\n\n<li><em><strong>edge-helper<\/strong><\/em> &#8211; an VM where supporting services are running, including <em>image-builder, dnsmasq(dhcp, tftp), nginx, nftables(masquerade)<\/em><\/li>\n\n\n\n<li><em><strong>RHEL for EDGE container<\/strong><\/em> &#8211; a pod with a single container providing repository needed to provision edge-server<\/li>\n\n\n\n<li><em><strong>edge-servers<\/strong><\/em> &#8211; a set of VMs simulating edge-devices which we provision using RHEL for EDGE<\/li>\n<\/ul>\n\n\n\n<p>All running on the top of Red Hat OpenShift Container Platform.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"1640\" height=\"680\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/rhel4edge-lab-diagram.png\" alt=\"\" class=\"wp-image-33\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/rhel4edge-lab-diagram.png 1640w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/rhel4edge-lab-diagram-300x124.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/rhel4edge-lab-diagram-1024x425.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/rhel4edge-lab-diagram-768x318.png 768w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/rhel4edge-lab-diagram-1536x637.png 1536w\" sizes=\"auto, (max-width: 1640px) 100vw, 1640px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Requirements<\/h2>\n\n\n\n<p>Before we start let&#8217;s establish what the requirements and assumptions are. You will need:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Red Hat OpenShift Container Platform with <a href=\"https:\/\/docs.openshift.com\/container-platform\/4.12\/virt\/about-virt.html\">Virtualization<\/a> support enabled\n<ul class=\"wp-block-list\">\n<li>it can be Single Node OpenShift (<a href=\"https:\/\/docs.openshift.com\/container-platform\/4.12\/installing\/installing_sno\/install-sno-installing-sno.html\">SNO<\/a>) deployment &#8211; even virtualized<\/li>\n\n\n\n<li>multi-node deployments need extra care for network and storage configurations to ensure connectivity between the elements and storage persistence<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Subscriptions\n<ul class=\"wp-block-list\">\n<li>Red Hat OpenShift subscription covering all the nodes being used (for SNO you need only one \ud83d\ude42 )<\/li>\n\n\n\n<li>Red Hat Enterprise Linux subscription for edge-helper VM<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Persistent storage\n<ul class=\"wp-block-list\">\n<li>for SNO scenario, storage provided by local-storage operator is sufficient<\/li>\n\n\n\n<li>for multi-node scenarios, the best is to use <a href=\"https:\/\/www.redhat.com\/en\/technologies\/cloud-computing\/openshift-data-foundation\">Red Hat OpenShift Data Foundation<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Internet access &#8211; so we can register our VM and download required packages from Red Hat&#8217;s CDN<\/li>\n<\/ul>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Installation<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\"><em>edge-lab<\/em> project<\/h4>\n\n\n\n<p>All the activities you will perform will happen within a single project. For the purpose of this document I create and use <strong><em>edge-lab<\/em><\/strong> project.<\/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>&#91;rafal@host ~]$ oc new-project edge-lab<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Edge network bridge &#8211; <em>br-edge<\/em><\/h4>\n\n\n\n<p>In order to simulate an <em>edge-network<\/em>, internal dummy bridge <em><strong>br-edge<\/strong><\/em> is being used in this scenario. <strong>The bridge does not have external connectivity<\/strong> so it works only for either Single Node OpenShift or for multi-node scenarios as long as all workloads will run on that single node.<br>For multi-node deployments where multiple nodes are being used you must use bridge connected to real NIC which provides communication between nodes being used.<\/p>\n\n\n\n<p>Please see <a href=\"https:\/\/docs.openshift.com\/container-platform\/4.12\/networking\/multiple_networks\/understanding-multiple-networks.html\">Understanding multiple networks<\/a> document for more details.<\/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>&#91;rafal@host ~]$ cat &lt;&lt; EOF | oc create -n edge-lab -f - \napiVersion: k8s.cni.cncf.io\/v1\nkind: NetworkAttachmentDefinition\nmetadata:\n  name: br-edge\nspec:\n  config: |-\n    {\n      \"cniVersion\": \"0.3.1\",\n      \"name\": \"br-edge\",\n      \"type\": \"bridge\"\n    }\nEOF<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Preparation of edge-helper virtual machine<\/h4>\n\n\n\n<p>This virtual machine will be used for us for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><em>image-builder<\/em><\/strong> &#8211; the tool to configure, build and export image of RHEL for Edge servers<\/li>\n\n\n\n<li><strong><em>dhcp server<\/em><\/strong> &#8211; for edge network where servers will be booted from<\/li>\n\n\n\n<li><strong><em>router<\/em><\/strong> with SNAT\/Masquerade &#8211; to allow access from edge network to the external world (including OpenShift routes)<\/li>\n\n\n\n<li><strong><em>tftp server<\/em><\/strong> &#8211; to facilitate network boot<\/li>\n\n\n\n<li><strong><em>nginx server<\/em><\/strong> &#8211; to provide ISO image, kickstart and other files required to boot the servers<\/li>\n<\/ul>\n\n\n\n<p>To create the VM please go to <strong><em>Virtualization -&gt; Templates -&gt; Find &#8220;Red Hat Enterprise Linux 9.X VM&#8221;<\/em><\/strong> template and click &#8220;<strong><em>Create VM<\/em><\/strong>&#8220;.<\/p>\n\n\n\n<p>Fill the form (name of the VM), use the biggest VM flavor possible since image-builder requires extra resources.<br>Expand &#8220;<em><strong>Authorized key<\/strong><\/em>&#8221; to add your ssh public key, check &#8220;<em><strong>Expose SSH access to this virtual machine<\/strong><\/em>&#8221; box.<\/p>\n\n\n\n<p>Now click &#8220;<strong><em>Customize virtual machine<\/em><\/strong>&#8221; button to custom it in more detail.<br>In General tab confirm the size of the VM or alternatively specify custom CPU and memory allocation. The bigger the better \ud83d\ude09<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1431\" height=\"1225\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-general.png\" alt=\"\" class=\"has-border-color wp-image-38\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-general.png 1431w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-general-300x257.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-general-1024x877.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-general-768x657.png 768w\" sizes=\"auto, (max-width: 1431px) 100vw, 1431px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>In the <strong>Networking<\/strong> tab, add extra network interface provided by <strong>Multus<\/strong> &#8211; you&#8217;ve created it earlier &#8211; with the following specification:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Name<\/strong>: nic-0<\/li>\n\n\n\n<li><strong>Model<\/strong>: virtio<\/li>\n\n\n\n<li><strong>Network<\/strong>: br-edge<\/li>\n\n\n\n<li><strong>Type<\/strong>: Bridge<\/li>\n\n\n\n<li><strong>MAC Address<\/strong>: <em>leave it blank<\/em><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1432\" height=\"1222\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-network-add-interface.png\" alt=\"\" class=\"has-border-color wp-image-40\" style=\"border-color:#787878a6\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-network-add-interface.png 1432w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-network-add-interface-300x256.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-network-add-interface-1024x874.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-network-add-interface-768x655.png 768w\" sizes=\"auto, (max-width: 1432px) 100vw, 1432px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Ensure &#8220;<strong><em>rootdisk<\/em><\/strong>&#8221; in &#8220;<strong><em>Storage<\/em><\/strong>&#8221; section is using <strong>persistent storage<\/strong> &#8211; in my case with SNO being used, it is <em>sno-storage<\/em> StorageClass.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1431\" height=\"1225\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-storage.png\" alt=\"\" class=\"has-border-color wp-image-52\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-storage.png 1431w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-storage-300x257.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-storage-1024x877.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-storage-768x657.png 768w\" sizes=\"auto, (max-width: 1431px) 100vw, 1431px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>In &#8220;<strong><em>Advanced<\/em><\/strong>&#8221; tab you probably don&#8217;t have to change anything, just confirm you have configured the right SSH key and if you REALLY need it, you can specify your own password for the default <em>cloud-user<\/em>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1430\" height=\"1225\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-advanced.png\" alt=\"\" class=\"has-border-color wp-image-53\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-advanced.png 1430w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-advanced-300x257.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-advanced-1024x877.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-advanced-768x658.png 768w\" sizes=\"auto, (max-width: 1430px) 100vw, 1430px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Now just a quick check on the review page and you can continue the VM creation. After a while your VM should be up and running.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1435\" height=\"1260\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-review.png\" alt=\"\" class=\"has-border-color wp-image-55\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-review.png 1435w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-review-300x263.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-review-1024x899.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/virt-templates-create-review-768x674.png 768w\" sizes=\"auto, (max-width: 1435px) 100vw, 1435px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Accessing <em>edge-helper<\/em> virtual machine<\/h2>\n\n\n\n<p>The <em>edge-helper<\/em> VM is up and running now, but before we start configuring it we need to somehow access it first \ud83d\ude09<br>Since you checked the option to expose SSH access before, you have to find now what is the IP address and the port number where the SSH of <em>edge-helper<\/em> VM can be accessed.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">The port<\/h4>\n\n\n\n<p>The port number can be found with CLI or VM&#8217;s detail page<\/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>&#91;rafal@host ~]$ oc get svc\nNAME                      TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)           AGE\nedge-helper-ssh-service   NodePort   172.30.169.111   &lt;none&gt;        22000:<strong>31094<\/strong>\/TCP   123m\n\n&#91;rafal@host ~]$ oc get svc edge-helper-ssh-service -o jsonpath='{.spec.ports&#91;].nodePort}'\n<strong>31094<\/strong><\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1436\" height=\"1205\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/vm-details-ssh-port.png\" alt=\"\" class=\"has-border-color wp-image-43\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/vm-details-ssh-port.png 1436w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/vm-details-ssh-port-300x252.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/vm-details-ssh-port-1024x859.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/vm-details-ssh-port-768x644.png 768w\" sizes=\"auto, (max-width: 1436px) 100vw, 1436px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">The IP address<\/h4>\n\n\n\n<p>SSH is exposed through <em><strong>NodeIP<\/strong><\/em> address, hence you need to get one of the nodes IPs. You can do it again either via CLI or WebUI<\/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>&#91;rafal@host ~]$ oc get nodes -o jsonpath='{.items&#91;].status.addresses &#91;?(@.type==\"InternalIP\")].address}'\n192.168.232.127<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1434\" height=\"1262\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/node-details-ip-address.png\" alt=\"\" class=\"has-border-color wp-image-44\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/node-details-ip-address.png 1434w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/node-details-ip-address-300x264.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/node-details-ip-address-1024x901.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/node-details-ip-address-768x676.png 768w\" sizes=\"auto, (max-width: 1434px) 100vw, 1434px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">The password<\/h4>\n\n\n\n<p>You should not need a password to access the VM since we got SSH key configured, however you will need the password later to access VM&#8217;s WebUI console. You can obtain it with the following command:<\/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>&#91;rafal@host ~]$ oc get vm edge-helper -o jsonpath='{.spec.template.spec.volumes&#91;?(@.name==\"cloudinitdisk\")].cloudInitNoCloud.userData}'  | grep ^password\npassword: <em>'__SuperSecretPassword.8__'<\/em><\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Connecting to the VM<\/h4>\n\n\n\n<p>Once you got both the IP address and the port number, you can SSH to it using previously configured SSH key. Let&#8217;s do it and verify you&#8217;ve got all the NICs available there.<\/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>&#91;rafal@host ~]$ ssh cloud-user@192.168.232.127 -p 31094\n&#91;cloud-user@edge-helper ~]$ ip -o l\n1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000    link\/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1400 qdisc mq state UP mode DEFAULT group default qlen 1000    link\/ether 02:bb:1e:00:00:0e brd ff:ff:ff:ff:ff:ff    altname enp1s0\n3: eth1: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000    link\/ether 02:bb:1e:00:00:0f brd ff:ff:ff:ff:ff:ff    altname enp2s0<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring edge-helper Virtual Machine<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">Registering VM with Red Hat<\/h4>\n\n\n\n<p>Once you&#8217;re logged in please register the VM with Red Hat in order to obtain access to packages and attach it to the right pool providing required RHEL packages<\/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>&#91;root@edge-helper ~]# subscription-manager register\nRegistering to: subscription.rhsm.redhat.com:443\/subscription\nUsername: <em>&lt;your RHN username&gt;<\/em>\nPassword: <em>&lt;your RHN password&gt;<\/em>\nThe system has been registered with ID: <em>__some-random-string-is-here__<\/em>\nThe registered system name is: edge-helper\n&#91;root@edge-helper ~]# subscription-manager attach --auto<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Installing base packages<\/h4>\n\n\n\n<p>The process of installation and configuration all the required services for <em><strong>edge-helper<\/strong><\/em> VM is automated through Ansible, so for now you need only the following three packages to be installed: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ansible-core<\/li>\n\n\n\n<li>python3-netaddr<\/li>\n\n\n\n<li>git<\/li>\n<\/ul>\n\n\n\n<p>Furthermore you need to install <strong><em>community.general <\/em><\/strong>and <strong><em>ansible.utils<\/em><\/strong> Ansible&#8217;s collections.<br><em><strong>Please note:<\/strong> This guide assumes you&#8217;re configuring the edge-helper VM locally, hence these packages are being installed directly on it. Alternatively you can do it remotely from some other host with the above packages and collections installed.<\/em><\/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>&#91;root@edge-helper ~]# dnf install -y ansible-core git python3-netaddr\n&#91;root@edge-helper ~]# ansible-galaxy collection install community.general ansible.utils<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Cloning <em>openshift-lab<\/em> repository<\/h4>\n\n\n\n<p>This is where all the good stuff that automates most of the things is hosted. Please clone it locally. The content for this lab is in <strong>rhel4edge-00<\/strong> directory.<\/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>&#91;root@edge-helper ~]# git clone https:\/\/github.com\/rszmigiel\/openshift-lab.git<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Configuring localhost ssh-key access<\/h4>\n\n\n\n<p>To make it easier, create and add ssh key for localhost authentication. This is just to automate localhost access on the <em>edge-helper<\/em> VM:<\/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>&#91;root@edge-helper ~]# ssh-keygen\nGenerating public\/private rsa key pair.\n(...)\n&#91;root@edge-helper ~]# cat .ssh\/id_rsa.pub &gt;&gt; .ssh\/authorized_keys<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Installing and configuring Image Builder service<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">Playbook variables<\/h4>\n\n\n\n<p>There is just one required variable you have to set, <strong><em>cluster-name<\/em><\/strong> which allows the playbook to download and install <strong><em>virtctl<\/em><\/strong> CLI tool on the <em>edge-helper <\/em>VM. It should include the domain name as well, for an instance: <strong>cluster-name.example.com<\/strong> <\/p>\n\n\n\n<p>The list of all available variables is as follows:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">variable<\/th><th class=\"has-text-align-left\" data-align=\"left\">required<\/th><th class=\"has-text-align-left\" data-align=\"left\">default<\/th><th class=\"has-text-align-left\" data-align=\"left\">description<\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-left\" data-align=\"left\">cluster_name<\/td><td class=\"has-text-align-left\" data-align=\"left\"><strong>yes<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\"><em>none<\/em><\/td><td class=\"has-text-align-left\" data-align=\"left\">cluster-name.example.com<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">ip_range<\/td><td class=\"has-text-align-left\" data-align=\"left\">no<\/td><td class=\"has-text-align-left\" data-align=\"left\">192.168.10.0\/24<\/td><td class=\"has-text-align-left\" data-align=\"left\">IP range for edge network<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">ip_address<\/td><td class=\"has-text-align-left\" data-align=\"left\">no<\/td><td class=\"has-text-align-left\" data-align=\"left\">2nd IP from <em>ip_range<\/em><\/td><td class=\"has-text-align-left\" data-align=\"left\">IP address for VM&#8217;s edge network interface<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">ip_gw<\/td><td class=\"has-text-align-left\" data-align=\"left\">no<\/td><td class=\"has-text-align-left\" data-align=\"left\">VM&#8217;s IP address<\/td><td class=\"has-text-align-left\" data-align=\"left\">Edge network gateway, by default it is edge-helper vm itself<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">dhcp_interface<\/td><td class=\"has-text-align-left\" data-align=\"left\">no<\/td><td class=\"has-text-align-left\" data-align=\"left\">eth1<\/td><td class=\"has-text-align-left\" data-align=\"left\">Name of the NIC connected to edge network<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Run the playbook<\/h4>\n\n\n\n<p>The playbook will perform the following actions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>one<\/li>\n\n\n\n<li>two<\/li>\n\n\n\n<li>three<\/li>\n\n\n\n<li>tbd<\/li>\n<\/ul>\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>&#91;root@edge-helper rhel4edge-00]# ansible-playbook -i localhost, install_image_builder.yml -e \"ocp_cluster-name=cluster-name.example.com\"<\/code><\/pre>\n\n\n\n<p>or alternatively if you want to override some of the default variables:<\/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>&#91;root@edge-helper rhel4edge-00]# ansible-playbook -i localhost, install_image_builder.yml -e \"ocp_cluster-name=cluster-name.example.com\" -e \"ip_range=192.168.20.0\/24\" -e \"ip_gw=192.168.20.254\"<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Logging to the OpenShift cluster from <em>edge-helper<\/em> VM<\/h4>\n\n\n\n<p>Firstly let&#8217;s login to the OCP cluster through oc CLI and straight away switch to edge-lab project. This will let you run all oc and virtctl commands from the <em>edge-helper<\/em> VM.<\/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>&#91;root@edge-helper ~]# oc login -u kubeadmin api.cluster-name.example.com:6443\nAuthentication required for https:\/\/api.cluster-name.example.com:6443 (openshift)\nUsername: kubeadmin\nPassword: ********\nLogin successful.\n\nYou have access to 92 projects, the list has been suppressed. You can list all projects with 'oc projects'\n\nUsing project \"default\".\n&#91;root@edge-helper ~]# oc project edge-lab\nNow using project \"edge-lab\" on server \"https:\/\/api.cluster-name.example.com:6443\".<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Adding OpenShift&#8217;s service CA to locally trusted certificates<\/h4>\n\n\n\n<p>Most likely your OCP cluster runs self-signed certificates which aren&#8217;t recognised by <em>edge-helper<\/em> VM. Let&#8217;s install them locally so we won&#8217;t be bothered by unknown CA warnings later.<\/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>&#91;root@edge-helper ~]# oc extract cm\/openshift-service-ca.crt --to=\/etc\/pki\/ca-trust\/source\/anchors\/\n\/etc\/pki\/ca-trust\/source\/anchors\/service-ca.crt\n&#91;root@edge-helper ~]# update-ca-trust --extract<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Get cloud-user password<\/h4>\n\n\n\n<p>If you didn&#8217;t explicitly configure password during VM creation or you didn&#8217;t obtain it previously, here is a snippet to get it from <em>cloudInit userData<\/em> stored in the VM definition. You will need the password to access WebUI console.<\/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>&#91;root@edge-helper ~]# oc get vm edge-helper -o jsonpath='{.spec.template.spec.volumes&#91;?(@.name==\"cloudinitdisk\")].cloudInitNoCloud.userData}'  | grep ^password\npassword: <em>'__SuperSecretPassword.8__'<\/em><\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Expose and access <em>edge-helper<\/em> WebUI console<\/h4>\n\n\n\n<p>By default you got SSH service created and exposed of <em>edge-helper<\/em> VM during its installation. You can also expose its WebUI console which listens on <em><strong>9090\/tcp<\/strong><\/em> port in order to access it externally.<\/p>\n\n\n\n<p>Using <em>virtctl<\/em> let&#8217;s create service first and with <em>oc<\/em> CLI create route pointing to it.<\/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>&#91;root@edge-helper ~]# virtctl expose vmi edge-helper --port=<strong>9090<\/strong> --name=<strong>image-builder<\/strong>\nService image-builder successfully exposed for vmi edge-helper\n&#91;root@edge-helper ~]# oc create route passthrough --service=<strong>image-builder<\/strong>\nroute.route.openshift.io\/image-builder created\n&#91;root@edge-helper ~]# oc get routes\nNAME            HOST\/PORT                                        PATH   SERVICES        PORT    TERMINATION   WILDCARD\nimage-builder   <strong>image-builder-edge-lab.apps.cluster-name.example.com<\/strong>          <strong>image-builder<\/strong>   &lt;all&gt;   passthrough   None<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>With the output above you can say the WebUI console is available at <a href=\"https:\/\/image-builder-edge-lab.apps.cluster-name.example.com\">https:\/\/<strong>image-builder-edge-lab.apps.cluster-name.example.com<\/strong><\/a>. In your case it will be obviously different but now you should be able to login there using <strong><em>cloud-user<\/em><\/strong> user and the<strong> password<\/strong> you retrieved step before.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1437\" height=\"966\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/image-builder-webui-console.png\" alt=\"\" class=\"has-border-color wp-image-59\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/image-builder-webui-console.png 1437w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/image-builder-webui-console-300x202.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/image-builder-webui-console-1024x688.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/image-builder-webui-console-768x516.png 768w\" sizes=\"auto, (max-width: 1437px) 100vw, 1437px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">The very first image<\/h2>\n\n\n\n<p>It takes a while to build an image, especially in resource limited environment, so let&#8217;s do it before we proceed with the second part of <em>edge-helper<\/em> VM configuration.<\/p>\n\n\n\n<p>To quickly explain what this image really is I will quote official <a rel=\"noreferrer noopener\" href=\"https:\/\/access.redhat.com\/documentation\/en-us\/red_hat_enterprise_linux\/9\/html\/composing_installing_and_managing_rhel_for_edge_images\/introducing-rhel-for-edge-images_composing-installing-managing-rhel-for-edge-images#doc-wrapper\" data-type=\"URL\" data-id=\"https:\/\/access.redhat.com\/documentation\/en-us\/red_hat_enterprise_linux\/9\/html\/composing_installing_and_managing_rhel_for_edge_images\/introducing-rhel-for-edge-images_composing-installing-managing-rhel-for-edge-images#doc-wrapper\" target=\"_blank\">Red Hat&#8217;s documentation<\/a>:<br>A RHEL for Edge image is an <em>rpm-ostree<\/em> image that includes system packages to remotely install <strong>RHEL on Edge<\/strong> servers.<br>The system packages include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Base OS package<\/li>\n\n\n\n<li>Podman as the container engine<\/li>\n\n\n\n<li>Additional RPM content<\/li>\n<\/ul>\n\n\n\n<p>Differently from RHEL images, <strong>RHEL for Edge is an immutable operating system<\/strong>, that is, it contains a read-only root directory with the following characteristics:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The packages are isolated from root directory<\/li>\n\n\n\n<li>Package installs create layers that make it easy to rollback to previous versions<\/li>\n\n\n\n<li>Efficient updates to disconnected environments<\/li>\n\n\n\n<li>Supports multiple operating system branches and repositories<\/li>\n\n\n\n<li>Has a hybrid rpm-ostree package system<\/li>\n<\/ul>\n\n\n\n<p>Images are being created from <strong>blueprints<\/strong>.  Blueprint is a kind of receipt of what should be included in the image on the top of the defaults provided out of the box by Red Hat. Oh &#8211; you can also use blueprint to remove unwanted bits as well \ud83d\ude42<\/p>\n\n\n\n<p><br>You&#8217;re now at <em>edge-helper<\/em> console page, so from the left menu chose <strong>Image Builder<\/strong> option and create a new blueprint.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1437\" height=\"1261\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-blueprint.png\" alt=\"\" class=\"has-border-color wp-image-62\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-blueprint.png 1437w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-blueprint-300x263.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-blueprint-1024x899.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-blueprint-768x674.png 768w\" sizes=\"auto, (max-width: 1437px) 100vw, 1437px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Once you got blueprint ready, please create image from it. You apply some customisations during this step.<br>Select <strong>Create image<\/strong> and ensure <strong>Image output type<\/strong> is set to <strong>RHEL for Edge Container (.tar)<\/strong>. There are other image output types which are described in detail here: <a rel=\"noreferrer noopener\" href=\"https:\/\/access.redhat.com\/documentation\/en-us\/red_hat_enterprise_linux\/9\/html\/composing_installing_and_managing_rhel_for_edge_images\/introducing-rhel-for-edge-images_composing-installing-managing-rhel-for-edge-images#edge-how-to-compose-and-deploy-a-rhel-for-edge-image_introducing-rhel-for-edge-images\" target=\"_blank\">1.2. How to compose and deploy a RHEL for Edge image<\/a>, but since you&#8217;re running OpenShift already let&#8217;s use it to host the container with image natively.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1433\" height=\"1260\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-output.png\" alt=\"\" class=\"has-border-color wp-image-63\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-output.png 1433w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-output-300x264.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-output-1024x900.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-output-768x675.png 768w\" sizes=\"auto, (max-width: 1433px) 100vw, 1433px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>In the <strong>OSTree settings<\/strong> section you don&#8217;t have to fill anything at this time, so please skip it and move to the next section.<\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>In <strong>Customizations \/ System<\/strong> please assign hostname to our edge server. If not defined here it could be provided via DHCP what probably makes better sense at the large scale deployments.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1436\" height=\"1264\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-customizations-system.png\" alt=\"\" class=\"has-border-color wp-image-64\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-customizations-system.png 1436w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-customizations-system-300x264.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-customizations-system-1024x901.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-customizations-system-768x676.png 768w\" sizes=\"auto, (max-width: 1436px) 100vw, 1436px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>In <strong>Customizations \/ Users<\/strong> you can add extra user to the system. Please note <strong>users can be added in the image only at the bootstrap time<\/strong>, later users have to be added locally (ie. adding new user to upgrade image won&#8217;t create user on existing system being upgraded). Also please note there is <strong>checkbox<\/strong> bellow to assign the user with <strong>Server administrator privileges<\/strong> (sudo permissions).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1438\" height=\"991\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-customizations-users.png\" alt=\"\" class=\"has-border-color wp-image-65\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-customizations-users.png 1438w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-customizations-users-300x207.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-customizations-users-1024x706.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-customizations-users-768x529.png 768w\" sizes=\"auto, (max-width: 1438px) 100vw, 1438px\" \/><\/figure>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>In <strong>Packages<\/strong> we can add extra packages to the image<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1435\" height=\"993\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-packages.png\" alt=\"\" class=\"has-border-color wp-image-66\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-packages.png 1435w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-packages-300x208.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-packages-1024x709.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-packages-768x531.png 768w\" sizes=\"auto, (max-width: 1435px) 100vw, 1435px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Before we create blueprint and image from it, let&#8217;s review the configuration we made. Ensure the output type is edge-container. <strong>Save the blueprint<\/strong> and <strong>Create the image<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1433\" height=\"991\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-summary.png\" alt=\"\" class=\"has-border-color wp-image-67\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-summary.png 1433w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-summary-300x207.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-summary-1024x708.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-summary-768x531.png 768w\" sizes=\"auto, (max-width: 1433px) 100vw, 1433px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>You can watch the <strong>image build status<\/strong> either via CLI or WebUI<\/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>&#91;root@edge-helper ~]# composer-cli compose list\n5ebc967a-c248-46ca-b817-dd22b395bc2c RUNNING rafal-test 0.0.1 edge-container<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1434\" height=\"990\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-progress.png\" alt=\"\" class=\"has-border-color wp-image-68\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-progress.png 1434w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-progress-300x207.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-progress-1024x707.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/create-image-progress-768x530.png 768w\" sizes=\"auto, (max-width: 1434px) 100vw, 1434px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Installing and configuring dnsmasq and nginx services on <em>edge-helper<\/em> VM.<\/h2>\n\n\n\n<p>Since it may take some time to get the image build process done, let&#8217;s configure <em>dnsmasq<\/em> and <em>nginx<\/em> on the <em>edge-helper<\/em> VM while image is being created. You have another playbook to be run and two mandatory variables to be specified with it. This playbook apart from dnsmasq and nginx installation and configuration will also do:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>one<\/li>\n\n\n\n<li>two<\/li>\n\n\n\n<li>three<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">variable<\/th><th class=\"has-text-align-left\" data-align=\"left\">required<\/th><th class=\"has-text-align-left\" data-align=\"left\">default<\/th><th class=\"has-text-align-left\" data-align=\"left\">description<\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-left\" data-align=\"left\">rhel_boot_url<\/td><td class=\"has-text-align-left\" data-align=\"left\">yes<\/td><td class=\"has-text-align-left\" data-align=\"left\">none<\/td><td class=\"has-text-align-left\" data-align=\"left\">The URL where Red Hat Enterprise Linux Boot ISO image can be downloaded from. Get it from <a href=\"https:\/\/access.redhat.com\/downloads\/content\/479\/ver=\/rhel---9\/9.1\/x86_64\/product-software\">https:\/\/access.redhat.com\/downloads\/content\/479\/ver=\/rhel&#8212;9\/9.1\/x86_64\/product-software<\/a><\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">image_location<\/td><td class=\"has-text-align-left\" data-align=\"left\">yes<\/td><td class=\"has-text-align-left\" data-align=\"left\">none<\/td><td class=\"has-text-align-left\" data-align=\"left\">This is URL where edge-container image will be exposed as an OpenShift&#8217;s route<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">ip_gw<\/td><td class=\"has-text-align-left\" data-align=\"left\">no<\/td><td class=\"has-text-align-left\" data-align=\"left\">VM&#8217;s IP address<\/td><td class=\"has-text-align-left\" data-align=\"left\">Edge network gateway, by default it is the VM<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">dhcp_interface<\/td><td class=\"has-text-align-left\" data-align=\"left\">no<\/td><td class=\"has-text-align-left\" data-align=\"left\">eth1<\/td><td class=\"has-text-align-left\" data-align=\"left\">Name of the NIC connected to edge network<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>The <em>image_location<\/em> variable is the location where image container content will be available for the bootstrap process. Typically in OpenShift the format is: <strong>service-name<\/strong>&#8211;<strong>project-name<\/strong>.apps.cluster-name.cluster-domain but it can be customised. For the purpose of this document I use the defaults. Let&#8217;s run the playbook and once it finish, you should have the image built process being completed.<\/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>&#91;root@edge-helper rhel4edge-00]# ansible-playbook -i localhost, install_dnsmasq.yml -e \"rhel_boot_url=https:\/\/access.cdn.redhat.com\/content\/origin\/files\/sha256\/(...)\/rhel-baseos-9.1-x86_64-boot.iso?user=(...)&amp;_auth_=(...)\" -e \"image_location=http:\/\/edge-container-edge-lab.apps.cluster-name.example.com\/repo\"<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Getting the image container running on OpenShift<\/h2>\n\n\n\n<p>Hopefully the build of the image has been complete now. Verify it with the following commands. You&#8217;re looking for your image with <strong>FINISHED<\/strong> state \ud83d\ude09 so you can download it to <em>edge-helper<\/em> VM using <code>composer-cli compose image<\/code> command and image&#8217;s UUID as the parameter.<\/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>&#91;root@edge-helper ~]# composer-cli compose list\n5ebc967a-c248-46ca-b817-dd22b395bc2c FINISHED rafal-test 0.0.1 edge-container\n\n&#91;root@edge-helper ~]# composer-cli compose image 5ebc967a-c248-46ca-b817-dd22b395bc2c\n5ebc967a-c248-46ca-b817-dd22b395bc2c-container.tar<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Once you get the tar file downloaded, load it to the local podman&#8217;s image registry and tag accordingly so you can put it to OpenShift&#8217;s image registry service as bellow.<\/p>\n\n\n\n<p>Please note: since the <em>edge-helper<\/em> VM is running on the top of OpenShift Virtualization, you can access other OpenShift services directly without the need of creating and using external route\/ingress.<\/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>&#91;root@edge-helper ~]# podman load -i 5ebc967a-c248-46ca-b817-dd22b395bc2c-container.tar\nGetting image source signatures\nCopying blob eee3c89aa887 done\nCopying config 66cc26987d done\nWriting manifest to image destination\nStoring signatures\nLoaded image: sha256:66cc26987d9c3e21d43b90b8949cfdd144391be496f3958aeb3f7d0070a85a7d\n\n&#91;root@edge-helper ~]# podman images\nREPOSITORY                       TAG         IMAGE ID      CREATED      SIZE\n&lt;none&gt;                           &lt;none&gt;      66cc26987d9c  2 hours ago  922 MB\n\n&#91;root@edge-helper ~]# podman tag 66cc26987d9c image-registry.openshift-image-registry.svc.cluster.local:5000\/edge-lab\/rafal-test:0.0.1\n\n&#91;root@edge-helper ~]# podman login -u kubeadmin -p $(oc whoami -t) image-registry.openshift-image-registry.svc.cluster.local:5000\/edge-lab\nLogin Succeeded!\n\n&#91;root@edge-helper ~]# podman push image-registry.openshift-image-registry.svc.cluster.local:5000\/edge-lab\/rafal-test:0.0.1\nGetting image source signatures\nCopying blob fa84083736a8 done\nCopying config 66cc26987d done\nWriting manifest to image destination\nStoring signatures<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Get that thing running now! \ud83d\ude42<\/p>\n\n\n\n<p>Please note: RHEL for Edge container is running nginx bound to 8080\/tcp port.<\/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>&#91;root@edge-helper ~]# oc run edge-container --image=image-registry.openshift-image-registry.svc.cluster.local:5000\/edge-lab\/rafal-test:0.0.1 --port=8080\npod\/edge-container created\n\n&#91;root@edge-helper ~]# oc get pods\nNAME                              READY   STATUS    RESTARTS   AGE\nedge-container                    1\/1     Running   0          5s\nvirt-launcher-edge-helper-mq7rt   1\/1     Running   0          24h<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>You got the pod running so now expose <code>8080\/tcp<\/code> port where the nginx serving the image content is listening and create route for it, so <em>edge-server<\/em> VM can reach it as it doesn&#8217;t have direct access to the <em>podNetwork<\/em> so it cannot access services directly, without route or ingress.<\/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>&#91;root@edge-helper ~]# oc expose pod edge-container\nservice\/edge-container exposed\n\n&#91;root@edge-helper ~]# oc get svc edge-container\nNAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE\nedge-container   ClusterIP   172.30.82.192   &lt;none&gt;        8080\/TCP   11s\n\n&#91;root@edge-helper ~]# oc expose svc edge-container\nroute.route.openshift.io\/edge-container exposed\n\n&#91;root@edge-helper ~]# oc get route edge-container\nNAME             HOST\/PORT                                         PATH   SERVICES         PORT   TERMINATION   WILDCARD\nedge-container   edge-container-edge-lab.apps.cluster-name.example.com          edge-container   8080                 None<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Let&#8217;s double check if we can really reach it as expected<\/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>&#91;root@edge-helper ~]# curl http:\/\/edge-container-edge-lab.apps.cluster-name.example.com\/repo\/refs\/heads\/rhel\/9\/x86_64\/edge\n\n8fad2a65c1873987dae3c5ed28be350180a3b4386b0650a4e24f06925c71c595<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Running an edge server<\/h2>\n\n\n\n<p>Or technically speaking, a VM which is going to simulate an edge server. There are few things to notice:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>bootOrder<\/em> parameter &#8211; which let you configure in what order server should try to boot from specific device. In the config bellow the server try to boot from disk first, then from network. Since disk is empty it will effectively boot over network through iPXE.<\/li>\n\n\n\n<li><em>secureBoot<\/em> parameter &#8211; it disables UEFI secure boot which is enabled by default since our image isn&#8217;t signed<\/li>\n\n\n\n<li><em>networkName<\/em> parameter &#8211; to specify the VM has to be attached to <em>br-edge<\/em> network<\/li>\n<\/ul>\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>&#91;root@edge-helper ~]# cat &lt;&lt; EOF | oc create -f - \napiVersion: kubevirt.io\/v1\nkind: VirtualMachine\nmetadata:\n  labels:\n    app: rhel-edge-server\n  name: rhel-edge-server\nspec:\n  dataVolumeTemplates:\n  - apiVersion: cdi.kubevirt.io\/v1beta1\n    kind: DataVolume\n    metadata:\n      name: rhel-edge-server\n    spec:\n      source:\n        blank: {}\n      storage:\n        resources:\n          requests:\n            storage: 30Gi\n  running: false\n  template:\n    metadata:\n      annotations:\n        vm.kubevirt.io\/flavor: small\n        vm.kubevirt.io\/os: rhel9\n        vm.kubevirt.io\/workload: server\n      labels:\n        kubevirt.io\/domain: rhel-edge-server\n        kubevirt.io\/size: small\n    spec:\n      domain:\n        cpu:\n          cores: 1\n          sockets: 1\n          threads: 1\n        devices:\n          disks:\n          - disk:\n              bus: virtio\n            name: rhel-edge-server\n<strong>            bootOrder: 1\n<\/strong>          interfaces:\n          - bridge: {}\n<strong>            bootOrder: 2\n<\/strong>            model: virtio\n            name: nic-0\n          networkInterfaceMultiqueue: true\n          rng: {}\n        features:\n          smm:\n            enabled: true\n        firmware:\n          bootloader:\n            efi:\n<strong>              secureBoot: false\n<\/strong>        machine:\n          type: pc-q35-rhel8.4.0\n        resources:\n          requests:\n            memory: 2Gi\n      evictionStrategy: LiveMigrate\n      networks:\n      - multus:\n<strong>          networkName: br-edge\n<\/strong>        name: nic-0\n      terminationGracePeriodSeconds: 180\n      volumes:\n      - dataVolume:\n          name: rhel-edge-server\n        name: rhel-edge-server\nEOF<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Once server is created and provisioned it will remain <strong>Stopped<\/strong>, start it and jump to the console. If everything is right you should see the following menu. Select <strong>Bootstrap this system&#8230;<\/strong> and have fun watching the bootstrap process \ud83d\ude42<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1434\" height=\"1045\" src=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/edge-server-bootstrap.png\" alt=\"\" class=\"has-border-color wp-image-76\" style=\"border-color:#777777\" srcset=\"https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/edge-server-bootstrap.png 1434w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/edge-server-bootstrap-300x219.png 300w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/edge-server-bootstrap-1024x746.png 1024w, https:\/\/blog.openshift.one\/wp-content\/uploads\/2023\/03\/edge-server-bootstrap-768x560.png 768w\" sizes=\"auto, (max-width: 1434px) 100vw, 1434px\" \/><\/figure>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Accessing the edge server<\/h2>\n\n\n\n<p>You can access the <em>edge-server<\/em> you created and bootstraped either via OpenShift Virtualization console with the password or via SSH using ssh key you configured in the blueprint earlier. Because <em>edge-server<\/em> is connected to internal bridge on the SNO instance, you have to SSH to it from the<em> edge-helper<\/em> VM.<\/p>\n\n\n\n<p>The easiest way to determine <em>edge-server<\/em>&#8216;s IP address is to check DHCP leases at <em>edge-helper <\/em>VM.<\/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>&#91;root@edge-helper ~]# cat \/var\/lib\/dnsmasq\/dnsmasq.leases\n0 02:bb:1e:00:00:10 <strong>192.168.10.194<\/strong> rhel-edge-server 01:02:bb:1e:00:00:10<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>In this first post about OCP-V and RHEL for Edge I demonstrated how to use OCP&#8217;s capabilities to run simple demo for virtualized RHEL for Edge lab. Stay tuned &#8211; in the next one I will show some more advanced topics around RHEL for Edge and OCP-V.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The purpose of this document is to explain how Red Hat OpenShift Container Platform with Virtualization could be used to practice and demo RHEL for Edge use-cases. This particular example is built on the top of Single Node OpenShift deployment, however it should run on any regular OpenShift Container Platform with OpenShift Virtualization enabled as [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,6,8],"tags":[10,12,9,13,11],"class_list":["post-27","post","type-post","status-publish","format-standard","hentry","category-edge","category-openshift","category-virtualization","tag-edge","tag-linux","tag-openshift","tag-rhel","tag-virtualization"],"_links":{"self":[{"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/posts\/27","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=27"}],"version-history":[{"count":37,"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/posts\/27\/revisions"}],"predecessor-version":[{"id":86,"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/posts\/27\/revisions\/86"}],"wp:attachment":[{"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/media?parent=27"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/categories?post=27"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.openshift.one\/index.php\/wp-json\/wp\/v2\/tags?post=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}