Showing posts with label CNV. Show all posts
Showing posts with label CNV. Show all posts

Wednesday, May 20, 2020

Installing OpenShift Container Storage and OpenShift Virtualization



There seem to be some mystery as to what might be inside the container when it comes to installing and configuring OpenShift Containerized Storage and OpenShift Virtualization (formerly CNV) but this blog will easily prove there is no need to fear the container.

This blog assumes the availability of an already installed OpenShift 4.4 environment with a 3 master and 3 worker setup.   The workers will be where we run our OCS storage pods so each of those nodes should have at least one extra unused disk for the OSDs to use.  Further the installation of OCS requires that we have local storage PVs already created for OCS to consume during the deployment.  With that said lets get started.

First lets take a quick look at our environment by showing the nodes and looking at one of the workers to see the extra disk (vdb in this case):

$ export KUBECONFIG=/home/cloud-user/scripts/ocp/auth/kubeconfig
$ oc get nodes
NAME       STATUS   ROLES    AGE    VERSION
master-0   Ready    master   59m    v1.18.2
master-1   Ready    master   51m    v1.18.2
master-2   Ready    master   60m    v1.18.2
worker-0   Ready    worker   4m9s   v1.18.2
worker-1   Ready    worker   27m    v1.18.2
worker-2   Ready    worker   27m    v1.18.2

$ oc debug node/worker-0
Starting pod/worker-0-debug ...
To use host binaries, run `chroot /host`
Pod IP: 10.20.0.200
If you don't see a command prompt, try pressing enter.

sh-4.2# chroot /host
sh-4.4# lsblk
NAME                         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda                          252:0    0  100G  0 disk 
|-vda1                       252:1    0  384M  0 part /boot
|-vda2                       252:2    0  127M  0 part /boot/efi
|-vda3                       252:3    0    1M  0 part 
|-vda4                       252:4    0 99.4G  0 part 
| `-coreos-luks-root-nocrypt 253:0    0 99.4G  0 dm   /sysroot
`-vda5                       252:5    0   65M  0 part 
vdb                          252:16   0  100G  0 disk 

Now that we have reviewed the environment lets first label the worker nodes as storage nodes:

$ oc label nodes worker-0 cluster.ocs.openshift.io/openshift-storage=''
node/worker-0 labeled

$ oc label nodes worker-1 cluster.ocs.openshift.io/openshift-storage=''
node/worker-1 labeled

$ oc label nodes worker-2 cluster.ocs.openshift.io/openshift-storage=''
node/worker-2 labeled

oc get nodes -l cluster.ocs.openshift.io/openshift-storage=
NAME       STATUS   ROLES    AGE    VERSION
worker-0   Ready    worker   5m7s   v1.18.2
worker-1   Ready    worker   28m    v1.18.2
worker-2   Ready    worker   28m    v1.18.2

Next we can proceed to the console and install the Local Storage operator.  First we will need to create a local-storage namespace:



Once we have created the namespace we can go to the Operators Hub and search for the LocalStorage operator:


Click on the LocalStorage operator to get the install button:


Click the install button and a page of options will be presented.  Choose the version applicable to the OCP cluster version.  In our case I will use 4.4.  Assign the namespace as the local-storage namespace we created previously and click install:


Once the operator successfully installs the following screen will be displayed:


Now that we have the LocalStorage operator installed lets go back to the command line and create our local storage PVs that will eventually be consumed by OCS.   The first step is to create the local-storage.yaml file and populate it with the following:

apiVersion: local.storage.openshift.io/v1
kind: LocalVolume
metadata:
  name: local-block
  namespace: local-storage
spec:
  nodeSelector:
    nodeSelectorTerms:
    - matchExpressions:
        - key: cluster.ocs.openshift.io/openshift-storage
          operator: In
          values:
          - ""
  storageClassDevices:
    - storageClassName: localblock
      volumeMode: Block
      devicePaths:
        - /dev/vdb
 

Save the file and then issue the following command to label our nodes with the OCS storage label:

$ oc get nodes -l cluster.ocs.openshift.io/openshift-storage -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}'
worker-0
worker-1
worker-2

Next we will create the block PVs using the local-storage.yaml we created:

$ oc create -f local-storage.yaml 
localvolume.local.storage.openshift.io/local-block created 

Lets validate that the pods and PVs were created:

$ oc -n local-storage get pods
NAME                                      READY   STATUS    RESTARTS   AGE
local-block-local-diskmaker-dxgwj         1/1     Running   0          42s
local-block-local-diskmaker-hrsvj         1/1     Running   0          42s
local-block-local-diskmaker-zsptk         1/1     Running   0          42s
local-block-local-provisioner-pwgfl       1/1     Running   0          42s
local-block-local-provisioner-s56f4       1/1     Running   0          42s
local-block-local-provisioner-wp8bz       1/1     Running   0          42s
local-storage-operator-5c46f48cfc-6ht8r   1/1     Running   0          15m

$ oc get pv
NAME                CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
local-pv-40d06fba   100Gi      RWO            Delete           Available           localblock              30s
local-pv-8aea98b7   100Gi      RWO            Delete           Available           localblock              28s
local-pv-e62c1b44   100Gi      RWO            Delete           Available           localblock              34s

$ oc get sc | grep localblock
localblock   kubernetes.io/no-provisioner   Delete          WaitForFirstConsumer   false                  60s
 

If everything looks good we can now return to the console and install the OCS operator.  As we did with the previous operator we will search for OpenShift Container and it will show the operator available to us:



Click on the operator and the install button will be displayed:


After clicking the install button the options for the operator will be displayed.  Select the option based on the environment.  The ones below are the default and I went with those:


After clicking install the operator will install and return to screen similar to the one below.  Notice that the AWS S3 Operator was installed as well given its a dependency for the OCS operator.


With the OCS operator installed and the local storage PVs ready we can now create our OCS cluster.   Lets use the cluster wizard within the console.  First we need to click on the OpenShift Container Storage operator in the list of installed operators:


Next we will click on the Storage Cluster heading which will display a button to the right for creating the OCS cluster service.  Click on this button:


This will bring up the following screen with the nodes labeled as OCS nodes being already checked and the amount of total raw capacity on those nodes once the local storage class is selected:


Click the create button the cluster will show a progress screen and begin to instantiate the cluster:


If we jump over to the command line we can also see pods are starting to instantiate:

