Giter VIP home page Giter VIP logo

little-vm-helper's Introduction

little-vm-helper

little-vm-helper (lvh) is a VM management tool, aimed for testing and development of features that depend on the kernel, such as BPF. It is used in cilium, tetragon, and pwru. It can also be used for kernel development. It is not meant, and should not be used for running production VMs. Fast booting and image building, as well as being storage efficient are the main goals.

It uses qemu and libguestfs tools. See dependencies.

Configurations for specific images used in the Cilium project can be found in: https://github.com/cilium/little-vm-helper-images.

Usage

For an example script, see scripts/example.sh.

LVH can be used to:

  • build root images for VMs
  • build kernels
  • download kernels
  • boot VMs using above

Build root images

Build example images:

$ mkdir _data
$ go run ./cmd/lvh images example-config > _data/images.json
$ go run ./cmd/lvh images build --dir _data # this may require sudo as relies on /dev/kvm

The first command will create a configuration file:

jq . < _data/images.json
[
  {
    "name": "base",
    "packages": [
      "less",
      "vim",
      "sudo",
      "openssh-server",
      "curl"
    ],
    "actions": [
      {
        "comment": "disable password for root",
        "op": {
          "Cmd": "passwd -d root"
        },
        "type": "run-command"
      }
    ]
  },
  {
    "name": "k8s",
    "parent": "base",
    "image_size": "20G",
    "packages": [
      "docker.io"
    ]
  }
]

The configuration file includes:

  • a set of packages for the image
  • an optional parent image
  • a set of actions to be performed after the installation of the packets. There are multiple actions supported, see pkg/images/actions.go.

Once the build-images command completes, the two images described in the configuration file will be present in the images directory. ote that the images are stored as sparse files so they take less space:

$ ls -sh1 _data/images/*.img
856M _data/images/base.img
1.7G _data/images/k8s.img

Build kernels

$ mkdir -p _data/kernels
$ go run ./cmd/lvh kernels --dir _data init
$ go run ./cmd/lvh kernels --dir _data add bpf-next git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git --fetch
$ go run ./cmd/lvh kernels --dir _data build bpf-next

Please note, to cross-build for a different architecture, you can use the --arch=arm64 or --arch=amd64 flag.

The configuration file keeps the url for a kernel, together with its configuration options:

$ jq . < _data/kernel.json
{
  "kernels": [
    {
      "name": "bpf-next",
      "url": "git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git"
    }
  ],
  "common_opts": [
    [
      "--enable",
      "CONFIG_LOCALVERSION_AUTO"
    ],
     ... more options ...
  ]
}

There are options that are applied to all kernels (common_opts) as well as kernel-specific options.

The kernels are kept in worktrees. Specifically, there is a git bare directory (git) that holds all the objects, and one worktree per kernel. This allows efficient fetching and, also, having each kernel on its own separate directory.

For example:

$ ls -1 _data/kernels
5.18/
bpf-next/
git/

Currently, kernels are built using the bzImage for x86_64 or Image.gz for arm64, and tar-pkg targets (see pkg/kernels/conf.go).

Download kernels

List the available versions

$ lvh kernels catalog
bpf-next
rhel8
4.9
4.19
[...]
6.3
6.6

Retrieve the tags for a given version:

$ lvh kernels catalog 6.6
6.6-20240123.120815
6.6-20240123.175813
[...]
6.6-20240404.144247
6.6-20240408.100959
6.6-main

See lvh kernels catalog --help for more details.

Download the kernel and related artifacts (BTF, modules, etc.)

$ lvh kernels pull 6.6-main
$ find 6.6-main/ -maxdepth 3
6.6-main/
6.6-main/boot
6.6-main/boot/vmlinuz-6.6.25
6.6-main/boot/btf-6.6.25
6.6-main/boot/System.map-6.6.25
6.6-main/boot/vmlinux-6.6.25
6.6-main/boot/config-6.6.25
6.6-main/lib
6.6-main/lib/modules
6.6-main/lib/modules/6.6.25

See lvh kernels pull --help for more details.

Booting images

You can use the run subcommand to start images.

For example:

go run ./cmd/lvh run --image _data/images/base.qcow2 --kernel _data/kernels/bpf-next/arch/x86_64/boot/bzImage

Or, to with the kernel installed in the image:

go run ./cmd/lvh run --image _data/images/base.qcow2

OCI images are also supported:

go run ./cmd/lvh run --image quay.io/lvh-images/root-images:main

Note: Building images and kernels is only supported on Linux. On the other hand, images and kernels already build on Linux can be booted in MacOS (both x86 and Arm). The only requirement is qemu-system-x86_64. As MacOS does not support KVM, the commands to boot images are:

go run ./cmd/lvh run --image _data/images/base.qcow2 --qemu-disable-kvm

FAQ

Why not use packer to build images?

Existing packer builders (e.g,.https://github.com/cilium/packer-ci-build/blob/710ad61e7d5b0b6872770729a30bcdade2ee1acb/cilium-ubuntu.json#L19, https://www.packer.io/plugins/builders/qemu) are meant to manage VMs with longer lifetimes than a single use, and use facilities that introduce unnecessary overhead for our use-case.

Also, packer does not seem to have a way to provision images without booting a machine. There is an outdated chroot package https://github.com/summerwind/packer-builder-qemu-chroot, and cloud chroot builders (e.g., https://www.packer.io/plugins/builders/amazon/chroot that uses https://github.com/hashicorp/packer-plugin-sdk/tree/main/chroot).

That being said, if we need packer functionality we can create a packer plugin (https://www.packer.io/docs/plugins/creation#developing-plugins).

Why not use vagrant (or libvirt-based tools)?

These tools also target production VMs with lifetime streching beyond a single use. As a result, they introduce overhead in booting time, provisioning time, and storage.

What are the dependencies of LVH?

On debian distribution, here is a list of packages needed for LVH to work.

Action Debian packages
Building images qemu-kvm mmdebstrap debian-archive-keyring libguestfs-tools
Building the Linux kernel libncurses-dev gawk flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf llvm
Cross-compile arm64 on x86_64 gcc-aarch64-linux-gnu
Cross-compile x86_64 on arm64 gcc-x86-64-linux-gnu

TODO

Notes

little-vm-helper's People

Contributors

aanm avatar brb avatar dependabot[bot] avatar dhawton avatar dramirez-qb avatar dylandreimerink avatar joestringer avatar kkourt avatar learnitall avatar lmb avatar markpash avatar mhofstetter avatar michi-covalent avatar mtardy avatar renovate[bot] avatar tklauser avatar tpapagian avatar willfindlay avatar yutarohayakawa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

little-vm-helper's Issues

lvh run without --host-mount fails

We should be able to call lvh run without a --host-mount argument.

Currently, if we do that we get:

$ lvh  run --image _data/images/base.qcow2             
qemu-system-x86_64: -device virtio-9p-pci,fsdev=host_id,mount_tag=host_mount: cannot initialize fsdev 'host_id': failed to open '': No such file or directory

Feature: allow users to specify kernel modules directory when running with custom kernel

At the time of writing, the LVH runner allows users to use a custom kernel path (to bzImage) via --kernel cmdline param. Unfortunately, it doesn't allow users to specify kernel modules directory. The pre-installed kmods in a VM image usually cannot be used with the custom kernel.

One workaround is to mount linux dir via --host-mount, and then from the VM cd /host/linux && make module_install. However, having the explicit kmods param would make the LVH runner easier to use.

Use hosts DNS resolver

In the cilium/cilium's ci-datapath pipeline we are using 1.1.1.1. Replace it with a host resolver.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

dockerfile
Dockerfile
  • golang 1.22.2@sha256:450e3822c7a135e1463cd83e51c8e2eb03b86a02113c89424e6f0f8344bb4168
  • busybox sha256:c3839dd800b9eb7603340509769c43e146a74c63dca3045a8e7dc8ee07e53966
github-actions
.github/workflows/basic.yaml
  • actions/checkout v4.1.1@b4ffde65f46336ab88eb53be808477a3936bae11
  • actions/setup-go v5.0.0@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
.github/workflows/build-image.yaml
  • actions/checkout v4.1.1@b4ffde65f46336ab88eb53be808477a3936bae11
  • docker/metadata-action v5.5.1@8e5442c4ef9f78752691e2d8f8d19755c6f78e81
  • docker/setup-qemu-action v3.0.0@68827325e0b33c7199eb31dd4e31fbe9023e06e3
  • docker/setup-buildx-action v3.3.0@d70bba72b1f3fd22344832f00baa16ece964efeb
  • docker/login-action v3.1.0@e92390c5fb421da1463c202d546fed0ec5c39f20
  • docker/build-push-action v5.3.0@2cdde995de11925a030ce8070c3d77a52ffcf1c0
.github/workflows/example.yaml
  • actions/checkout v4.1.1@b4ffde65f46336ab88eb53be808477a3936bae11
  • actions/setup-go v5.0.0@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
.github/workflows/quay.yaml
  • actions/checkout v4.1.1@b4ffde65f46336ab88eb53be808477a3936bae11
  • actions/setup-go v5.0.0@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
  • imjasonh/setup-ko v0.6@ace48d793556083a76f1e3e6068850c1f4a369aa
  • ubuntu 22.04
gomod
go.mod
  • go 1.22.1
  • github.com/docker/docker v25.0.3+incompatible
  • github.com/go-git/go-git/v5 v5.11.0
  • github.com/google/go-containerregistry v0.19.1
  • github.com/moby/term v0.5.0
  • github.com/sirupsen/logrus v1.9.3
  • github.com/spf13/cobra v1.8.0
  • github.com/stretchr/testify v1.9.0
  • golang.org/x/mod v0.12.0
  • golang.org/x/sys v0.17.0
  • golang.org/x/net v0.19.0

  • Check this box to trigger a request for Renovate to run again on this repository

CI: Add test for action.yaml to prevent breakage in main

PR #133 (commit 218de8b) broke the way that action.yaml runs VMs due to the new pull --cache feature. To discover that this was broken, we had to merge the PR, release a new version of LVH, and update cilium/cilium to invoke the new action.yaml. Furthermore, in order to test the fix, it seems like we also need to merge the PR (not yet knowing if it fixes everything), release a new LVH, and update cilium/cilium to invoke the new action.yaml.

It'd be an easier developer experience with lower likelihood to break things if we could push a branch to this repo with a PR, then run the action.yaml + proposed code in the branch before merging. Note that if we implement this, we should be careful not to expose the ability to write untrusted images to official LVH images if a drive-by contributor submits a PR from a fork.

arm64 support

Having arm64 support would allow Tetragon to run the tests with specific kernel versions ๐Ÿ™‚ !

Switch from docker library to crane

As proposed in #184 , crane is a smaller, simpler library than pulling in docker for lvh run --image <OCI tag>.

Tasks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.