Ubuntu Vm On Mac



I first learned about libvirt and QEMU three years ago when I wrote a guide on how to virtualize macOS on a Linux system. Today I will be showing the opposite, virtualizing Linux on macOS using the same tools. I was surprised that with so many software developers using MacBooks everyday, nobody has created a guide on how to use libvirt and QEMU with macOS.

  1. Run Ubuntu Vm On Mac
  2. Ubuntu Vm On Mac
Mac on vm

Start VMware Fusion and use File New, select Install from disc or image, and click Continue on the dialog. Choose 'Use another disc or disc image', find your Ubuntu image where it's stored and select it, then click Continue. On a Mac, you must open Virtual Machine - Settings. And choose Sharing to bring up a dialog where you can add the folders you want to be visible in Ubuntu. Just choose your home folder. Then turn on the file sharing button (or turn off and on again). Go to Ubuntu and check if you can see all your host system's files in /mnt/hgfs/.

Why is libvirt and QEMU better? First of all, it's free and open-source. Unlike Parallels Desktop and VMWare Fusion, you won't need to pay for expensive subscriptions or manage licenses. There does exist an open-source alternative (from Oracle!) called VirtualBox, which works pretty well. However, VirtualBox does not support macOS's Hypervisor.Framework, a virtualization API created to limit kernel modification. This means the installer will ask for admin access to install kernel extensions, a feature Apple is now phasing out for security reasons. QEMU on the other hand has had support for Hypervisor.Framework since 2018. Just say no to kexts!

Furthermore, like many developers, I like to run VMs headless, i.e. without a desktop GUI, so that I can SSH into them. Running VMs in the background seems like a simple feature, but it requires a lot of complex configuration for both VirtualBox and VMWare Fusion. And Parallels wants you buy the Pro Edition to gain access. Market segmentation at its finest... With libvirt, VMs start headless. Plus, when you shutdown macOS, it sends a shutdown signal to your VMs as well.

To be clear, this method doesn't support USB Passthrough, GPU Passthrough, or bridge networking. But if you just need to test, for example, node.js or nginx on a Linux VM, then this method is great.

Before we begin, you should have VMware Fusion. installed on your Mac and have downloaded the Ubuntu Desktop 20.04 ISO. Create the Ubuntu Desktop VM. Open VMware Fusion, click + then New. Click Install from disc or image. Either drag the Ubuntu ISO image from finder into the box with the arrow or click the Use another disc or image button. There are two ways that we can run Ubuntu on the Mac. We can either setup a dual boot or we can run Ubuntu as a virtual machine. We will be using the virtual machine method in this tutorial. There are pros and cons to each method, however a virtual machine will be plenty adequate for most dual operating system requirements.

Installing libvirt and QEMU

  1. First, install homebrew, which is a package manager for macOS.
  2. Run brew install qemu gcc libvirt.
  3. Since macOS doesn't support QEMU security features, we need to disable them:
  4. Finally start the libvirt service, with brew services start libvirt. It will start after boot as well.

Installing Ubuntu Server 20.04

There are two ways to access the virtual display of the VM, either using a VNC client or the virt-viewer program. I recommend RealVNC Viewer. The VNC client is responsive and quick to install, but if you have multiple VMs you need to manually manage the different ports. With virt-viewer, you get a popup with all the VMs currently running, but it is laggy and takes an eternity to install. virt-viewer can be installed through homebrew. The rest of this guide uses VNC.

  1. Create a vms folder in your home directory, and generate a disk image. Change 50g to the size of your prefered disk:

  2. Download the Ubuntu Server 20.04 Install Image and my libvirt XML template and place the .iso and .xml files in the same folder.

  3. Modify the following elements in the ubuntu.xml file to match your your VM preferences and file paths. Save, then run virsh define ubuntu.xml followed by virsh start ubuntu.

  4. Start RealVNC Viewer and connect to localhost. Click the Ctrl+Alt+Del button to reboot the machine, and quickly press Esc to get into the boot menu. Press the number that matches the Ubuntu Server image.

  5. Install Ubuntu Server normally, making sure to enable the SSH server. Once it restarts you can connect to the VM from your terminal by running ssh -p 2222 user@localhost.

  6. To send a shutdown signal to your VM, run virsh shutdown ubuntu. To force shutdown, run virsh destroy ubuntu.

  7. To forward a port, e.g. port 443 from the VM to port 8443 locally, run the following: ssh -p 2222 -L8443:localhost:443 user@localhost

Multiple VMs

Mac

If you want to create multiple VMs, create an XML file for each machine with a unique UUID, VM name, and VNC port. Also, change the hostfwd argument so that each VM exposes a different port for SSH, e.g. 2223 instead of 2222. After you have defined them all, you can get a list of the VMs that are currently running with virsh list.

References:

Note: More discussion on Hacker News

Recently /u/Elezium asked the following question on Reddit: Tools to deploy k8s on-premise on top of Ubuntu. This is a question that a lot of people have answered using a combination of MAAS/VMWare/OpenStack for on premise multi-node Kubernetes. If you’re looking for something with more than a two or three machines, those resources are bountiful.

However, the question came to “How do I do Kubernetes on an existing Ubuntu VM”. This is different from LXD, which is typically a good solution — though without a bunch of networking modifications it won’t be reachable from outside that VM.

So, how do you make a single — or even small handful — of VMs run Kubernetes in a production fashion? You could do it all by hand, but we’re well beyond the point where doing things from scratch in a non-repeatable fashion is reasonable, let alone desireable.

First, get two VMs. This is probably the easiest thing, I’m going to use a simple VM running the latest 16.04 Ubuntu Server — though you could use the Desktop or Cloud flavor of Ubuntu. I’ll also be doing these steps from a Mac terminal, but you could do this from an Ubuntu or Windows machine the steps are the same.