$ oc get pods -n openshift-storage
NAME                                            READY   STATUS              RESTARTS   AGE
aws-s3-provisioner-85b697dd54-zcrv5             1/1     Running             0          12m
csi-cephfsplugin-646jk                          0/3     ContainerCreating   0          27s
csi-cephfsplugin-b6c66                          0/3     ContainerCreating   0          27s
csi-cephfsplugin-ppqdb                          3/3     Running             0          27s
csi-cephfsplugin-provisioner-785b9d8bd5-45cwm   0/5     ContainerCreating   0          26s
csi-cephfsplugin-provisioner-785b9d8bd5-nk9gl   0/5     ContainerCreating   0          26s
csi-cephfsplugin-rfw2m                          0/3     ContainerCreating   0          27s
csi-cephfsplugin-vpzp8                          0/3     ContainerCreating   0          27s
csi-cephfsplugin-xv484                          0/3     ContainerCreating   0          27s
csi-rbdplugin-864jc                             3/3     Running             0          27s
csi-rbdplugin-crgr4                             0/3     ContainerCreating   0          27s
csi-rbdplugin-hwtr4                             0/3     ContainerCreating   0          28s
csi-rbdplugin-provisioner-66c87f8bd4-48q6q      0/5     ContainerCreating   0          27s
csi-rbdplugin-provisioner-66c87f8bd4-js247      0/5     ContainerCreating   0          27s
csi-rbdplugin-s9fr7                             0/3     ContainerCreating   0          27s
csi-rbdplugin-t7tgb                             0/3     ContainerCreating   0          28s
csi-rbdplugin-x25f5                             0/3     ContainerCreating   0          28s
noobaa-operator-6f7d47dff6-dw62k                1/1     Running             0          12m
ocs-operator-6cf4c9fc95-qxllg                   0/1     Running             0          12m
rook-ceph-mon-a-canary-6fb7d8ff5d-bl6kq         1/1     Running             0          9s
rook-ceph-mon-b-canary-864586477c-n6tjs         0/1     ContainerCreating   0          8s
rook-ceph-mon-c-canary-cb7d94fd8-mvvzc          0/1     ContainerCreating   0          3s
rook-ceph-operator-674cfcd899-hpvmr             1/1     Running             0          12m

Once the cluster has installed the console will display the status similar to the image below:


We can also see all the pods are up and running from the command line as well:

$ oc get pods -n openshift-storage
NAME                                                              READY   STATUS      RESTARTS   AGE
aws-s3-provisioner-85b697dd54-zcrv5                               1/1     Running     0          22m
csi-cephfsplugin-646jk                                            3/3     Running     0          10m
csi-cephfsplugin-b6c66                                            3/3     Running     0          10m
csi-cephfsplugin-ppqdb                                            3/3     Running     0          10m
csi-cephfsplugin-provisioner-785b9d8bd5-45cwm                     5/5     Running     0          10m
csi-cephfsplugin-provisioner-785b9d8bd5-nk9gl                     5/5     Running     1          10m
csi-cephfsplugin-rfw2m                                            3/3     Running     0          10m
csi-cephfsplugin-vpzp8                                            3/3     Running     0          10m
csi-cephfsplugin-xv484                                            3/3     Running     0          10m
csi-rbdplugin-864jc                                               3/3     Running     0          10m
csi-rbdplugin-crgr4                                               3/3     Running     0          10m
csi-rbdplugin-hwtr4                                               3/3     Running     0          10m
csi-rbdplugin-provisioner-66c87f8bd4-48q6q                        5/5     Running     1          10m
csi-rbdplugin-provisioner-66c87f8bd4-js247                        5/5     Running     0          10m
csi-rbdplugin-s9fr7                                               3/3     Running     0          10m
csi-rbdplugin-t7tgb                                               3/3     Running     0          10m
csi-rbdplugin-x25f5                                               3/3     Running     0          10m
noobaa-core-0                                                     1/1     Running     0          7m15s
noobaa-db-0                                                       1/1     Running     0          7m15s
noobaa-endpoint-7cdcc9bdc6-85s2v                                  1/1     Running     0          5m57s
noobaa-operator-6f7d47dff6-dw62k                                  1/1     Running     0          22m
ocs-operator-6cf4c9fc95-qxllg                                     1/1     Running     0          22m
rook-ceph-crashcollector-worker-0-7fd95579db-jt85v                1/1     Running     0          8m38s
rook-ceph-crashcollector-worker-1-7f547f4dc-s9q5l                 1/1     Running     0          8m7s
rook-ceph-crashcollector-worker-2-bd6d78488-4pzz7                 1/1     Running     0          8m27s
rook-ceph-drain-canary-worker-0-64d6558fcb-x52z4                  1/1     Running     0          7m16s
rook-ceph-drain-canary-worker-1-7f8858f74-vsc6f                   1/1     Running     0          7m16s
rook-ceph-drain-canary-worker-2-5fd88c555c-2rmnx                  1/1     Running     0          7m18s
rook-ceph-mds-ocs-storagecluster-cephfilesystem-a-8458f9c54l4zx   1/1     Running     0          6m59s
rook-ceph-mds-ocs-storagecluster-cephfilesystem-b-bf76744474rnz   1/1     Running     0          6m58s
rook-ceph-mgr-a-5488b747df-2bmnn                                  1/1     Running     0          7m49s
rook-ceph-mon-a-7884697548-tp5pw                                  1/1     Running     0          8m38s
rook-ceph-mon-b-7b47c5c597-5jdrv                                  1/1     Running     0          8m27s
rook-ceph-mon-c-69f945d575-4pmtn                                  1/1     Running     0          8m7s
rook-ceph-operator-674cfcd899-hpvmr                               1/1     Running     0          22m
rook-ceph-osd-0-7f98849d5-vfhsn                                   1/1     Running     0          7m18s
rook-ceph-osd-1-594cc64794-p45h2                                  1/1     Running     0          7m17s
rook-ceph-osd-2-655df8c45c-wb9g6                                  1/1     Running     0          7m16s
rook-ceph-osd-prepare-ocs-deviceset-0-0-65zj5-fzwxt               0/1     Completed   0          7m29s
rook-ceph-osd-prepare-ocs-deviceset-1-0-w2hl2-z2xns               0/1     Completed   0          7m29s
rook-ceph-osd-prepare-ocs-deviceset-2-0-bj7qz-zhsfs               0/1     Completed   0          7m29s
rook-ceph-rgw-ocs-storagecluster-cephobjectstore-a-66b5b7dh8nzc   1/1     Running     0          6m36s

We can also see a bunch of new storage classes are also available to us:

