diff --git a/.gitignore b/.gitignore index cdded28..5e01b1d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ +/out /target -/bin/ -/targets/ diff --git a/Makefile b/Makefile index bdd884b..aad0aeb 100644 --- a/Makefile +++ b/Makefile @@ -7,30 +7,35 @@ CARGO ?= cargo SELINUXOPT ?= $(shell test -x /usr/sbin/selinuxenabled && selinuxenabled && echo -Z) binpath := $(DESTDIR)/$(PREFIX)/bin/crun-vm +manpath := $(DESTDIR)/$(PREFIX)/share/man/man1/crun-vm.1.gz -.PHONY: build -build: +all: out/crun-vm out/crun-vm.1.gz + +.PHONY: out/crun-vm +out/crun-vm: + mkdir -p $(@D) $(CARGO) build --release - mkdir -p bin - cp target/release/crun-vm bin/crun-vm + cp target/release/crun-vm $@ -.PHONY: build-debug -build-debug: - $(CARGO) build - mkdir -p bin - cp target/debug/crun-vm bin/crun-vm.debug +out/crun-vm.1.gz: docs/5-crun-vm.1.ronn + mkdir -p $(@D) + ronn --pipe --roff $< | gzip > $@ .PHONY: clean clean: - rm -fr bin target + rm -fr out target .PHONY: install -install: build - install ${SELINUXOPT} -D -m 0755 bin/crun-vm $(binpath) +install: out/crun-vm install-man + install ${SELINUXOPT} -D -m 0755 $< $(binpath) + +.PHONY: install-man +install-man: out/crun-vm.1.gz + install ${SELINUXOPT} -D -m 0644 $< $(manpath) .PHONY: uninstall uninstall: - rm -f $(binpath) + rm -f $(binpath) $(manpath) .PHONY: lint lint: diff --git a/README.md b/README.md index d384514..1d596b2 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,107 @@ # The crun-vm OCI Runtime **crun-vm** is an [OCI Runtime] that enables [Podman], [Docker], and -[Kubernetes] to run QEMU-compatible Virtual Machine (VM) images. +[Kubernetes] to run QEMU-compatible Virtual Machine (VM) images. This means you +can: -- Run **VMs** as easily as you run **containers**. -- Manage containers and VMs **together** using the **same** standard tooling. -- **No need** for in-depth knowledge on virtualization technologies like libvirt - or KubeVirt. + - Run **VMs** as easily as you run **containers**. + - Manage containers and VMs **together** using the **same** standard tooling. + +---

+--- + + + + + + +
+ +### Quick start + +Install crun-vm: + +```console +$ dnf install crun-vm +``` + +Launch a VM from a disk image packaged in a container: + +```console +$ podman run --runtime crun-vm -it \ + quay.io/containerdisks/fedora:40 +``` + +Launch a VM from a disk image under `my-image-dir/`: + +```console +$ podman run --runtime crun-vm -it \ + --rootfs my-image-dir/ +``` + +Launch a VM from a [bootable container]: + +```console +$ podman run --runtime crun-vm -it \ + quay.io/fedora/fedora-bootc:40 +``` + +Set the password for a VM's default user: + +```console +$ podman run --runtime crun-vm -it \ + quay.io/containerdisks/fedora:40 \ + --password pass # for user "fedora" +``` + +Exec (ssh) into a VM: + +```console +$ podman exec -it --latest -- --as fedora +``` + +

+
+ ### Major features - - Use it with **Podman**, **Docker**, or **Kubernetes**. - - Launch VMs from VM **image files** present on the host or packaged into - **container images**. - Control VM **CPU** and **memory** allocation. - - Provide **cloud-init** and **Ignition** configurations to VMs. - - **Mount directories** into VMs. + - Pass **cloud-init** or **Ignition** configs to VMs. + - Mount **directories** into VMs. - Pass **block devices** through to VMs. - - Expose **qcow2 files** and other **disk images** to VMs as block devices. + - Expose additional **disk images** to VMs. - **Forward ports** from the host to VMs. - - **`podman exec`**/**`docker exec`**/**`kubectl exec`** into VMs. + - **`podman|docker|kubectl exec`** into VMs. + +--- ### Documentation 1. [Installing crun-vm](docs/1-installing.md) - 2. [Using crun-vm as a Podman or Docker runtime](docs/2-podman-docker.md) - 3. [Using crun-vm as a Kubernetes runtime](docs/3-kubernetes.md) + 2. [Running VMs with **Podman** or **Docker**](docs/2-podman-docker.md) + 3. [Running VMs as **systemd** services](docs/3-systemd.md) + 4. [Running VMs in **Kubernetes**](docs/4-kubernetes.md) + 5. [**crun-vm(1)** man page](docs/5-crun-vm.1.ronn) -> [!TIP] -> See also how you can [combine **crun-vm** and **Podman Quadlet** to easily -> manage both containers and VMs through **systemd**](/examples/quadlet). +--- ### License This project is released under the GPL 2.0 (or later) license. See [LICENSE](LICENSE). +

