Quick and dirty RHEL8 VM for testing on your Mac using just vagrant and virtualbox

I'm often asked a quick RHEL question, which entails me trying something out to provide the best answers. I don't want to maintain a number of servers just for this. So it would be nice to be able to fire up a VM on demand, with minimal effort.

Luckily, there are some excellent tools we can use for this. I use a Mac for my day-to-day duties, so it would be nice to be able to do things locally where I can.

Firstly, we need a hypervisor able to provide the underlying virtualisation. I use virtualbox. Secondly, we need something able to define and orchestrate our VM. Vagrant is perfect for this. Along with a few plugins we don't need anything else.

I wanted to create a RHEL8 VM where I could try out the latest osbuild tooling for creating RHEL images from blueprints for various platforms. This was my use case for the platform.

Firstly, let's create a directory where we can store various information:

mkdir ~/rhel-builds
cd ~/rhel-builds

If you don't have virtualbox, then download it. As I hadn't used it for a while, I took the opportunity to update my version:

vboxmanage --version
6.1.16r140961

I'm running MacOS Big Sur 11.0.1 which now mandates kernel extensions are signed. This was problematic with older versions of virtualbox, now has seems to be sorted. Due to the update, I had to reboot my Mac, but the installation process will inform you if required.

Now download and 'install' vagrant. I moved the binary to /usr/local/bin which is on my $PATH. I took the opportunity to upgrade this as well:

vagrant version
Installed Version: 2.2.14
Latest Version: 2.2.14
You're running an up-to-date version of Vagrant!

Vagrant has a raft of plugins for extending functionality and I'm going to make use of a few here for [potential] disk resizing, adding a data disk to the VM, and being able to register it automatically with subscription-manager:

vagrant plugin list
vagrant-disksize (0.1.3, global)
vagrant-persistent-storage (0.0.49, global)
vagrant-registration (1.3.4, global)

I'll explain their use in a minute when we look through the Vagrantfile, but for now just install them:

for p in vagrant-disksize vagrant-persistent-storage vagrant-registration; do vagrant plugin install $p; done

You'll see output like this:

Installing the 'vagrant-disksize' plugin. This can take a few minutes...
Installed the plugin 'vagrant-disksize (0.1.3)'!
Installing the 'vagrant-persistent-storage' plugin. This can take a few minutes...
Installed the plugin 'vagrant-persistent-storage (0.0.49)'!
Installing the 'vagrant-registration' plugin. This can take a few minutes...
Installed the plugin 'vagrant-registration (1.3.4)'!

Now we have the tooling installed, we just need a Vagrantfile, which will define what we create. I'll break it down into sections for explanation, but will provide the complete file at the bottom of this article. The # comment lines are just to make things a little clearer and can be stripped out to streamline further.

  # THE VAGRANT SOURCE BASE BOX
  config.vm.box = "generic/rhel8"

We don't even need to download an ISO, as we can just fetch a 'box' from the provided Vagrant Cloud. This boxes are versioned, so you can match a particular box. I'm just going to use the latest. If you're running an older version, vagrant will notify you and you can update quite simply using 'vagrant box update'

  # NAME THE VM SO WE CAN IDENTIFY IT
  config.vm.define "rhelbuilds"
  config.vm.hostname = "rhelbuilds"

I use the above 2 lines just for easier identification, otherwise vagrant tends to name things like 'default' which I don't find particularly useful.

  # DISKS
  # use this via the vagrant-disksize plugin to increase the default primary disk size:
  #config.disksize.size = '200GB'

 Now let's look at storage. I leave the above lines in commented out just in case I want to resize the primary root disk at some point. Virtualbox seems to create a 130Gb disk OOB for me, which is normally plenty, but there's nothing worse than running out of space!

  # use this via the vagrant-persistent-storage plugin to add other disks
  config.persistent_storage.enabled = true
  config.persistent_storage.diskdevice = '/dev/sdb'
  config.persistent_storage.location = "datadisk.vdi"
  config.persistent_storage.size = 20000
  config.persistent_storage.mountname = 'data'
  config.persistent_storage.filesystem = 'ext4'
  config.persistent_storage.mountpoint = '/data'
  config.persistent_storage.volgroupname = 'datavg'
      