$ oc get storageclass
NAME                          PROVISIONER                             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
localblock                    kubernetes.io/no-provisioner            Delete          WaitForFirstConsumer   false                  32m
ocs-storagecluster-ceph-rbd   openshift-storage.rbd.csi.ceph.com      Delete          Immediate              false                  12m
ocs-storagecluster-cephfs     openshift-storage.cephfs.csi.ceph.com   Delete          Immediate              false                  12m
openshift-storage.noobaa.io   openshift-storage.noobaa.io/obc         Delete          Immediate              false                  8m35s

At this point OpenShift Container Storage is ready to be consumed by OpenShift Virtualization.  However we still need to install OpenShift Virtualization.  Again we will use the console to install the operator and do so by first searching for it:


Click on the operator to bring up the install button:


Once the install button is clicked it will present the options for the OpenShift Vritualization operator:


Once the options and install have been clicked the operator will install and once complete the following screen is displayed:



Clicking on the OpenShift Virtualization operator and then clicking on CNV Operator Deployment will bring us to the following screen:


Then click on Create HyperConverged Cluster button, accept the defaults and click on create:


This will begin the process of launching the required pods for OpenShift Virtualization.  If we jump over to the command line we can see the pods spinning up:

$ oc get pods -n openshift-cnv
openshift-cnv                                      bridge-marker-4q57k                                               0/1     ContainerCreating   0          12s
openshift-cnv                                      bridge-marker-66vzn                                               1/1     Running             0          11s
openshift-cnv                                      bridge-marker-m6ll8                                               1/1     Running             0          11s
openshift-cnv                                      bridge-marker-slch2                                               0/1     ContainerCreating   0          12s
openshift-cnv                                      bridge-marker-xthw9                                               1/1     Running             0          12s
openshift-cnv                                      bridge-marker-zgvxq                                               1/1     Running             0          11s
openshift-cnv                                      cdi-apiserver-c6bfbc6b9-rjnl4                                     0/1     Running             0          13s
openshift-cnv                                      cdi-deployment-7c4fd9cb5b-rr8fk                                   0/1     ContainerCreating   0          13s
openshift-cnv                                      cdi-operator-7467d4478-9xcrm                                      1/1     Running             0          16m
openshift-cnv                                      cdi-uploadproxy-54c7876d47-wpzvf                                  0/1     ContainerCreating   0          13s
openshift-cnv                                      cluster-network-addons-operator-687c79cc7b-94fdm                  1/1     Running             0          16m
openshift-cnv                                      hco-operator-7cd98b5686-jmb8t                                     0/1     Running             0          16m
openshift-cnv                                      hostpath-provisioner-operator-5d8f6bc547-4f5rd                    1/1     Running             0          16m
openshift-cnv                                      kube-cni-linux-bridge-plugin-cd4zb                                0/1     ContainerCreating   0          15s
openshift-cnv                                      kube-cni-linux-bridge-plugin-cgpkz                                0/1     ContainerCreating   0          15s
openshift-cnv                                      kube-cni-linux-bridge-plugin-cxzvv                                1/1     Running             0          15s
openshift-cnv                                      kube-cni-linux-bridge-plugin-d9qnn                                1/1     Running             0          15s
openshift-cnv                                      kube-cni-linux-bridge-plugin-f9k7g                                1/1     Running             0          15s
openshift-cnv                                      kube-cni-linux-bridge-plugin-gj6th                                1/1     Running             0          15s
openshift-cnv                                      kubevirt-a2582644e49387db02a9524312c0792c76605518-jobczrpsrrgjc   0/1     Completed           0          16s
openshift-cnv                                      kubevirt-ssp-operator-69fbcd58f4-kpqr9                            1/1     Running             0          16m
openshift-cnv                                      nmstate-handler-kwt7d                                             0/1     ContainerCreating   0          8s
openshift-cnv                                      nmstate-handler-llj8z                                             0/1     ContainerCreating   0          8s
openshift-cnv                                      nmstate-handler-vct84                                             0/1     ContainerCreating   0          8s
openshift-cnv                                      nmstate-handler-worker-5rr47                                      0/1     ContainerCreating   0          8s
openshift-cnv                                      nmstate-handler-worker-jg4v4                                      1/1     Running             0          8s
openshift-cnv                                      nmstate-handler-worker-wjnz2                                      0/1     ContainerCreating   0          8s
openshift-cnv                                      node-maintenance-operator-6c76fbb8d-qllp6                         1/1     Running             0          16m
openshift-cnv                                      ovs-cni-amd64-2rgn7                                               0/2     ContainerCreating   0          5s
openshift-cnv                                      ovs-cni-amd64-8rbb6                                               0/2     ContainerCreating   0          5s
openshift-cnv                                      ovs-cni-amd64-hc5b8                                               0/2     ContainerCreating   0          5s
openshift-cnv                                      ovs-cni-amd64-hkdjb                                               0/2     ContainerCreating   0          5s
openshift-cnv                                      ovs-cni-amd64-hw995                                               0/2     ContainerCreating   0          5s
openshift-cnv                                      ovs-cni-amd64-jqg8x                                               0/2     ContainerCreating   0          5s
openshift-cnv                                      virt-operator-6d766f7698-bmsdc                                    1/1     Running             0          16m
openshift-cnv                                      virt-operator-6d766f7698-m2fxl                                    1/1     Running             0          16m


Looking back at the console once all the pods are running we will be presented with the following on the screen:


And if we look back at the command line we can see all the pods running under the opensihft-cnv namespace:

