Documentation reorg for v4.6.0
Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
469
userdocs/images/images.rst
Normal file
469
userdocs/images/images.rst
Normal file
@@ -0,0 +1,469 @@
|
||||
.. _images:
|
||||
|
||||
===========
|
||||
Node Images
|
||||
===========
|
||||
|
||||
Warewulf node images are a "Virtual Node File System" (VNFS) that serves as a
|
||||
base image for cluster nodes. This is similar to a "golden master" image, except
|
||||
that the image source exists mutably within a directory on the Warewulf control
|
||||
node (e.g. a ``chroot()``).
|
||||
|
||||
Warewulf node images have several similarities to Linux containers; so Warewulf
|
||||
v4 integrates directly within the container ecosystem to facilitate the process
|
||||
of image creation and image management: images can be built, for example, with
|
||||
Docker, Podman, or Apptainer, and imported directly from OCI registries or local
|
||||
container image archives. But you can also still build your own chroot
|
||||
directories manually.
|
||||
|
||||
Structure
|
||||
=========
|
||||
|
||||
A Warewulf image is a directory that populates the base runtime root file system
|
||||
of a cluster node. The image source directory must contain a single ``rootfs``
|
||||
directory which represents the actual root directory for the image.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
/var/lib/warewulf/chroots/rockylinux-9
|
||||
└── rootfs
|
||||
├── afs
|
||||
├── bin -> usr/bin
|
||||
├── boot
|
||||
├── dev
|
||||
├── etc
|
||||
├── home
|
||||
├── lib -> usr/lib
|
||||
├── lib64 -> usr/lib64
|
||||
├── media
|
||||
├── mnt
|
||||
├── opt
|
||||
├── proc
|
||||
├── root
|
||||
├── run
|
||||
├── sbin -> usr/sbin
|
||||
├── srv
|
||||
├── sys
|
||||
├── tmp
|
||||
├── usr
|
||||
└── var
|
||||
|
||||
Importing Images
|
||||
================
|
||||
|
||||
Before any cluster nodes can be provisioned, you must import an image. Images
|
||||
may be imported from an OCI registry, a local OCI archive, or a local directory
|
||||
or Apptainer sandbox.
|
||||
|
||||
OCI Registry
|
||||
------------
|
||||
|
||||
You can import node images from an OCI registry, public or private.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl image import docker://ghcr.io/warewulf/warewulf-rockylinux:8 rockylinux-8
|
||||
Getting image source signatures
|
||||
Copying blob d7f16ed6f451 done
|
||||
Copying config da2ca70704 done
|
||||
Writing manifest to image destination
|
||||
Storing signatures
|
||||
[LOG] info unpack layer: sha256:d7f16ed6f45129c7f4adb3773412def4ba2bf9902de42e86e77379a65d90a984
|
||||
Updating the image's /etc/resolv.conf
|
||||
Building image: rockylinux-8
|
||||
|
||||
.. note::
|
||||
|
||||
Most images in Docker Hub are not "bootable": they typically do not include
|
||||
a kernel, and likely don't include any init system. For this reason, don't
|
||||
expect a base image from DockerHub (e.g. ``docker://rockylinux`` or
|
||||
``docker://debian``) to boot properly with Warewulf.
|
||||
|
||||
The Warewulf project maintains a set of `example node images
|
||||
<https://github.com/warewulf/warewulf-node-images>`_ that are configured to
|
||||
boot when used with Warewulf. These images can be imported directly into
|
||||
Warewulf or used as base images for local custom image.
|
||||
|
||||
A few environmental variables can be used to control communication with the OCI
|
||||
registry:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
WAREWULF_OCI_USERNAME
|
||||
WAREWULF_OCI_PASSWORD
|
||||
WAREWULF_OCI_NOHTTPS
|
||||
|
||||
They can be overwritten with ``--nohttps``, ``--username`` and ``--password``.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl import --username tux --password supersecret docker://ghcr.io/privatereg/rocky:8
|
||||
|
||||
You can also set ``HTTP_PROXY``, ``HTTPS_PROXY``, and ``NO_PROXY`` (or their
|
||||
lower-case versions) to use a proxy during ``wwctl image import``.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
export HTTPS_PROXY=squid.localdomain
|
||||
wwctl image import docker://ghcr.io/warewulf/warewulf-rockylinux:8
|
||||
|
||||
See ProxyFromEnvironment_ for more information.
|
||||
|
||||
.. _ProxyFromEnvironment: https://pkg.go.dev/net/http#ProxyFromEnvironment
|
||||
|
||||
.. note::
|
||||
|
||||
OCI and ORAS registries typically use HTTPS, so you probably need to set
|
||||
``HTTPS_PROXY`` or ``https_proxy`` rather than the ``HTTP`` variants.
|
||||
|
||||
The above is just an example. Consideration should be done before doing it this
|
||||
way if you are in a security sensitive environment or shared environments as
|
||||
this command line wil show up in the process table.
|
||||
|
||||
Local OCI Archive
|
||||
-----------------
|
||||
|
||||
It is also possible to import an image from a local OCI archive. For example,
|
||||
Podman can save a ``.tar`` archive of an OCI image.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
podman save ghcr.io/warewulf/warewulf-rockylinux:8 >rockylinux-8.tar
|
||||
wwctl image import rockylinux-8.tar rockylinux-8
|
||||
|
||||
Local Directories and Apptainer Sandboxes
|
||||
-----------------------------------------
|
||||
|
||||
Chroot directories and Apptainer sandbox images can also be imported directly.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
apptainer build --sandbox ./rockylinux-8/ docker://ghcr.io/warewulf/warewulf-rockylinux:8
|
||||
wwctl image import ./rockylinux-8/ rockylinux-8
|
||||
|
||||
Listing Imported Images
|
||||
=======================
|
||||
|
||||
Once the image has been imported, you can list them all with ``wwctl image
|
||||
list``.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl image list
|
||||
IMAGE NAME
|
||||
----------
|
||||
rockylinux-8
|
||||
|
||||
Additional detail is available using ``wwctl image list --long``, among others.
|
||||
(See ``--help`` for more options.)
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl image list --long
|
||||
IMAGE NAME NODES KERNEL VERSION CREATION TIME MODIFICATION TIME SIZE
|
||||
---------- ----- -------------- ------------- ----------------- ----
|
||||
rockylinux-8 0 4.18.0-553.30.1 11 Feb 25 13:57 MST 11 Feb 25 13:57 MST 1.4 GiB
|
||||
|
||||
Modifying Images Interactively
|
||||
==============================
|
||||
|
||||
An image that has been imported into Warewulf remains mutable, and can be
|
||||
modified on the Warewulf server. For example, you can "shell" into the image and
|
||||
make changes interactively.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl image shell rockylinux-8
|
||||
[warewulf:rockylinux-8] /# dnf -y install apptainer
|
||||
[...]
|
||||
|
||||
Installed:
|
||||
apptainer-1.3.6-1.el8.aarch64
|
||||
fakeroot-1.33-1.el8.aarch64
|
||||
fakeroot-libs-1.33-1.el8.aarch64
|
||||
fuse3-libs-3.3.0-19.el8.aarch64
|
||||
lzo-2.08-14.el8.aarch64
|
||||
squashfs-tools-4.3-21.el8.aarch64
|
||||
|
||||
Complete!
|
||||
|
||||
Binding Files and Directories
|
||||
-----------------------------
|
||||
|
||||
You can ``--bind`` directories from the Warewulf server into the image when
|
||||
using the exec command. This is particularly useful for installing locally-built
|
||||
packages.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# wwctl image shell --bind /var/lib/mock/rocky+epel-9-$(arch)/result:/mnt
|
||||
[warewulf:rockylinux-8] /# dnf -y install /mnt/warewulf-dracut-*.noarch.rpm
|
||||
|
||||
.. note::
|
||||
|
||||
As with any mount command, both the source and the target must exist. This is
|
||||
why the example uses the ``/mnt/`` directory location, as it is almost always
|
||||
present and empty in every Linux distribution (as prescribed by the LSB file
|
||||
hierarchy standard).
|
||||
|
||||
Files may also be automatically bound into the image during ``wwctl image
|
||||
shell`` by configuring ``warewulf.conf:image mounts``.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
image mounts:
|
||||
- source: /etc/resolv.conf
|
||||
dest: /etc/resolv.conf
|
||||
readonly: true
|
||||
|
||||
.. note::
|
||||
|
||||
Instead of ``readonly: true`` you can set ``copy: true``. This causes the
|
||||
source file to be copied to the image and removed if it was not modified.
|
||||
This can be useful for files used for registrations.
|
||||
|
||||
When the command completes, if anything within the image changed, the image will
|
||||
be rebuilt into a bootable static object automatically. (To skip the automatic
|
||||
image rebuild, specify ``--build=false``.)
|
||||
|
||||
If the files ``/etc/passwd`` or ``/etc/group`` were updated, there will be an
|
||||
additional check to confirm if the users are in sync as described in `Syncuser`_
|
||||
section.
|
||||
|
||||
Specifying a Prompt
|
||||
-------------------
|
||||
|
||||
Warewulf sets a custom prompt during a ``wwctl image shell`` session. This
|
||||
prompt may be customized using the ``WW_PS1`` variable, which is used to
|
||||
construct the final ``PS1`` variable for the shell.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# export WW_PS1="\u@\h:\w\$ "
|
||||
# wwctl image shell rockylinux-8
|
||||
[warewulf:rockylinux-8] root@rocky:/$
|
||||
|
||||
Shell History
|
||||
-------------
|
||||
|
||||
By default, Warewulf image shell sessions don't retain history; but you can
|
||||
specify a history file by specifying ``WW_HISTFILE``. Note that this file is
|
||||
stored within the image; you may want to :ref:`exclude` it when the image is
|
||||
built.
|
||||
|
||||
Running Specific Commands
|
||||
-------------------------
|
||||
|
||||
A single command can also be executed in an image, as an alternative to an
|
||||
interactive shell.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
wwctl image exec rockylinux-8 -- /usr/bin/dnf -y install apptainer
|
||||
|
||||
Building Images
|
||||
===============
|
||||
|
||||
Warewulf images must be built (e.g., with ``wwctl image build``) into compressed
|
||||
images for distribution to cluster nodes during provisioning.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl image build rockylinux-9
|
||||
Building image: rockylinux-9
|
||||
Created image for Image rockylinux-9: /var/lib/warewulf/provision/images/rockylinux-9.img
|
||||
Compressed image for Image rockylinux-9: /var/lib/warewulf/provision/images/rockylinux-9.img.gz
|
||||
|
||||
.. _exclude:
|
||||
|
||||
Excluding Files
|
||||
---------------
|
||||
|
||||
Warewulf can exclude files from an image to prevent them from being delivered to
|
||||
the compute node. This is typically used to reduce the size of the image when
|
||||
some files are unnecessary.
|
||||
|
||||
Patterns for excluded files are read from the file ``/etc/warewulf/excludes`` in
|
||||
the image itself. For example, the default Rocky Linux images exclude these
|
||||
paths:
|
||||
|
||||
.. code-block::
|
||||
|
||||
/boot/
|
||||
/usr/share/GeoIP
|
||||
|
||||
``/etc/warewulf/excludes`` supports the patterns implemented by `filepath.Match
|
||||
<https://pkg.go.dev/path/filepath#Match>`_.
|
||||
|
||||
Exit Script
|
||||
-----------
|
||||
|
||||
Warewulf executes the script ``/etc/warewulf/image_exit.sh`` in the image after
|
||||
a ``wwctl image shell`` or ``wwctl image exec`` and prior to (re)building the
|
||||
final node image for delivery. This is typically used to remove cache or log
|
||||
files that may have been generated by the executed command or interactive
|
||||
session.
|
||||
|
||||
For example, the default Rocky Linux images runs ``dnf clean all`` to remove any
|
||||
package repository caches that may have been generated.
|
||||
|
||||
Defining New Images
|
||||
===================
|
||||
|
||||
It is absolutely possible to import a base image into Warewulf and make all
|
||||
changes interactively with ``wwctl image shell``; but it is often better to
|
||||
define new images with a container image definition file. This can be done using
|
||||
the OCI and Singularity (Apptainer) ecoystems.
|
||||
|
||||
Podman
|
||||
------
|
||||
|
||||
An OCI Containerfile can build from an existing container image to add local
|
||||
customizations.
|
||||
|
||||
.. code-block::
|
||||
|
||||
FROM ghcr.io/warewulf/warewulf-rockylinux:9
|
||||
|
||||
RUN dnf -y install epel-release \
|
||||
&& dnf -y install apptainer
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# podman build . --file Containerfile --tag custom-image
|
||||
[...]
|
||||
Successfully tagged localhost/custom-image:latest
|
||||
|
||||
# wwctl image import $(podman image mount localhost/custom-image) custom-image
|
||||
# podman image unmount localhost/custom-image
|
||||
|
||||
Apptainer
|
||||
---------
|
||||
|
||||
It is absolutely possible to create an `OCI base image`_ from scratch, but it is
|
||||
particularly easy to do with Apptainer.
|
||||
|
||||
.. _OCI base image: https://docs.docker.com/build/building/base-images/
|
||||
|
||||
Consider the following file called `warewulf-rockylinux-9.def`:
|
||||
|
||||
.. code-block:: singularity
|
||||
|
||||
Bootstrap: yum
|
||||
MirrorURL: https://download.rockylinux.org/pub/rocky/9/BaseOS/x86_64/os/
|
||||
Include: dnf
|
||||
|
||||
%post
|
||||
dnf -y install --allowerasing \
|
||||
NetworkManager \
|
||||
basesystem \
|
||||
bash \
|
||||
curl-minimal \
|
||||
kernel \
|
||||
nfs-utils \
|
||||
openssh-server \
|
||||
systemd
|
||||
|
||||
dnf -y remove \
|
||||
glibc-gconv-extra
|
||||
rm -rf /boot/* /run/*
|
||||
dnf clean all
|
||||
|
||||
Warewulf cannot directly import a container image from an Apptainer SIF yet, so
|
||||
an Apptainer image must be built as a *sandbox*.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# apptainer build --sandbox warewulf-rockylinux-9 warewulf-rockylinux-9.def
|
||||
[...]
|
||||
INFO: Creating sandbox directory...
|
||||
INFO: Build complete: warewulf-rockylinux-9
|
||||
|
||||
Once a sandbox container image has been built, it can be imported into Warewulf.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl container import ./warewulf-rockylinux-9 rockylinux-9
|
||||
|
||||
.. note::
|
||||
|
||||
Although warewulf does not currently support importing a SIF directly, a SIF
|
||||
can be converted to a sandbox with Apptainer and then imported into Warewulf.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# apptainer build --sandbox my-sandbox my-image.sif
|
||||
# wwctl container import ./my-sandbox my-image
|
||||
|
||||
Duplicating an image
|
||||
====================
|
||||
|
||||
It is possible to duplicate an installed image by using:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl image copy IMAGE_NAME DUPLICATED_IMAGE_NAME
|
||||
|
||||
This kind of duplication can be useful if you are looking for canary tests.
|
||||
|
||||
.. note::
|
||||
|
||||
If an image source includes persistent sockets, these sockets may cause the
|
||||
copy operation to fail.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
Copying sources...
|
||||
ERROR : could not duplicate image: lchown /var/lib/warewulf/chroots/rocky-8/rootfs/run/user/0/gnupg/d.kg8ijih5tq41ixoeag4p1qup/S.gpg-agent: no such file or directory
|
||||
|
||||
To resolve this, remove the sockets from the image source.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
find $(wwctl image show rocky-8) -type s -delete
|
||||
|
||||
Image Architecture
|
||||
==================
|
||||
|
||||
By default, Warewulf will try to import an image of the same platform (e.g.,
|
||||
amd64, arm64) as the local system. To specify the platform to import, either
|
||||
specify `WAREWULF_OCI_PLATFORM` or use the argument `--platform` during import.
|
||||
|
||||
It is possible to build, edit, and provision images of different architectures
|
||||
(i.e. aarch64) from an x86_64 host by using QEMU. Simply run the appropriate
|
||||
command below based on your image management tools.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
# podman run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
# apptainer run docker://multiarch/qemu-user-static --reset -p yes
|
||||
|
||||
Then, ``wwctl image exec`` will work regardless of the architecture of the
|
||||
image. For more information about QEMU, see their `GitHub
|
||||
<https://github.com/multiarch/qemu-user-static>`_
|
||||
|
||||
To use wwclient on a booted image using a different architecture, wwclient must
|
||||
be compiled for the specific architecture. This requires GOLang build tools 1.21
|
||||
or newer. Below is an example for building wwclient for arm64:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# git clone https://github.com/warewulf/warewulf
|
||||
# cd warewulf
|
||||
# GOARCH=arm64 PREFIX=/ make wwclient
|
||||
# mkdir -p /var/lib/warewulf/overlays/wwclient_arm64/rootfs/warewulf
|
||||
# cp wwclient /var/lib/warewulf/overlays/wwclient_arm64/rootfs/warewulf
|
||||
|
||||
Then, apply the new "wwclient_arm64" system overlay to your arm64 node/profile
|
||||
|
||||
Read-only images
|
||||
================
|
||||
|
||||
An image may be marked "read-only" by creating a ``readonly`` file in its source
|
||||
directory, typically next to ``rootfs``.
|
||||
|
||||
.. note::
|
||||
|
||||
Read-only images are a preview feature primarily meant to enable future
|
||||
support for image subscriptions and updates.
|
||||
33
userdocs/images/kernel.rst
Normal file
33
userdocs/images/kernel.rst
Normal file
@@ -0,0 +1,33 @@
|
||||
=============
|
||||
Image Kernels
|
||||
=============
|
||||
|
||||
Warewulf nodes require a Linux kernel to boot. As of Warewulf v4.6, the kernel
|
||||
you wish to use must be present in the relevant image. Warewulf locates and
|
||||
provisions the kernel automatically for any node configured to use that image.
|
||||
|
||||
You can see what kernels are available in imported images by using the ``wwctl
|
||||
image kernels`` command.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl image kernels
|
||||
Image Kernel Version Default Nodes
|
||||
----- ------ ------- ------- -----
|
||||
newroot-test /boot/vmlinuz-5.14.0-427.37.1.el9_4.aarch64 5.14.0-427.37.1 true 0
|
||||
newroot-test /lib/modules/5.14.0-427.37.1.el9_4.aarch64/vmlinuz 5.14.0-427.37.1 false 0
|
||||
rocky-8 /boot/vmlinuz-4.18.0-372.13.1.el8_6.x86_64 4.18.0-372.13.1 true 2
|
||||
rocky-8 /lib/modules/4.18.0-372.13.1.el8_6.x86_64/vmlinuz 4.18.0-372.13.1 false 0
|
||||
rocky-9.3 /lib/modules/5.14.0-362.13.1.el9_3.aarch64/vmlinuz 5.14.0-362.13.1 true 0
|
||||
rockylinux-9-custom /lib/modules/5.14.0-427.40.1.el9_4.aarch64/vmlinuz 5.14.0-427.40.1 true 0
|
||||
|
||||
Kernel Version
|
||||
==============
|
||||
|
||||
If an image includes multiple kernels, the desired kernel may be selected by
|
||||
specifying the desired version or an explicit path.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl node set n1 --kernelversion=4.18.0-372.13.1
|
||||
# wwctl node set n1 --kernelversion=/boot/vmlinuz-4.18.0-372.13.1.el8_6.x86_64
|
||||
29
userdocs/images/selinux.rst
Normal file
29
userdocs/images/selinux.rst
Normal file
@@ -0,0 +1,29 @@
|
||||
.. _selinux_images:
|
||||
|
||||
======================
|
||||
SELinux-enabled Images
|
||||
======================
|
||||
|
||||
Warewulf supports booting SELinux-enabled images, though nodes using SELinux
|
||||
must be configured to use tmpfs for their image file system. ("ramfs," often
|
||||
used by default, does not support extended file attributes, which are required
|
||||
for SELinux context labeling.)
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
wwctl profile set default --root tmpfs
|
||||
|
||||
.. note::
|
||||
|
||||
Versions of Warewulf prior to v4.5.8 also required a kernel argument
|
||||
"rootfstype=ramfs" in order for wwinit to copy the node image to tmpfs; but
|
||||
this is no longer required.
|
||||
|
||||
Once that is done, enable SELinux in ``/etc/sysconfig/selinux`` and install the
|
||||
appropriate packages in the image. `An example`_ of such an image is available
|
||||
in the warewulf-node-images repository.
|
||||
|
||||
.. _An example: https://github.com/warewulf/warewulf-node-images/tree/main/examples/rockylinux-9-selinux
|
||||
|
||||
SELinux requires extended attributes, which aren't supported on a default
|
||||
``initrootfs``. Nodes using SELinux should specify ``--root=tmpfs``.
|
||||
30
userdocs/images/syncuser.rst
Normal file
30
userdocs/images/syncuser.rst
Normal file
@@ -0,0 +1,30 @@
|
||||
========
|
||||
Syncuser
|
||||
========
|
||||
|
||||
Warewulf can optionally synchronize UIDs and GIDs from the Warewulf server to an
|
||||
image. This can be particularly useful when there is no central directory (e.g.,
|
||||
an LDAP server).
|
||||
|
||||
.. note::
|
||||
|
||||
Some system services (notably "munge") require a user to have the same UID across all nodes.
|
||||
|
||||
Combined with the "syncuser" overlay, Warewulf syncuser also supports defining
|
||||
local users on the Warewulf server for synchronization to cluster nodes.
|
||||
|
||||
If there is mismatch between the server and the image, the import command will
|
||||
generate a warning.
|
||||
|
||||
Syncuser may be invoked during image import, exec, shell, or build.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# wwctl image import --syncuser docker://ghcr.io/warewulf/warewulf-rockylinux:9 rockylinux-9
|
||||
# wwctl image exec --syncuser rockylinux-9 -- /usr/bin/echo "Hello, world!"
|
||||
# wwctl image shell --syncuser rockylinux-9
|
||||
# wwctl image build --syncuser rockylinux-9
|
||||
# wwctl image syncuser rockylinux-9
|
||||
|
||||
After syncuser, ``/etc/passwd`` and ``/etc/group`` in the image are updated, and
|
||||
permissions on files belonging to these UIDs and GIDs are updated to match.
|
||||
Reference in New Issue
Block a user