We may want to import/attach a disk with existing data, or store of files etc as part of the testing, so we can create/attach a 'data' disk for this if we like using the above. It'll create a 20Gb .vdi disk in the local directory, and mount it as /data formatted as ext4. It'll also create a datavg for it, as we're using LVM by default.

  # NETWORKING - gets DHCP address from my local net
  config.vm.network "public_network", bridge: "en0: Wi-Fi (Wireless)"

Now for networking. I want to do as little as possible here, but have an internet facing address, so I use public_network which uses my default DHCP service to get a valid IP. Note that this is very insecure, this the docs point out time and time again. If you are concerned, RTFM!

How do you know what interface to use?

vboxmanage list bridgedifs | grep "^Name:"
Name:            en0: Wi-Fi (Wireless)
Name:            en5: USB Ethernet(?)
Name:            ap1
Name:            en1: Thunderbolt 1
Name:            en2: Thunderbolt 2
Name:            en3: Thunderbolt 3
Name:            en4: Thunderbolt 4
Name:            bridge0
Name:            awdl0
Name:            llw0

So my broadband router serves up a local IP using DHCP, and it's associated with a bridge network. There is also a NAT'd interface creating as well by default, which can be used allows me to get internet access from within the VM, but I want to connect from my local MAC terminal, hence using the bridge.

  # SHARED HOST FOLDER
  config.vm.synced_folder "~/Downloads", "/vagrant_data"

I add the above in, in case I want to get files in and out from my local Mac drive. ~Downloads works for me!

  # RHSM BITS using the vagrant-registration plugin
  config.registration.username = ENV['SUB_USERNAME']
  config.registration.password = ENV['SUB_PASSWORD']
  #config.registration.pools = ['pool1', 'pool2']
  config.registration.unregister_on_halt = false

 As we're using RHEL, we need to use subscription-manager to get access to the entitlements we might need for software testing. This can be automated using the vagrant-registration plugin, which is neat.

If you don't have access to RHEL subs, you can get free access using the Red Hat Developers route. Just register for your free account!

You can hardcode the username and password in the Vagrantfile, which isn't best practice, so I use ENV variables, which get picked up by the plugin. To do this, just set:

export SUB_USERNAME="your_rhn_id"
export SUB_PASSWORD="your_rhn_password"

config.registration.pools = ['pool1', 'pool2'] can be used to narrow down selections to particular pools if required.

As I might want to stop and restart this VM a bit, I use config.registration.unregister_on_halt = false to keep my subscription enabled to save time.

Ok, last bit! In this section, we're specifying the size of the VM:

    vb.gui = false
    vb.name = "rhelbuilds"
    vb.memory = "2048"
    vb.cpus = "2"

This is pretty self explanatory. I set the GUI to false, to stop virtualbox firing that up on screen, as I don't need it. You can still go into virtualbox at any stage to watch what's happening or get console access from there.

Ok, that's config done! You can create the complete Vagrantfile using:

cat >Vagrantfile<<EOF
# -*- mode: ruby -*-
# vi: set ft=ruby :