Once you have two VMs running with at least 1 core and 1 GB RAM (ideally 2 core and 2 GB RAM each) you’ll need to make sure you have a few things set. First, make sure you can connect to the two VMs over SSH. This is important as the tools we’ll be using are for remote setups.

From your host machine verify you can connect to the IP address of your VM. In my setup, this IP addresses are 172.16.94.129 and 172.16.94.130. Make sure you replace this with the address for your machine.

Ubuntu Vm On Mac

If you created a different user, switch ubuntu with that username. You should get a successful connection and may be prompted for a password. Now that you have successfully connected, close this connection by typing exit this will return you to your host machine and we can continue!

If you haven’t already, make sure you have conjure-up installed on your machine. In short, that’s either going to be brew install conjure-up or snap install conjure-up for MacOS and Linux respectively. To verify everything worked issue the following two commands:

The output should be equal to or greater than 2.2 for both conjure-up and juju.

Now we’re going to bootstrap Juju, creating a controller for which we can deploy software to. Normally, this is when you’d just run conjure-up kubernetes but since we’re working in such a unique case — deploying scale out software into a single machine — we’re going to do a lot of the steps conjure-up does, only manually.

To do this, we need to know the IP address of the VM and the username for a sudo user on that machine. Again the user is typically ubuntu and the IP address is from earlier.

You may get prompted several times for a password, which are all passwords for your VM user.

Once the bootstrap is complete, issue a juju status to verify that you have an empty model. This is an abbreviated instruction for manual bootstrapping, a lot more details are available in the full Juju documentation.

Juju uses models like namespaces for deployment. If you notice when you issue a juju status the default model name is default and there are no machines, applications, or units deployed. However, there is a machine because we used it for bootstrapping. We are tip-toeing into dangerous territory as you shouldn’t use the controller (the machine we bootstrapped) to deploy software. However, that means we would need more VMs!

If you can create more VMs, I’d suggest adding another machine to this deployment and avoid doing this switch to the controller. To do this, skip this step and continue below. If you only have/want two VMs, continue with this step.

If you issue juju models you’ll notice there is a controller model in addition to the default model. If we switch to that model, juju switch controller and issue another juju status you’ll see that there are no applications, no units, but one machine — and it’s our VM from earlier!

Now that we have a model with a machine we can get to work. What we’re going to do is manually place a few components, then let the process take care of the rest!

We’ll need to add our other VMs. During this step you can add as many VMs as you’d like, the process is the same. In the following sections I’ll address how to scale out the components beyond this very small deployment.

In order to do so, we’ll need to add the other machines so Juju knows where we want to put our components. To do this, run the following command for each additional machine we’ve not yet told Juju about:

As with before, replace <user> and <ip> with the proper values from your setup.

Run juju status to verify you have all machines added and registered.

Kubernetes is comprised of a handful of components: etcd, easyrsa, kubernetes-master, kubernetes-worker, and flannel. When you complete a deployment of Kubernetes using conjure-up these components are installed, configured, and connected for you. Conjure-up uses Juju as the driver for these instructions and we’re doing this “manual” deployment manually with the Juju pieces directly.

First, we need to deploy EasyRSA and ETCD onto the machine. However, we don’t want to just smash them together, we’ll use LXD to separate and isolate these components.

Depending on your networking, this will take a few moments to create LXC machines and setup the software. Eventually you’ll end up with a state where etcd is blocked. You don’t need to wait for this to complete before issuing the following commands:

This will combine these two components on the single machine. We’re not going to use LXD for these components since it won’t be routable from outside the VM without messing with the network configuration. As such, we’re deploying --to machine 0, the components will be directly accessible through the VMs IP address.

After a few moments, you’ll find something like the following in juju status

As you can see, there’s still items executing. We could wait for these to complete, but if you’re as impatient as I am, then be thankful we live in an asynchronous world and press forward! The final step is to glue all these components together (and deploy the SDN). To do that, we’ll take the kubernetes-core bundle, which is a super light weight Kubernetes cluster, and deploy that now. It’ll skip over any component you’ve already deployed, add any components not yet deployed, and execute all the required relationships.

The output for this is pretty verbose, and should look something like the following:

This is to be expected. We see in several places Juju skips over components we’ve already deployed, adds things (flannel) that we’re missing, and finally adds all the relations for these components. This is how we resolve the etcd “blocked” message that it’s missing a certificate authority. You’ll notice that etcd:certificates is connected to easyrsa:client which will provider certs for etcd!

Eventually, after running juju status for a few mins you should end up with the following. A completely deployed Kubernetes cluster.

From this point forward, we’ll need to get the credentials for the cluster. This is done automatically for you with conjure-up. With this method you’ll just need to issue the following

If you already have a Kubernetes config file, choose another path, like ~/.kube/config.cdk and make sure you use export KUBECONFIG=$HOME/.kube/config.cdk to use the new configuration file.

Mac

For the final touch, I wanted to show how to scale this up. Ideally, you’d want to use a public cloud, private cloud (VMWare, OpenStack), or MAAS for bare metal. The manual provider is just that — very manual. That said, if you have more VMs you can add them and scale the applications to spread across them. I’m going to add another machine and use it for both etcd and kubernetes-worker.

The result will be a three node etcd and two nodes for Kubernetes workloads. Again, juju status will show you the status of the cluster at anytime. Eventually everything will converge on active and idle. Once this is done you’ve scaled out the deployment. From here you can continue to add VMs, redeploy everything again, or actually start using Kubernetes!

Ubuntu cloud

Run Ubuntu Vm On Mac

Ubuntu offers all the training, software infrastructure, tools, services and support you need for your public and private clouds.

Ubuntu Vm On Mac

Newsletter signup