$ oc get pods -n openshift-cnv
NAME                                               READY   STATUS    RESTARTS   AGE
bridge-marker-4q57k                                1/1     Running   0          11m
bridge-marker-66vzn                                1/1     Running   0          11m
bridge-marker-m6ll8                                1/1     Running   0          11m
bridge-marker-slch2                                1/1     Running   0          11m
bridge-marker-xthw9                                1/1     Running   0          11m
bridge-marker-zgvxq                                1/1     Running   0          11m
cdi-apiserver-c6bfbc6b9-rjnl4                      1/1     Running   0          11m
cdi-deployment-7c4fd9cb5b-rr8fk                    1/1     Running   0          11m
cdi-operator-7467d4478-9xcrm                       1/1     Running   0          28m
cdi-uploadproxy-54c7876d47-wpzvf                   1/1     Running   0          11m
cluster-network-addons-operator-687c79cc7b-94fdm   1/1     Running   0          28m
hco-operator-7cd98b5686-jmb8t                      1/1     Running   0          28m
hostpath-provisioner-operator-5d8f6bc547-4f5rd     1/1     Running   0          28m
kube-cni-linux-bridge-plugin-cd4zb                 1/1     Running   0          11m
kube-cni-linux-bridge-plugin-cgpkz                 1/1     Running   0          11m
kube-cni-linux-bridge-plugin-cxzvv                 1/1     Running   0          11m
kube-cni-linux-bridge-plugin-d9qnn                 1/1     Running   0          11m
kube-cni-linux-bridge-plugin-f9k7g                 1/1     Running   0          11m
kube-cni-linux-bridge-plugin-gj6th                 1/1     Running   0          11m
kubevirt-node-labeller-9947m                       1/1     Running   0          11m
kubevirt-node-labeller-ckqbn                       1/1     Running   0          11m
kubevirt-node-labeller-hn9xt                       1/1     Running   0          11m
kubevirt-node-labeller-kw5hb                       1/1     Running   0          11m
kubevirt-node-labeller-n4lxc                       1/1     Running   0          11m
kubevirt-node-labeller-vhmkk                       1/1     Running   0          11m
kubevirt-ssp-operator-69fbcd58f4-kpqr9             1/1     Running   0          28m
nmstate-handler-kwt7d                              1/1     Running   0          11m
nmstate-handler-llj8z                              1/1     Running   0          11m
nmstate-handler-vct84                              1/1     Running   0          11m
nmstate-handler-worker-5rr47                       1/1     Running   0          11m
nmstate-handler-worker-jg4v4                       1/1     Running   0          11m
nmstate-handler-worker-wjnz2                       1/1     Running   0          11m
node-maintenance-operator-6c76fbb8d-qllp6          1/1     Running   0          28m
ovs-cni-amd64-2rgn7                                2/2     Running   0          11m
ovs-cni-amd64-8rbb6                                2/2     Running   0          11m
ovs-cni-amd64-hc5b8                                2/2     Running   0          11m
ovs-cni-amd64-hkdjb                                2/2     Running   0          11m
ovs-cni-amd64-hw995                                2/2     Running   0          11m
ovs-cni-amd64-jqg8x                                2/2     Running   0          11m
virt-api-84fd45c455-2jjbb                          1/1     Running   0          11m
virt-api-84fd45c455-ct7dt                          1/1     Running   0          11m
virt-controller-74c54b549-qz4q9                    1/1     Running   0          11m
virt-controller-74c54b549-zt5qj                    1/1     Running   0          11m
virt-handler-69644                                 1/1     Running   0          11m
virt-handler-7857r                                 1/1     Running   0          11m
virt-handler-bpsjg                                 1/1     Running   0          11m
virt-handler-j48c7                                 1/1     Running   0          11m
virt-handler-rrl6d                                 1/1     Running   0          11m
virt-handler-vr9bf                                 1/1     Running   0          11m
virt-operator-6d766f7698-bmsdc                     1/1     Running   0          28m
virt-operator-6d766f7698-m2fxl                     1/1     Running   0          28m
virt-template-validator-bd96cdfcd-4qgcz            1/1     Running   0          11m
virt-template-validator-bd96cdfcd-6d27x            1/1     Running   0          11m


Finally at this point we can actually go and launch a virtual machine.   If we navigate to workloads in the console we can see there is a Virtualization option:


It is here where we can click on the create a virtual machine button to start the wizard.  In the wizard the first screen is where we set VM specific attributes: name, OS source, OS type, VM size etc.  Below is an example of my VM:


Clicking next we are presented with a networking screen.  Again options for adding various network connectivity are available here but in this example I am just going to accept the defaults:



Next we are brought to storage and by default there is no storageclass assigned to the disk.  If a default storageclass was set on the OCP cluster then it would most likely default to that but I did not have that configured.  Given that I needed to edit the disk using the three dots on the right and set the storageclass:



On the advanced screen we can set the hostname, an SSH key if we desire and also attach a virtual CD-ROM:



Finally we get to a summary screen which shows all the settings as they were chosen through the wizard.  Once reviewed we can click next and create the VM:



Once the VM is creating we can view the status of the VM on the detail page:



Waiting a little bit we can now see the VM is running:


If we jump over to the console we can see we have a login prompt:



Hopefully this gives everyone a tastes of how easy it is to configure OpenShift Container Storage and OpenShift Virtualization in a OpenShift Container Platform 4.4 environment.

Monday, June 17, 2019

Centralized vBMC Controller


In my lab I use KVM virtual machines as my "baremetal" machines for testing OpenStack and Openshift.  In both of those cases I need something that provides power management to power off/on the virtual machines during deployment phases.   This is where Virtual BMC (vBMC) comes in as a handy tool to provide that functionality.   However I really don't want to install vBMC on all of the physical hosts that were providing my virtual machines.   Thankfully as this blog will explain there is a way to run vBMC where you can centrally manage all the virtual machines.

First lets pick a host that will be our centralized vBMC controller.   This host could be a physical box or a virtual machine it does not matter.  It does however need to have SSH key authentication to any of the KVM hypervisor hosts that contain virtual machines we wish to control with vBMC.

Once I have my vBMC host I will install the required package via rpm since I did not have a repo that contained the package.  If you have a repo that does container the package I would suggest using yum install instead:

# rpm -ivh python2-virtualbmc-1.4.0-1.el7.noarch.rpm 
Preparing...                          ################################# [100%]
Updating / installing...
   1:python2-virtualbmc-1.4.0-1.el7   ################################# [100%]

Once the package is installed we should be able to run the following command to see the command line usage for vbmc when adding a host.  If you get errors about cliff.app and zmq please install these packages (python2-cliff.noarch & python2-zmq.x86_64):

# vbmc add --help
usage: vbmc add [-h] [--username USERNAME] [--password PASSWORD] [--port PORT]
                [--address ADDRESS] [--libvirt-uri LIBVIRT_URI]
                [--libvirt-sasl-username LIBVIRT_SASL_USERNAME]
                [--libvirt-sasl-password LIBVIRT_SASL_PASSWORD]
                domain_name

Create a new BMC for a virtual machine instance

positional arguments:
  domain_name           The name of the virtual machine

optional arguments:
  -h, --help            show this help message and exit
  --username USERNAME   The BMC username; defaults to "admin"
  --password PASSWORD   The BMC password; defaults to "password"
  --port PORT           Port to listen on; defaults to 623
  --address ADDRESS     The address to bind to (IPv4 and IPv6 are supported);
                        defaults to ::
  --libvirt-uri LIBVIRT_URI
                        The libvirt URI; defaults to "qemu:///system"
  --libvirt-sasl-username LIBVIRT_SASL_USERNAME
                        The libvirt SASL username; defaults to None
  --libvirt-sasl-password LIBVIRT_SASL_PASSWORD
                        The libvirt SASL password; defaults to None