Vagrant.configure("2") do |config|


  # THE VAGRANT SOURCE BASE BOX
  config.vm.box = "generic/rhel8"


  # NAME THE VM SO WE CAN IDENTIFY IT
  config.vm.define "rhelbuilds"
  config.vm.hostname = "rhelbuilds"


  # DISKS
  # use this via the vagrant-disksize plugin to increase the default primary disk size:
  #config.disksize.size = '200GB'


  # use this via the vagrant-persistent-storage plugin to add other disks
  config.persistent_storage.enabled = true
  config.persistent_storage.diskdevice = '/dev/sdb'
  config.persistent_storage.location = "datadisk.vdi"
  config.persistent_storage.size = 20000
  config.persistent_storage.mountname = 'data'
  config.persistent_storage.filesystem = 'ext4'
  config.persistent_storage.mountpoint = '/data'
  config.persistent_storage.volgroupname = 'datavg'

  # NETWORKING - gets DHCP address from my local net
  config.vm.network "public_network", bridge: "en0: Wi-Fi (Wireless)"


  # SHARED HOST FOLDER
  config.vm.synced_folder "~/Downloads", "/vagrant_data"


  # RHSM BITS using the vagrant-registration plugin
  config.registration.username = ENV['SUB_USERNAME']
  config.registration.password = ENV['SUB_PASSWORD']
  #config.registration.pools = ['pool1', 'pool2']
  config.registration.unregister_on_halt = false


  # VM CUSTOMISATIONS
  config.vm.provider "virtualbox" do |vb|
    vb.gui = false
    vb.name = "rhelbuilds"
    vb.memory = "2048"
    vb.cpus = "2"
  end


end
EOF


We can now create the VM!

vagrant up

Bringing machine 'rhelbuilds' up with 'virtualbox' provider...
==> rhelbuilds: Using /Users/pgriffit/rhel-builds/datadisk.vdi for persistent storage.
==> rhelbuilds: Importing base box 'generic/rhel8'...
==> rhelbuilds: Matching MAC address for NAT networking...
==> rhelbuilds: Using /Users/pgriffit/rhel-builds/datadisk.vdi for persistent storage.
==> rhelbuilds: Checking if box 'generic/rhel8' version '3.1.20' is up to date...
==> rhelbuilds: Setting the name of the VM: rhelbuilds
==> rhelbuilds: Clearing any previously set network interfaces...
==> rhelbuilds: Preparing network interfaces based on configuration...
    rhelbuilds: Adapter 1: nat
    rhelbuilds: Adapter 2: bridged
==> rhelbuilds: Forwarding ports...
    rhelbuilds: 22 (guest) => 2222 (host) (adapter 1)
==> rhelbuilds: Using /Users/pgriffit/rhel-builds/datadisk.vdi for persistent storage.
==> rhelbuilds: Running 'pre-boot' VM customizations...
==> rhelbuilds: Using /Users/pgriffit/rhel-builds/datadisk.vdi for persistent storage.
==> rhelbuilds: ** Persistent Storage Volume exists, not creating **
==> rhelbuilds: Using /Users/pgriffit/rhel-builds/datadisk.vdi for persistent storage.
==> rhelbuilds: ** Attaching persistent storage **
==> rhelbuilds: Booting VM...
==> rhelbuilds: Waiting for machine to boot. This may take a few minutes...
    rhelbuilds: SSH address: 127.0.0.1:2222
    rhelbuilds: SSH username: vagrant
    rhelbuilds: SSH auth method: private key
    rhelbuilds:
    rhelbuilds: Vagrant insecure key detected. Vagrant will automatically replace
    rhelbuilds: this with a newly generated keypair for better security.
    rhelbuilds:
    rhelbuilds: Inserting generated public key within guest...
    rhelbuilds: Removing insecure key from the guest if it's present...
    rhelbuilds: Key inserted! Disconnecting and reconnecting using new SSH key...
==> rhelbuilds: Machine booted and ready!
==> rhelbuilds: Registering box with vagrant-registration...
==> rhelbuilds: Checking for guest additions in VM...
    rhelbuilds: The guest additions on this VM do not match the installed version of
    rhelbuilds: VirtualBox! In most cases this is fine, but in rare cases it can
    rhelbuilds: prevent things such as shared folders from working properly. If you see
    rhelbuilds: shared folder errors, please make sure the guest additions within the
    rhelbuilds: virtual machine match the version of VirtualBox you have installed on
    rhelbuilds: your host and reload your VM.
    rhelbuilds:
    rhelbuilds: Guest Additions Version: 5.2.44
    rhelbuilds: VirtualBox Version: 6.1
