Installing CoreOS On KVM Libvirt Using virt-install Without PXE

This guide explains how to do a custom installation of CoreOS inside a QEMU/KVM virtual machine without the use of scripts, ISO’s or PXE servers.

Firstly you are going to need root access to a KVM host which we assume you already have. The KVM host we are using has a storage pool configured called vm_storage which points to a logical volume, you may use flat files if so you will need to adjust certain aspects of this guide (mainly the virt-install commands)

  1. Download the CoreOS kernel image and ramdisk to /var/lib/libvirt/images.
    [root@microserver ~]# wget https://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe.vmlinuz -O /var/lib/libvirt/images/coreos_production_pxe.vmlinuz
    
    [root@microserver ~]# wget https://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe_image.cpio.gz -O /var/lib/libvirt/images/coreos_production_pxe_image.cpio.gz
  2. Create the temporary virtual machine to configure the image. You will want to configure the name, ram, disk, network and CPU’s to your requirements.
    [root@microserver ~]# virt-install --name vm103 --ram 2048 --disk pool=vm_storage,size=20,bus=virtio,sparse=false --network bridge=br0,model=virtio --noautoconsole --vcpus 2 --graphics none --boot kernel=/var/lib/libvirt/images/coreos_production_pxe.vmlinuz,initrd=/var/lib/libvirt/images/coreos_production_pxe_image.cpio.gz,kernel_args="console=ttyS0 coreos.autologin=ttyS0" --os-type=linux --os-variant=virtio26 
    Starting install...
    Allocating 'vm103' | 20 GB 00:00:00
    Creating domain... | 0 B 00:00:00
    Domain creation completed.
  3. Shortly after the virtual machine should be booted, you can now get to it by typing. Once connected to the console you will already be logged in, no need for a username and password yet.
    [root@microserver ~]# virsh console vm103
    Connected to domain vm103
    Escape character is ^]
    
    core@localhost ~ $
  4. Next up, you need to configure networking. This will allow to download your cloud-config.yml file from where-ever it may be.
    core@localhost ~ $ sudo ip addr add 192.168.2.100/24 dev eth0
    core@localhost ~ $ sudo ip route add default via 192.168.2.1
    core@localhost ~ $ sudo bash
    bash-4.3# echo "nameserver 8.8.8.8" > /etc/resolv.conf
  5. Networking should now be enabled, and you should be able to reach the outside world if you have configured the network settings correctly.
    bash-4.3# ping google.co.uk
    PING google.co.uk (216.58.208.131) 56(84) bytes of data.
    64 bytes from google.co.uk (216.58.208.131): icmp_seq=1 ttl=54 time=4.75 ms
  6. Now download your cloud-config.yml file.
    bash-4.3# wget http://www.greglangford.co.uk/cloud-config.yml
  7. It’s time to install CoreOS to the disk of the virtual machine, you can do this by running the following.
    bash-4.3# coreos-install -d /dev/vda -c cloud-config.yml
  8. After sometime CoreOS should now be installed to disk. You will see several files being downloaded such as coreos_production_image.bin.bz2 followed by a message indicating that CoreOS has been installed.
    [ 654.261067] GPT:Primary header thinks Alt. header is not at the end of the disk.
    [ 654.262990] GPT:9289727 != 41943039
    [ 654.263805] GPT:Alternate GPT header not at the end of the disk.
    [ 654.265395] GPT:9289727 != 41943039
    [ 654.266316] GPT: Use GNU Parted to correct GPT errors.
    [ 654.268226] vda: vda1 vda2 vda3 vda4 vda6 vda7 vda9
    [ 654.360897] GPT:Primary header thinks Alt. header is not at the end of the disk.
    [ 654.362542] GPT:9289727 != 41943039
    [ 654.363193] GPT:Alternate GPT header not at the end of the disk.
    [ 654.364297] GPT:9289727 != 41943039
    [ 654.364946] GPT: Use GNU Parted to correct GPT errors.
    [ 654.365878] vda: vda1 vda2 vda3 vda4 vda6 vda7 vda9
    Success! CoreOS stable 1068.9.0 is installed on /dev/vda
  9. It’s time to shutdown your virtual machine and destroy it!
    bash-4.3# shutdown -h now

    You might find it odd that we are destroying the virtual machine. However remember when we first booted it we specified the kernel and ramdisk to load? Well we no longer need these, CoreOS is installed to disk and has it’s own bootloader, in a moment we will import our new disk image into a fresh virtual machine.

  10. Time to destroy the old virtual machine, be careful not to remove the disk image / logical volume that was created as we will need this. You may get an error running virsh destroy as the virtual machine should already be in an off state from running shutdown -h now. If so you can ignore this error.
    [root@microserver ~]# virsh destroy vm103
    error: Failed to destroy domain vm103
    error: Requested operation is not valid: domain is not running
    
    [root@microserver ~]# virsh undefine vm103
    Domain vm103 has been undefined
  11. Finally it’s time to bring your brand new shiny CoreOS virtual machine online.
    [root@microserver ~]# virt-install --import --name vm103 --ram 2048 --disk path=/dev/vm_storage/vm103,bus=virtio --network bridge=br0,model=virtio --noautoconsole --vcpus 2 --graphics none --os-type=linux --os-variant=virtio26
    
    Starting install...
    Creating domain... | 0 B 00:00:00
    Domain creation completed.

    The above command looks very familiar, however note the subtle differences. We have used –import to tell virt-install not to create a new disk image or logical volume. Instead we are importing the one from our original virtual machine. Other settings such as name, ram, disk, network, cpu etc should stay the same.

  12. You can now load a console to your CoreOS virtual-machine.
    [root@microserver ~]# virsh console vm103
    Connected to domain vm103
    Escape character is ^]
    
    
    This is localhost (Linux x86_64 4.6.3-coreos) 23:28:06
    SSH host key: SHA256:roBG5+kn34mjBKfGimAI4gtRtEh0qsjkk4KD3rPF7jM (ECDSA)
    SSH host key: SHA256:lugGHjMdEThSXzK8UpB94nTprGfG5Aqdz4CM+S3FZuA (RSA)
    SSH host key: SHA256:j7bCgrKOaUcjt/qWeAmbSZq+bqtvXKszvHLDcQhXz+U (ED25519)
    SSH host key: SHA256:gNKZztPfsw89wFnIIJ66ciHK+/hwFq/a3L865vit5OQ (DSA)
    eth0: 192.168.2.39 2a00:23c4:3f1b:7801:5054:ff:fe43:becb
    
    localhost login:

    Depending on how quickly you connect to the console, you may see a different output until the virtual machine finishes booting.

I hope you have enjoyed this guide and found it useful, if you have any questions or feedback you can get in contact with me via the comments. Thanks for reading.

Mounting CDROM ISO To a Running KVM Guest

When you created your virtual machine with KVM maybe you specified a CDROM image file but need to attach a different image during install to load drivers? This is almost guaranteed if you are setting up a Windows virtual machine with virtio devices. You must first ensure that your ISO image is within /var/lib/libvirt/images (it may vary on your distro) however this path is correct for my install of CentOS 7.

To attach a CDROM ISO image use the following, in my case I am attaching the virtio drivers iso. The command is formatted as follows attach-disk <virtual machine name> <image file> <device> <type> <mode>

virsh attach-disk vm102 /var/lib/libvirt/images/virtio-win.iso hda –type cdrom –mode readonly

If you are in the same position as me and need the virtio drivers you will find after attaching the Virtio iso image you can not continue the Windows install. Once the drivers are installed you must attach the Windows ISO image again.

virsh attach-disk vm102 /var/lib/libvirt/images/en_windows_7_professional_with_sp1_x64_dvd_u_676939.iso hda –type cdrom –mode readonly