Now lets try adding a virtual machine called kube-master located on a remote hypervisor host:

# vbmc add --username admin --password password --port 6230 --address 192.168.0.10 --libvirt-uri qemu+ssh://root@192.168.0.4/system kube-master

Now lets add a second virtual machine on a different hypervisor and notice I increment the port number in use as this is the unique port number that gets called when using ipmi to actually connection to the specific host we wish to power on/off or get a power status from:

# vbmc add --username admin --password password --port 6231 --address 192.168.0.10 --libvirt-uri qemu+ssh://root@192.168.0.5/system cube-vm1

Now lets start the vbmc process for them and confirm they are up and running:

# vbmc start kube-master
2019-06-17 08:48:05,649.649 6915 INFO VirtualBMC [-] Started vBMC instance for domain kube-master

# vbmc start cube-vm1
2019-06-17 14:49:39,491.491 6915 INFO VirtualBMC [-] Started vBMC instance for domain cube-vm1
# vbmc list
+-------------+---------+--------------+------+
| Domain name | Status  | Address      | Port |
+-------------+---------+--------------+------+
| cube-vm1    | running | 192.168.0.10 | 6231 |
| kube-master | running | 192.168.0.10 | 6230 |
+-------------+---------+--------------+------+

Now that we have added a few virtual machines lets validate that things are working by trying to power the hosts up and get a status. In this example we will check the power status of kube-master and power on if it is off:

# ipmitool -I lanplus -H192.168.0.10 -p6230 -Uadmin -Ppassword chassis status
System Power         : off
Power Overload       : false
Power Interlock      : inactive
Main Power Fault     : false
Power Control Fault  : false
Power Restore Policy : always-off
Last Power Event     : 
Chassis Intrusion    : inactive
Front-Panel Lockout  : inactive
Drive Fault          : false
Cooling/Fan Fault    : false

# ipmitool -I lanplus -H192.168.0.10 -p6230 -Uadmin -Ppassword chassis power on
Chassis Power Control: Up/On

# ipmitool -I lanplus -H192.168.0.10 -p6230 -Uadmin -Ppassword chassis status
System Power         : on
Power Overload       : false
Power Interlock      : inactive
Main Power Fault     : false
Power Control Fault  : false
Power Restore Policy : always-off
Last Power Event     : 
Chassis Intrusion    : inactive
Front-Panel Lockout  : inactive
Drive Fault          : false
Cooling/Fan Fault    : false

In the next example we will see that cube-vm1 is powered on and we should power it off:

# ipmitool -I lanplus -H192.168.0.10 -p6231 -Uadmin -Ppassword chassis status
System Power         : on
Power Overload       : false
Power Interlock      : inactive
Main Power Fault     : false
Power Control Fault  : false
Power Restore Policy : always-off
Last Power Event     : 
Chassis Intrusion    : inactive
Front-Panel Lockout  : inactive
Drive Fault          : false
Cooling/Fan Fault    : false

# ipmitool -I lanplus -H192.168.0.10 -p6231 -Uadmin -Ppassword chassis power off
Chassis Power Control: Down/Off

# ipmitool -I lanplus -H192.168.0.10 -p6231 -Uadmin -Ppassword chassis status
System Power         : off
Power Overload       : false
Power Interlock      : inactive
Main Power Fault     : false
Power Control Fault  : false
Power Restore Policy : always-off
Last Power Event     : 
Chassis Intrusion    : inactive
Front-Panel Lockout  : inactive
Drive Fault          : false
Cooling/Fan Fault    : false

Lets summarize what we just did.  We had a vBMC host that was ipaddress 192.168.0.10 where we installed vBMC and configured two different virtual machines kube-master and cube-vm1 which were on two completely different hypervisor guests, ip address 192.168.0.4 and 192.168.0.5 respectively.  This allowed us to remotely power manage those virtual machines without the need to install any additional software on those hypervisor hosts.

Given this flexibility one could foresee maybe in the future have a centalized vBMC container that could then in turn access any KubeVirt deployed virtual machines that are deployed within that Kubernetes cluster.  I guess its only a matter of time.

Monday, March 18, 2019

Stacking OpenShift with Rook and CNV


In previous blogs I was working with Rook/Ceph on Kubernetes and demonstrating how to setup a Ceph cluster and even replace failed OSDs. With that in mind I wanted to shift gears a bit and bring it more into alignment with OpenShift and Container Native Virtualization(CNV).

The following blog will guide us through a simple OpenShift deployment with Rook/Ceph and CNV configured. I will also demonstrate the use of a Rook PVC that provides the back end storage for a CNV deployed virtual instance.

The configuration for this lab is four virtual machines where one node is the master and compute and the other 3 nodes compute.  Each of these nodes has a base install of Red Hat Enterprise Linux 7 on it and the physical host they are on allows for nested virtualization.

Before we start with the installation of various software lets make sure we do a bit of user setup to ensure our install runs smoothly.  The next few steps will need to be done on all nodes to ensure a user origin (this could be any non root user) is created and has sudo rights without use of a password:

# useradd origin
# passwd origin
# echo -e 'Defaults:origin !requiretty\norigin ALL = (root) NOPASSWD:ALL' | tee /etc/sudoers.d/openshift 
# chmod 440 /etc/sudoers.d/openshift

Then we need to perform the the following steps to setup keyless authentication for the origin user from the master node to the rest of the nodes that will make up the cluster:

# ssh-keygen -q -N ""
# vi /home/origin/.ssh/config
Host ocp-master
    Hostname ocp-master.schmaustech.com
    User origin
Host ocp-node1
    Hostname ocp-node1.schmaustech.com
    User origin
Host ocp-node2
    Hostname ocp-node2.schmaustech.com
    User origin
Host ocp-node3
    Hostname ocp-node3.schmaustech.com
    User origin

# chmod 600 /home/origin/.ssh/config
# ssh-copy-id ocp-master
# ssh-copy-id ocp-node1
# ssh-copy-id ocp-node2
# ssh-copy-id ocp-node3

Now we can move on to enabling the necessary repositries on all nodes to ensure we can get access to the right packages we will need for installation:

[origin@ocp-master ~]$ sudo subscription-manager repos --enable=rhel-7-server-rpms --enable=rhel-7-server-extras-rpms --enable=rhel-7-server-rh-common-rpms --enable=rhel-7-server-ose-3.11-rpms --enable=rhel-7-server-ansible-2.6-rpms --enable=rhel-7-server-cnv-1.4-tech-preview-rpms

Next lets install the initial required packages on all the nodes:

[origin@ocp-master ~]$ sudo yum -y install openshift-ansible docker-1.13.1 kubevirt-ansible kubevirt-virtctl

On the master node lets configure the Ansible hosts file for our OpenShift installation.   The following is the example I used and I simply replaced /etc/ansible/hosts with it.

[OSEv3:children]
masters
nodes
etcd
[OSEv3:vars]
# admin user created in previous section
ansible_ssh_user=origin
ansible_become=true
oreg_url=registry.access.redhat.com/openshift3/ose-${component}:${version}
openshift_deployment_type=openshift-enterprise
#  use HTPasswd for authentication
openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider'}]
# define default sub-domain for Master node
openshift_master_default_subdomain=apps.schmaustech.com
# allow unencrypted connection within cluster
openshift_docker_insecure_registries=172.30.0.0/16
[masters]
ocp-master.schmaustech.com openshift_schedulable=true containerized=false
[etcd]
ocp-master.schmaustech.com
[nodes]
# defined values for [openshift_node_group_name] in the file below
# [/usr/share/ansible/openshift-ansible/roles/openshift_facts/defaults/main.yml]
ocp-master.schmaustech.com openshift_node_group_name='node-config-all-in-one'
ocp-node1.schmaustech.com openshift_node_group_name='node-config-compute'
ocp-node2.schmaustech.com openshift_node_group_name='node-config-compute'
ocp-node3.schmaustech.com openshift_node_group_name='node-config-compute'

With the Ansible host file in place we are ready to run the OpenShift prerequisite playbook:

[origin@ocp-master ~]$ ansible-playbook /usr/share/ansible/openshift-ansible/playbooks/prerequisites.yml

Once the prerequisite playbook executes sucessfully we can then run the OpenShift deploy cluster playbook:

[origin@ocp-master ~]$ ansible-playbook /usr/share/ansible/openshift-ansible/playbooks/deploy_cluster.yml

Lets validate OpenShift is up and running:

[origin@ocp-master ~]$ oc get nodes
NAME         STATUS    ROLES                  AGE       VERSION
ocp-master   Ready     compute,infra,master   15h       v1.11.0+d4cacc0
ocp-node1    Ready     compute                14h       v1.11.0+d4cacc0
ocp-node2    Ready     compute                14h       v1.11.0+d4cacc0
ocp-node3    Ready     compute                14h       v1.11.0+d4cacc0

[origin@ocp-master ~]$ oc get pods --all-namespaces -o wide
NAMESPACE                           NAME                                           READY     STATUS      RESTARTS   AGE       IP              NODE         NOMINATED NODE
default                             docker-registry-1-g4hgd                        1/1       Running     0          14h       10.128.0.4      ocp-master   <none>
default                             registry-console-1-zwhrd                       1/1       Running     0          14h       10.128.0.6      ocp-master   <none>
default                             router-1-v8pkp                                 1/1       Running     0          14h       192.168.3.100   ocp-master   <none>
kube-service-catalog                apiserver-gxjst                                1/1       Running     0          14h       10.128.0.17     ocp-master   <none>
kube-service-catalog                controller-manager-2v6qs                       1/1       Running     3          14h       10.128.0.18     ocp-master   <none>
openshift-ansible-service-broker    asb-1-d8clq                                    1/1       Running     0          14h       10.128.0.21     ocp-master   <none>
openshift-console                   console-566f847459-pk52j                       1/1       Running     0          14h       10.128.0.12     ocp-master   <none>
openshift-monitoring                alertmanager-main-0                            3/3       Running     0          14h       10.128.0.14     ocp-master   <none>
openshift-monitoring                alertmanager-main-1                            3/3       Running     0          14h       10.128.0.15     ocp-master   <none>
openshift-monitoring                alertmanager-main-2                            3/3       Running     0          14h       10.128.0.16     ocp-master   <none>
openshift-monitoring                cluster-monitoring-operator-79d6c544f5-c8rfs   1/1       Running     0          14h       10.128.0.7      ocp-master   <none>
openshift-monitoring                grafana-8497b48bd5-bqzxb                       2/2       Running     0          14h       10.128.0.10     ocp-master   <none>
openshift-monitoring                kube-state-metrics-7d8b57fc8f-ktdq4            3/3       Running     0          14h       10.128.0.19     ocp-master   <none>
openshift-monitoring                node-exporter-5gmbc                            2/2       Running     0          14h       192.168.3.103   ocp-node3    <none>
openshift-monitoring                node-exporter-fxthd                            2/2       Running     0          14h       192.168.3.102   ocp-node2    <none>
openshift-monitoring                node-exporter-gj27b                            2/2       Running     0          14h       192.168.3.101   ocp-node1    <none>
openshift-monitoring                node-exporter-r6vjs                            2/2       Running     0          14h       192.168.3.100   ocp-master   <none>
openshift-monitoring                prometheus-k8s-0                               4/4       Running     1          14h       10.128.0.11     ocp-master   <none>
openshift-monitoring                prometheus-k8s-1                               4/4       Running     1          14h       10.128.0.13     ocp-master   <none>
openshift-monitoring                prometheus-operator-5677fb6f87-4czth           1/1       Running     0          14h       10.128.0.8      ocp-master   <none>
openshift-node                      sync-7rqcb                                     1/1       Running     0          14h       192.168.3.103   ocp-node3    <none>
openshift-node                      sync-829ql                                     1/1       Running     0          14h       192.168.3.101   ocp-node1    <none>
openshift-node                      sync-mwq6v                                     1/1       Running     0          14h       192.168.3.102   ocp-node2    <none>
openshift-node                      sync-vc4hw                                     1/1       Running     0          15h       192.168.3.100   ocp-master   <none>
openshift-sdn                       ovs-n55b8                                      1/1       Running     0          14h       192.168.3.101   ocp-node1    <none>
openshift-sdn                       ovs-nvtgq                                      1/1       Running     0          14h       192.168.3.103   ocp-node3    <none>
openshift-sdn                       ovs-t8dgh                                      1/1       Running     0          14h       192.168.3.102   ocp-node2    <none>
openshift-sdn                       ovs-wgw2v                                      1/1       Running     0          15h       192.168.3.100   ocp-master   <none>
openshift-sdn                       sdn-7r9kn                                      1/1       Running     0          14h       192.168.3.101   ocp-node1    <none>
openshift-sdn                       sdn-89284                                      1/1       Running     0          15h       192.168.3.100   ocp-master   <none>
openshift-sdn                       sdn-hmgjg                                      1/1       Running     0          14h       192.168.3.103   ocp-node3    <none>
openshift-sdn                       sdn-n7lzh                                      1/1       Running     0          14h       192.168.3.102   ocp-node2    <none>
openshift-template-service-broker   apiserver-md5sr                                1/1       Running     0          14h       10.128.0.22     ocp-master   <none>
openshift-web-console               webconsole-674f79b6fc-cjrhw                    1/1       Running     0          14h       10.128.0.9      ocp-master   <none>