==> rhelbuilds: Using /Users/pgriffit/rhel-builds/datadisk.vdi for persistent storage.
==> rhelbuilds: ** Managing persistent storage **
==> rhelbuilds: Setting hostname...
==> rhelbuilds: Configuring and enabling network interfaces...
==> rhelbuilds: Mounting shared folders...
    rhelbuilds: /vagrant_data => /Users/pgriffit/Downloads

Login to your new fresh VM and have fun knowing that if you screw things up, you can vagrant halt/destroy/up again to start over!

vagrant status
Current machine states:


rhelbuilds                running (virtualbox)


The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.


vagrant ssh

[vagrant@rhelbuilds ~]$ cat /etc/redhat-release
Red Hat Enterprise Linux release 8.3 (Ootpa)

[vagrant@rhelbuilds ~]$ sudo -i

[root@rhelbuilds ~]# df -h
Filesystem                   Size  Used Avail Use% Mounted on
devtmpfs                     891M     0  891M   0% /dev
tmpfs                        909M     0  909M   0% /dev/shm
tmpfs                        909M   17M  892M   2% /run
tmpfs                        909M     0  909M   0% /sys/fs/cgroup
/dev/mapper/rhel_rhel8-root   70G  2.2G   68G   4% /
/dev/sda1                   1014M  185M  830M  19% /boot
/dev/mapper/datavg-data       20G   45M   19G   1% /data
vagrant_data                 932G  261G  672G  28% /vagrant_data
tmpfs                        182M     0  182M   0% /run/user/1000








要查看或添加评论,请登录

Phil Griffiths的更多文章

  • Still using vi for Ansible? No problem!

    Still using vi for Ansible? No problem!

    Having grown up using vi as a main editor on UN*X systems, I still love it and often fire it up for quick demos etc. I…

    3 条评论
  • Calling the Ansible Automation Platform API Using 'Friendly' Job Template Names

    Calling the Ansible Automation Platform API Using 'Friendly' Job Template Names

    Have you ever wanted to call the AAP/Tower API to launch a Job Template? The REST API allows you to do that, fast and…

    1 条评论
  • Creating a custom EE for AWX

    Creating a custom EE for AWX

    This is a quick and rough guide to creating and consuming a custom execution environment (EE) in AWX. What You'll Need…

    29 条评论
  • Ansible Execution Environments

    Ansible Execution Environments

    Introduction Ansible as a automation platform offering is evolving further, making customer automation runtimes easier…

    15 条评论
  • AWX 18.0.0 with Containerised Execution Environments

    AWX 18.0.0 with Containerised Execution Environments

    The upstream of Ansible Automation Platform, AWX has just landed with a new exciting release. Thought I'd give it a try…

    4 条评论
  • Ansible Features I Missed

    Ansible Features I Missed

    Well, ok some of these aren't particularly new, but I've only just become aware of them. Even after years of Ansible…

    4 条评论
  • Tuning RHEL Using Ansible System Roles

    Tuning RHEL Using Ansible System Roles

    Take the pain out of some performance tuning using RHEL's tuned functionality. Take even more pain out setting it up…

    1 条评论
  • Oh Molecule You've Come A Long Way

    Oh Molecule You've Come A Long Way

    I often get asked about Ansible testing, best practices and related topics. If there's one tool I'd have in the kit bag…

    4 条评论
  • Holy crap batman! sudo's bust!

    Holy crap batman! sudo's bust!

    As we all know, software has bugs, no one escapes! How you respond and fix those bugs is what's important. If you ever…

    1 条评论
  • RHEL OS Image Builder (part two)

    RHEL OS Image Builder (part two)

    This is part 2 of the blog series. Part one is here.

    1 条评论

社区洞察

其他会员也浏览了