408 lines
14 KiB
ReStructuredText
408 lines
14 KiB
ReStructuredText
new virtual machine
|
|
###################
|
|
|
|
:date: 2019-11-10 00:00
|
|
:modified: 2021-09-13 00:00
|
|
:tags: infra
|
|
:category: documentation
|
|
:slug: create_vm
|
|
:authors: Ms.Leave-A-Mix
|
|
:summary: How-To install a new virtual machine with libvirt
|
|
|
|
This is an how-to, and it's goal is not to explain how virtual machines with
|
|
Libvirt/KVM work. For more information, see wikipedia or libvirt_ website.
|
|
|
|
.. _libvirt: https://libvirt.org
|
|
|
|
-----------------
|
|
Create the domain
|
|
-----------------
|
|
|
|
First of all, we create an XML based file that will describe the attributes of
|
|
our new virtual machine. Important points are : name, number of virtual CPUs, maximum amount
|
|
of RAM dedicated to the machine, base filesystem, boot device and network.
|
|
|
|
Here is a template to fill : domain.xml_ (save as)
|
|
|
|
After everyhing is set up, define this domain using the "virsh" tool.
|
|
|
|
:code:`virsh define <my_domain.xml>`
|
|
|
|
.. _domain.xml: /static/domain-base.xml
|
|
|
|
-------------------------
|
|
Create the storage device
|
|
-------------------------
|
|
|
|
We'll use an LVM storage device for this virtual machine, this is the standard
|
|
way to do on Freepoteries' server. Choose wisely the name, and size of the
|
|
volume.
|
|
|
|
:code:`lvcreate --name rootfs-<my_domain> --size 5G vg0`
|
|
|
|
Then, refresh the *already defined* pool with virsh.
|
|
|
|
:code:`virsh pool-refresh vg0`
|
|
|
|
--------------------------
|
|
Use a new distribution iso
|
|
--------------------------
|
|
|
|
*This is an optional step, only if you need an distro's iso that is not already
|
|
stored on the server*
|
|
|
|
The iso's are all stored on the vg0/iso volume that is mounted on /mnt/iso. If
|
|
the ones that are available don't fit your needs, you may add a new one by
|
|
downloading it directly in that folder. When it's done, refresh the iso pool of
|
|
libvirt, with virsh.
|
|
|
|
:code:`virsh pool-refresh iso`
|
|
|
|
Be sure to change the "volume" attribute of the "source" node in the domain XML,
|
|
by specifying the name of your iso file. You can check that your iso has been
|
|
registered by libvirt by the following command.
|
|
|
|
:code:`virsh vol-list iso`
|
|
|
|
------------------------
|
|
Boot the virtual machine
|
|
------------------------
|
|
|
|
*If it's a new installation from an iso file, be sure to specify the boot device
|
|
as "cdrom" in the VM's xml. Check this with the following command*
|
|
|
|
:code:`virsh dumpxml <my_domain>|grep "<boot dev="`
|
|
|
|
If this command output looks like this : :code:`<boot dev='hd'/>`, you're not in
|
|
the right way. Edit the VM's definition with :code:`virsh edit <my_domain>`, and
|
|
change the *dev* attribute of the *boot* node to *cdrom*: :code:`<boot
|
|
dev='cdrom'/>`.
|
|
|
|
Now that everything is read, the start command can be invoked.
|
|
|
|
:code:`virsh start <my_domain>`
|
|
|
|
If this command outputs the following : :code:`Domain <my_domain> started`, your
|
|
domain is booting : smooth!
|
|
|
|
---------------------------------
|
|
Virtual machine's OS installation
|
|
---------------------------------
|
|
|
|
We now need a way to communicate with the VM, so we can setup the new system.
|
|
Rare are the distributions that gives us an SSH access as the iso is booted. We
|
|
then need to use another remote-control technology, that's handled by libvirt.
|
|
It's name is VNC_ : Virtual Network Computing. It works as a client-server
|
|
protocol, and here is how you can connect to it. You will need to act on the
|
|
server, by ssh, and on your own machine. To help you differ on which machine the
|
|
actions are done, I'll define 3 entities :
|
|
|
|
- local: your own machine's OS, that is physically in front of you
|
|
- server: the remote server's OS, on which you are usually connect via SSH
|
|
- vm: the remote virtual machine, that is running on the server
|
|
|
|
First of all, define on which port the VNC server for your VM is running :
|
|
|
|
:code:`(server)# virsh domdisplay <my_domain>`
|
|
|
|
If the output of this command is : :code:`vnc://127.0.0.1:37`, that means that
|
|
the VNC port is **5937** (not 37!!), you must now make something that
|
|
demonstrate the power of SSH. This is named `SSH Tunnelling`_! Locally, you can
|
|
create a tunnel with this simple command example :
|
|
|
|
:code:`(local)$ ssh <user>@<server.ip> -L <local_port>:127.0.0.1:<remote_port>`
|
|
|
|
This magic will simply redirect all your local calls on **<local_port>** to the
|
|
**<server.ip**> **<remote_port>**. You can try this with the following example :
|
|
|
|
.. code-block:: bash
|
|
|
|
(server)# nc -l -s 127.0.0.1 -p 4242 # open a netcat server on the 4242 port
|
|
# ONLY FOR local connections (127.0.0.1)
|
|
|
|
(local)$ ssh user@server -L 8000:127.0.0.1:4242 # create the tunnel by
|
|
# connecting to server, and redirect his 4242 port to your 8000 port
|
|
|
|
# Now open a new terminal, but keep the ssh connection open.
|
|
|
|
(local)$ echo 'Hello, world!' | nc 127.0.0.1 8000
|
|
|
|
# You will see your message appear on the server's side!
|
|
|
|
Ok then, when you've understood this principle, this should come clearly that,
|
|
for the VNC server that's running on 127.0.0.1:5934, we need the following
|
|
tunnel :
|
|
|
|
:code:`(local)$ ssh <user>@<server.ip> -L 5900:127.0.0.1:5934`
|
|
|
|
**5900** is the default port for VNC, but you can choose any other one if 5900
|
|
is busy on your machine, just change it in the previous command.
|
|
|
|
Now you can connect to the VNC server, by using the - now standard - tool
|
|
"TigerVNC_". Download it from your OS's repositories, or, for Windows, on their
|
|
website. Calling TigerVNC this way will directly open the connection :
|
|
|
|
:code:`(local)$ vncviewer 127.0.0.1:5900`
|
|
|
|
An X window pops out, and your connected. Then, the following instructions will
|
|
depend on the OS you choose to install, if it's a Devuan standard iso install
|
|
that you've put into the virtual cd-rom drive of your VM, just follow the steps
|
|
as usual, and go to the final step of this how-to.
|
|
|
|
.. _VNC: https://en.wikipedia.org/wiki/Virtual_Network_Computing
|
|
.. _SSH Tunnelling: https://www.ssh.com/ssh/tunneling/
|
|
.. _TigerVNC: https://tigervnc.org
|
|
|
|
---------------------------
|
|
Gentoo installation on a VM
|
|
---------------------------
|
|
|
|
With Gentoo, the bootable iso that is provided in the download section of their
|
|
website is not a "step by step install", it's just a live OS that contains just
|
|
what you need to make an installation. The advantage of this is that, after a
|
|
Gentoo install, you will be able to understand what are the different parts of
|
|
your OS, and you'll be capable of choosing what is the best for the needs of a
|
|
specific machine, even if you don't use Gentoo everytime.
|
|
|
|
To make the process fast and avoid re-building packages, we'll use a local
|
|
binary repository, that is already setup on Freepoteries' host server (that runs
|
|
gentoo). This will make us gain a lot of time during installation. If you have
|
|
no access to a binary repository, use the standard Gentoo installation handbook.
|
|
|
|
**Version of Gentoo : 17.1**
|
|
|
|
Boot
|
|
^^^^
|
|
|
|
When you :code:`virsh start <my_domain>`, the machine will boot on the CD-rom
|
|
iso that you defined. For Gentoo's one, there's no automatic boot, you'll then
|
|
have to press enter within 10 seconds after boot. To do so, open the VNC window
|
|
as fast as possible after the VM starts.
|
|
|
|
You will see :code:`boot:` prompt waiting for you to press enter, DO SO!
|
|
|
|
Then, after booting, you will be asked for the keymap to use, **16** is for
|
|
**fr**, enter the correct number for your keymap.
|
|
|
|
SSH
|
|
^^^
|
|
|
|
When the system has booted, check if it is connected to the local network. It
|
|
normally should (of course set the IP to the gateway of your local network):
|
|
|
|
:code:`(vnc)# ping -c 1 192.168.42.1`
|
|
|
|
If everything's ok, we can begin! If not, contact your local administrator to
|
|
see if there is not a networking problem (as no more available IPs in the local
|
|
network, or a DHCP server that is missing his duty).
|
|
|
|
Set a password for root. No, I'm not laughing. Gentoo scrambles the root's
|
|
password when booting, that IS security. You can choose an empty password BTW.
|
|
|
|
:code:`(vnc)# passwd`
|
|
|
|
It will be more convenient (and less bandwidth consuming) to be connected by
|
|
SSH. To do so (I do NOT force you!), just launch SSH, using the OpenRC command
|
|
(or **service** if you're an old-timer) :
|
|
|
|
:code:`(vnc)# rc-service sshd start`
|
|
|
|
Retrieve your local ip, using the **iproute2** command :
|
|
|
|
:code:`(vnc)# ip a s`
|
|
|
|
If you can read this, and that you can find your IP in all these informations,
|
|
I think you're ready to work with Gentoo. As a remember, an IPv4 is in the
|
|
standard format : a.b.c.d, each of the letters being a number between 0 and 255.
|
|
But this is theory, now let's close this VNC window that is consuming all our
|
|
networks bandwidth, and let's open a nice SSH connection.
|
|
|
|
Did I say to remember your IP before closing the VNC window?.
|
|
|
|
:code:`(server)# ssh root@<vm_ip>`
|
|
|
|
If **known_hosts** cries about dangerous behaviour, if
|
|
so, verifiy the IP and if it's correct, just remove the line of
|
|
**~/.ssh/known_hosts** that sets the fingerprint to your VM's IP, and retry the
|
|
command.
|
|
|
|
When you're connected with SSH to the VM, we can begin the real installation!
|
|
|
|
Hard Disk
|
|
'''''''''
|
|
|
|
Normally, you should have set the hard disk (the one you will use for the OS)
|
|
device name to the default one : **vda**. If not change this in the following
|
|
commands.
|
|
|
|
.. code-block:: bash
|
|
|
|
# let's create the partitions
|
|
(my-domain)# fdisk /dev/vda
|
|
# delete all existing partitions, if there are with the "d" command"
|
|
# now create the new one
|
|
n <enter>
|
|
p <enter>
|
|
1 <enter>
|
|
<enter>
|
|
<enter>
|
|
w <enter>
|
|
|
|
# create the filesystem
|
|
(my-domain)# mkfs.ext4 /dev/vda1
|
|
|
|
# mount the new "/" partition
|
|
(my-domain)# mount /dev/vda1 /mnt/gentoo
|
|
|
|
|
|
OS Installation
|
|
'''''''''''''''
|
|
|
|
.. code-block:: bash
|
|
|
|
# download the "stage3" archive (retrieve the download link
|
|
# on gentoo's download page https://www.gentoo.org/downloads)
|
|
wget -O stage3.tar.xz http://distfiles.gentoo.org/releases/amd64/autobuilds/20191106T214502Z/stage3-amd64-20191106T214502Z.tar.xz
|
|
|
|
# untar (source : https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Stage)
|
|
# DON'T FORGET THE "-C /mnt/gentoo" OPTION IF YOU'RE NOT IN THIS DIRECTORY
|
|
tar xpvf stage3.tar.xz -C /mnt/gentoo --xattrs-include='*.*' --numeric-owner
|
|
|
|
# mount the rest of the partitions so you are ready to chroot
|
|
(my-domain)# mount -t proc /proc /mnt/gentoo/proc
|
|
(my-domain)# mount --rbind /dev /mnt/gentoo/dev
|
|
(my-domain)# mount --make-rslave /mnt/gentoo/dev
|
|
(my-domain)# mount --rbind /sys /mnt/gentoo/sys
|
|
(my-domain)# mount --make-rslave /mnt/gentoo/sys
|
|
|
|
# chroot into the new system
|
|
(my-domain)# chroot /mnt/gentoo
|
|
|
|
# change portage's options, these are the current ones for Freepoteries, and
|
|
# this may change
|
|
(my-domain)# cat << EOF >> /etc/portage/make.conf
|
|
PORTAGE_BINHOST="http://repo.freepoteries.fr"
|
|
FEATURES="getbinpkg"
|
|
USE="mmx sse sse2 multilib dlz -X -gtk -sdl -qt -nptl -xpm -gpm -python_targets_python2_7"
|
|
ACCEPT_LICENSE="* -@EULA"
|
|
EOF
|
|
|
|
(my-domain)# echo "=sys-boot/grub-2.02-r4 -nls -themes -grub_platforms_efi-64
|
|
-efiemu -libzfs -mount -fonts -device-mapper" > /etc/package.use/grub
|
|
|
|
# emerge the gentoo's latests snapshot - may take time
|
|
(my-domain)# emerge-webrsync
|
|
|
|
# choose the right profile
|
|
(my-domain)# eselect profile list
|
|
# this should be the same as on the host : 17.1 multilib
|
|
(my-domain)# eselect profile set 16
|
|
|
|
# let's emerge the basic necessary packages (answer yes if everything goes
|
|
# well)
|
|
(my-domain)# emerge --ask --update --deep --newuse @world
|
|
(my-domain)# emerge -aG sys-kernel/gentoo-sources sys-kernel/genkernel sys-boot/grub
|
|
|
|
# generate the kernel (yes, and this is the most time-consuming)
|
|
(my-domain)# genkernel --virtio all
|
|
|
|
# grub installation
|
|
(my-domain)# dispatch-conf
|
|
(my-domain)# grub-install /dev/vda
|
|
(my-domain)# grub-mkconfig > /boot/grub/grub.cfg
|
|
|
|
|
|
System configuration
|
|
''''''''''''''''''''
|
|
|
|
.. code-block:: bash
|
|
|
|
# set a root password
|
|
(my-domain)# passwd
|
|
|
|
# fstab
|
|
(my-domain)# echo '/dev/vda1 / ext4 defaults,errors=remount-ro,relatime 0 1' > /etc/fstab
|
|
|
|
# set locale parameters (time and locale)
|
|
(my-domain)# echo 'Europe/Paris' > /etc/timezone
|
|
(my-domain)# emerge --config sys-libs/timezone-data
|
|
(my-domain)# echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen
|
|
(my-domain)# locale-gen
|
|
(my-domain)# eselect locale list
|
|
# choose the right locale
|
|
(my-domain)# eselect locale 3
|
|
(my-domain)# env-update && source /etc/profile
|
|
|
|
|
|
# network
|
|
(my-domain)# echo 'hostname="my-domain" > /etc/conf.d/hostname'
|
|
(my-domain)# cat << EOF >> /etc/conf.d/net
|
|
config_eth0="dhcp"
|
|
EOF
|
|
|
|
(my-domain)# cd /etc/init.d
|
|
(my-domain)# ln -s net.lo net.eth0
|
|
(my-domain)# rc-update add net.eth0 default
|
|
|
|
# install a dhcp client
|
|
(my-domain)# emerge -G net-misc/dhcpcd
|
|
|
|
# go back to the live iso
|
|
(my-domain)# exit
|
|
# and switch it off
|
|
(my-domain)# poweroff
|
|
|
|
|
|
-----------------------
|
|
Finalization and checks
|
|
-----------------------
|
|
|
|
Now that you're back into the server's prompt, you can edit the VM's
|
|
configuration so it can boot on the hard disk. To do so, switch the boot device:
|
|
:code:`<boot dev='cdrom'/>`, to :code:`<boot dev='hd'/>`, and save the file.
|
|
|
|
If you want your machine to have a DHCP static lease, copy in the same time the MAC
|
|
address that is located under the **interface** node, at the **address**
|
|
attribute of the **mac** node.
|
|
|
|
:code:`(server)# virsh edit <my_domain>`
|
|
|
|
DHCP static leases should now execute the following script.
|
|
|
|
.. code-block:: bash
|
|
|
|
# this script adds a static lease for a virtual machine within libvirt
|
|
# it's advantage is that it do so without having to restart the libvirt
|
|
# network management
|
|
|
|
NAME=<my_domain>
|
|
MAC=<your_mac>
|
|
IP=<desired_ip>
|
|
|
|
virsh net-update default add ip-dhcp-host \
|
|
"<host mac='${MAC}' \
|
|
name='${NAME}' ip='${IP}' />" \
|
|
--live --config
|
|
|
|
# if you wish to use dnsmasq's dns service, execute also the following
|
|
|
|
virsh net-update default add dns-host \
|
|
"<host ip='${3}'> \
|
|
<hostname>${1}</hostname> \
|
|
</host>" \
|
|
--live --config
|
|
|
|
# you may have to reload the iptables rules if libvirt messes with them
|
|
# and if you don't want to restart the machine
|
|
|
|
cat /etc/network/iptables|iptables-restore
|
|
|
|
|
|
You can now re-start the machine.
|
|
|
|
:code:`(server)# virsh destroy <my_domain> && virsh start <my_domain>`
|
|
|
|
If you can ping it's IP (either the static on you choose, or the one the DHCP
|
|
server gave her), your machine is now up, and you may be able to log in it,
|
|
either via SSH, or as usual with the VNC server!
|