# Virtual machines: what? * A program that emulates a physical computer: CPU, RAM, hard drives, networking, screen, keyboard, mouse, etc * More or less faithful to real hardware ----------------------------------------------------------------------------- # Virtual machines: why? * Can hit with a bat, axe, hammer. * Can be version controlled. * Easy to create with desired virtual hardware configuration * Share physical hardware resources more efficiently ----------------------------------------------------------------------------- # Why not containers? * Possibly less secure than virtual machines (jury is still out) * Containers and host share kernel instance, CPU; can't use different CPU architecture, operating system than host * But containers start faster, are easier to use, when they suit the use case. ----------------------------------------------------------------------------- # Virtualisation options * VirtualBox, QEmu, KVM, Xen, libvirt, ... * I use KVM + QEmu orchestrated by libvirt ----------------------------------------------------------------------------- # What you need: Linux + KVM * Enable virtualization in BIOS, rest should be automatic. * `lsmod | grep kvm` * `ls -l /dev/kvm` * [`https://wiki.debian.org/KVM`](https://wiki.debian.org/KVM) ----------------------------------------------------------------------------- # libvirt + friends - `apt install virt-manager virt-install libvirt-clients libnss-libvirt` - `sudo adduser $USER libvirt` - log out, back in - `virsh -c qemu:///system net-start default` - `virsh -c qemu:///system net-autostart default` - edit `/etc/nsswitch.conf`, line with `hosts`, include `libvirt libvirt_guest` ----------------------------------------------------------------------------- # Install Debian in a VM: virt-manager * Download ISO image: `get.debian.org` - `debian-10.9.0-amd64-netinst.iso`, and `SHA256SUMS` - check validity: `sha256sum -c SHA256SUMS --ignore-missing` * start `virt-manager` - unless you already did the `virsh` magic earlier: activate default network via Edit → Connection details → Virtual networks → default * create new VM with virt-manager * log in via ssh ----------------------------------------------------------------------------- # Create VM with virt-install ```sh virt-install \ --name "${name}" --connect qemu:///system \ --virt-type kvm --memory 2048 --vcpus 2 \ --boot hd,menu=off -disk path="${image},device=disk" \ --graphics vnc --os-type Linux --os-variant debian10 \ --console pty,target_type=serial --noautoconsole \ --import ``` * use OpenStack image from `cloud.debian.org` - needs a `cloud-init` ISO image with config to set up SSH access, hostname - not _difficult_ to make, but a bit of a bother * or custom image made some way ----------------------------------------------------------------------------- # Manual SSH known host key management is so 90s * Every new VM has a new host key - create VM, SSH is tiresome - delete VM, create new VM with same name, SSH is really upset: YOU ARE UNDER ATTACK! HELP! HELP! PANIC! * SSH CA and host certificates is bliss - create CA key - sign host key with CA key → host certificate - configure SSH client to accept certificates made with CA key - new hosts, re-created hosts are silently accepted - security **and** comfort is bliss! ----------------------------------------------------------------------------- # SSH CA * create CA key: `ssh-keygen -f ~/.ssh/ca -N '' -t ed25519` - edit `~/.ssh/known_hosts` to have a line with `@cert-authority * ssh-ed25519 AAAA....` - make and install the host certificate: `ssh-keygen -s ~/.ssh/ca -I "my SSH CA v1" \ -h -n shell.example.com host.key.pub` - install `host.key-cert.pub` on server `/etc/ssh` - edit `/etc/ssh/sshd_config` to point to certificate - still a bit tedious, but can be automated - [`https://liw.fi/sshca/`](https://liw.fi/sshca/) ----------------------------------------------------------------------------- # Install and configure vmadm Create `~/.config/vmadm/config.yaml` ```yaml image_directory: ~/vm-talk default_base_image: ~/vm-talk/debian-10-openstack-amd64.qcow2 default_image_gib: 5 default_memory_mib: 2048 default_cpus: 1 default_generate_host_certificate: true default_autostart: true ca_key: ~/.ssh/ca authorized_keys: - ~/.ssh/liw-openpgp.pub ``` ----------------------------------------------------------------------------- # Create a vmadm specification * Create `toys.yaml`, using defaults from configuration (or override attributes per-VM, as needed): ```yaml toy1: {} toy2: {} ``` * Manage VMs as a group. * `vmadm new toys.yaml` * `ssh debian@toy1` * `ssh debian@toy2` * `vmadm delete toys.yaml` ----------------------------------------------------------------------------- # Create VM image using vmdb2 * A VM image is a file is used as a virtual hard disk. Installing operating system can be done manually, or automated from a specification file. ----------------------------------------------------------------------------- ```{.yaml .numberLines} steps: - mkimg: "{{ output }}" size: 4G - mklabel: msdos device: "{{ output }}" - mkpart: primary device: "{{ output }}" start: 0% end: 100% tag: rootfs - kpartx: "{{ output }}" - mkfs: ext4 partition: rootfs - mount: rootfs ``` ----------------------------------------------------------------------------- ```{.yaml .numberLines} - unpack-rootfs: rootfs - debootstrap: buster target: rootfs mirror: http://deb.debian.org/debian unless: rootfs_unpacked - apt: install tag: rootfs packages: - linux-image-amd64 unless: rootfs_upacked - cache-rootfs: rootfs unless: rootfs_upacked - fstab: rootfs - grub: bios tag: rootfs ``` ------------------------------------------------------------------------------ ```sh sudo vmdb2 toy.vmdb --output toy.raw \ --verbose --rootfs-tarball toy.tar.gz \ --log toy.log ``` * simplistic example: doesn't sets hostname or SSH access - could be done, via Ansible - or install `cloud-init` in image * convert image: `qemu-img convert -O qcow2 toy.raw toy.qcow2` * tool could be polished a lot, but works --- title: "Computers you can't hit with a bat" subtitle: A brief introduction to virtual machines author: Lars Wirzenius date: 2021-06-21 ...