+
+ +[bootable container]: https://containers.github.io/bootable [Docker]: https://www.docker.com/ [Kubernetes]: https://kubernetes.io/ -[Podman]: https://podman.io/ +[KubeVirt]: https://kubevirt.io/ [OCI Runtime]: https://github.com/opencontainers/runtime-spec/blob/v1.1.0/spec.md +[Podman]: https://podman.io/ +[systemd]: https://systemd.io/ diff --git a/docs/1-installing.md b/docs/1-installing.md index 44cb689..c607c9d 100644 --- a/docs/1-installing.md +++ b/docs/1-installing.md @@ -1,96 +1,156 @@ # 1. Installing crun-vm -## On Fedora +There are two steps to setting up crun-vm on a system: -Run: + - Installing the actual `crun-vm` binary; + - Configuring Podman, Docker, and/or Kubernetes (whichever you intend to use + crun-vm with) to recognize crun-vm as a runtime. + +These steps are detailed in the sections below. + +
+ Navigation + + 1. **Installing crun-vm** + - [**Installing the `crun-vm` binary**](#installing-the-crun-vm-binary) + - [On Fedora](#on-fedora) + - [From source](#from-source) + - [**Making crun-vm available as a runtime**](#making-crun-vm-available-as-a-runtime) + - [To Podman](#to-podman) + - [To Docker](#to-docker) + - [To Kubernetes](#to-kubernetes) + 2. [Running VMs with **Podman** or **Docker**](2-podman-docker.md) + 3. [Running VMs as **systemd** services](3-systemd.md) + 4. [Running VMs in **Kubernetes**](4-kubernetes.md) + 5. [**crun-vm(1)** man page](5-crun-vm.1.ronn) + +
+ +## Installing the `crun-vm` binary + +### On Fedora ```console $ dnf install crun-vm ``` -Podman will then be able to make use of the crun-vm runtime. - -To also set up crun-vm for use with Docker: +### From source + +1. Install crun-vm's build dependencies: + + - [cargo](https://doc.rust-lang.org/stable/cargo/getting-started/installation.html) + - [gzip](https://www.gzip.org/) + - [libselinux](https://github.com/SELinuxProject/selinux/tree/main/libselinux), + including development headers + - [ronn-ng](https://github.com/apjanke/ronn-ng) + +2. Install crun-vm's runtime dependencies: + + - bash + - [coreutils](https://www.gnu.org/software/coreutils/) + - [crun](https://github.com/containers/crun) + - [crun-krun](https://github.com/containers/crun/blob/main/krun.1.md) + - [genisoimage](https://github.com/Distrotech/cdrkit) + - grep + - [libselinux](https://github.com/SELinuxProject/selinux/tree/main/libselinux) + - [libvirtd](https://gitlab.com/libvirt/libvirt) or + [virtqemud](https://gitlab.com/libvirt/libvirt) + - [passt](https://passt.top/) + - [qemu-img](https://gitlab.com/qemu-project/qemu) + - qemu-system-x86_64-core, qemu-system-aarch64-core, and/or other [QEMU + system emulators](https://gitlab.com/qemu-project/qemu) for the VM + architectures you want to support + - ssh + - [util-linux](https://github.com/util-linux/util-linux) + - [virsh](https://gitlab.com/libvirt/libvirt) + - [virtiofsd](https://gitlab.com/virtio-fs/virtiofsd) + - [virtlogd](https://gitlab.com/libvirt/libvirt) + +3. Install crun-vm's binary and man page: - - Merge the following configuration into `/etc/docker/daemon.json`: + ```console + $ make install + ``` - ```json - { - "runtimes": { - "crun-vm": { - "path": "/usr/bin/crun-vm" - } - } - } - ``` +## Making crun-vm available as a runtime - - Reload the `docker` service for the new configuration to take effect: +### To Podman - ```console - $ service docker reload - ``` +Nothing to do here, since Podman automatically recognizes crun-vm as a runtime. +Commands like `podman create` and `podman run` can be made to use the crun-vm +runtime by passing them the `--runtime crun-vm` option. -## Build and install from source (on Fedora) + -1. Install crun-vm's runtime dependencies: +See [2. Using crun-vm and **Podman** or **Docker** to run a +VM](2-podman-docker.md) to get started. - ```console - $ dnf install bash coreutils crun crun-krun genisoimage grep libselinux-devel libvirt-client libvirt-daemon-driver-qemu libvirt-daemon-log openssh-clients qemu-img qemu-system-x86-core sed shadow-utils util-linux virtiofsd - ``` +### To Docker -2. Install Rust and Cargo if you do not already have Rust tooling available: +1. Merge the following configuration into `/etc/docker/daemon.json` (creating + that directory and file if necessary): - ```console - $ dnf install cargo + ```json + { + "runtimes": { + "crun-vm": { + "path": "/usr/bin/crun-vm" + } + } + } ``` -3. Build crun-vm: +2. Reload the `docker` service for the new configuration to take effect: ```console - $ cargo build + $ service docker reload ``` -4. Copy the `target/debug/crun-vm` binary to wherever you prefer: +Commands like `docker create` and `docker run` can then be made to use the +crun-vm runtime by passing them the `--runtime crun-vm` option. - ```console - $ cp target/debug/crun-vm /usr/local/bin/ - ``` +See [2. Using crun-vm and **Podman** or **Docker** to run a +VM](2-podman-docker.md) to get started. -5. If you're using Podman: +### To Kubernetes - - Merge the following configuration into - `/etc/containers/containers.conf`: +For crun-vm to be usable as a runtime in a Kubernetes cluster, the latter must +be use the [CRI-O] runtime. See the Kubernetes docs on [runtimes] for more +information. - > For rootless Podman, you can instead use - > `${XDG_CONFIG_PATH}/containers/containers.conf`, where - > `$XDG_CONFIG_PATH` defaults to `${HOME}/.config`. +1. Install crun-vm on all cluster nodes where pods may be scheduled, using any + of the methods [described above](#installing-the-crun-vm-binary). - ```toml - [engine.runtimes] - crun-vm = ["/usr/local/bin/crun-vm"] - ``` +2. Append the following to `/etc/crio/crio.conf`: - If you're using Docker: + ```toml + [crio.runtime.runtimes.crun-vm] + runtime_path = "/usr/bin/crun-vm" + ``` - - Merge the following configuration into `/etc/docker/daemon.json`: +3. Create a `RuntimeClass` object in the cluster that references crun-vm: - ```json - { - "runtimes": { - "crun-vm": { - "path": "/usr/local/bin/crun-vm" - } - } - } - ``` + ```yaml + apiVersion: node.k8s.io/v1 + kind: RuntimeClass + metadata: + name: crun-vm # a name of your choice + handler: crun-vm + ``` - - Reload the `docker` service for the new configuration to take effect: +Pods can then be configured to use this `RuntimeClass` by specifying its name +under `Pod.spec.runtimeClassName`. - ```console - $ service docker reload - ``` +See [4. Using crun-vm and **Pod YAML** to run a VM with **Podman**, **systemd**, +or **Kubernetes**](4-pod-yaml.md) to get started. -With Podman, it is possible to use crun-vm without installing it, *i.e.*, -performing only steps 1–3 above. In this case, instead of setting the runtime -with `--runtime crun-vm`, specify an absolute path to the runtime binary: -`--runtime "$PWD"/target/debug/crun-vm`. +[runtimes]: https://kubernetes.io/docs/setup/production-environment/container-runtimes/#cri-o +[CRI-O]: https://cri-o.io/ diff --git a/docs/2-podman-docker.md b/docs/2-podman-docker.md index afb8e59..a7a70eb 100644 --- a/docs/2-podman-docker.md +++ b/docs/2-podman-docker.md @@ -1,39 +1,66 @@ -# 2. Using crun-vm as a Podman or Docker runtime - -Here we overview some of the major features provided by crun-vm. The commands -below use `podman`, but unless otherwise stated you can simply replace it with -`docker`. +# 2. Running VMs with **Podman** or **Docker** + +Here, we outline how to use crun-vm to run VMs using the Podman or Docker +container engines. See [crun-vm(1)] for a full reference and additional details +on crun-vm specific options. + +We use `podman` in the example commands below. Unless otherwise noted, the same +commands also with `docker`. + +
+ Navigation + + 1. [Installing crun-vm](1-installing.md) + 2. **Running VMs with **Podman** or **Docker**** + - [**Booting VMs**](#booting-vms) + - [From containerdisks](#from-containerdisks) + - [From VM image files](#from-vm-image-files) + - [From bootable containers](#from-bootable-containers) + - [**Configuring VMs on first boot**](#configuring-vms-on-first-boot) + - [Default user password](#default-user-password) + - [cloud-init](#cloud-init) + - [Ignition](#ignition) + - [**Interacting with VMs**](#interacting-with-vms) + - [Exec'ing into VMs](#execing-into-vms) + - [Port forwarding](#port-forwarding) + - [**Sharing resources with VMs**](#sharing-resources-with-vms) + - [Files](#files) + - [Directories](#directories) + - [Block devices](#block-devices) + 3. [Running VMs as **systemd** services](3-systemd.md) + 4. [Running VMs in **Kubernetes**](4-kubernetes.md) + 5. [**crun-vm(1)** man page](5-crun-vm.1.ronn) + +
## Booting VMs -### From regular VM image files +### From containerdisks -First, obtain a QEMU-compatible VM image and place it in a directory by itself: +A "containerdisk" is a container image that packages a sole VM image file under +`/` or `/disk/`. This is how you would boot a VM from the +quay.io/containerdisks/fedora:40 containerdisk using crun-vm: ```console -$ mkdir my-vm-image -$ curl -LO --output-dir my-vm-image https://download.fedoraproject.org/pub/fedora/linux/releases/40/Cloud/x86_64/images/Fedora-Cloud-Base-Generic.x86_64-40-1.14.qcow2 +$ podman run --runtime crun-vm -it quay.io/containerdisks/fedora:40 +Booting `Fedora Linux (6.8.5-301.fc40.x86_64) 40 (Cloud Edition)' +[...] ``` -Then run: - -> This example does not work with Docker, as docker-run does not support the -> `--rootfs` flag; see the next section for a Docker-compatible way of running -> VM images. - -```console -$ podman run \ - --runtime crun-vm \ - -it --rm \ - --rootfs my-vm-image \ - "" # unused, but must specify command -``` +> Several regularly-updated containerdisks may be found at +> https://quay.io/organization/containerdisks. You can also easily build your +> own: +> +> ```dockerfile +> FROM scratch +> COPY my-vm-image.qcow2 / +> ENTRYPOINT ["no-entrypoint"] +> ``` -The VM console should take over your terminal. At this point, the -qcow2 image does not have any ssh keys, root password, or alternative -users installed, so although you can interact with the VM's login -screen, you will be unable to access a command prompt until more -options are used in later sections. To abort the VM, press `ctrl-]`. +The VM console should take over your terminal. This VM image has no users that +you may log in as using a password, so although you can interact with the VM's +login screen, you will be unable to access a command prompt for now. To abort +the VM, press `ctrl-]`. You can also detach from the VM without terminating it by pressing `ctrl-p, ctrl-q`. Afterwards, reattach by running: @@ -50,137 +77,131 @@ podman-run, in which case you won't be able to interact with the VM but can still observe its console. Note that pressing `ctrl-]` will have no effect, but you can always use the following command to terminate the VM: -> For this command to work with Docker, you must replace the `--latest` flag -> with the container's name or ID. - ```container $ podman stop --latest ``` -Changes made by the VM to its image are by default not persisted in the original -image file. This can be changed by passing in the non-standard option -`--persistent` *after* the `--rootfs` option: +### From VM image files + +> This feature is only supported with Podman. + +It is also possible to boot VMs directly from disk image files by using Podman's +`--rootfs` option to point at a directory containing a sole image file. For +instance, these commands download and boot a Fedora 40 VM: ```console -$ podman run \ - --runtime crun-vm \ - -it --rm \ - --rootfs my-vm-image \ - --persistent -``` +$ mkdir my-vm-image/ && curl -LO --output-dir my-vm-image/ https://download.fedoraproject.org/pub/fedora/linux/releases/40/Cloud/x86_64/images/Fedora-Cloud-Base-Generic.x86_64-40-1.14.qcow2 -> [!WARNING] -> -> When using `--persistent`, make sure that the image file is never -> simultaneously used by another process or VM, otherwise **data corruption may -> occur**. +$ podman run --runtime crun-vm -it --rootfs my-vm-image/ +Booting `Fedora Linux (6.8.5-301.fc40.x86_64) 40 (Cloud Edition)' +[...] +``` -### From VM image files packaged into container images +### From bootable containers -crun-vm also works with container images that contain a VM image file with -any name under `/` or under `/disk/`. No other files may exist in those -directories. Containers built for use as [KubeVirt `containerDisk`s] follow this -convention, so you can use those here: +crun-vm can also launch VMs from [bootc bootable container images], which are +containers that package a full operating system: ```console -$ podman run \ - --runtime crun-vm \ - -it --rm \ - quay.io/containerdisks/fedora:40 +$ podman run --runtime crun-vm -it quay.io/fedora/fedora-bootc:40 +Converting quay.io/fedora/fedora-bootc:40 into a VM image... +[...] +Caching VM image as a containerdisk... +[...] +Booting VM... +[...] ``` -You can also use `util/package-vm-image.sh` to easily package a VM image into a -container image, and `util/extract-vm-image.sh` to extract a VM image contained -in a container image. +crun-vm generates a VM image from the bootable container and then boots it. The +generated VM image is packaged as a containerdisk and cached in the host's +container storage, so that subsequent runs will boot faster: -Note that flag `--persistent` has no effect when running VMs from container -images. +```console +$ podman run --runtime crun-vm -it quay.io/crun-vm/example-fedora-bootc:40 +Retrieving cached VM image... +[...] +Booting VM... +[...] +``` + +## Configuring VMs on first boot -### From bootable container images +### Default user password -crun-vm can also work with [bootable container images], which are containers -that package a full operating system: +In the examples above, you were able to boot a VM but not to log in. An easy way +to fix this when a VM has [cloud-init] installed is to use the [`--password`] +option, which sets the password for the VM's "default" user (as determined in +the image's cloud-init configuration). For quay.io/containerdisks/fedora:40, +that is the `fedora` user: ```console -$ podman run \ - --runtime crun-vm \ - -it --rm \ - quay.io/crun-vm/example-fedora-bootc:40 +$ podman run --runtime crun-vm -it quay.io/containerdisks/fedora:40 --password pass +Booting `Fedora Linux (6.8.5-301.fc40.x86_64) 40 (Cloud Edition)' +[...] +3b0232a04046 login: fedora +Password: pass +[fedora@3b0232a04046 ~]$ ``` -Internally, crun-vm generates a VM image from the bootable container and then -boots it. - -By default, the VM image is given a disk size roughly double the size of the -bootc container image. To change this, use the `--bootc-disk-size [KMGT]` -option. - -## First-boot customization +Like all crun-vm specific options, [`--password`] must be passed in *after* the +image specification. ### cloud-init -In the examples above, you were able to boot the VM but not to log in. To fix -this and do other first-boot customization, you can provide a [cloud-init] -NoCloud configuration to the VM by passing in the non-standard option -`--cloud-init` *after* the image specification: +You can provide a full [cloud-init] NoCloud configuration to a VM by passing in +the crun-vm specific option [`--cloud-init`] *after* the image specification: ```console -$ ls examples/cloud-init/config/ -meta-data user-data vendor-data +$ ls my-cloud-init-config/ +meta-data user-data -$ podman run \ - --runtime crun-vm \ - -it --rm \ - quay.io/containerdisks/fedora:40 \ - --cloud-init ~/examples/cloud-init/config # path must be absolute -``` +$ cat my-cloud-init-config/meta-data # empty -You should now be able to log in with the default `fedora` username and password -`pass`. +$ cat my-cloud-init-config/user-data +#cloud-config +write_files: + - path: $home/file + content: | + hello -Alternatively, you can set the default user's password with the `--password` -option: - -```console -$ podman run \ - --runtime crun-vm \ - -it --rm \ - quay.io/containerdisks/fedora:40 \ - --password pass +$ podman run --runtime crun-vm -it quay.io/containerdisks/fedora:40 \ + --cloud-init $PWD/my-cloud-init-config/ # path must be absolute ``` ### Ignition -Similarly, you can provide an [Ignition] configuration to the VM by passing in -the `--ignition` option: +You can also provide an [Ignition] configuration to a VM using the crun-vm +specific [`--ignition`] option: ```console -$ podman run \ - --runtime crun-vm \ - -it --rm \ - quay.io/crun-vm/example-fedora-coreos:40 \ - --ignition ~/examples/ignition/config.ign # path must be absolute +$ cat my-ignition-config.ign +{ + "ignition": { + "version": "3.0.0" + }, + "passwd": { + "users": [ + { + "name": "core", + "passwordHash": "$y$j9T$USdd8CBvFNVU1xKwQUnsU/$aE.3arHcRxD0ZT3vkvsSpEsteUj6vC4ZdRHY8eOj1f4" + } + ] + } +} + +$ podman run --runtime crun-vm -it quay.io/crun-vm/example-fedora-coreos:40 \ + --ignition $PWD/my-ignition-config.ign # path must be absolute ``` -You should now be able to log in with the default `core` username and password -`pass`. - -Note that the `--password` option requires cloud-init support and doesn't work -if the VM uses Ignition. - -## SSH'ing into the VM +## Interacting with VMs -Assuming the VM supports cloud-init or Ignition and exposes an SSH server on -port 22, you can `ssh` into it as root using podman-exec: +### Exec'ing into VMs -> For this command to work with Docker, you must replace the `--latest` flag -> with the container's name or ID. +Assuming a VM supports cloud-init or Ignition and exposes an SSH server on port +22, you can `ssh` into it as root using podman-exec: ```console -$ podman run \ - --runtime crun-vm \ - --detach --rm \ - quay.io/containerdisks/fedora:40 +$ podman run --runtime crun-vm --detach quay.io/containerdisks/fedora:40 8068a2c180e0f4bf494f5e0baa37d9f13a9810f76b361c0771b73666e47ec383 $ podman exec --latest whoami @@ -188,7 +209,7 @@ Please login as the user "fedora" rather than the user "root". ``` This particular VM image does not allow logging in as root. To `ssh` into the VM -as a different user, specify its username using the `--as` option immediately +as a different user, specify its username using the [`--as`] option immediately before the command (if any). You may need to pass in `--` before this option to prevent podman-exec from trying to interpret it: @@ -200,38 +221,30 @@ fedora If you just want a login shell, pass in an empty string as the command. The following would be the output if this VM image allowed logging in as root: -``` +```console $ podman exec -it --latest "" [root@8068a2c180e0 ~]$ ``` -You can also log in as a specific user: +You may also log in as a specific user: -``` +```console $ podman exec -it --latest -- --as fedora [fedora@8068a2c180e0 ~]$ ``` -When the VM supports cloud-init, `authorized_keys` is automatically set up to +When a VM supports cloud-init, `authorized_keys` is automatically set up to allow SSH access by podman-exec for users `root` and the default user as set in the image's cloud-init configuration. With Ignition, this is set up for users `root` and `core`. -> If you want to exec into the container in which the VM is running (probably to -> debug some problem with crun-vm itself), pass in the `--container` flag -> immediately before the command (if any). - -## Port forwarding +### Port forwarding -You can use podman-run's standard `-p`/`--publish` option to set up TCP and/or +You can use podman-run's standard `-p`/`--publish` option to enable TCP and/or UDP port forwarding: ```console -$ podman run \ - --runtime crun-vm \ - --detach --rm \ - -p 8000:80 \ - quay.io/crun-vm/example-http-server:latest +$ podman run --runtime crun-vm --detach -p 8000:80 quay.io/crun-vm/example-http-server:latest 36c8705482589cfc4336a03d3802e7699f5fb228123d18e693488ac7b80116d1 $ curl localhost:8000 @@ -245,125 +258,73 @@ $ curl localhost:8000 [...] ``` -## Passing things through to the VM +## Sharing resources with VMs -### Directories +### Files -Bind mounting directories into the VM is supported: +You can bind mount regular files into a VM: -> [!WARNING] -> -> This example recursively modifies the SELinux context of all files under the -> path being mounted, in this case `./util`, which in the worst case **may cause -> you to lose access to your files**. This is due to the `:z` volume mount -> modifier, which instructs Podman to relabel the volume so that the VM can -> access it. -> -> Alternatively, you may remove this modifier from the command below and add -> `--security-opt label=disable` instead to disable SELinux enforcement. +```console +$ podman run --runtime crun-vm -it \ + -v ./README.md:/home/fedora/README.md:z \ + quay.io/containerdisks/fedora:40 +``` + +Regular files currently appear as block devices in the VM, but this is subject +to change. + +### Directories + +It is also possible to bind mount directories into a VM: ```console -$ podman run \ - --runtime crun-vm \ - -it --rm \ +$ podman run --runtime crun-vm -it \ -v ./util:/home/fedora/util:z \ - quay.io/containerdisks/fedora:40 \ - --password pass + quay.io/containerdisks/fedora:40 ``` If the VM supports cloud-init or Ignition, the volume will automatically be mounted at the given destination path. Otherwise, you can mount it manually with -the following command, where `` must be the 0-based index of the volume +the following command, where `` is the 0-based index of the volume according to the order the `-v`/`--volume` or `--mount` flags where given in: ```console $ mount -t virtiofs virtiofs- /home/fedora/util ``` -### Regular files - -Similarly to directories, you can bind mount regular files into the VM: - -> [!WARNING] -> -> The warning about SELinux relabeling on the command above also applies here. - -```console -$ podman run \ - --runtime crun-vm \ - -it --rm \ - -v ./README.md:/home/fedora/README.md:z \ - quay.io/containerdisks/fedora:40 \ - --password pass -``` - -Regular files currently appear as block devices in the VM, but this is subject -to change. - ### Block devices -If cloud-init or Ignition are supported by the VM, it is possible to pass block -devices through to it at a specific path using podman-run's `--device` flag -(this example assumes `/dev/ram0` to exist and to be accessible by the current -user): +If cloud-init or Ignition are supported by a VM, it is possible to pass block +devices through to it and make them appear at a specific path using podman-run's +`--device` flag. For instance, assuming `/dev/ram0` exists on the host and is +accessible by the current user: ```console -$ podman run \ - --runtime crun-vm \ - -it --rm \ +$ podman run --runtime crun-vm -it \ --device /dev/ram0:/home/fedora/my-disk \ - quay.io/containerdisks/fedora:40 \ - --password pass + quay.io/containerdisks/fedora:40 ``` -You can also use the more powerful `--blockdev -source=,target=,format=` custom option to this effect. This -option also allows you specify a regular file as the source, and the source may -be in any disk format known to QEMU (*e.g.*, raw, qcow2; when using `--device`, -raw format is assumed): +You can also use the more powerful, crun-vm specific [`--blockdev`] +`source=,target=,format=` option to this effect. This option +also allows you to specify a regular file as the source, and the source may be +in any disk format known to QEMU (*e.g.*, raw, qcow2; when using `--device`, raw +format is assumed): ```console -$ podman run \ - --runtime crun-vm \ - -it --rm \ +$ podman run --runtime crun-vm -it \ quay.io/containerdisks/fedora:40 \ - --password pass \ - --blockdev source=~/my-disk.qcow2,target=/home/fedora/my-disk,format=qcow2 # paths must be absolute + --blockdev source=$PWD/my-disk.qcow2,target=/home/fedora/my-disk,format=qcow2 # paths must be absolute ``` -## Advanced options - -### System emulation - -To use system emulation instead of hardware-assisted virtualization, specify the -`--emulated` flag. Without this flag, attempting to create a VM on a host tbat -doesn't support KVM will fail. - -It's not currently possible to use this flag when the container image is a bootc -bootable container. - -### Inspecting and customizing the libvirt domain XML - -crun-vm internally uses [libvirt] to launch a VM, generating a [domain XML -definition] from the options provided to podman-run. This XML definition can be -printed by adding the non-standard `--print-libvirt-xml` flag to your podman-run -invocation. - -The generated XML definition can also be customized by specifying an XML file to -be merged with it using the non-standard option `--merge-libvirt-xml `. - -> [!NOTE] -> -> While `--merge-libvirt-xml` gives you maximum flexibility, it thwarts -> crun-vm's premise of isolating the user from such details as libvirt domain -> definitions, and you have instead to take care that your XML is valid *and* -> that the customized definition is compatible with what crun-vm expects. -> -> Before using this flag, consider if you would be better served using libvirt -> directly to manage your VM. - -[bootable container images]: https://containers.github.io/bootable/ +[`--as`]: 5-crun-vm.1.ronn#exec-options +[`--blockdev`]: 5-crun-vm.1.ronn#createrun-options +[`--cloud-init`]: 5-crun-vm.1.ronn#createrun-options +[`--ignition`]: 5-crun-vm.1.ronn#createrun-options +[`--password`]: 5-crun-vm.1.ronn#createrun-options +[bootc bootable container images]: https://containers.github.io/bootable/ [cloud-init]: https://cloud-init.io/ +[crun-vm(1)]: 5-crun-vm.1.ronn [domain XML definition]: https://libvirt.org/formatdomain.html [Ignition]: https://coreos.github.io/ignition/ [KubeVirt `containerDisk`s]: https://kubevirt.io/user-guide/virtual_machines/disks_and_volumes/#containerdisk diff --git a/docs/3-kubernetes.md b/docs/3-kubernetes.md deleted file mode 100644 index 7c17b57..0000000 --- a/docs/3-kubernetes.md +++ /dev/null @@ -1,153 +0,0 @@ -# 3. Using crun-vm as a Kubernetes runtime - -It is possible to use crun-vm as a [Kubernetes] runtime, allowing you to run -VMs as regular pods. - -## Preparation - -To enable crun-vm on a Kubernetes cluster, follow these steps: - -1. Ensure that the cluster is using the [CRI-O] container runtime. Refer to the - Kubernetes docs on [container runtimes]. - -2. Install crun-vm on all cluster nodes where pods may be scheduled. Refer to - the [installation instructions]. - -3. Append the following to `/etc/crio/crio.conf` (adjust the `runtime_path` if - necessary): - - ```toml - [crio.runtime.runtimes.crun-vm] - runtime_path = "/usr/local/bin/crun-vm" - ``` - -4. Create a `RuntimeClass` that references crun-vm: - - ```yaml - apiVersion: node.k8s.io/v1 - kind: RuntimeClass - metadata: - name: crun-vm - handler: crun-vm - ``` - -## Using the runtime - -> Under [examples/minikube] you can find a script that sets up a local minikube -> Kubernetes cluster with crun-vm available as a runtime. You can use it to -> easily try out the examples below. - -From then on, you can run VM images packaged in container images by creating -pods that use this `RuntimeClass`: - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: my-vm -spec: - containers: - - name: my-vm - image: quay.io/crun-vm/example-http-server:latest - ports: - - containerPort: 80 - runtimeClassName: crun-vm -``` - -### Logging - -The VM's console output is logged: - -```console -$ kubectl logs my-vm -``` - -### SSH'ing into the pod/VM - -Assuming the VM supports cloud-init or Ignition, you can also SSH into it using -`kubectl exec`: - -```console -$ kubectl exec my-vm -- --as fedora whoami -fedora - -$ kubectl exec -it my-vm -- --as fedora bash -[fedora@my-vm ~]$ -``` - -### Port forwarding - -The pod/VM defined above actually exposes an HTTP server on port 80. To talk to -it, we must first forward a local port to the pod/VM: - -```console -$ kubectl port-forward my-vm 8000:80 -Forwarding from 127.0.0.1:8000 -> 80 -Forwarding from [::1]:8000 -> 80 -``` - -With this command running, navigate to [`localhost:8000`] on your browser, or -run the following on a second terminal: - -```console -$ curl localhost:8000 - - - - -Directory listing for / - - -[...] -``` - -### cloud-init and Ignition - -When using crun-vm as a Kubernetes runtime, paths given to `--cloud-init` and -`--ignition` are interpreted in the context of the container/VM, instead of the -host. This means that config files can be retrieved from mounted volumes. For -instance, you could store your cloud-init config in a `ConfigMap`: - -```yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: my-cloud-init-config -data: - meta-data: "" - user-data: | - #cloud-config - runcmd: - - echo 'Hello, world!' > /home/fedora/hello-world -``` - -And pass it to your VMs like so: - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: my-other-vm -spec: - containers: - - name: my-other-vm - image: quay.io/containerdisks/fedora:40 - args: - - --cloud-init=/etc/cloud-init - volumeMounts: - - name: cloud-init-vol - mountPath: /etc/cloud-init - volumes: - - name: cloud-init-vol - configMap: - name: my-cloud-init-config - runtimeClassName: crun-vm -``` - -[container runtimes]: https://kubernetes.io/docs/setup/production-environment/container-runtimes/#cri-o -[CRI-O]: https://cri-o.io/ -[examples/minikube]: /examples/minikube -[installation instructions]: 1-installing.md -[Kubernetes]: https://kubernetes.io/ -[`localhost:8000`]: http://localhost:8000/ -[SSH'ing into the VM]: 2-podman-docker.md#sshing-into-the-vm diff --git a/docs/3-systemd.md b/docs/3-systemd.md new file mode 100644 index 0000000..8452c1f --- /dev/null +++ b/docs/3-systemd.md @@ -0,0 +1,130 @@ +# 3. Running VMs as **systemd** services + +crun-vm also enables you to define a [systemd] service corresponding to a VM, +and thus manage it through systemd. This relies on Podman's [Quadlet] feature, +through which you can define systemd unit files for containers. + +> [!TIP] +> +> This means that system **containers** and **VMs** can both be deployed and +> managed **using the same tooling**, *i.e.*, systemd! + +Here, we overview how you can create Quadlet-powered systemd services to manage +VMs. Make sure you have installed both crun-vm and Podman (see [1. Installing +crun-vm]). + +
+ Navigation + + 1. [Installing crun-vm](1-installing.md) + 2. [Running VMs with **Podman** or **Docker**](2-podman-docker.md) + 3. **Running VMs as **systemd** services** + - [**Creating a systemd service for a VM**](#creating-a-systemd-service-for-a-vm) + - [**Further information**](#further-information) + 4. [Running VMs in **Kubernetes**](4-kubernetes.md) + 5. [**crun-vm(1)** man page](5-crun-vm.1.ronn) + +
+ +## Creating a systemd service for a VM + +The easiest way to do this is using [Podlet], a tool that can generate a systemd +unit file corresponding to a given podman-run command. (Follow the instructions +at https://github.com/containers/podlet to install Podlet.) This means we can +apply it to the podman-run commands we use to launch VMs. + +For instance, say you're using this command to launch a VM that runs a web +service (see [2. Running VMs with **Podman** or **Docker**] to learn how crun-vm +can be used with Podman): + +```console +$ podman run --runtime crun-vm --detach -p 8000:80 quay.io/crun-vm/example-http-server:latest +``` + +To convert this invocation into an equivalent systemd container unit definition, +you would run: + +```console +$ podlet \ + --install \ + --wanted-by default.target \ + podman run --runtime crun-vm --detach -p 8000:80 quay.io/crun-vm/example-http-server:latest +#example-http-server.container +[Container] +Image=quay.io/crun-vm/example-http-server:latest +PublishPort=8000:80 +GlobalArgs=--runtime crun-vm + +[Install] +WantedBy=default.target +``` + +The `--install`, `--wanted-by default.target` options configure the service to +run automatically on boot. + +Finally, to actually install this unit definition, you would instead run (using +`sudo` to become root): + +```console +$ sudo podlet \ + --name my-web-service \ + --unit-directory \ + --install \ + --wanted-by default.target \ + podman run --runtime crun-vm --detach -p 8000:80 quay.io/crun-vm/example-http-server:latest +Wrote to file: /etc/containers/systemd/my-web-service.container + +$ systemctl daemon-reload # load the new service +``` + +With this, your web server VM becomes a systemd service: + +```console +$ sudo systemctl status my-web-service +○ my-web-service.service + Loaded: loaded (/etc/containers/systemd/my-web-service.container; generated) + Drop-In: /usr/lib/systemd/system/service.d + └─10-timeout-abort.conf + Active: inactive (dead) + +$ sudo systemctl start my-web-service # start the service without having to reboot + +$ sudo systemctl status my-web-service +● my-web-service.service + Loaded: loaded (/etc/containers/systemd/my-web-service.container; generated) + Drop-In: /usr/lib/systemd/system/service.d + └─10-timeout-abort.conf + Active: active (running) since Tue 2024-04-30 21:14:36 WEST; 4s ago + Main PID: 1531707 (conmon) + Tasks: 48 (limit: 76805) + Memory: 1.1G (peak: 1.1G) + CPU: 11.768s +[...] + +$ curl localhost:8000 + + + + +Directory listing for / + + +[...] +``` + +## Further information + +See [this article] for additional information on Podman Quadlet, and the +[podman-systemd.unit(5)] man page for the reference format of container unit +files. + +The `podlet` commands provides several options to further customize the +generated container unit file. Run `podlet -h` to know more. + +[1. Installing crun-vm]: 1-installing.md +[2. Running VMs with **Podman** or **Docker**]: 2-podman-docker.md +[Podlet]: https://github.com/containers/podlet +[podman-systemd.unit(5)]: https://docs.podman.io/en/stable/markdown/podman-systemd.unit.5.html +[Quadlet]: https://docs.podman.io/en/stable/markdown/podman-systemd.unit.5.html +[systemd]: https://systemd.io/ +[this article]: https://www.redhat.com/sysadmin/quadlet-podman diff --git a/docs/4-kubernetes.md b/docs/4-kubernetes.md new file mode 100644 index 0000000..e62a981 --- /dev/null +++ b/docs/4-kubernetes.md @@ -0,0 +1,182 @@ +# 4. Running VMs in **Kubernetes** + +crun-vm can also be used as a [Kubernetes] runtime, allowing you to run VMs as +regular pods. + +Note that there is already a very featureful project, [KubeVirt], that enables +using Kubernetes to run VMs with great configurability. However, for simple use +cases, crun-vm may be a good fit. + +
+ Navigation + + 1. [Installing crun-vm](1-installing.md) + 2. [Running VMs with **Podman** or **Docker**](2-podman-docker.md) + 3. [Running VMs as **systemd** services](3-systemd.md) + 4. **Running VMs in **Kubernetes**** + - [**Setting up**](#setting-up) + - [**Creating VMs**](#creating-vms) + - [**Interacting with VMs**](#interacting-with-vms) + - [Exec'ing into VMs](#execing-into-vms) + - [Port forwarding](#port-forwarding) + - [**First-boot configuration**](#first-boot-configuration) + 5. [**crun-vm(1)** man page](5-crun-vm.1.ronn) + +
+ +## Setting up + +You can use the [util/minikube-start.sh] script to set up a local [minikube] +Kubernetes cluster with crun-vm available as a runtime, and use it to easily try +out the examples below (note that this also points `kubectl` at the minikube +cluster): + +```console +$ ./minikube-start.sh + Compiling crun-vm v0.2.0 (/home/afaria/crun-vm) + Finished dev [unoptimized + debuginfo] target(s) in 1.70s +😄 [crun-vm-example] minikube v1.32.0 on Fedora 40 +[...] +🏄 Done! kubectl is now configured to use "crun-vm-example" cluster and "default" namespace by default +runtimeclass.node.k8s.io/crun-vm created +``` + +Once you're done, you can delete the cluster with: + +```console +$ minikube -p crun-vm-example delete +``` + +To enable crun-vm on a real Kubernetes cluster, follow the instructions in [1. +Installing crun-vm]. + +## Creating VMs + +To run a VM in your cluster, simply create a pod that references the +`RuntimeClass` corresponding to crun-vm (here we assume it is named `crun-vm`): + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: my-vm +spec: + containers: + - name: my-vm + image: quay.io/crun-vm/example-http-server:latest + ports: + - containerPort: 80 + runtimeClassName: crun-vm +``` + +All the image formats supported by crun-vm when using Podman or Docker are also +supported here. See [2. Running VMs with **Podman** or +**Docker**](2-podman-docker.md#booting-vms) to know more. + +You can inspect the VM's console output with the standard [`kubectl logs`] +command: + +```console +$ kubectl logs my-vm +``` + +## Interacting with VMs + +### Exec'ing into VMs + +Assuming a VM supports cloud-init or Ignition, you can `ssh` into it using +`kubectl exec`: + +```console +$ kubectl exec my-vm -- --as fedora whoami +fedora + +$ kubectl exec -it my-vm -- --as fedora bash +[fedora@my-vm ~]$ +``` + +The supported crun-vm specific options like `--as fedora` are the same as when +using crun-vm with Podman or Docker. See [2. Running VMs with **Podman** or +**Docker**](2-podman-docker.md#execing-into-vms) to know more. + +### Port forwarding + +The VM pod defined above actually exposes an HTTP server on port 80. To talk to +it, we must first forward a local port to the VM: + +```console +$ kubectl port-forward my-vm 8000:80 +Forwarding from 127.0.0.1:8000 -> 80 +Forwarding from [::1]:8000 -> 80 +``` + +With this command running, navigate to [`localhost:8000`] on your browser, or +run the following on a second terminal: + +```console +$ curl localhost:8000 + + + + +Directory listing for / + + +[...] +``` + +## First-boot configuration + +Options supported when using crun-vm with Podman or Docker, like `--password`, +`--cloud-init`, and `--ignition`, are also supported here (see [2. Running VMs +with **Podman** or **Docker**](2-podman-docker.md#execing-into-vms) for more +information). + +However, paths given to `--cloud-init` and `--ignition` are interpreted in the +context of the VM, instead of the host. This means that first-boot configuration +files can be retrieved from mounted volumes. For instance, you could store your +cloud-init configuration in a `ConfigMap`: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: my-cloud-init-config +data: + meta-data: "" + user-data: | + #cloud-config + runcmd: + - echo 'Hello, world!' > /home/fedora/hello-world +``` + +And apply it to your VMs like so: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: my-other-vm +spec: + containers: + - name: my-other-vm + image: quay.io/containerdisks/fedora:40 + args: + - --cloud-init=/etc/cloud-init + volumeMounts: + - name: cloud-init-vol + mountPath: /etc/cloud-init + volumes: + - name: cloud-init-vol + configMap: + name: my-cloud-init-config + runtimeClassName: crun-vm +``` + +[`kubectl logs`]: https://kubernetes.io/docs/reference/kubectl/ +[`localhost:8000`]: http://localhost:8000/ +[1. Installing crun-vm]: 1-installing.md +[Kubernetes]: https://kubernetes.io/ +[KubeVirt]: https://kubevirt.io/ +[minikube]: https://minikube.sigs.k8s.io/ +[util/minikube-start.sh]: ../util/minikube-start.sh diff --git a/docs/5-crun-vm.1.ronn b/docs/5-crun-vm.1.ronn new file mode 100644 index 0000000..cffa85d --- /dev/null +++ b/docs/5-crun-vm.1.ronn @@ -0,0 +1,186 @@ + + +# 5. crun-vm(1) -- an OCI Runtime that runs VM images + +
+ Navigation + + 1. [Installing crun-vm](1-installing.md) + 2. [Running VMs with **Podman** or **Docker**](2-podman-docker.md) + 3. [Running VMs as **systemd** services](3-systemd.md) + 4. [Running VMs in **Kubernetes**](4-kubernetes.md) + 5. ****crun-vm(1)** man page** + - [**SYNOPSIS**](#synopsis) + - [**DESCRIPTION**](#description) + - [**QUICK START**](#quick-start) + - [**CREATE/RUN USAGE**](#createrun-usage) + - [**CREATE/RUN OPTIONS**](#createrun-options) + - [**EXEC USAGE**](#exec-usage) + - [**EXEC OPTIONS**](#exec-options) + - [**ENVIRONMENT**](#environment) + +
+ +## SYNOPSIS + +`podman|docker` `create|run` --runtime crun-vm [...] [""] [...]
+`podman|docker` `exec` [...] [...] ...`|`"" + +## DESCRIPTION + +**crun-vm** is an OCI Runtime that enables Podman, Docker, and Kubernetes to run +QEMU-compatible Virtual Machine (VM) images. + +This man page enumerates the crun-vm specific options that may be used with +Podman/Docker engine commands like `podman create` and `docker run`, and how +they can be specified alongside standard engine options. Visit + for additional guides. + +## QUICK START + +Launch a VM from a "containerdisk" (a disk image packaged in a container): + + $ podman run --runtime crun-vm -it quay.io/containerdisks/fedora:40 + +Launch a VM from a disk image under *my-image-dir/*: + + $ podman run --runtime crun-vm -it --rootfs my-image-dir/ + +Launch a VM from a bootable container (): + + $ podman run --runtime crun-vm -it quay.io/fedora/fedora-bootc:40 + +Set the password for a VM's default user: + + $ podman run --runtime crun-vm -it quay.io/containerdisks/fedora:40 \ + --password pass # for user "fedora" + +Exec (ssh) into a VM: + + $ podman exec -it --latest -- --as fedora + +## CREATE/RUN USAGE + +`podman|docker` `create|run` --runtime crun-vm [...] [""] [...] + +Standard engine options are specified in . + + identifies a container image of one the following kinds: + + 1. A "containerdisk", i.e., a container image with a sole VM image file + residing under `/` or `/disk/`, such as *quay.io/containerdisks/fedora:40*; + + 2. The Podman-specific `--rootfs` option pointing at a directory containing a + sole VM image file; + + 3. A bootc bootable container, such as *quay.io/fedora/fedora-bootc:40* + (see for more information). + +crun-vm specific options are specified in , i.e., where the +command to execute in the container would usually by specified. Since this +notion does not apply to VMs as it does to regular containers, no command should +be specified here. However, if you're using Docker and the container you +specified defines no default entrypoint, you have to also pass in an empty `""` +argument to satisfy Docker's syntax. + +## CREATE/RUN OPTIONS + +All crun-vm specific options that may be passed to `podman|docker` `create|run` +commands are listed here. + +These options configure the VM's environment: + + * `--blockdev` source=,target=,format=: + Expose the file or block device at path in the VM. + and must be absolute paths. specifies the + QEMU-compatible image format of , such as *raw* or *qcow2*. When + *format=raw*, the same effect can be achieved with the standard + `-m`/`--mount`/`-v`/`--volume` Podman/Docker options. + + * `--persistent`: + When using `podman|docker` `create|run` with the standard `--rootfs` option, + this flag causes writes made by the VM to its disk to be persisted in the + user's image file. Make sure that the image is never simultaneously used by + another process or VM, otherwise **data corruption may occur**. + + * `--bootc-disk-size` [KMGT]: + Set the disk size of the VM image generated from a bootc bootable container. + The default is twice the size of the container image. + + * `--emulated`: + Emulate the VM in software rather than using KVM for hardware-assisted + virtualization. It's not currently possible to use this flag when the + container image is a bootc bootable container. + +These options control the VM's first-boot customization: + + * `--password` : + Set the password of the VM image's default user. Only works when the VM + supports cloud-init. + + * `--cloud-init` <config_dir>: + Expose the given cloud-init configuration to the VM. <config_dir> must be an + absolute path. + + * `--ignition` <config_file>: + Expose the given Ignition configuration to the VM. <config_dir> must be an + absolute path. + + * `--random-ssh-key-pair`: + By default, when using podman-exec, the host user's ssh key pair (if any) is + used to ssh into the VM. This is useful when the VM isn't easily + customizable at first boot but already authorizes the user's public key. + Otherwise, or if this flag is specified, a new random key pair is always + used. + +These options are mostly helpful when debugging crun-vm itself: + + * `--merge-libvirt-xml` <xml_path>: + Merge the given XML file into the libvirt domain XML generated by crun-vm, + prior to using it to launch the VM. <xml_path> must be an absolute path. + + * `--print-libvirt-xml`: + Print the libvirt domain XML that would be used to launch the VM, and exit + without launching the VM. + + * `--print-config-json`: + Print the OCI Runtime config.json file with crun-vm's modifications that was + passed to *crun(1)*, and exit without launching the VM. + +## EXEC USAGE + +`podman|docker` `exec` [<engine_opts>...] [--] [<crun_vm_opts>...] <cmd_and_args>...`|`"" + +Standard engine arguments and options are specified in <engine_opts>. + +crun-vm specific options are specified in <crun_vm_opts>, i.e., as a prefix to +the command to be executed. To launch a login shell, pass `""` as the command. + +When using Podman's `--latest` flag instead of providing a container name or ID, +you may need pass in `--` to delimit standard options from crun-vm specific +options. + +## EXEC OPTIONS + +Options that may be used with `podman|docker` `exec` as a prefix to the actual +command to run, if any: + + * `--as` <user_name>: + The user to ssh into the VM as. Defaults to *root*. + + * `--timeout` <max_secs>: + The timeout, in seconds, to apply to a `podman|docker` `run` command. + Defaults to the value of the `CRUN_VM_EXEC_TIMEOUT` environment variable if + set, or *0* otherwise, which means no timeout. + +These options are mostly helpful when debugging crun-vm itself: + + * `--container`: + Exec into the container where the VM hypervisor is running, instead of + ssh'ing into the actual VM. Incompatible with `--as`. + +## ENVIRONMENT + + * `CRUN_VM_EXEC_TIMEOUT`: + The timeout, in seconds, to apply to a `podman|docker` `exec` command. + Defaults to *0*, which means no timeout. Is overridden by `--timeout`. diff --git a/docs/example.gif b/docs/example.gif index cad1500..7405677 100644 Binary files a/docs/example.gif and b/docs/example.gif differ diff --git a/examples/cloud-init/README.md b/examples/cloud-init/README.md deleted file mode 100644 index 957ee2e..0000000 --- a/examples/cloud-init/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Example: cloud-init configuration - -Under [config/](config/) you can find the cloud-init NoCloud configuration that -is used as an example throughout the documentation. diff --git a/examples/cloud-init/config/meta-data b/examples/cloud-init/config/meta-data deleted file mode 100644 index 33b62d4..0000000 --- a/examples/cloud-init/config/meta-data +++ /dev/null @@ -1 +0,0 @@ -local-hostname: my-vm diff --git a/examples/cloud-init/config/user-data b/examples/cloud-init/config/user-data deleted file mode 100644 index d301288..0000000 --- a/examples/cloud-init/config/user-data +++ /dev/null @@ -1,4 +0,0 @@ -#cloud-config -password: pass -chpasswd: - expire: False diff --git a/examples/cloud-init/config/vendor-data b/examples/cloud-init/config/vendor-data deleted file mode 100644 index e69de29..0000000 diff --git a/examples/ignition/README.md b/examples/ignition/README.md deleted file mode 100644 index 1350f19..0000000 --- a/examples/ignition/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Example: Ignition configuration - -At [config.ign](config.ign) you can find the Ignition configuration that is used -as an example throughout the documentation. diff --git a/examples/ignition/config.ign b/examples/ignition/config.ign deleted file mode 100644 index cc71773..0000000 --- a/examples/ignition/config.ign +++ /dev/null @@ -1,25 +0,0 @@ -{ - "ignition": { - "version": "3.0.0" - }, - "passwd": { - "users": [ - { - "name": "core", - "passwordHash": "$y$j9T$USdd8CBvFNVU1xKwQUnsU/$aE.3arHcRxD0ZT3vkvsSpEsteUj6vC4ZdRHY8eOj1f4" - } - ] - }, - "storage": { - "files": [ - { - "path": "/etc/hostname", - "mode": 420, - "overwrite": true, - "contents": { - "source": "data:,my-vm" - } - } - ] - } -} diff --git a/examples/minikube/README.md b/examples/minikube/README.md deleted file mode 100644 index 0905d83..0000000 --- a/examples/minikube/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Example: Minikube cluster with crun-vm available as a runtime - -You can use the `./minikube-start.sh` script in this directory to create a local -[minikube] Kubernetes cluster with crun-vm available as a runtime (note that -this also points `kubectl` at the minikube cluster): - -```console -$ ./minikube-start.sh - Compiling crun-vm v0.1.3 (/home/afaria/repos/crun-vm) - Finished dev [unoptimized + debuginfo] target(s) in 1.38s -😄 [crun-vm-example] minikube v1.32.0 on Fedora 39 -[...] -🏄 Done! kubectl is now configured to use "crun-vm-example" cluster and "default" namespace by default -runtimeclass.node.k8s.io/crun-vm created -``` - -Try going through the examples at [Using crun-vm as a Kubernetes runtime]. - -Once you're done, you can delete the cluster with: - -```console -$ minikube -p crun-vm-example delete -``` - -[minikube]: https://minikube.sigs.k8s.io/ -[Using crun-vm as a Kubernetes runtime]: /docs/3-kubernetes.md diff --git a/examples/quadlet/README.md b/examples/quadlet/README.md deleted file mode 100644 index fb2798a..0000000 --- a/examples/quadlet/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# Example: Manage VMs with systemd using Podman Quadlet and crun-vm - -[Podman Quadlet] is a feature that allows you to define systemd unit files for -containers, such that they can be managed like any other systemd service. - -crun-vm is fully compatible with Podman Quadlet, meaning that you can also -launch and manage your VMs through systemd. Here's an example of how to do so: - -1. Create file `$HOME/.config/containers/systemd/my-vm.container` with the - following contents: - - ```toml - [Unit] - Description=My VM - After=local-fs.target - - [Container] - PodmanArgs=--runtime crun-vm # make Podman use crun-vm as the runtime - Image=quay.io/containerdisks/fedora:40 # the container image containing our VM image - Exec=--password pass # optional crun-vm arguments - - [Install] - WantedBy=multi-user.target default.target # start on boot by default - ``` - - The options under `[Container]` in this unit file will effectively translate - into the following podman invocation: - - ```console - $ podman run --runtime crun-vm quay.io/containerdisks/fedora:40 --password pass - ``` - -2. Inform systemd of the new unit file: - - ```console - $ systemctl --user daemon-reload - ``` - - This will creates a my-vm.service file based on my-vm.container above. - -3. Manage my-vm.service as you would any other service. For instance, we can - start it up: - - ```console - $ systemctl --user start my-vm.service - ``` - - And then check its status: - - ```console - $ systemctl --user status my-vm.service - ``` - -See [this article] for additional information on using Podman Quadlet, and -[podman-systemd.unit(5)] for the reference format for Quadlet systemd units. - -[Podman Quadlet]: https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html -[podman-systemd.unit(5)]: https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html -[this article]: https://www.redhat.com/sysadmin/quadlet-podman diff --git a/examples/minikube/minikube-start.sh b/util/minikube-start.sh similarity index 94% rename from examples/minikube/minikube-start.sh rename to util/minikube-start.sh index 2a6db1b..0378eba 100755 --- a/examples/minikube/minikube-start.sh +++ b/util/minikube-start.sh @@ -3,8 +3,7 @@ set -o errexit -o pipefail -o nounset -script_dir="$( dirname "$0" | xargs readlink -e )" -repo_root=$script_dir/../.. +repo_root=$( readlink -e "$( dirname "$0" )/.." ) __minikube() { minikube -p=crun-vm-example "$@"