With OpenShift up and running we can move onto install Rook/Ceph cluster.  The first step is to clone the Rook Git repo down to the master node and make an adjustment for the kubelet-plugins.  Please note here I am cloning down a colleagues Rook clone and not direct from the Rook project:

[origin@ocp-master ~]$ git clone https://github.com/ksingh7/ocp4-rook.git
[origin@ocp-master ~]$ sed -i.bak s+/etc/kubernetes/kubelet-plugins/volume/exec+/usr/libexec/kubernetes/kubelet-plugins/volume/exec+g /home/origin/ocp4-rook/ceph/operator.yaml

With the repository cloned we can now apply the the security context constraints needed by the Rook pods using the scc.yaml and then launch the Rook operator with operator.yaml:

[origin@ocp-master ~]$ oc create -f /home/origin/ocp4-rook/ceph/scc.yaml
[origin@ocp-master ~]$ oc create -f /home/origin/ocp4-rook/ceph/operator.yaml

Lets validate the Rook operator came up:

[origin@ocp-master ~]$ oc get pods -n rook-ceph-system 
NAME                                 READY     STATUS    RESTARTS   AGE
rook-ceph-agent-77x5n                1/1       Running   0          1h
rook-ceph-agent-cdvqr                1/1       Running   0          1h
rook-ceph-agent-gz7tl                1/1       Running   0          1h
rook-ceph-agent-rsbwh                1/1       Running   0          1h
rook-ceph-operator-b76466dcd-zmscb   1/1       Running   0          1h
rook-discover-6p5ht                  1/1       Running   0          1h
rook-discover-fnrf4                  1/1       Running   0          1h
rook-discover-grr5w                  1/1       Running   0          1h
rook-discover-mllt7                  1/1       Running   0          1h

Once the operator is up we can proceed on deploying the Ceph cluster and once that is up deploy the Ceph toolbox pod:

[origin@ocp-master ~]$ oc create -f /home/origin/ocp4-rook/ceph/cluster.yaml  
[origin@ocp-master ~]$ oc create -f /home/origin/ocp4-rook/ceph/toolbox.yaml

Lets validate the Ceph cluster is up:

[origin@ocp-master ~]$ oc get pods -n rook-ceph
NAME                                     READY     STATUS      RESTARTS   AGE
rook-ceph-mgr-a-785ddd6d6c-d4w56         1/1       Running     0          1h
rook-ceph-mon-a-67855c796b-sdvqm         1/1       Running     0          1h
rook-ceph-mon-b-6d58cd7656-xkrdz         1/1       Running     0          1h
rook-ceph-mon-c-869b8d9d9-m7544          1/1       Running     0          1h
rook-ceph-osd-0-d6cbd5776-987p9          1/1       Running     0          1h
rook-ceph-osd-1-cfddf997-pzq69           1/1       Running     0          1h
rook-ceph-osd-2-79fc94c6d5-krtnj         1/1       Running     0          1h
rook-ceph-osd-3-f9b55c4d6-7jp7c          1/1       Running     0          1h
rook-ceph-osd-prepare-ocp-master-ztmhs   0/2       Completed   0          1h
rook-ceph-osd-prepare-ocp-node1-mgbcd    0/2       Completed   0          1h
rook-ceph-osd-prepare-ocp-node2-98rtw    0/2       Completed   0          1h
rook-ceph-osd-prepare-ocp-node3-ngscg    0/2       Completed   0          1h
rook-ceph-tools                          1/1       Running     0          1h

Lets also validate from the Ceph toolbox that the cluster health is ok:

[origin@ocp-master ~]$ oc -n rook-ceph rsh rook-ceph-tools
sh-4.2# ceph status
  cluster:
    id:     6ddab3e4-1730-412f-89b8-0738708adac8
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum b,a,c
    mgr: a(active)
    osd: 4 osds: 4 up, 4 in
 
  data:
    pools:   1 pools, 100 pgs
    objects: 281  objects, 1.1 GiB
    usage:   51 GiB used, 169 GiB / 220 GiB avail
    pgs:     100 active+clean


Now that we have confirmed the Ceph cluster is deployed lets configure a Ceph storage class and also make it the default storage class for the environment:

[origin@ocp-master ~]$ oc create -f /home/origin/ocp4-rook/ceph/storageclass.yaml
[origin@ocp-master ~]$ oc patch storageclass rook-ceph-block -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

And now if we display the storage class we can see Rook/Ceph is our default:

[origin@ocp-master ~]$ oc get storageclass
NAME                        PROVISIONER          AGE
rook-ceph-block (default)   ceph.rook.io/block   6h


Proceeding with our stack installation lets get CNV installed.  Again with the use of the Ansible playbook we used earlier for OpenShift this is a relatively easy task:

[origin@ocp-master ~]$ oc login -u system:admin
[origin@ocp-master ~]$ cd /usr/share/ansible/kubevirt-ansible
[origin@ocp-master ~]$ ansible-playbook -i /etc/ansible/hosts -e @vars/cnv.yml playbooks/kubevirt.yml -e apb_action=provision

Once the installation completes lets run the following command to ensure the pods for CNV are up:

[origin@ocp-master ~]$ oc get pods --all-namespaces -o wide|egrep "kubevirt|cdi"
cdi                                 cdi-apiserver-7bfd97d585-tqjgt                 1/1       Running     0          6h        10.129.0.11     ocp-node3    
cdi                                 cdi-deployment-6689fcb476-4klcj                1/1       Running     0          6h        10.131.0.12     ocp-node1    
cdi                                 cdi-operator-5889d7588c-wvgl4                  1/1       Running     0          6h        10.130.0.12     ocp-node2    
cdi                                 cdi-uploadproxy-79c9fb9f59-pkskw               1/1       Running     0          6h        10.129.0.13     ocp-node3    
cdi                                 virt-launcher-f29vm-h6mc9                      1/1       Running     0          6h        10.129.0.15     ocp-node3    
kubevirt-web-ui                     console-854d4585c8-hgdhv                       1/1       Running     0          6h        10.129.0.10     ocp-node3    
kubevirt-web-ui                     kubevirt-web-ui-operator-6b4574bb95-bmsw7      1/1       Running     0          6h        10.130.0.11     ocp-node2    
kubevirt                            kubevirt-cpu-node-labeller-fvx9n               1/1       Running     0          6h        10.128.0.29     ocp-master   
kubevirt                            kubevirt-cpu-node-labeller-jr858               1/1       Running     0          6h        10.131.0.13     ocp-node1    
kubevirt                            kubevirt-cpu-node-labeller-tgq5g               1/1       Running     0          6h        10.129.0.14     ocp-node3    
kubevirt                            kubevirt-cpu-node-labeller-xqpbl               1/1       Running     0          6h        10.130.0.13     ocp-node2    
kubevirt                            virt-api-865b95d544-hg58l                      1/1       Running     0          6h        10.129.0.8      ocp-node3    
kubevirt                            virt-api-865b95d544-jrkxh                      1/1       Running     0          6h        10.131.0.10     ocp-node1    
kubevirt                            virt-controller-5c89d4978d-q79lh               1/1       Running     0          6h        10.130.0.8      ocp-node2    
kubevirt                            virt-controller-5c89d4978d-t58l7               1/1       Running     0          6h        10.130.0.10     ocp-node2    
kubevirt                            virt-handler-gblbk                             1/1       Running     0          6h        10.128.0.28     ocp-master   
kubevirt                            virt-handler-jnwx6                             1/1       Running     0          6h        10.130.0.9      ocp-node2    
kubevirt                            virt-handler-r94fb                             1/1       Running     0          6h        10.129.0.9      ocp-node3    
kubevirt                            virt-handler-z7775                             1/1       Running     0          6h        10.131.0.11     ocp-node1    
kubevirt                            virt-operator-68984b585c-265bq                 1/1       Running     0          6h        10.129.0.7      ocp-node3    

Now that CNV is up running lets pull down a Fedora 29 image and upload it into a PVC of the default storageclass which of course is Rook/Ceph:

[origin@ocp-master ~]$ curl -L -o /home/origin/f29.qcow2 http://ftp.usf.edu/pub/fedora/linux/releases/29/Cloud/x86_64/images/Fedora-Cloud-Base-29-1.2.x86_64.qcow2
[origin@ocp-master ~]$ virtctl image-upload --pvc-name=f29vm --pvc-size=5Gi --image-path=/home/origin/f29.qcow2 --uploadproxy-url=https://`oc describe route cdi-uploadproxy-route|grep Endpoints|cut -f2` --insecure

We can execute the following to see that the PVC has been created:

[origin@ocp-master ~]$ oc get pvc
NAME      STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
f29vm     Bound     pvc-4815df9e-4987-11e9-a732-525400767d62   5Gi        RWO            rook-ceph-block   6h

Besides the PVC we will also need a virtual machine configuration yaml file.  The one below is an example that will be used in this demonstration:

apiVersion: kubevirt.io/v1alpha3
kind: VirtualMachine
metadata:
  creationTimestamp: null
  labels:
    kubevirt-vm: f29vm
  name: f29vm
spec:
  running: true
  template:
    metadata:
      creationTimestamp: null
      labels:
        kubevirt.io/domain: f29vm
    spec:
      domain:
        cpu:
          cores: 2
        devices:
          disks:
          - disk:
              bus: virtio
            name: osdisk
            volumeName: osdisk
          - disk:
              bus: virtio
            name: cloudinitdisk
            volumeName: cloudinitvolume
          interfaces:
          - name: default
            bridge: {}
        resources:
          requests:
            memory: 1024M
      terminationGracePeriodSeconds: 0
      volumes:
      - name: osdisk
        persistentVolumeClaim:
          claimName: f29vm
      - name: cloudinitdisk
        cloudInitNoCloud:
          userData: |-
            #cloud-config
            password: ${PASSWORD}
            disable_root: false
            chpasswd: { expire: False }
            ssh_authorized_keys:
            - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUs1KbLraX74mBM/ksoGwbsEejfpCVeMzbW7JLJjGXF8G1jyVAE3T0Uf5mO8nbNOfkjAjw24lxSsEScF2wslBzA5MIm+GB6Z+ZzR55FcRlZeouGVrfLmb67mYc2c/F/mq35TruHdRk2G5Y0+6cf8cfDs414+yiVA0heHQvWNfO7kb1z9kIOhyD6OOwdNT5jK/1O0+p6SdP+pEal51BsEf6GRGYLWc9SLIEcqtjoprnundr5UPvmC1l/pkqFQigMehwhthrdXC4GseWiyj9CnBkccxQCKvHjzko/wqsWGQLwDG3pBsHhthvbY0G5+VPB9a8YV58WJhC6nHpUTDA8jpB origin@ocp-master"
      networks:
      - name: default
        pod: {}

At this point we have all the necessary components to launch our containerized virtual machine instance.   The following command does the creation using the yaml file we created in the previous step:

[origin@ocp-master ~]$ oc create -f /home/origin/f29vm.yaml

There are multiple ways to validate the virtual machine has been instantiated.   I like to do the following to confirm the instance is running and has an IP address:

[origin@ocp-master ~]$ oc get vms
NAME      AGE       RUNNING   VOLUME
f29vm     6h        true      
[origin@ocp-master ~]$ oc get vmi
NAME      AGE       PHASE     IP            NODENAME
f29vm     6h        Running   10.129.0.15   ocp-node3

One final step you can do is actually log into the instance assuming a key was set in the yaml file:

[origin@ocp-master ~]$ ssh -i /home/origin/.ssh/id_rsa -o "StrictHostKeyChecking=no" fedora@10.129.0.15
[fedora@f29vm ~]$ cat /etc/fedora-release
Fedora release 29 (Twenty Nine)

Hopefully this demonstrated how easy it is to get OpenShift, Rook and CNV up and running and how one can then leverage the storage of Rook to provide a backend for the virtual instance that gets spun up in CNV.   What is awesome is that I have taken the steps above and put them into a DCI job where I can automatically rerun the deployment using newer version of the code base for testing.   If you are not familiar with DCI I will leave with this tease link to DCI: https://doc.distributed-ci.io/