Documentation reorg for v4.6.0

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
Jonathon Anderson
2025-02-18 16:26:05 -07:00
parent 98695cbbff
commit 9e41378e1c
65 changed files with 3493 additions and 4654 deletions

View File

@@ -36,7 +36,7 @@ jobs:
- name: Install Sphinx - name: Install Sphinx
run: | run: |
pip install --user --upgrade --upgrade-strategy eager sphinx sphinx-rtd-theme restructuredtext_lint pygments pip install --user --upgrade --upgrade-strategy eager sphinx sphinx-rtd-theme restructuredtext_lint pygments sphinx_reredirects
- name: Include reference docs - name: Include reference docs
run: | run: |

View File

@@ -69,6 +69,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Renamed /warewulf/wwinit to /warewulf/prescripts. #1156 - Renamed /warewulf/wwinit to /warewulf/prescripts. #1156
- Display auto-detected kernel version during iPXE and GRUB. #1742 - Display auto-detected kernel version during iPXE and GRUB. #1742
- Reduced default verbosity of `wwctl overlay build`. - Reduced default verbosity of `wwctl overlay build`.
- Reorganized and updated userdocs. #1116, #1324
### Fixed ### Fixed

View File

@@ -46,6 +46,8 @@ config = include/systemd/warewulfd.service \
.PHONY: config .PHONY: config
config: $(config) config: $(config)
$(config): Defaults.mk
apiconfig = etc/wwapic.conf \ apiconfig = etc/wwapic.conf \
etc/wwapid.conf \ etc/wwapid.conf \
etc/wwapird.conf etc/wwapird.conf

View File

@@ -62,12 +62,12 @@ TFTPDIR ?= /var/lib/tftpboot
# Warewulf directory paths # Warewulf directory paths
VARLIST += WWCLIENTDIR WWCONFIGDIR WWPROVISIONDIR WWOVERLAYDIR WWCHROOTDIR WWTFTPDIR WWDOCDIR IPXESOURCE VARLIST += WWCLIENTDIR WWCONFIGDIR WWPROVISIONDIR WWOVERLAYDIR WWCHROOTDIR WWTFTPDIR WWDOCDIR IPXESOURCE
WWCONFIGDIR := $(SYSCONFDIR)/$(WAREWULF) WWCONFIGDIR ?= $(SYSCONFDIR)/$(WAREWULF)
WWPROVISIONDIR := $(LOCALSTATEDIR)/$(WAREWULF)/provision WWPROVISIONDIR ?= $(LOCALSTATEDIR)/$(WAREWULF)/provision
WWOVERLAYDIR := $(LOCALSTATEDIR)/$(WAREWULF)/overlays WWOVERLAYDIR ?= $(LOCALSTATEDIR)/$(WAREWULF)/overlays
WWCHROOTDIR := $(LOCALSTATEDIR)/$(WAREWULF)/chroots WWCHROOTDIR ?= $(LOCALSTATEDIR)/$(WAREWULF)/chroots
WWTFTPDIR := $(TFTPDIR)/$(WAREWULF) WWTFTPDIR ?= $(TFTPDIR)/$(WAREWULF)
WWDOCDIR := $(DOCDIR)/$(WAREWULF) WWDOCDIR ?= $(DOCDIR)/$(WAREWULF)
WWCLIENTDIR ?= /warewulf WWCLIENTDIR ?= /warewulf
CONFIG := $(shell pwd) CONFIG := $(shell pwd)
@@ -85,5 +85,7 @@ export GOPROXY
WW_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree WW_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree
.PHONY: defaults .PHONY: defaults
defaults: defaults: Defaults.mk
Defaults.mk:
printf " $(foreach V,$(VARLIST),$V := $(strip $($V))\n)" >Defaults.mk printf " $(foreach V,$(VARLIST),$V := $(strip $($V))\n)" >Defaults.mk

View File

@@ -14,7 +14,44 @@ release = 'main'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = ['sphinx.ext.graphviz'] extensions = [
'sphinx.ext.graphviz',
'sphinx_reredirects',
]
redirects = {
'contents/background': '../getting-started/introduction.html',
'contents/glossary': '../getting-started/glossary.html',
'contents/introduction': '../getting-started/introduction.html',
'contents/provisioning': '../getting-started/provisioning.html',
'contents/stateless': '../getting-started/provisioning.html',
'quickstart/debian12': '../getting-started/debian-quickstart.html',
'quickstart/el': '../getting-started/el-quickstart.html',
'quickstart/suse15': '../getting-started/suse-quickstart.html',
'contents/images': 'images/images.html',
'contents/kernel': 'images/kernel.html',
'contents/disks': 'nodes/disks.html',
'contents/ipmi': 'nodes/ipmi.html',
'contents/nodeconfig': 'nodes/nodes.html',
'contents/overlays': 'overlays/overlays.html',
'contents/templating': 'overlays/templates.html',
'contents/profiles': 'nodes/profiles.html',
'contents/boot-management': 'server/bootloaders.html',
'contents/configuration': 'server/configuration.html',
'contents/dnsmasq': 'server/dnsmasq.html',
'contents/initialization': 'server/configuration.html',
'contents/installation': 'server/installation.html',
'contents/security': 'server/security.html',
'contents/setup': 'getting-started/network.html',
'contents/upgrade': 'server/upgrade.html',
'contents/wwctl': 'server/wwctl.html',
'contents/known-issues': 'troubleshooting/known-issues.html',
'contents/troubleshooting': 'troubleshooting/troubleshooting.html',
'contributing/development-environment-devcontainer': 'contributing/development-environment',
'contributing/development-environment-kvm': 'contributing/development-environment',
'contributing/development-environment-vagrant': 'contributing/development-environment',
'contributing/development-environment-vbox': 'contributing/development-environment',
}
templates_path = ['_templates'] templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']

View File

@@ -1,38 +0,0 @@
==========
Background
==========
Warewulf is based on the design of the original Beowulf Cluster design
(and thus the name, soft\ **WARE** implementation of the beo\
**WULF**)
The `Beowulf Cluster <https://en.wikipedia.org/wiki/Beowulf_cluster>`_
design was developed in 1996 by Dr. Thomas Sterling and Dr. Donald
Becker at NASA. The architecture is defined as a group of similar
compute worker nodes all connected together using standard commodity
equipment on a private network segment. The control node (historically
referred to as the "master" or "head" node) is dual homed (has two
network interface cards) with one of these network interface cards
attached to the upstream public network and the other connected to a
private network which connects to all of the compute worker nodes (as
seen in the figure below).
.. image:: beowulf_architecture.png
:alt: Beowulf architecture
This simple topology is the foundation for creating every scalable HPC
cluster resource. Even today, almost 30 years after the inception of
this architecture, this is the baseline architecture that traditional
HPC systems are built to.
Other considerations for a working HPC-type cluster are storage,
scheduling and resource management, monitoring, interactive systems,
etc. For smaller systems, much of these requirements can be managed
all from a single control node, but as the system scales, it may need
to have groups of nodes dedicated to these different services.
Warewulf is easily capable of building simple and turnkey HPC
clusters, to giant massive complex multi-purpose computing clusters,
through next generation computing platforms.
Anytime a cluster of systems is needed, Warewulf is your tool!

View File

@@ -1,252 +0,0 @@
======================
Warewulf Configuration
======================
The default installation of Warewulf will put all of the configuration
files into ``/etc/warewulf/``. In that directory, you will find the
primary configuration files needed by Warewulf.
warewulf.conf
=============
The Warewulf configuration exists as follows in the current version of
Warewulf (4.6.0):
.. code-block:: yaml
ipaddr: 10.0.0.1
netmask: 255.255.252.0
network: 10.0.0.0
warewulf:
port: 9873
secure: false
update interval: 60
autobuild overlays: true
host overlay: true
dhcp:
enabled: true
range start: 10.0.1.1
range end: 10.0.1.255
systemd name: dhcpd
tftp:
enabled: true
systemd name: tftp
nfs:
enabled: true
export paths:
- path: /home
export options: rw,sync
- path: /opt
export options: ro,sync,no_root_squash
systemd name: nfs-server
image mounts:
- source: /etc/resolv.conf
dest: /etc/resolv.conf
readonly: true
ssh:
key types:
- ed25519
- ecdsa
- rsa
- dsa
wwclient:
port: 0
Generally you can leave this file as is, as long as you set the
appropriate networking information. Specifically the following
configurations:
* ``ipaddr``: This is the control node's networking interface
connecting to the cluster's **PRIVATE** network. This configuration
must match the host's network IP address for the cluster's private
interface.
* ``netmask``: Similar to the ``ipaddr``, this is the subnet mask for
the cluster's **PRIVATE** network and it must also match the host's
subnet mask for the cluster's private interface.
* ``dhcp:range start`` and ``dhcp:range end``: This address range must
exist in the network defined above. If it is outside of this
network, failures will occur. This specifies the range of addresses
you want DHCP to use.
* ``dhcp:template`` defines an optional DHCP template variable to control the
generation of the DHCP template.
Specifying ``template: static`` populates ``dhcpd.conf`` with static leases
for each host, bypassing the DHCP range. Run ``wwctl configure dhcp`` to
update ``dhcpd.conf`` when nodes are added, removed, or changed.
The other configuration options are usually not touched, but they are
explained as follows:
* ``*:enabled``: This can be used to disable Warewulf's control of a
system service. This is useful if you want to manage that service
directly.
* ``*:systemd name``: This is so Warewulf can control some of the
host's services. For the distributions that we've built and tested
this on, these will require no changes.
* ``warewulf:port``: This is the port that the Warewulf web server
will be listening on. It is recommended not to change this so there
is no misalignment with node's expectations of how to contact the
Warewulf service.
* ``warewulf:secure``: When ``true``, this limits the Warewulf server
to only respond to runtime overlay requests originating from a
privileged port. This prevents non-root users from requesting the
runtime overlay, which may contain sensitive information.
When ``true``, ``wwclient`` uses TCP port 987 by default. A different port can
be specified at `wwclient.port`.
Changing this option requires rebuilding node overlays and rebooting compute
nodes to configure them to use a privileged port for `wwclient`.
* ``warewulf:update interval``: This defines the frequency (in
seconds) with which the Warewulf client on the compute node fetches
overlay updates.
* ``warewulf:autobuild overlays``: This determines whether per-node
overlays will automatically be rebuilt, e.g., when an underlying
overlay is changed.
* ``warewulf:host overlay``: This determines whether the special
``host`` overlay is applied to the Warewulf server during
configuration. (The host overlay is used to configure the dependent
services.)
* ``nfs:export paths``: Warewulf can automatically set up these NFS
exports.
* ``image mounts``: These paths are mounted into the image
during ``image exec`` or ``image shell``, typically to allow
them to operate in the host environment prior to deployment.
Paths
-----
*New in Warewulf v4.5.0*
Default paths to images, overlays, and other Warewulf components
may be overridden using ``warewulf.conf:paths``.
.. code-block:: yaml
paths:
sysconfdir: /etc
localstatedir: /var/lib
ipxesource: /usr/share/ipxe
wwoverlaydir: /var/lib/warewulf/overlays
wwchrootdir: /var/lib/warewulf/chroots
wwprovisiondir: /var/lib/warewulf/provision
wwclientdir: /warewulf
* ``sysconfdir``: The parent directory for the ``warewulf`` configuration directory,
which stores ``warewulf.conf`` and ``nodes.conf``.
* ``ipxesource``: Where to get iPXE binaries.
These files are copied to ``warewulf.conf:tftp:tftproot`` by ``wwctl configure``.
* ``wwoverlaydir``: The source for Warewulf overlays.
* ``wwchrootdir``: The source for Warewulf images.
* ``wwprovisiondir``: Where to store built overlays and images.
* ``wwclientdir``: Where the Warewulf client looks for its configuration on a provisioned node.
SSH key types
-------------
*New in Warewulf v4.5.1*
SSH key types to generate during ``wwctl configure ssh`` may be overridden using ``warewulf.conf:ssh:key types``.
.. code-block:: yaml
ssh:
key types:
- ed25519
- ecdsa
- rsa
- dsa
Warewulf will generate host keys for each listed key type.
The first listed key type is used to generate authentication ssh keys.
nodes.conf
==========
The ``nodes.conf`` file is the primary registry for all compute
nodes. It is a flat text YAML configuration file that is managed by
the ``wwctl`` command, but some sites manage the compute nodes and
infrastructure via configuration management. This file being flat text
and very light weight makes management of the node configurations very
easy no matter what your configuration paradigm is.
For the purpose of this document, we will not go into the detailed
format of this file as it is recommended to edit with the ``wwctl``
command.
.. note::
This configuration is not written at install time; but, the first
time you attempt to run ``wwctl``, this file will be generated if
it does not exist already.
.. note::
When ``nodes.conf`` is edited directly, ``warewulfd`` does not know that the image profile has been changed. Therefore the changes to ``nodes.conf`` are not taken into account by ``warewulfd`` until it is restarted.
Once you restart ``warewulfd``, the ``nodes.conf`` file is then successfully reloaded.
This also goes for ``warewulf.conf`` as well - any changes made also require ``warewulfd`` to be restarted.
The restart should be done using the following command: ``systemctl restart warewulfd``
Directories
===========
The ``/etc/warewulf/ipxe/`` directory contains *text/templates* that
are used by the Warewulf configuration process to configure the
``ipxe`` service.
FirewallD
=========
When using ``firewalld`` with Warewulf, the following services are required to be added for successful node interconnectivity:
.. code-block:: console
firewall-cmd --permanent --add-service=warewulf
firewall-cmd --permanent --add-service=dhcp
firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-service=tftp
Make sure the ``--reload`` command is ran afterwards:
.. code-block:: console
firewall-cmd --reload
nftables
========
When deploying ``nftables`` with Warewulf, ensure that TCP port ``9873`` for HTTP requests is available, else you will not be able to add new nodes to the cluster.
This can be done with the ``nft add rule`` command:
.. code-block:: console
nft add rule inet filter input tcp dport 9873 accept
Save the changes to your ``nftables.conf`` file:
.. code-block:: console
nft list ruleset > /etc/nftables.conf
Restart the ``nftables`` service:
.. code-block:: console
systemctl restart nftables

View File

@@ -1,137 +0,0 @@
===============
Disk Management
===============
Warewulf itself does not manage disks, partitions, or file systems directly, but provides structures in the configuration for these objects.
At the moment warewulf supports `ignition`_ to create the partitions and file systems.
.. _ignition: https://coreos.github.io/ignition/
.. note::
It is not currently possible to manage the root file system with
Warewulf.
Warewulf can be used, for example, to create ``swap`` partitions or ``/scratch`` file systems.
Requirements
============
Partition and file system creation requires both ``ignition`` and ``sgdisk`` to be installed in the image.
Rocky Linux
-----------
.. code-block:: shell
dnf install ignition gdisk
.. note::
Packages for Ignition are not currently available for Rocky Linux 8,
but it is available for Rocky Linux 9 as part of "appstream."
openSuse Leap
-------------
.. code-block:: shell
zypper install ignition gptfdisk
Storage objects
===============
The format of the storage objects is inspired by ``butane/ignition``;
but, where ``butane/ignition`` uses lists for holding disks, partitions and file systems, Warewulf uses maps instead.
A node or profile can have several disks, where each disk is identified by the path to its block device.
Every disks holds a map to its partitions and a ``bool`` switch to indicate if an existing partition table should be overwritten if it does not matched the desired configuration.
Each partition is identified by its label.
The partition number can be omitted, but specifying it is recommended as ``ignition`` may fail without it.
Partition sizes should also be set (specified in MiB), except of the last partition:
if no size is given, the maximum available size is used.
Each partition has the switches ``should_exist`` and ``wipe_partition_entry`` which control the partition creation process. When omitting a partition number the `wipe_partition_entry` should be true, as this allows ignition to replace the existing partition.
File systems are identified by their underlying block device, preferably using the ``/dev/by-partlabel`` format.
Except for a ``swap`` partition, an absolute path for the mount point must be specified for each file system.
Depending on the image used, valid formats are ``btrfs``, ``ext3``, ``ext4``, and ``xfs``.
Each file system has the switch ``wipe_filesystem`` to control whether an existing file system is wiped.
Ignition Implementation
=======================
The ignition implementation uses systemd services, as the underlying ``sgdisk`` command relies on dbus notifications.
All necessary services are distributed by the ``ignition`` overlay and depends on the existence of the file ``/warewulf/ignition.json``.
This file is created by the template function ``{{ createIgnitionJson }}`` only if the configuration contains necessary specifications for disks, partitions, and file systems.
If the file ``/warewulf/ignition.json`` exists, the service ``ignition-disks-ww4.service`` calls the ignition binary which takes creates partitions and file systems.
A systemd ``.mount`` unit is created for each configured file system, which also creates the necessary mount points in the root file system.
These mount units are required by the enabled ``ww4-disks.target``.
Entries in ``/etc/fstab`` are created with the ``no_auto`` option so that file systems can be easily mounted.
Example disk configuration
==========================
The following command will create a ``/scratch`` file system on the node ``n01``.
.. code-block:: shell
wwctl node set n01 \
--diskname /dev/vda --diskwipe \
--partname scratch --partcreate --partnumber 1 \
--fsname scratch --fsformat btrfs --fspath /scratch
As this is a single file system, the partition number can be omitted.
A swap partition with 1Gig can be added with
.. code-block:: shell
wwctl node set n01 \
--diskname /dev/vda \
--partname swap --partsize=1024 --partnumber 2 \
--fsname swap --fsformat swap --fspath swap
which has the partition number ``1`` so that it will be added before the
``/scratch`` partition.
Wiping disks
============
Unless you specify the `--fswipe` flag for a filesystem, `ignition` will try to
reuse existing file systems. For empty disks this means that the desired configuration
is created and the filesystems are mounted; and so the `--fswipe` can be omitted so
data is on the disk isn't wiped.
If there are pre-existing partitions and filesystem on the disk, omitting the `--fswipe` may lead to the outcome that no filesystems are created and mounted.
In that case you should:
* wipe the existing data with the means of tools like `wipefs` or `dd` [#]_
* set the `--fswipe` flag and remove it after one reboot, if you want to keep
existing data on the disk.
.. [#] With `wipefs` you have to remove the filesystem *and* parition information. E.g. use `wipefs -fa /dev/vda*` to remove all filesystem information and partition information.
See also `ignition documentation`_ for additional information.
.. _ignition documentation: https://coreos.github.io/ignition/operator-notes/#filesystem-reuse-semantics
Troubleshooting
===============
If the partition creation didn't work as expected you have a few options to investigate:
- Add ``systemd.log_level=debug`` and or ``rd.debug`` to the kernelArgs of the node you're working on.
- After the next boot you should be able to find verbose information on the node with ``journalctl -u ignition-ww4-disks.service``.
- You could also check the content of ``/warewulf/ignition.json``.
- You could try to tinker with ``/warewulf/ignition.json`` calling
.. code-block:: shell
/usr/lib/dracut/modules.d/30ignition/ignition \
--platform=metal \
--stage=disks \
--config-cache=/warewulf/ignition.json \
--log-to-stdout
after each iteration on the node directly until you find the settings you need.
(Make sure to unmount all partitions if ``ignition`` was partially successful.)
- Sometimes you need to add ``should_exist: "true"`` for the swap partition as well.

View File

@@ -1,68 +0,0 @@
=======
Dnsmasq
=======
Usage
=====
As experimental feature its possible to use ``dnsmasq`` instead of the ISC ``dhcpd`` server in combination with a ``TFTP`` server.
The ``dnsmasq`` service is then acting as ``dhcp`` and ``TFTP`` server.
In order to keep the file ``/etc/dnsmasq.d/ww4-hosts.conf`` is created and must be included in the main ``dnsmasq.conf`` via the ``conf-dir=/etc/dnsmasq.d`` option.
Installation
------------
Before the installation, make sure that ``dhcpd`` and ``tftp`` are disabled.
You can do that with the commands:
.. code-block:: shell
systemctl disable dhcpd
systemctl stop dhcpd
systemctl disable tftp
systemctl stop tftp
Now you can install ``dnsmasq``.
.. code-block:: shell
zypper install dnsmasq
After the installation you have to instruct ``warewulf`` to use ``dnsmasq`` as its ``dhcpd`` and ``tftp`` service.
``dnsmasq`` has to be specified in the configuration file ``/etc/warewulf/warewulf.conf``.
.. code-block:: shell
tftp:
systemd name: dnsmasq
dhcp:
systemd name: dnsmasq
The configuration of ``dnsmasq`` doesn't need to be changed, as the default configuration includes all files with following pattern ``/etc/dnsmasq.d/*conf`` into its configuration.
This configuration is created by the overlay template ``host:/etc/dnsmasq.d/ww4-hosts.conf.ww``.
.. note::
In certain OS versions, such as Rocky Linux 9, ``dnsmasq`` is configured to listen locally via the ``interface=lo`` option by default in ``/etc/dnsmasq.conf``.
Replace this with the interface associated with your Warewulf network, or remove/comment out the interface option entirely to enable listening on all interfaces.
In order to build this template run
.. code-block:: shell
wwctl overlay build -H
After that the ``dnsmasq`` service has to be enabled.
Either
.. code-block:: shell
systemctl enable --now dnsmasq
or by (re)configuring warewulf with
.. code-block:: shell
wwctl configure dhcp
wwctl configure tftp

View File

@@ -1,56 +0,0 @@
========
Glossary
========
Image
The node images that Warewulf manages and provisions.
Images may be mported from OCI image registries, OCI image archives, Apptainer sandboxes, and manual chroot directories.
Warewulf images are maintained as an uncompressed "virtual node file system" or VNFS, (sometimes also referred to as a "chroot").
These images are then built as images which may then be used to provision a node.
Controller
The Warewulf controller runs the Warewulf daemon (``warewulfd``) and is responsible for the management, control, and administration of the cluster.
This system may also sometimes be referred to as the "master," "head," or "admin" node.
A typical Warewulf controller also runs a DHCP service and a TFTP service, and often an NFS service;
though these services may be managed separately and on separate servers.
Kernel
In addition to an image, Warewulf also requires a kernel (typically a Linux kernel) in order to provision a node.
Warewulf (after v4.3.0) automatically provisions a kernel detected and extracted from the image itself.
In most cases, kernels may be installed in the image using normal system packages, and no special consideration is necessary.
Node
Warewulf nodes are the systems that are being provisioned by Warewulf.
The roles of these systems could be "compute", "storage", "GPU", "IO", etc.
nodes.conf
One of two primary Warewulf configuration files, ``nodes.conf`` is a YAML document which records all configuration parameters for Warewulf's nodes and profiles.
It does not contain the images or overlays, but refers to them by name.
Overlay
Warewulf overlays provide customization for the provisioned image.
Overlays may be configured on nodes or profiles, as either **system** or **runtime** overlays.
**System overlays** are applied only once, when a node is first provisioned.
**Runtime overlays** are applied when a node is first provisioned and periodically during the runtime of the node. (The default period is 1 minute.)
Profile
Warewulf profiles are abstract nodes that carry the same configuration attributes but do not provision any specific node.
Warewulf nodes may then refer to one or more such profiles for their configuration.
In this way, profiles provide a simple mechanism for applying configuration to a group of nodes,
and this configuration may be mixed with configuration from other profiles.
wwctl
The main administrative interface for Warewulf is the ``wwctl`` command, which provides commands to manage nodes, profiles, images, overlays, kernels, and more.
wwinit
Warewulf performs some setup during the provisioning process before control is passed to the provisioned operating system.
This process is referred to as "wwinit," and is implemented and configured by a script and overlay of the same name.
wwclient
Warewulf adds a ``wwclient`` daemon to provisioned nodes.
This daemon is responsible for periodically fetching and applying runtime overlays.

View File

@@ -1,473 +0,0 @@
================
Image Management
================
Since the inception of Warewulf over 20 years ago, Warewulf has used
the model of the "Virtual Node File System" (VNFS) as a template image
for the compute nodes. This is similar to a golden master image,
except that the node file system exists within a directory on the
Warewulf control node (e.g. a ``chroot()``).
Meanwhile, the enterprise has created
a lot of tooling and standards around defining, building,
distributing, securing, and managing containers, so Warewulf v4 now
integrates directly within the container ecosystem to facilitate the
process of image management.
If you are not currently leveraging the container ecosystem in any
other way, you can still build your own chroot directories and use
Warewulf as before.
It is important to understand that Warewulf is not running a container
runtime on cluster nodes. While it is absolutely possible to run
containers on cluster nodes, Warewulf is provisioning the
image to the bare metal and booting it. This image will be used as
the base operating system and, by default, it will run entirely in
memory. This means that when you reboot the node, the node retains no
information about Warewulf or how it booted.
Tools
=====
There are different container managment tools available. Docker is
probably the most recognizable one in the enterprise. Podman is
another one that is gaining traction on the RHEL platforms. In HPC,
Apptainer is the most utilized container management tool. You can use
any of these to create and manage the images to be later imported
into Warewulf.
Structure
=========
A Warewulf image is a directory that populates the 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
Warewulf images are built (e.g., with ``wwctl image build``) into compressed images for
distribution to cluster nodes.
.. code-block:: none
/var/lib/warewulf/provision/image
├── rockylinux-9.img
└── rockylinux-9.img.gz
Importing Images
================
Warewulf supports importing an image from any OCI compliant
registry. This means you can import from a public registry or from a
private registry.
Here is an example of importing from Docker Hub.
.. code-block:: console
# wwctl image import docker://ghcr.io/warewulf/warewulf-rockylinux:8 rocky-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: rocky-8
.. note::
Most images in Docker Hub are not "bootable", in that, they
have a limited version of Systemd to make them lighter weight for
image purposes. For this reason, don't expect any base Docker
image (e.g. ``docker://rockylinux`` or ``docker://debian``) to
boot properly. They will not, as they will get stuck into a single
user mode. The images in `https://github.com/warewulf/warewulf-node-images
<https://github.com/warewulf/warewulf-node-images>`_ are not limited and thus
they boot as you would expect.
Platform
--------
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.
Private Registry
----------------
It is possible to use a private registry that is password protected or
does not have the requirement for TLS. In order to do so, you have two
choices for handling the credentials.
* Set environmental variables
* Use ``docker login`` or ``podman login`` which will store the
credentials locally
Please note, there is no requirement to install and use docker or
podman on your control node just for importing images into Warewulf.
Here are the environmental variables that can be used.
.. 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
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 Files
-----------
It is also possible to import an image from a local file or
directory. For example, Podman can save a `.tar` archive of an OCI
image. This archive can be directly imported into Warewulf, no
registry required.
.. code-block:: console
# podman save alpine:latest >alpine.tar
# wwctl image import alpine.tar alpine
Chroot directories and Apptainer sandbox images can also be imported
directly.
.. code-block:: console
$ apptainer build --sandbox ./rockylinux-8/ docker://ghcr.io/warewulf/warewulf-rockylinux:8
$ sudo wwctl image import ./rockylinux-8/ rockylinux-8
HTTP proxies
------------
You can 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.
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). Some system services (notably "munge") require a user to have
the same UID across all nodes.
With the addition of 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
print out 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.
Listing All Imported Images
===========================
Once the image has been imported, you can list them all with the
following command:
.. code-block:: console
# wwctl image list
IMAGE NAME
----------
rocky-8
Once an image has been imported and showing up in this list you can
configure it to boot compute nodes.
Making Changes To Images
========================
You can run commands inside of any of the images and make changes to
them as follows:
.. code-block:: console
# wwctl image exec rocky-8 /bin/sh
[rocky-8] Warewulf> cat /etc/rocky-release
Rocky Linux release 8.4 (Green Obsidian)
[rocky-8] Warewulf> exit
Rebuilding image...
[INFO] Skipping (image is current)
You can also ``--bind`` directories from your host into the image
when using the exec command. This works as follows:
.. code-block:: console
# wwctl image shell --bind /tmp:/mnt rocky-8
[rocky-8] Warewulf>
.. 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 which should always be present in an image like ``resolv.conf``
can be specified in ``warewulf.conf``:
.. 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::
# wwctl image shell rockylinux-9
[warewulf:rockylinux-9] /#
# env WW_PS1="\u@\h:\w\$ " wwctl image shell rockylinux-9
[warewulf:rockylinux-9] root@rocky:/$
Shell history
-------------
By default, Warewulf image shell sessions don't retain history; but you can
specify a history file by specifing ``WW_HISTFILE``. Note that this file is
stored within the image; you may want to exclude it when the image is built.
(See :ref:`exclude`.)
.. _exclude:
Excluding Files from an Image
-----------------------------
Warewulf can exclude files from an image source 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>`_.
Preparing an image for build
----------------------------
Warewulf executes the script ``/etc/warewulf/image_exit.sh`` 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.
Creating Images From Scratch
============================
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
Multi-arch image management
===========================
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
# sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
# sudo podman run --rm --privileged multiarch/qemu-user-static --reset -p yes
# sudo singularity 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.

View File

@@ -1,50 +0,0 @@
=======================
Warewulf Initialization
=======================
System Services
===============
Once Warewulf has been installed and configured, it is ready to be
initialized and have the associated system services started. To do
this, start by configuring the system services that Warewulf depends
on for operation. To do that, run the following command:
.. code-block:: console
# wwctl configure --all
This command will configure the system for Warewulf to run
properly. Here are the things it will do:
* **dhcp**: (re)Write the DHCP configuration and restart the service
from the **host** template under ``/etc/dhcpd.conf.ww`` and enable
the system service.
* **hostfile**: Update the system's /etc/hosts file based on the
**host** template ``/etc/hosts.ww``.
* **nfs**: Configure the NFS server on the control node based on the
configuration in ``/etc/warewulf/warewulf.conf`` and enable the NFS
service. Also the file ``/etc/exports.ww`` from the **host** template is
installed.
* **ssh**: Create the appropriate host keys (stored in
``/etc/warewulf/keys/``) and user keys for passwordless ``ssh`` into
the nodes. Addionally the shell profiles
``/etc/profile.d/ssh_setup.csh`` and ``/etc/profile.d/ssh_setup.sh``
are installed.
* **tftp**: Write the appropriate binary PXE/iPXE blobs to the TFTP
root directory and enable the system service.
This command will quickly setup the system services per the Warewulf
configuration. Watch this output carefully for errors and resolve them
in the configuration portion of this manual.
Warewulf Service
================
The Warewulf installation attempts to register the Warewulf service
with systemd, so it should be as easy to start/stop/check as any other
systemd service:
.. code-block:: console
# systemctl enable --now warewulfd

View File

@@ -1,143 +0,0 @@
=====================
Warewulf Installation
=====================
There are multiple methods to install Warewulf. This page describes
the installation process for some of those methods.
Binary RPMs
===========
The Warewulf project builds binary RPMs as part of its CI/CD
process. You can obtain them from the `GitHub releases`_ page.
.. _GitHub releases: https://github.com/warewulf/warewulf/releases
Rocky Linux 8
-------------
.. code-block:: console
# dnf install https://github.com/warewulf/warewulf/releases/download/v4.6.0rc3/warewulf-4.6.0rc3-1.el8.x86_64.rpm
openSuse Leap
-------------
.. code-block:: console
# zypper install https://github.com/warewulf/warewulf/releases/download/v4.6.0rc3/warewulf-4.6.0rc3-1.suse.lp155.x86_64.rpm
Container images
================
Warewulf is prepared to be built inside and packaged into a Linux container.
This can be especially useful for testing and development or just replace classic package installation.
It is also possible to only use the container for building and the install it in the host system afterwards.
For that look at the INSTALL, UNINSTALL and PURGE labels inside the `Dockerfile`_
.. _Dockerfile: https://github.com/warewulf/warewulf/blob/main/Dockerfile
Docker
------
.. code-block:: console
# docker build -t warewulf .
# docker run -d --replace --name warewulf-test --privileged --net=host -v /:/host -v /etc/warewulf:/etc/warewulf -v /var/lib/warewulf/:/var/lib/warewulf/ -e NAME=warewulf-test -e IMAGE=warewulf warewulf
Systemd-nspawn
--------------
Since Warewulf runs multiple services inside one single container it uses systemd as init system.
Since a full privileged Docker container running a systemd can cause some side effects,
it might be a better option to use `systemd-nspawn`_ in some cases which was explicitly made to run
containers with a full init system.
.. _systemd-nspawn: https://www.freedesktop.org/software/systemd/man/latest/systemd-nspawn.html
.. code-block:: console
# docker build -t warewulf .
# mkdir warewulf-nspawn
# docker export "$(docker create --name warewulf-test warewulf true)" | tar -x -C warewulf-nspawn
# systemd-nspawn -D warewulf-nspawn/ passwd
# systemd-nspawn -D warewulf-nspawn/ --boot
Compiled Source code
====================
Before you build the Warewulf source code you will first need to
install the build dependencies:
* ``make``: This should be available via your Linux distribution's
package manager (e.g. ``dnf install make``)
* ``go``: Golang is also available on most current Linux
distributions, but if you wish to install the most recent version,
you can find that here: `https://golang.org/dl/
<https://golang.org/dl/>`_
* Depending on your Linux Distribution, you may need to install other
development packages. Typically it is recommended to install the
entire development group like ``dnf groupinstall "Development
Tools"``
Once these dependencies are installed, you can obtain and build the
source code as follows:
Release Tarball
---------------
The Warewulf project releases source distributions alongside its
binary RPMs. You can obtain them from the `GitHub releases`_ page.
Select the version you wish to install and download the tarball to any
location on the server, then follow these directions making the
appropriate substitutions:
.. code-block:: bash
curl -LO https://github.com/warewulf/warewulf/releases/download/v4.6.0rc3/warewulf-4.6.0rc3.tar.gz
tar -xf warewulf-4.6.0rc3.tar.gz
cd warewulf-4.6.0rc3
make all && sudo make install
Git
---
Warewulf is developed in GitHub, a source code management platform
that allows collaborative development and revision control. From the
Git repository, you can download different versions of the project
either from tags or branches. By default, when you go to the GitHub
page, you will find the default branch entitled ``main``. The
``main`` branch is where most of the active development occurs,
so if you want to obtain the latest and greatest version of Warewulf,
this is where to go. But be forewarned, using a snapshot from
``main`` is not guaranteed to be stable or generally supported
for production.
If you are building for production, it is best to download a release
tarball from the main site, the GitHub releases page, or from a Git
tag.
.. code-block:: bash
git clone https://github.com/warewulf/warewulf.git
cd warewulf
git checkout main # or switch to a tag like 'v4.6.0rc3'
make all && sudo make install
Runtime Dependencies
--------------------
In Warewulf's default configuration, it will require some operating
system provided services. Generally these are provided by your
installation vendor and can be installed over the network.
These are the services you will need to install:
* ``dhcp-server``
* ``tftp-server``
* ``nfs-utils``
If you are using an Enterprise Linux compatible distribution you can
install them with ``yum install dhcp-server tftp-server nfs-utils``.

View File

@@ -1,74 +0,0 @@
============
Introduction
============
The Warewulf Vision
===================
Warewulf has had a number of iterations over the last 20 years, but
its design tenets have always remained the same: a simple, scalable,
stateless (however some versions were able to provision stateful), and
very flexible operating system provisioning system for all types of
clusters. This is an overview of how Warewulf works.
About Warewulf
==============
Warewulf is an operating system provisioning platform for Linux that
is designed to produce secure, scalable, turnkey cluster deployments
that maintain flexibility and simplicity.
Since its initial release in 2001, Warewulf has become the most
popular open source and vendor-agnostic provisioning system within the
global HPC community. Warewulf is known for its massive scalability
and simple management of stateless (disk optional) provisioning.
Warewulf leverages a simple administrative model centralizing
administration around virtual node images which are used to provision
out to the cluster nodes. This means you can have hundreds or
thousands of cluster nodes all booting and running on the same,
identical virtual node file system image. As of Warewulf v4, the
virtual node image can be managed using any existing
container tooling and/or CI pipelines that are being used. This can be
as simple as DockerHub or your own private GitLab CI infrastructure.
With this architecture, Warewulf combines the best of High Performance
Computing (HPC), Cloud, Hyperscale, and Enterprise deployment
principals to create and maintain large scalable stateless clusters.
While Warewulf's roots are in HPC, it has been used for many different
types of tasks and use cases. Everything from clustered web servers,
to rendering farms, and even Kubernetes and cloud deployments,
Warewulf brings benefit in experience of general operating system
management at scale.
Features
========
* **Lightweight**: Warewulf provisions stateless operating system
images and then gets out of the way. There should be no underlying
system dependencies or changes to the provisioned cluster node
operating systems.
* **Simple**: Warewulf is used by hobbyists, researchers, scientists,
engineers and systems administrators because it is easy,
lightweight, and simple.
* **Flexible**: Warewulf is highly flexible and can address the needs
of any environment-- from a computer lab with graphical
workstations, to under-the-desk clusters, to massive supercomputing
centers providing traditional HPC capabilities to thousands of
users.
* **Agnostic**: From the Linux distribution of choice to the
underlying hardware, Warewulf is agnostic and standards
compliant. From ARM to x86, Atos to Dell, Debian, SUSE, Rocky,
CentOS, and RHEL, Warewulf can do it all.
* **Secure**: Warewulf is the only stateless provisioning system that
will support SELinux out of the box. Just enable your node image to
support SELinux, and let Warewulf do the rest!
* **Open Source**: For the last 20 years, Warewulf has remained open
source and continues to be the golden standard for cluster
provisioning.

View File

@@ -1,261 +0,0 @@
====
IPMI
====
It is possible to control the power or connect a console to your nodes
being managed by Warewulf by connecting to the BMC through the use of
`ipmitool`. Other methods can also configured, but require additional
configuration.
We will discuss how to set this up below.
IPMI Settings
=============
The common settings for the IPMI interfaces on all nodes can be set on
a Profile level. The only field that would need to be assigned to each
individual node would be the IP address.
The settings are only written to the IPMI interface if ``--ipmiwrite``
is set to `true`. The write process happens at every boot of the node
through the script ``/warewulf/init.d/50-ipmi`` in the **system**
overlay and are done with `ipmitool`.
If an individual node has different settings, you can set the IPMI
settings for that specific node, overriding the default settings.
Here is a table outlining the fields on a Profile and Node which is
the same as the parameter that can be used when running ``wwctl
profile set`` or ``wwctl node set``.
+---------------------+---------+------+--------------------+---------------+
| Parameter | Profile | Node | Valid Values | Default Value |
+=====================+=========+======+====================+===============+
| ``--ipmiaddr`` | false | true | | |
+---------------------+---------+------+--------------------+---------------+
| ``--ipminetmask`` | true | true | | |
+---------------------+---------+------+--------------------+---------------+
| ``--ipmiport`` | true | true | | 623 |
+---------------------+---------+------+--------------------+---------------+
| ``--ipmigateway`` | true | true | | |
+---------------------+---------+------+--------------------+---------------+
| ``--ipmiuser`` | true | true | | |
+---------------------+---------+------+--------------------+---------------+
| ``--ipmipass`` | true | true | | |
+---------------------+---------+------+--------------------+---------------+
| ``--ipmiinterface`` | true | true | 'lan' or 'lanplus' | lan |
+---------------------+---------+------+--------------------+---------------+
| ``--ipmiwrite`` | true | true | true or false | false |
+---------------------+---------+------+--------------------+---------------+
| ``--ipmiescapechar``| true | true | single character | ~ |
+---------------------+---------+------+--------------------+---------------+
| ``--ipmitemplate`` | true | true | path to template | |
+---------------------+---------+------+--------------------+---------------+
Reviewing Settings
==================
There are multiple ways to review the IPMI settings. They can be
reviewed from a Profile level, all the way down to a specific Node.
Profile View
------------
.. code-block:: console
# wwctl profile list -a
PROFILE FIELD PROFILE VALUE
=====================================================================================
default Id -- default
default comment -- This profile is automatically included for each node
default cluster -- --
default image -- sle-micro-5.3
default ipxe -- --
default runtime -- --
default wwinit -- --
default root -- --
default discoverable -- --
default init -- --
default asset -- --
default profile -- --
default default:type -- --
default default:onboot -- --
default default:netdev -- --
default default:hwaddr -- --
default default:ipaddr -- --
default default:ipaddr6 -- --
default default:netmask -- --
default default:gateway -- --
default default:mtu -- --
default default:primary -- --
Node View
---------
.. code-block:: console
# wwctl node list -a n001
NODE FIELD PROFILE VALUE
=====================================================================================
n001 Id -- n001
n001 comment default This profile is automatically included for each node
n001 cluster -- --
n001 image default sle-micro-5.3
n001 ipxe -- (default)
n001 runtime -- (hosts,ssh.authorized_keys)
n001 wwinit -- (wwinit,wwclient,fstab,hostname,ssh.host_keys,issue,resolv,udev.netname,systemd.netname,ifcfg,NetworkManager,debian.interfaces,wicked,ignition)
n001 root -- (initramfs)
n001 discoverable -- --
n001 init -- (/sbin/init)
n001 asset -- --
n001 kernelargs -- (quiet crashkernel=no net.ifnames=1)
n001 ipmiaddr -- --
n001 ipminetmask -- --
n001 ipmiport -- --
n001 ipmigateway -- --
n001 ipmiuser -- --
n001 ipmipass -- --
n001 ipmiinterface -- --
n001 ipmiwrite -- --
n001 ipmiescapechar -- --
n001 profile -- default
n001 default:type -- (ethernet)
n001 default:onboot -- --
n001 default:netdev -- eth0
n001 default:hwaddr -- 11:22:33:44:55:66
n001 default:ipaddr -- 10.0.2.1
n001 default:ipaddr6 -- --
n001 default:netmask -- 255.255.252.0
n001 default:gateway -- --
n001 default:mtu -- --
n001 default:primary -- true
Review Only IPMI Settings
-------------------------
The above views show you everything that is set on a Profile or Node
level. That is a lot of detail. If you want to view key IPMI connecton
details for a node or all nodes, you can do the following.
.. code-block:: console
# wwctl node list -i
NODE NAME IPMI IPADDR IPMI PORT IPMI USERNAME IPMI INTERFACE
==================================================================================================
n001 192.168.1.11 -- hwadmin --
n002 192.168.1.12 -- hwadmin --
n003 192.168.1.13 -- hwadmin --
n004 192.168.1.14 -- hwadmin --
Power Commands
==============
The ``power`` command can be used to manage the current power state of
your nodes through IPMI.
``wwctl power [command]`` where ``[command]`` is one of:
cycle
Turns the power off and then on
off
Turns the power off
on
Turns the power on
reset
Issues a reset
soft
Shutdown gracefully
status
Shows current power status
Console
=======
If your node is setup to use serial over lan (SOL), Warewulf can
connect a console to the node.
.. code-block:: console
# wwctl node console n001
Ipmi template
=============
As warewulf doesn't manage the ipmi/bmc interfaces directly, but calls ``ipmitool``
this managed with a template which defines the behavior. For ``ipmitool`` following
template is used
.. code-block::
{{/* used command to access the ipmi interface of the nodes */}}
{{- $escapechar := "~" }}
{{- $port := "623" }}
{{- $interface := "lan" }}
{{- $args := "" }}
{{- if .EscapeChar }} $escapechar = .EscapeChar {{ end }}
{{- if .Port }} {{ $port = .Port }} {{ end }}
{{- if .Interface }} {{ $interface = .Interface }} {{ end }}
{{- if eq .Cmd "PowerOn" }} {{ $args = "chassis power on" }} {{ end }}
{{- if eq .Cmd "PowerOff" }} {{ $args = "chassis power off" }} {{ end }}
{{- if eq .Cmd "PowerCycle" }} {{ $args = "chassis power cycle" }} {{ end }}
{{- if eq .Cmd "PowerReset" }} {{ $args = "chassis power reset" }} {{ end }}
{{- if eq .Cmd "PowerSoft" }} {{ $args = "chassis power soft" }} {{ end }}
{{- if eq .Cmd "PowerStatus" }} {{ $args = "chassis power status" }} {{ end }}
{{- if eq .Cmd "SDRList" }} {{ $args = "sdr list" }} {{ end }}
{{- if eq .Cmd "SensorList" }} {{ $args = "sensor list" }} {{ end }}
{{- if eq .Cmd "Console" }} {{ $args = "sol activate" }} {{ end }}
{{- $cmd := printf "ipmitool -I %s -H %s -p %s -U %s -P %s -e %s %s" $interface .Ipaddr $port .UserName .Password $escapechar $args }}
{{ $cmd }}
In order to use another template, its filename must be specified for a node or profile via the
``--ipmitemplate`` switch and the template must placed under ``/usr/lib/warewulf/bmc`` or to the
path which is was defined as ``datadir`` in ``warwulf.conf`` or during compile time.
All IPMI specific variables are accessible in the template which are the following
+---------------------+--------------------+
| Parameter | Template variable |
+=====================+====================+
| ``--ipmiaddr`` | ``.Ipaddr`` |
+---------------------+--------------------+
| ``--ipminetmask`` | ``.Netmask`` |
+---------------------+--------------------+
| ``--ipmiport`` | ``.Port`` |
+---------------------+--------------------+
| ``--ipmigateway`` | ``.Gateway`` |
+---------------------+--------------------+
| ``--ipmiuser`` | ``.UserName`` |
+---------------------+--------------------+
| ``--ipmipass`` | ``.Password`` |
+---------------------+--------------------+
| ``--ipmiinterface`` | ``.Interface`` |
+---------------------+--------------------+
| ``--ipmiwrite`` | ``.Write`` |
+---------------------+--------------------+
| ``--ipmiescapechar``| ``.EscapeChar`` |
+---------------------+--------------------+
| ``--ipmitemplate`` | ``.Template`` |
+---------------------+--------------------+
Additional the ``.Args`` variable is accessible which can have following
values:
* `PowerOn`
* `PowerOff`
* `PowerCycle`
* `PowerReset`
* `PowerSoft`
* `PowerStatus`
* `SDRList`
* `SensorList`
* `Console`
which are the calls done by `wwctl power` commands.
Also the script ``/warewulf/init.d/50-ipmi`` in the **system**
overlay may need an update. There the variables must have the prefix ``.Ipmi``

View File

@@ -1,98 +0,0 @@
============
Known issues
============
SELinux and IPMI write not working when using two-stage boot
============================================================
The dracut implementation of two-stage boot in versions of Warewulf prior to v4.6.0 bypasses the
``wwinit`` process by default, invoking the image's init system directly. While cluster nodes will
often still boot mostly successfully this way, features implemented by wwinit will not complete. In
particular, SELinux relabeling and IPMI write are not executed.
To ensure that dracut runs the full ``wwinit`` process, pass ``init=/init`` or
``init=/warewulf/wwinit`` on the kernel command line.
.. code-block:: bash
# wwctl profile set default --kernelargs="init=/init"
Images are read-only
====================
Warewulf v4.5 uses the permissions on an image's ``rootfs/`` to determine a "read-only" state of
the image: if the root directory of the image is ``u-w``, it will be mounted read-only
during ``wwctl image <exec|shell``, preventing interactive changes to the image.
In the past, the root directory was ``u+w``, but Enterprise Linux 9.5 (including Red Hat, Rocky, _et
al._) includes an update to the ``filesystem`` package that marks the root directory ``u-w``. This
causes Warewulf images to be "read only" by default.
To mark a Warewulf image as writeable, use `chmod u+w`.
.. code-block:: bash
# chmod u+w $(wwctl image show rockylinux-9.5)
This behavior is changed in v4.6 to use an explicit ``readonly`` file stored outside of ``rootfs/``.
Image sockets cause build failures
==================================
If an image source directory includes persistent sockets, these sockets may cause the import operation to fail.
.. code-block:: console
Copying sources...
ERROR : could not import image: lchown ./rockylinux-8/run/user/0/gnupg/d.kg8ijih5tq41ixoeag4p1qup/S.gpg-agent: no such file or directory
To resolve this, remove the sockets from the source directory.
.. code-block:: bash
find ./rockylinux-8/ -type s -delete
This issue was fixed in an upstream library and `should be resolved in Warewulf
v4.6.0. <https://github.com/warewulf/warewulf/issues/892>`_
Image Size Considerations
=========================
Node images can grow quickly as packages and other files are added
to them. Even these larger images are often not an issue in modern
environments; but some architectural limits exist that can impede the
use of images larger than a few gigabytes. Workarounds exist for these
issues in most circumstances:
* Warewulf's :ref:`two-stage boot support <booting with dracut>` effectively
eliminates this problem by handling the bulk of the image management within
Linux. This feature is currently in preview, and is subject to change; but it
is likely to become the default boot method in a future release.
* Systems booting in legacy / BIOS mode, being a 32-bit environment,
cannot boot an image that requires more than 4GB to decompress. This
means that the compressed image and the decompressed image together
must be < 4GB. This is typically reported by the system as "No space
left on device (https://ipxe.org/34182006)."
The best work-around for this limitation is to switch to UEFI. UEFI
is 64-bit and should support booting significantly larger images,
though sometimes system-specific implementation details have led to
artificial limitations on image size.
* The Linux kernel itself can only decompress an image up to 4GB due
to the use of 32-bit integers in critical sections of the kernel
initrd decompression code.
The best work-around for this limitation is to use an iPXE with
support for `imgextract <https://ipxe.org/cmd/imgextract>`_. This
allows iPXE to decompress the image rather than the kernel.
* Some BIOS / firmware retain a "memory hole" feature for legacy
devices, e.g., reserving a 1MB block of memory at the 15MB-16MB
address range. this feature can interfere with booting stateless
node images.
If you are still getting "Not enough memory" or "No space left on
device" errors, try disabling any "memory hole" features or updating
your system BIOS or firmware.

View File

@@ -1,351 +0,0 @@
==================
Node Configuration
==================
The Node Configuration DB
=========================
As mentioned in the :doc:`Warewulf Configuration <configuration>`
section, node configs are persisted to the ``nodes.conf`` YAML file,
but generally it is best not to edit this file directly (however that
is supported, it is just prone to errors).
This method of using a YAML configuration file as a backend datastore
is both scalable and very lightweight. We've tested this out to over
10,000 node entries which yielded update latencies under 1 second,
which we felt was both tolerable and advantageous.
Adding a New Node
=================
Creating a new node is as simple as running the following command:
.. code-block:: console
# wwctl node add n001 -I 10.0.2.1
Added node: n001
Adding several nodes
--------------------
Several nodes can be added with a single command if a node range is
given. An additional IP address will incremented. So the command
.. code-block:: console
# wwctl node add n00[2-4] -I 10.0.2.2
Added node: n002
Added node: n003
Added node: n004
# wwctl node list -n n00[1-4]
NODE NAME NAME HWADDR IPADDR GATEWAY DEVICE
n001 default -- 10.0.2.1 -- (eth0)
n002 default -- 10.0.2.2 -- (eth0)
n003 default -- 10.0.2.3 -- (eth0)
n004 default -- 10.0.2.4 -- (eth0)
has added 4 nodes with the incremented IP addresses.
Node Names
----------
For small clusters, you can use simple names (e.g. ``n0000``); but for
larger, more complicated clusters that are comprised of multiple
clusters and roles it is highly recommended to use node names that
include a cluster descriptor. In Warewulf, this is generally done by
using a domain name (e.g. ``n001.cluster01``). Warewulf will
automatically assume that the domain is the equivalent of the cluster
name.
This also means that you can address groups of nodes by the cluster
descriptor with globs. For example, you are able to refer to all nodes
in "cluster01" with the following string: ``*.cluster01`` which is
valuable for other ``wwctl`` commands.
Listing Nodes
=============
Once you have configured one or more nodes, you can list them and
their attributes as follows:
.. code-block:: console
# wwctl node list
NODE NAME PROFILES NETWORK
n001 default
You can also see the node's full attribute list by specifying the
``-a`` option (all):
.. code-block:: console
# wwctl node list -a n001
NODE FIELD PROFILE VALUE
n001 Id -- n001
n001 comment default This profile is automatically included for each node
n001 cluster -- --
n001 image default sle-micro-5.3
n001 ipxe -- (default)
n001 runtime -- (hosts,ssh.authorized_keys)
n001 wwinit -- (wwinit,wwclient,fstab,hostname,ssh.host_keys,issue,resolv,udev.netname,systemd.netname,ifcfg,NetworkManager,debian.interfaces,wicked,ignition)
n001 root -- (initramfs)
n001 discoverable -- --
n001 init -- (/sbin/init)
n001 asset -- --
n001 kernelargs -- (quiet crashkernel=no net.ifnames=1)
n001 ipmiaddr -- --
n001 ipminetmask -- --
n001 ipmiport -- --
n001 ipmigateway -- --
n001 ipmiuser -- --
n001 ipmipass -- --
n001 ipmiinterface -- --
n001 ipmiwrite -- --
n001 profile -- default
n001 default:type -- (ethernet)
n001 default:onboot -- --
n001 default:netdev -- (eth0)
n001 default:hwaddr -- --
n001 default:ipaddr -- 172.16.1.11
n001 default:ipaddr6 -- --
n001 default:netmask -- (255.255.255.0)
n001 default:gateway -- --
n001 default:mtu -- --
n001 default:primary -- true
.. note::
The attribute values in parenthesis are default values and can be
overridden in the next section, granted, the default values are
generally usable.
Setting Node Attributes
=======================
Node configurations are set using the ``wwctl node set`` command. To
see a list of all configuration attributes, use the command ``wwctl
node set --help``.
Configuring the Node's Image
----------------------------
.. code-block:: console
# wwctl node set --image rocky-8 n001
Are you sure you want to modify 1 nodes(s): y
And you can check that the image name is set for ``n001``:
.. code-block:: console
# wwctl node list -a n001 | grep Image
n0000 Image -- rocky-8
Configuring the Node's Network
------------------------------
To configure the network, we have to pick a network device name and
provide the network information as follows:
.. code-block:: console
# wwctl node set --netdev eno1 --hwaddr 11:22:33:44:55:66 --ipaddr 10.0.2.1 --netmask 255.255.252.0 n001
Are you sure you want to modify 1 nodes(s): y
You can now see that the node contains configuration attributes for
image and network:
.. code-block:: console
# wwctl node list -a n001
NODE FIELD PROFILE VALUE
n001 Id -- n001
n001 comment default This profile is automatically included for each node
n001 cluster -- --
n001 image default sle-micro-5.3
n001 ipxe -- (default)
n001 runtime -- (hosts,ssh.authorized_keys)
n001 wwinit -- (wwinit,wwclient,fstab,hostname,ssh.host_keys,issue,resolv,udev.netname,systemd.netname,ifcfg,NetworkManager,debian.interfaces,wicked,ignition)
n001 root -- (initramfs)
n001 discoverable -- --
n001 init -- (/sbin/init)
n001 asset -- --
n001 kernelargs -- (quiet crashkernel=no net.ifnames=1)
n001 ipmiaddr -- --
n001 ipminetmask -- --
n001 ipmiport -- --
n001 ipmigateway -- --
n001 ipmiuser -- --
n001 ipmipass -- --
n001 ipmiinterface -- --
n001 ipmiwrite -- --
n001 profile -- default
n001 default:type -- (ethernet)
n001 default:onboot -- --
n001 default:netdev -- eno1
n001 default:hwaddr -- 11:22:33:44:55:66
n001 default:ipaddr -- 10.0.2.1
n001 default:ipaddr6 -- --
n001 default:netmask -- 255.255.252.0
n001 default:gateway -- --
n001 default:mtu -- --
n001 default:primary -- true
# wwctl node set --cluster cluster01 n001
Are you sure you want to modify 1 nodes(s): y
# wwctl node list -a n001 | grep cluster
n001 cluster -- cluster01
.. note::
Due to the way network interface names are assigned by the Linux kernel and overwritten by udev
and systemd in the default warewulf configuration, the use of `eth0/1/...` as interface names can lead to issues.
We recommend the use of the original predictable names assigned to the interfaces (`eno1, ...`),
as otherwise an interface may remain unconfigured if its name conflicts with the name of an already existing interface during boot.
Additional networks
-------------------
Additional networks for the node can also be configured.
You will have provide all the necessary network information.
.. code-block:: shell
wwctl node set \
--netdev ib0 \
--hwaddr aa:bb:cc:dd:ee:ff \
--ipaddr 10.0.20.1 \
--netmask 255.255.252.0 \
--netname iband \
--type infiniband \
n001
Bonding
-------
Support for bonded / link aggregation network interfaces depends on the network overlay being used.
The ``ifcfg`` and ``NetworkManager`` overlays can configure a network bond like this:
.. code-block:: yaml
network devices:
bond0:
type: Bond
device: bond0
ipaddr: 192.168.3.100
netmask: 255.255.255.0
en1:
device: en1
hwaddr: e6:92:39:49:7b:03
tags:
master: bond0
en2:
device: en2
hwaddr: 9a:77:29:73:14:f1
tags:
master: bond0
VLAN
----
You can set the type also to ``vlan``.
Some network configuration systems use the network device name
(e.g., of the form ``eno1.100``)
to configure VLANs.
Other network systems need additional network tags:
- ``vlan_id``: configures the VLAN ID of the interface
- ``parent_device``: configures which physical interface to use
.. code-block:: shell
wwctl node set \
--netdev vlan42 \
--ipaddr 10.0.42.1 \
--netmask 255.255.252.0 \
--netname iband \
--type vlan \
--nettagadd "vlan_id=42,parent_device=eth0" \
n001
Static Routes
-------------
The included Warewulf network overlays support the configuration of static routes
using a network tag of the form ``route<N>=<dest>,<gateway>``.
.. code-block:: shell
wwctl node set n001 \
--nettagadd "route1=192.168.2.0/24,192.168.1.254"
Node Discovery
--------------
The hwaddr of a node can be automatically discovered by setting
``--discoverable`` on a node. If a node attempts to provision against
Warewulf using an interface that is unknown to Warewulf, that address
is associated with the first discoverable node. (Multiple discoverable
nodes are sorted lexically, first by cluster, then by ID.)
Once a node has been discovered its "discoverable" flag is
automatically cleared.
Setting list values
===================
Some node fields, such as overlays and kernel args, accept a list of values.
These may be specified as a comma-separated list or as multiple arguments.
To include an explicit comma in the value, enclose the value in inner-quotes.
.. code-block:: console
# wwctl profile set default --kernelargs 'quiet,crashkernel=no,nosplash' --kernelargs='"console=ttyS0,115200"'
Un-setting Node Attributes
==========================
If you wish to ``unset`` a particular value, set the value to
``UNDEF``. For example:
And to unset this configuration attribute:
.. code-block:: console
# wwctl node set --cluster UNDEF n001
Are you sure you want to modify 1 nodes(s): y
# wwctl node list -a n001 | grep Cluster
n001 Cluster -- --
Resources
=========
Warewulf nodes (and profiles) support generic "resources" that may hold arbitrarily complex YAML
data. This data, along with tags, may be used by both distribution and site overlays.
.. code-block:: yaml
nodeprofiles:
default:
resources:
fstab:
- spec: warewulf:/home
file: /home
vfstype: nfs
mntops: defaults
freq: 0
passno: 0
- spec: warewulf:/opt
file: /opt
vfstype: nfs
mntops: defaults,ro
freq: 0
passno: 0
Due to the arbitrary nature of generic resource data, it can only be managed with `wwctl
<node|profile> edit`.

View File

@@ -1,507 +0,0 @@
=================
Warewulf Overlays
=================
Warewulf is designed to scalably provision and manage thousands of cluster nodes by utilizing
identical stateless boot images. But if these boot images are completely identical, then how do we
configure things like hostnames? IP addresses? Or any other node-specific configurations?
Some of configuration can be managed by services like DHCP. You can also use traditional
configuration management on a provisioned Warewulf cluster node. But these are heavy-weight
solutions to a simple problem.
Warewulf addresses cluster node configuration with its **overlay** system. Overlays are collections
of files and templates that are rendered and built per-node and then applied over the image
image during the provisioning process.
Structure
=========
An overlay is a directory that is applied to the root of a cluster node's runtime file system. The
overlay source directory should contain a single ``rootfs`` directory which represents the actual
root directory for the overlay.
.. code-block:: none
/usr/share/warewulf/overlays/issue
└── rootfs
└── etc
└── issue.ww
System and runtime overlays
===========================
A node or profile can configure an overlay in two different ways:
* An overlay can be configured to apply only during boot as part of the ``wwinit`` process. These
overlays are called **system overlays**.
* An overlay can be configured to also apply periodically while the system is running. These overlays
are called **runtime overlays**.
Overlays are built (e.g., with ``wwctl overly build``) into compressed overlay images for
distribution to cluster nodes. These images typically match these two use cases: system and
runtime. As such, each cluster node typically has two overlay images.
.. code-block:: none
/var/lib/warewulf/provision/overlays/tn1
├── __RUNTIME__.img
├── __RUNTIME__.img.gz
├── __SYSTEM__.img
└── __SYSTEM__.img.gz
Distribution and site overlays
==============================
Warewulf also distinguishes between **distribution** overlays, which are included with Warewulf, and
**site** overlays, which are created or added locally. A site overlay always takes precedence over a
distribution overlay with the same name. Any modification of a distribution overlay with ``wwctl``
actually makes changes to an automatically-generated **site** overlay cloned from the distribution
overlay.
Site overlays are often stored at ``/var/lib/warewulf/overlays/``. Distribution overlays are often
stored at ``/usr/share/warewulf/overlays/``. But these paths are dependent on compilation,
distribution, packaging, and configuration settings.
Provided distribution overlays
------------------------------
These overlays are provided as part of Warewulf.
wwinit
------
The **wwinit** overlay performs initial configuration of the Warewulf node.
Its `wwinit` script runs before ``systemd`` or other init is called and
contains all configurations which are needed to boot.
In particular:
- Configure the loopback interface
- Configure the BMC based on the node's configuration
- Update PAM configuration to allow missing shadow entries
- Relabel the file system for SELinux
Other overlays may place additional scripts in ``/warewulf/init.d/`` to affect
node configuration in this pre-boot environment.
wwclient
--------
All configured overlays are provisioned initially along with the node image
itself; but **wwclient** periodically fetches and applies the runtime overlay
to allow configuration of some settings without a reboot.
Network interfaces
------------------
Warewulf ships with support for many different network interface configuration
systems. All of these are applied by default; but the list may be trimmed to
the desired system.
- ifcfg
- NetworkManager
- debian.interfaces
- wicked
Warewulf also configures both systemd and udev with the intended names of
configured network interfaces, typically based on a known MAC address.
- systemd.netname
- udev.netname
Several of the network configuration overlays support netdev tags to further
customize the interface:
- **``DNS[0-9]*``:** one or more DNS servers
- **``DNSSEARCH``:** domain search path
- **``MASTER``:** the master for a bond interface
NetworkManager
^^^^^^^^^^^^^^
- **``parent_device``:** the parent device of a vlan interface
- **``vlan_id``:** the vlan id for a vlan interface
- **``downdelay``, ``updelay``, ``miimon``, ``mode``, ``xmit_hash_policy``:**
bond device settings
Basics
------
The **hostname** overlay sets the hostname based on the configured Warewulf
node name.
The **hosts** overlay configures ``/etc/hosts`` to include all Warewulf nodes.
The **issue** overlay configures a standard Warewulf status message for display
during login.
The **resolv** overlay configures ``/etc/resolv.conf`` based on the value of
"DNS" nettags. (In most situations this should be unnecessary, as the network
interface configuration should handle this dynamically.)
fstab
-----
The **fstab** overlay configures ``/etc/fstab`` based on the data provided in the "fstab"
resource. It also creates entries for file systems defined by Ignition.
.. code-block:: yaml
nodeprofiles:
default:
resources:
fstab:
- spec: warewulf:/home
file: /home
vfstype: nfs
- spec: warewulf:/opt
file: /opt
vfstype: nfs
ssh
---
Two SSH overlays configure host keys (one set for all node in the cluster) and
``authorized_keys`` for the root account.
- ssh.authorized_keys
- ssh.host_keys
syncuser
--------
The **syncuser** overlay updates ``/etc/passwd`` and ``/etc/group`` to include
all users on both the Warewulf server and from the image.
To function properly, ``wwctl image syncuser`` (or the ``--syncuser`` option
during ``import``, ``exec``, ``shell``, or ``build``) must have also been run on
the image to synchronize its user and group IDs with those of the server.
If a ``PasswordlessRoot`` tag is set to "true", the overlay will also insert a
"passwordless" root entry. This can be particularly useful for accessing a
cluster node when its network interface is not properly configured.
ignition
--------
The **ignition** overlay defines partitions and file systems on local disks.
debug
-----
The **debug** overlay is not intended to be used in configuration, but is
provided as an example. In particular, the provided `tstruct.md.ww` demonstrates
the use of most available template metadata.
.. code-block:: console
# wwctl overlay show --render <nodename> debug tstruct.md.ww
host
----
Configuration files used for the configuration of the Warewulf host /
server are stored in the **host** overlay. Unlike other overlays, it
*must* have the name ``host``. Existing files on the host are copied
to backup files with a ``wwbackup`` suffix at the first
run. (Subsequent use of the host overlay won't overwrite existing
``wwbackup`` files.)
The following services get configuration files via the host overlay:
* ssh keys are created with the scrips ``ssh_setup.sh`` and
``ssh_setup.csh``
* hosts entries are created by manipulating ``/etc/hosts`` with the
template ``hosts.ww``
* nfs kernel server receives its exports from the template
``exports.ww``
* the dhcpd service is configured with ``dhcpd.conf.ww``
Combining and overriding overlays
=================================
Multiple overlays can be applied to a single node, and overlays from multiple profiles are appended
together. The configuration fields for the system and runtime overlays are lists and can contain
several overlays. As an example for this, we will overwrite the ``/etc/issue`` file from the "issue"
overlay. For this we will create a new overlay called "welcome" and import the file ``/etc/issue``
from the host to it. This overlay is then combined with the existing overlays.
.. code-block:: console
# wwctl overlay create welcome
# wwctl overlay mkdir welcome /etc
# wwctl overlay import welcome /etc/issue
# wwctl profile set default --system-overlay=wwinit,wwclient,welcome
? Are you sure you want to modify 1 profile(s)? [y/N] y
# wwctl profile list default -a |grep welcome
default SystemOverlay wwinit,wwclient,welcome
Templates
=========
Templates allow you to create dynamic content such that the files
downloaded for each node will be customized for that node. Templates
allow you to insert everything from variables, to including files from
the control node, as well as conditional content and loops.
Warewulf uses the ``text/template`` engine to facilitate implementing dynamic
content in a simple and standardized manner. This template format is documented
at https://pkg.go.dev/text/template.
All template files will end with the suffix of ``.ww``. That tells
Warewulf that when building a file, that it should parse that file as
a template. When it does that, the resulting file is static and can
have node customizations that are obtained from the node configuration
attributes.
.. note::
When the file is persisted within the built overlay, the ``.ww``
will be dropped, so ``/etc/hosts.ww`` will end up being
``/etc/hosts``.
Template functions
==================
Warewulf templates have access to a number of functions.
In addition to the custom functions below, the `sprig functions`_ are also
available.
.. _sprig functions: https://masterminds.github.io/sprig/
Include
-------
Reads content from the given file into the template. If the file does not begin
with ``/`` it is considered relative to ``Paths.Sysconfdir``.
.. code-block:: plaintext
{{ Include "/root/.ssh/authorized_keys" }}
IncludeFrom
-----------
Reads content from the given file from the given image into the template.
.. code-block:: plaintext
{{ IncludeFrom $.ImageName "/etc/passwd" }}
IncludeBlock
------------
Reads content from the given file into the template, stopping when the provided
abort string is found.
.. code-block:: plaintext
{{ IncludeBlock "/etc/hosts" "# Do not edit after this line" }}
ImportLink
----------
Causes the processed template file to becoma a symlink to the same target as the
referenced symlink.
.. code-block:: plaintext
{{ ImportLink "/etc/localtime" }}
basename
--------
Returns the base name of the given path.
.. code-block:: plaintext
{{- range $type, $name := $.Tftp.IpxeBinaries }}
if option architecture-type = {{ $type }} {
filename "/warewulf/{{ basename $name }}";
}
{{- end }}
file
----
Write the content from the template to the specified file name. May be specified
more than once in a template to write content to multiple files.
.. code-block:: plaintext
{{- range $devname, $netdev := .NetDevs }}
{{- $filename := print "ifcfg-" $devname ".conf" }}
{{ file $filename }}
{{/* content here */}}
{{- end }}
softlink
--------
Causes the processed template file to become a symlink to the referenced target.
.. code-block:: plaintext
{{ printf "%s/%s" "/usr/share/zoneinfo" .Tags.localtime | softlink }}
readlink
--------
Equivalent to ``filepath.EvalSymlinks``. Returns the target path of a named
symlink.
.. code-block:: plaintext
{{ readlink /etc/localtime }}
IgnitionJson
------------
Generates JSON suitable for use by Ignition to create
abort
-----
Immediately aborts processing the template and does not write a file.
.. code-block::
{{ abort }}
nobackup
--------
Disables the creation of a backup file when replacing files with the current
template.
.. code-block::
{{ nobackup }}
Managing overlays
=================
Warewulf includes a command group for manipulating overlays (``wwctl
overlay``). With this you can add, edit, remove, change ownership,
permissions, etc.
..
note::
It is not possible to delete files with an overlay.
Build
-----
.. code-block:: console
wwctl overlay build [-H,--hosts|-N,--nodes|-o,--output directory|-O,--overlay-name] nodepattern
Without any arguments the command will interpret the templates for all
overlays for every compute node and also all the templates in the host
overlay. For every overlay of the compute nodes a gzip compressed cpio
archive is created. The range of the nodes can be restricted as the
last argument. With the ``-H`` flag only the host overlay is
built. With the ``-N`` flag only compute node overlays are
built. Specific overlays can be selected with ``-O`` flag. For
debugging purposes the templates can be written to a directory given
via the ``-o`` flag.
Overlay images for multiple node are built in parallel. By default, each CPU in
the Warewulf server will build overlays independently. The number of workers
can be specified with the ``--workers`` option.
Warewulf will attempt to build/update overlays as needed
(configurable in the ``warewulf.conf``); but not all cases are detected,
and manual overlay builds are often necessary.
Chmod
-----
.. code-block:: console
wwctl overlay chmod overlay-name filename mode
This subcommand changes the permissions of a single file within an
overlay. You can use any mode format supported by the chmod command.
Chown
-----
.. code-block:: console
wwctl overlay chown overlay-name filename UID [GID]
With this command you can change the ownership of a file within a
given overlay to the user specified by UID. Optionally, it will also
change group ownership to GID.
Create
------
.. code-block:: console
wwctl overlay create overlay-name
This command creates a new empty overlay with the given name.
Delete
------
.. code-block:: console
wwctl overlay delete [-f,--force] overlay-name [File [File ...]]
Either the given overlay is deleted (must be empty or use the
``--force`` flag) or the specified file within the overlay is
deleted. With the ``--parents`` flag the directory of the deleted file
is also removed if no other file is in the directory.
Edit
----
.. code-block:: console
wwctl overlay edit [--mode,-m MODE|--parents,-p] overlay-name file
Use this command to edit an existing or a new file in the given
overlay. If a the new file ends with a ``.ww`` suffix an example
template header is added to the file. With the ``--parents`` flag
necessary parent directories for a new file are created.
Import
------
.. code-block:: console
wwctl overlay import [--mode,-m|--noupdate,-n] overlay-name file-name [new-file-name]
The given file is imported to the overlay. If no new-file-name is
given, the file will be placed in the overlay at the same path as on
the host. With the ``--noupdate`` flag you can block the rebuild of
the overlays.
List
----
.. code-block:: console
wwctl overlay list [--all,-a|--long,-l] [overlay-name]
With this command all existing overlays and files in them can be
listed. Without any option only the overlay names and their number of
files are listed. With the ``--all`` switch also the every file is
shown. The ``--long`` option will also display the permissions, UID,
and GID of each file.
Show
----
.. code-block:: console
wwctl overlay show [--quiet,-q|--render,-r nodename] overlay-name file
The content of the file for the given overlay is displayed with this
command. With the ``--render`` option a template is rendered as it
will be rendered for the given node. The node name is a mandatory
argument to the ``--render`` flag. Additional information for the file
can be suppressed with the ``--quiet`` option.

View File

@@ -1,205 +0,0 @@
=============
Node Profiles
=============
Profiles provide a way to scalably group node configurations
together. Instead of redundant configurations for each node, you can
put that into a profile and the nodes will inherit these
configurations. This is very handy if you have groups of node specific
customizations. For example, a few hundred nodes that are running a
particular image or kernel, and another group of nodes that are
running a different kernel or image.
Profiles may, themselves, reference other profiles, supporting complex
mixtures of profile configuration and negation.
Any node configuration attributes can be applied to a profile, but
there are always going to be some node configurations which must be
specific to a node, like a network HW/MAC address or an IP address.
An Introduction To Profiles
===========================
Every new node is automatically added to a profile called
``default``. You can view the configuration attributes of this profile
by using the ``wwctl profile list`` command. Like the ``wwctl node
list`` command, this will provide a summary, but you can see **all**
configuration attributes by using the ``--all`` or ``-a`` flag as
follows:
.. code-block:: console
# wwctl profile list
PROFILE NAME COMMENT/DESCRIPTION
default This profile is automatically included for each node
And with the ``-a`` flag:
.. code-block:: console
# wwctl profile list -a
PROFILE FIELD PROFILE VALUE
default Id -- default
default Comment -- This profile is automatically included for each node
default Cluster -- --
default Image -- --
default Kernel -- --
default KernelArgs -- --
default Init -- --
default Root -- --
default RuntimeOverlay -- --
default SystemOverlay -- --
default Ipxe -- --
default IpmiIpaddr -- --
default IpmiNetmask -- --
default IpmiPort -- --
default IpmiGateway -- --
default IpmiUserName -- --
default IpmiInterface -- --
As you can see here, there is only one attribute set by default in
this profile, and that is the "Comment" field. That Comment is
inherited by any nodes that are configured to use this profile. So if
we look at the node we configured in the last section, we can see that
configuration attribute there:
.. code-block:: console
# wwctl node list -a | head -n 5
NODE FIELD PROFILE VALUE
n0000 Id -- n0000
n0000 Comment default This profile is automatically included for each node
n0000 Cluster -- --
Here you can see that the "Comment" attribute was inherited by this
node, and it also provides you with the information of which profile
this attribute was inherited from. This is very useful information as
nodes can be part of multiple profiles with inheritance being
cascading.
Multiple Profiles
=================
For demonstration purposes, let's create another profile and
demonstrate how to use this second profile.
.. code-block:: console
# wwctl profile add test_profile
# wwctl profile list
PROFILE NAME COMMENT/DESCRIPTION
default This profile is automatically included for each node
test_profile --
Now that we've created a new profile, let's create a configuration
attribute in this profile:
.. code-block:: console
# wwctl profile set --cluster cluster01 test_profile
? Are you sure you want to modify 1 profile(s)? [y/N] y
# wwctl profile list -a test_profile | grep Cluster
test_profile Cluster cluster01
Lastly we just need to configure this profile to our node(s):
.. code-block:: console
# wwctl node set --profile test_profile n0000
Are you sure you want to modify 1 nodes(s): y
And you can now verify that the node has both profile configurations:
.. code-block:: console
# wwctl node list -a | head -n 6
NODE FIELD PROFILE VALUE
n0000 Id -- n0000
n0000 Comment default This profile is automatically included for each node
n0000 Cluster test_profile cluster01
n0000 Profiles -- default,test_profile
Cascading Profiles
==================
In the previous example, we set a single node to have two profile
configurations. We can also overwrite configurations as follows:
.. code-block:: console
# wwctl profile set --comment "test comment" test_profile
Are you sure you want to modify 1 profile(s): y
# wwctl node list -a | head -n 6
NODE FIELD PROFILE VALUE
n0000 Id -- n0000
n0000 Comment test_profile test comment
n0000 Cluster test_profile cluster01
n0000 Profiles -- default,test_profile
And if we delete the superseded profile attribute from
``test_profile`` we can now see the previous configuration:
.. code-block:: console
# wwctl profile set --comment UNDEF test_profile
Are you sure you want to modify 1 profile(s): y
# wwctl node list -a | head -n 6
NODE FIELD PROFILE VALUE
n0000 Id -- n0000
n0000 Comment default This profile is automatically included for each node
n0000 Cluster test_profile cluster01
n0000 Profiles -- default,test_profile
This is a very useful feature for dealing with many groups of cluster
nodes and/or testing new configurations on smaller subsets of cluster
nodes. For example, you can use this method to run a different kernel
on only a subset or group of cluster nodes without changing any other
node attributes.
Overriding Profiles
===================
All profile configurations can be overwritten by a node configuration
as can be seen here:
.. code-block:: console
# wwctl node set --comment "This value takes precedent" n0000
Are you sure you want to modify 1 nodes(s): y
# wwctl node list -a | head -n 6
NODE FIELD PROFILE VALUE
n0000 Id -- n0000
n0000 Comment SUPERSEDED This value takes precedent
n0000 Cluster test_profile cluster01
n0000 Profiles -- default,test_profile
Negating Profiles
=================
Profiles may also be negated by later profiles. For example, ``p2,~p1``
adds the profile ``p2`` to a node and removes a previously-applied ``p1``
profile from a node.
How To Use Profiles Effectively
===============================
There are a lot of ways to use profiles to facilitate the management
of large cluster node attributes, but there is nothing inherent in the
design of Warewulf that requires use of them for anything. It is
completely reasonable to not use profiles at all to help with node
configuration attributes.
But if you do wish to use profiles, the best way to use them is to
manage "fixed" configurations of groups of cluster nodes. For example,
if you have multiple sub-clusters in your cluster, it might be
advantageous to have a ``cluster_name`` profile which includes things
like network configurations, and/or a specific kernel, image, boot
arguments, etc.
Node specific information, like HW/MAC addresses and IP addresses
should always be put in a node configuration rather than a profile
configuration.

View File

@@ -1,100 +0,0 @@
=================
Node Provisioning
=================
Once the nodes are configured in Warewulf, they are ready to boot.
Node Hardware Setup
===================
The only thing that Warewulf requires to provision is that the node is
set to PXE boot. You may need to change the boot order if there is a
local disk present and bootable. This is a configuration change you
will have to make in the BIOS of the cluster node.
Each vendor does this differently and as a result we won't go into the
setup specifics here and if you can not find information on how to PXE
boot your nodes, please contact your hardware vendor support.
.. note::
If you find that you are going to use Warewulf, or any other
cluster provisioning tool, it is very helpful to require that
hardware vendors preconfigure your cluster nodes with values of
your choosing, and ask them to provide a text file that includes
all of the HW/MAC addresses of the compute nodes in the order they
are racked (which most creditable vendors will do). You can also
ask them to certify their computing stack for the operating system
you wish to use and the provisioning system. This helps hardware
vendors to ensure their stack works with open source projects like
Warewulf, Debian, OpenSuSE, and Rocky Linux.
The Provisioning Process
========================
When the cluster node boots, the following order of operations will
occur:
#. BIOS:
#. The system BIOS will bootstrap the initialization of the
hardware
#. The network card will register its option ROM into the BIOS
#. The BIOS will run through all of its functions and finish with
boot devices
#. The boot devices are attempted in order
#. When it gets to the network boot device, PXE is run from the
firmware on the network card
#. PXE:
#. PXE will request a BOOTP/DHCP address on the network
#. The Warewulf controller's DHCP server will respond with a
network configuration and filename to try and boot
#. PXE will attempt to download the filename referred to in the
DHCP response via TFTP
#. The downloaded file will execute an iPXE stack which will reach
out to the Warewulf server for it's configuration
#. Bootstrap:
#. The Warewulf server will generate the iPXE configuration which
will include directions of what else is necessary to download
and how to boot.
#. The kernel, image, and overlays
are all downloaded over REST HTTP from the Warewulf Server
#. iPXE executes the kernel and processes the overlays to provide
a unified root file system
#. Warewulf bootstraps the initialization of cluster node's
operating system
#. File System (re)configuration
#. SELinux
#. ``wwclient`` is called as a background daemon and sleeps until network is ready
#. The Warewulf bootstrap execs the image's ``/sbin/init``
#. Image:
#. The image now boots exactly as any operating system would
expect
Node status
========================
During the whole provisioning process of your nodes, you can check their status
through the following command :
.. code-block:: console
# wwctl node status
NODENAME STAGE SENT LASTSEEN (s)
================================================================================
c001 RUNTIME_OVERLAY __RUNTIME__.img.gz 16
For each node, there are 4 different stages :
* **IPXE**
* **KERNEL**
* **SYSTEM_OVERLAY**
* **RUNTIME_OVERLAY**
Those stages are directly linked to the The Provisioning Process section and are provided
by the wwclient
Thanks to ``wwctl node status`` command, you can also check your communication between
the warewulf client and server.
Depending on your warewulf version, you should see a reset of the last seen counter every 1 minute due to the
warewulf runtime overlay update.

View File

@@ -1,95 +0,0 @@
========
Security
========
Historically, most HPC clusters utilize a security model that is "hard
on the exterior and soft and gushy on the interior". It is not that a
user has free roam once logged in, but rather we tend to rely on just
simple POSIX security models on the inside. For example, one of the
common practices is to completely disable SELinux on a new cluster
setup. Just kill it because it gets in the way.
For that reason, most critical HPC clusters leverage VPNs and/or
bastion hosts with multi-factor authentication (MFA) to help secure it
on the outside. But even with MFA and secure ssh connections through a
bastion host, it is still possible for malicious users to gain access
to these systems. Security being like layers of an onion is accurate,
but on an HPC system, those layers are predominately on the outside of
the cluster, not the inside.
Warewulf was written and designed from the ground up to go a bit
further. And while certain parallelization and high performance
library capabilities still require lowering the security threshold,
Warewulf strives to not be a blocker here.
SELinux
=======
The Warewulf server itself was developed with SELinux enabled in
"targeted" and "enforcing" mode and with the firewall active.
The provisioning process also fully supports booting SELinux-enabled
images, though nodes must be configured to use tmpfs for init. ("ramfs"
(often used by default) does not support extended file attributes.)
.. 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, you just need to enable SELinux in
``/etc/sysconfig/selinux`` and install the appropriate profiles into 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
Provisioning Security
=====================
Provisioning in generally is known to be rather "insecure" because
when a user lands on a compute node, there is generally nothing
stopping them from spoofing a provision request and downloading the
provisioned raw materials for inspection.
In Warewulf there are ways multiple to secure the provisioning process:
#. The provisioning connections and transfers are not secure due to
not being able to manage a secure root of trust through a PXE
process. The best way to secure the provisioning process is to
enact a vLAN used specifically for provisioning. Warewulf supports
this but you must consult your switch documentation and features to
implement a default vLAN for provisioning and ensure that the
runtime operating system is configured for a different tagged vLAN
once booted.
#. Warewulf will leverage hardware "asset tags" which almost all
vendors support. It is a configurable string that is configured in
firmware and accessible only via root or physical access. During
provisioning (as well as post provisioning via ``wwclient``)
Warewulf, can use the asset tag as a secure token. If you have
setup your hardware with an asset tag, you simply need to tell
Warewulf what that asset tag is. When the asset tag is defined in
Warewulf (``wwctl node set --assetkey "..."``), it will only
provision and communicate with requests from that system matching
that asset tag.
#. When the nodes are booted via `shim` and `grub` Secure Boot can be
enabled. This means that the nodes only boot the kernel which is
provided by the distributor and also custom complied modules can't
be loaded.
Summary
=======
Warewulf does not limit the security posture of a cluster at all, and
perhaps it increases it as not all provisioners work with firewalls
and SELinux enabled and enforcing. But even with that, cluster
security is always up to the system manager and organizational
policies. Our job is just to ensure that we don't limit those policies
in any way.

View File

@@ -1,85 +0,0 @@
======================
Stateless Provisioning
======================
Why is Provisioning Important
=============================
Clusters are pools of servers bundled together to do a particular job
or set of jobs. While there are a number of different use cases for
clustering today, Warewulf was originally designed out of necessity.
Back in 2000, when Linux clustering was growing up for HPC, the issues
of scale became apparent. Of course in HPC, there are many scalability
factors which needed to be overcome as we continued to scale up
clusters. Pretty early on was the "administrative scaling" which is
the factor that full time systems administrators could only maintain
so many servers. While homogeneous configurations were able to help
that, we still had the problem that every installed server became a
point of administration, version drift, and debugging. The larger the
cluster, the harder this problem was to solve.
Warewulf was created to help with exactly this.
Provisioning Overview
=====================
Provisioning in this definition is the process of putting an operating
system onto a system. There are many ways to provision operating
system images, from copying hard drives, to scripted installs, to
automated installs. There are many valuable tools to facilitate this
and they all helped to solve this problem.
In a cluster environment, this means one could group all of the nodes
together, to be installed in bulk. Previous to cluster provisioning
system administrators would go around to each cluster node, and
install it from scratch, with an ISO or USB thumb drive. This
obviously is not scalable. But being able to automatically install
hundreds or thousands of computers in parallel and automate the
management of these systems completely changed the paradigm.
There were several cluster provision and management toolkits already
available when Warewulf was created and while these tools absolutely
helped, there was even more optimization to be had.
Why Stateless Provisioning
==========================
The next step past automated installs is to just skip the installation
completely; boot directly into the runtime operating system without
ever doing an installation.
This is Warewulf.
Stateless provisioning is realizing you never have to install another
compute node. Think of it like booting a LiveOS or LiveISO on nodes
over the network. This means that no node individually is a point of
system administration, but rather the entire cluster is administrated
as a single unit.
If all cluster nodes are booting the same OS image (or set of OS
images), then any individual nodes that have problems is
hardware. Debugging software and doing system administration in single
points within a cluster is not needed. There is no version drift,
because it is not possible for nodes to fall out of sync. Every reboot
makes it exactly the same as its neighbors.
Warewulf provisions the operating system by default to system
memory. There is no need for hard drives with Warewulf.
Previous versions of Warewulf had the ability to write the operating
system to hard disk as well as do hybrid provisioning (the core
operating system in memory, other pieces overlaid over NFS) but these
have been obsoleted in Warewulf v4 as there are easier ways to
accomplish the same thing (e.g. use of swap space).
.. note::
If you wish to provision to the hard drive, we might add that
feature back based on user requests but in the mean time, you may
wish to look at an automated or scripted installation platform
instead of a cluster provisioning system.
In our experience, the Warewulf provisioning model is by far the most
advantageous, simplest, and most flexible and scalable cluster
provisioning platform available.

View File

@@ -1,261 +0,0 @@
==========
Templating
==========
Warewulf uses the ``text/template`` engine to convert dynamic content
into static content and auto-populate files with the appropriate data
on demand.
In Warewulf, you can find templates both for the provisioning services
(e.g. ``/etc/warewulf/ipxe/``, ``/etc/warewulf/dhcp/``, and
``/etc/warewulf/hosts.tmpl``) as well as within many of the provided
overlays.
(more documentation coming soon)
Examples
========
Comment
-------
.. code-block::
{{ /* This comment won't show up in file, but an empty line /* }}
{{ /* No empty line, line break removed at end of this line /* -}}
{{- /* No empty line, line break removed at front of this line /* }}
Range
-----
iterate over elements of an array
.. code-block::
{{ range $devname, $netdev := .NetDevs }}
# netdev = {{ $netdev.Hwaddr }}
{{ end }}
Increment Variable In Loop
^^^^^^^^^^^^^^^^^^^^^^^^^^
iterate over elements of an array and increment ``i`` each loop cycle
.. code-block::
{{ $i := 0 }}
{{ range $devname, $netdev := .NetDevs }}
# netdev{{$i}} = {{ $netdev.Hwaddr }}
{{ $i = inc $i }}
{{ end }}
Decrement
^^^^^^^^^
iterate over elements of an array and decrement ``i`` each loop cycle
.. code-block::
{{ $i := 10 }}
{{ range $devname, $netdev := .NetDevs }}
# netdev{{$i}} = {{ $netdev.Hwaddr }}
{{ $i = dec $i }}
{{ end }}
Access Tag
----------
Acces the value of an individual tag ``foo``
.. code-block::
foo: {{ index .Tags "foo" }}
{{ if eq (index .Tags "foo") "baar" -}}
foo: {{ index .Tags "foo" }}
{{ end -}}
Create Multiple Files
---------------------
The following template will create a file called
``ifcfg-NETWORKNAME.xml`` for every network present on the node
.. code-block::
{{- $host := .BuildHost }}
{{- $time := .BuildTime }}
{{- $source := .BuildSource }}
{{range $devname, $netdev := .NetDevs -}}
{{- $filename := print "ifcfg-" $devname ".xml" }}
{{ file $filename }}
<!--
This file is autogenerated by warewulf
Host: {{ $host }}
Time: {{ $time }}
Source: {{ $source }}
-->
<interface origin="static generated warewulf config">
<name>{{$netdev.Device}}</name>
{{ if $netdev.Type -}}
<link-type>{{ $netdev.Type }}</link-type>
{{ end -}}
<control>
<mode>boot</mode>
</control>
<firewall/>
<link/>
<ipv4>
<enabled>true</enabled>
<arp-verify>true</arp-verify>
</ipv4>
<ipv4:static>
<address>
<local>{{$netdev.Ipaddr}}/{{$netdev.Ipmask}}</local>
</address>
{{ if $netdev.Gateway -}}
<route>
<nexthop>
<gateway>{{$netdev.Gateway}}</gateway>
</nexthop>
</route>
{{ end -}}
</ipv4:static>
<ipv6>
<enabled>true</enabled>
<privacy>prefer-public</privacy>
<accept-redirects>false</accept-redirects>
</ipv6>
{{ if $netdev.Ipaddr6 -}}
<ipv6:static>
<address>
<local>{{ $netdev.Ipaddr6 }}</local>
</address>
</ipv6:static>
{{ end -}}
</interface>
{{ end -}}
Special Functions
-----------------
Include
^^^^^^^
A file from the host can be included with following template
.. code-block::
{{ Include file }}
IncludeFrom
^^^^^^^^^^^
With following snippet a file from a given image can be included
.. code-block::
{{ IncludeFrom image file }}
IncludeBlock
^^^^^^^^^^^^
Includes a file up to the line where a abort string is found. This is
useful, e.g., for the hosts file, which can have local modifications
which are not controlled by warewulf. For this example the abort
string is "# Do not edit after this line"
.. code-block::
{{ IncludeBlock "/etc/hosts" "# Do not edit after this line" }}
# This block is autogenerated by warewulf
# Host: {{.BuildHost}}
# Time: {{.BuildTime}}
# Source: {{.BuildSource}}
# Warewulf Server
{{$.Ipaddr}} warewulf {{$.BuildHost}}
{{- range $node := $.AllNodes}} {{/* for each node */}}
# Entry for {{$node.Id}}
{{- range $devname, $netdev := $node.NetDevs}} {{/* for each network device on the node */}}
{{- if $netdev.Ipaddr}} {{/* if we have an ip address on this network device */}}
{{- /* emit the node name as hostname if this is the primary */}}
{{$netdev.Ipaddr}} {{$node.Id}}-{{$devname}}
{{- if $netdev.Device}} {{$node.Id()}}-{{$netdev.Device}}{{end}}
{{- if $netdev.Primary}} {{$node.Id()}}{{end}}
{{- end}} {{/* end if ip */}}
{{- end}} {{/* end for each network device */}}
{{- end}} {{/* end for each node */}}
Abort
^^^^^
If ``{{ abort }}`` is found in a template, the resulting file isn't written.
Nobackup
^^^^^^^^
If a file exists on the target, a backup file is written with the
suffix ``.wwbackup``. This only happens for the ``host`` overlay, as
e.g. the ``/etc/hosts`` exists on the host. If this is not the
intended behavior, the ``{{ nobackup }}`` flag can be added to a
template.
Split
^^^^^
A given string can be split into substrings.
.. code-block::
{{ $x := "a:b:c" -}}
{{ $y := (split $x ":") -}}
{{ range $y }} {{.}} {{ end }}
softlink
^^^^^^^^
Creates a soft link to the given string for the template.
ImportLink
^^^^^^^^^^
Evaluates the soft link on the Warewulf server and
then create the soft link to it in the overlay.
readlink
^^^^^^^^
Evaluates the soft link on the Warewulf server and returns the target.
UniqueField
^^^^^^^^^^^
UniqueField returns a filtered version of a multi-line input string. input is
expected to be a field-separated format with one record per line (terminated by
`\n`). Order of lines is preserved, with the first matching line taking
precedence.
For example, the following template snippet has been used in the ``syncuser`` overlay
to generate a combined ``/etc/passwd``.
.. code-block::
{{
printf "%s\n%s"
(IncludeFrom $.ImageName "/etc/passwd" | trim)
(Include (printf "%s/%s" .Paths.Sysconfdir "passwd") | trim)
| UniqueField ":" 0 | trim
}}
Node specific files
-------------------
Sometimes there is the need to have specific files for every node
which can't be generated by a template. You can include these files
with following template:
.. code-block::
{{- $filename := print "/root/" .Id "-payload" }}
{{ Include $filename }}

View File

@@ -1,124 +0,0 @@
Troubleshooting
===============
warewulfd
---------
The Warewulf server (``warewulfd``) sends logs to the systemd journal.
.. code-block::
journalctl -u warewulfd.service
To increase the verbosity of the log, specify either ``--verbose`` or
``--debug`` in the warewulfd OPTIONS.
.. code-block::
echo "OPTIONS=--debug" >>/etc/default/warewulfd
systemctl restart warewulfd.service
iPXE
----
If you're using iPXE to boot (the default), you can get a command prompt by pressing with C-b during boot.
From the iPXE command prompt, you can run the same commands from `default.ipxe`_ to troubleshoot potential boot problems.
.. _default.ipxe: https://github.com/warewulf/warewulf/blob/main/etc/ipxe/default.ipxe
For example, the following commands perform a (relatively) normal Warewulf boot.
(Substitute your Warewulf server's IP address in place of 10.0.0.1,
update the port number if you have changed it from the default of 9873,
and substitute your cluster node's MAC addres in place of 00:00:00:00:00:00.)
.. code-block::
set uri http://10.0.0.1:9873/provision/00:00:00:00:00:00
kernel --name kernel ${uri}?stage=kernel
imgextract --name image ${uri}?stage=image&compress=gz
imgextract --name system ${uri}?stage=system&compress=gz
imgextract --name runtime ${uri}?stage=runtime&compress=gz
boot kernel initrd=image initrd=system initrd=runtime
- The ``uri`` variable points to ``warewulfd`` for future reference.
This includes the cluster node's MAC address so that Warewulf knows what image and overlays to provide.
- The ``kernel`` command fetches a kernel for later booting.
- The ``imgextract`` command fetches and decompresses the images that will make up the booted noe image.
In a typical environment this is used to load a minimal "initial ramdisk" which, then, boots the rest of the system.
Warewulf, by default, loads the entire image as an initial ramdisk,
and also loads the system and runtime overlays at this time time.
- The ``boot`` command tells iPXE to boot the system with the given kernel and ramdisks.
.. note::
This example does not provide ``assetkey`` information to ``warewulfd``.
If your nodes have defined asset tags, provide it in the ``uri`` variable for the node you are trying to boot.
For example, you may want to try booting to a pre-init shell with debug logging enabled.
To do so, substitute the ``boot`` command above.
.. code-block::
boot kernel initrd=image initrd=system initrd=runtime rdinit=/bin/sh
.. note::
You may be more familiar with specifying ``init=`` on the kernel command line.
``rdinit`` indicates "ramdisk init."
Since Warewulf, by default, boots the node image as an initial ramdisk, we must use ``rdinit=`` here.
GRUB
----
If you're using GRUB to boot, you can get a command prompt by pressing "c" when prompted during boot.
From the GRUB command prompt, you can enter the same commands that you would otherwise find in `grub.cfg.ww`_.
.. _grub.cfg.ww: https://github.com/warewulf/warewulf/blob/main/etc/grub/grub.cfg.ww
For example, the following commands perform a (relatively) normal Warewulf boot.
(Substitute your Warewulf server's IP address in place of 10.0.0.1,
and update the port number if you have changed it from the default of 9873.)
.. code-block::
uri="(http,10.0.0.1:9873)/provision/${net_default_mac}"
linux "${uri}?stage=kernel" wwid=${net_default_mac}
initrd "${uri}?stage=image&compress=gz" "${uri}?stage=system&compress=gz" "${uri}?stage=runtime&compress=gz"
boot
- The ``uri`` variable points to ``warewulfd`` for future reference.
``${net_default_mac}`` provides Warewulf with the MAC address of the booting node,
so that Warewulf knows what image and overlays to provide it.
- The ``linux`` command tells GRUB what kernel to boot, as provided by ``warewulfd``.
The ``wwid`` kernel argument helps ``wwclient`` identify the node during runtime.
- The ``initrd`` command tells GRUB what images to load into memory for boot.
In a typical environment this is used to load a minimal "initial ramdisk" which, then, boots the rest of the system.
Warewulf, by default, loads the entire image as an initial ramdisk,
and also loads the system and runtime overlays at this time time.
- The ``boot`` command tells GRUB to boot the system with the previously-defined configuration.
.. note::
This example does not provide ``assetkey`` information to ``warewulfd``.
If your nodes have defined asset tags, provide it in the ``uri`` variable for the node you are trying to boot.
For example, you may want to try booting to a pre-init shell with debug logging enabled.
To do so, substitute the ``linux`` command above.
.. code-block::
linux "${uri}?stage=kernel" wwid=${net_default_mac} debug rdinit=/bin/sh
.. note::
You may be more familiar with specifying ``init=`` on the kernel command line.
``rdinit`` indicates "ramdisk init."
Since Warewulf, by default, boots the node image as an initial ramdisk, we must use ``rdinit=`` here.

View File

@@ -1,20 +0,0 @@
==================
Upgrading Warewulf
==================
New versions of Warewulf might introduce changes to ``warewulf.conf`` and ``nodes.conf``.
The ``wwctl upgrade`` command can help ease the transition between versions.
.. note::
``wwctl upgrade`` will back up any files before it changes them (to ``<name>-old``)
but it is good practice to back up your configuration manually.
.. code-block:: console
# wwctl upgrade config
# wwctl upgrade nodes --add-defaults --replace-overlays
Both upgrade commands support specifying ``--output-path=-``
to print the upgraded configuration file to standard out
for inspection before replacing the configuration files.

View File

@@ -1,32 +0,0 @@
============================
Controlling Warewulf (wwctl)
============================
Warewulf's command-line interface is based primarily around the
``wwctl`` command. This command has sub-commands for each major
component of Warewulf's functionality.
* ``configure`` configures system services that Warewulf depends on
* ``image`` configures (node) images
* ``node`` manages nodes in the cluster
* ``profiles`` defines configuration which can be applied to multiple
nodes
* ``overlays`` manages overlays
* ``power`` turns nodes on and off
* ``ssh`` provides basic parallel ssh functionality
All of these subcommands (and their respective sub-subcommands) have
built-in help with either ``wwctl help`` or ``--help``.
Hostlists
=========
Many of the commands (e.g., ``wwctl node list`` support a "hostlist"
syntax for referring to multiple nodes at once. Hostlist expressions
support both ranges and comma-separated numerical lists.
For example:
* ``node[1-2]`` expands to ``node1 node2``
* ``node[1,3]`` expands to ``node1 node3``
* ``node[1,5-6]`` expands to ``node1 node5 node6``

View File

@@ -2,154 +2,47 @@
Contributing Contributing
============ ============
Warewulf is an open source project, meaning we have the challenge of Warewulf is an open source project, and we are grateful for any support or
limited resources. We are grateful for any support that you can contributions. Helping other users, raising issues, writing documentation, and
offer. Helping other users, raising issues, helping write contributing code are all ways to help!
documentation, or contributing code are all ways to help!
Join the community Join the community
================== ==================
This is a huge endeavor, and your help would be greatly appreciated! Whether you develop Warewulf or use it to deploy clusters, we hope ypu'll spread
Post to online communities about Warewulf, and request that your the word! Share your experiences online. Ask your distribution to include
distribution vendor, service provider, and system administrators support for Warewulf. Consider giving a talk at a conference or meetup!
include Warewulf for you!
Warewulf on Slack Warewulf on Slack
----------------- -----------------
Many members of the Warewulf community, including developers, communicate via Slack. Many members of the Warewulf community, including its developers, communicate
It's a great place to get help with an issue or talk about how you're using Warewulf. via Slack. It's a great place to get help with an issue or talk about your
deployment.
An invite link is available at `https://warewulf.org/help/ <https://warewulf.org/help/>`. An invite link is available at `https://warewulf.org/help/ <https://warewulf.org/help/>`.
OpenHPC
-------
OpenHPC includes Warewulf v4 (and Warewulf 3 before it) as a supported cluster
management system and deployment strategy. Participating in the OpenHPC
community is also a great way to support Warewulf!
Raise an Issue Raise an Issue
============== ==============
For general bugs/issues, you can open an issue `at the GitHub repo For general bugs/issues, you can open an issue `at the GitHub repo
<https://github.com/warewulf/warewulf/issues/new>`_. <https://github.com/warewulf/warewulf/issues/new>`_.
Contribute to the code Contribute to the Code
====================== ======================
We use the traditional `GitHub Flow We use the traditional `GitHub Flow
<https://guides.github.com/introduction/flow>`_ to develop. This means <https://guides.github.com/introduction/flow>`_ to develop. This means that you
that you fork the main repo, create a new branch to make changes, and fork the main repo, create a new branch to make changes, and `submit a pull
submit a pull request (PR) to the master branch. request (PR) <https://help.github.com/articles/creating-a-pull-request>`_ to the
main branch.
Check out our official `CONTRIBUTING.md Check out our official `CONTRIBUTING.md
<https://github.com/warewulf/warewulf/blob/master/CONTRIBUTING.md>`_ <https://github.com/warewulf/warewulf/blob/main/CONTRIBUTING.md>`_ document.
document, which also includes a `code of conduct
<https://github.com/warewulf/warewulf/blob/master/CONTRIBUTING.md#code-of-conduct>`_.
Step 1. Fork the repo
---------------------
To contribute to Warewulf, you should obtain a GitHub account and fork
the `Warewulf <https://github.com/warewulf/warewulf>`_ repository. Once
forked, clone your fork of the repo to your computer. (Obviously, you
should replace ``your-username`` with your GitHub username.)
.. code-block:: bash
git clone https://github.com/your-username/warewulf.git
cd warewulf
Step 2. Checkout a new branch
-----------------------------
`Branches <https://guides.github.com/introduction/flow>`_ are a way
of isolating your features from the main branch. Given that weve just
cloned the repo, we will probably want to make a new branch from
master in which to work on our new feature. Lets call that branch
``new-feature``:
.. code-block:: bash
git checkout master
git checkout -b new-feature
.. note::
You can always check which branch you are in by running ``git
branch``.
Step 3. Make your changes
-------------------------
On your new branch, go nuts! Make changes, test them, and when you are
happy commit the changes to the branch:
.. code-block:: bash
git add file-changed1 file-changed2...
git commit -m "what changed?"
This commit message is important - it should describe exactly the
changes that you have made. Good commit messages read like so:
.. code-block:: bash
git commit -m "changed function getConfig in functions.go to output csv to fix #2"
git commit -m "updated docs about shell to close #10"
The tags ``close #10`` and ``fix #2`` are referencing issues that are
posted on the upstream repo where you will direct your pull
request. When your PR is merged into the master branch, these messages
will automatically close the issues, and further, they will link your
commits directly to the issues they intend to fix. This will help
future maintainers understand your contribution, or (hopefully not)
revert the code back to a previous version if necessary.
Step 4. Push your branch to your fork
-------------------------------------
When you are done with your commits, you should push your branch to
your fork (and you can also continuously push commits here as you
work):
.. code-block:: bash
git push origin new-feature
Note that you should always check the status of your branches to see
what has been pushed (or not):
.. code-block:: bash
git status
Step 5. Submit a Pull Request
-----------------------------
Once you have pushed your branch, then you can go to your fork (in the
web GUI on GitHub) and `submit a Pull Request
<https://help.github.com/articles/creating-a-pull-request>`_. Regardless
of the name of your branch, your PR should be submitted to the
``main`` branch. Submitting your PR will open a conversation thread
for the maintainers of Warewulf to discuss your contribution. At this
time, the continuous integration that is linked with the code base
will also be executed. If there is an issue, or if the maintainers
suggest changes, you can continue to push commits to your branch and
they will update the Pull Request.
Step 6. Keep your branch in sync
--------------------------------
Cloning the repo will create an exact copy of the Warewulf repository
at that moment. As you work, your branch may become out of date as
others merge changesinto the upstream master. In the event that you
need to update a branch, you will need to follow the next steps:
.. code-block:: bash
# add a new remote named "upstream"
git remote add upstream https://github.com/warewulf/warewulf.git
# or another branch to be updated
git checkout master
git pull upstream master
# to update your fork
git push origin master
git checkout new-feature
git merge master

View File

@@ -2,309 +2,37 @@
Debugging Debugging
========= =========
Whether developing a new feature or fixing a bug, using the automated Whether developing a new feature or fixing a bug, using the automated test suite
test suite together with a debugger is a potent combination. This together with a debugger is a potent combination. This guide here can't
guide here can't substitute for full documentation on a given substitute for full documentation on a given debugger; but it might help you get
debugger; but it might help you get started debugging Warewulf. started debugging Warewulf.
Validating the code with vet Validating the code with vet
============================ ============================
The Warewulf ``Makefile`` includes a ``vet`` target which runs ``go The Warewulf ``Makefile`` includes a ``vet`` target which runs ``go vet`` on the
vet`` on the full codebase. full codebase.
.. code-block:: console .. code-block:: shell
$ make vet make vet
Running the Full Test Suite
Running the full test suite
=========================== ===========================
The Warewulf ``Makefile`` includes a ``test`` target which runs the The Warewulf ``Makefile`` includes a ``test`` target which runs the full test
full test suite. suite.
.. code-block:: console .. code-block:: shell
$ make test make test
Individual test cases are particularly useful when coupled with a debugger. For
Using delve example, you can install delve as a regular user directly with Go.
===========
If you have a failing test but you're having trouble tracking down
why, try using a debugger to step through the test. These instructions
use delve.
Installing delve
----------------
You can install delve as a regular user directly with Go.
.. code-block:: console .. code-block:: console
$ go install github.com/go-delve/delve/cmd/dlv@latest $ go install github.com/go-delve/delve/cmd/dlv@latest
The ``dlv`` binary will be installed by default at Visual Studio Code also includes a full-featured golang debugger that includes
``$HOME/go/bin/dlv``. You can, of course, add ``$HOME/go/bin`` to your testsuite integration.
path if you prefer.
.. code-block:: console
$ PATH=$HOME/go/bin:$PATH
Running delve against a specific test
-------------------------------------
You can use delve to specifically run the test suite and, even more
specifically, a single failing test. In this example delve is
instructed to run the tests for Warewulf's ``node`` package, and
specifically the ``Test_GetAllNodeInfoDefaults`` test.
.. code-block:: console
$ dlv test github.com/warewulf/warewulf/internal/pkg/node -- -test.v -test.run Test_GetAllNodeInfoDefaults
Type 'help' for list of commands.
(dlv) break node.Test_GetAllNodeInfoDefaults
Breakpoint 1 set at 0x26c0d0 for github.com/warewulf/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51
Setting a breakpoint at ``node.Test_GetAllNodeInfoDefaults`` pauses
execution once the test starts, and allows us to ``continue`` through
all the setup prior to that point.
.. code-block:: console
(dlv) continue
=== RUN Test_GetAllNodeInfoDefaults
> github.com/warewulf/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51 (hits goroutine(35):1 total:1) (PC: 0x26c0d0)
46: assert.Contains(t, nodeYaml.Nodes, "test_node")
47: assert.Equal(t, "A single node", nodeYaml.Nodes["test_node"].Comment)
48: }
49:
50:
=> 51: func Test_GetAllNodeInfoDefaults(t *testing.T) {
52: file, writeErr := writeTestConfigFile(`
53: nodes:
54: test_node: {}`)
55: if file != nil {
56: defer os.Remove(file.Name())
Helpful commands from here include
``next``
Execute the current line (marked by ``=>``) and proceed to the next
line.
``step``
Execute the current line (marked by ``=>``) and proceed to the next
line, potentially moving into a function call.
``list``
Display a contextual Go code listing, marking the next instruction.
``locals``
Display all local variables in the current scope.
``print``
Display (in detail) the value of a single variable from the current
scope.
Read about other commands available within delve using the ``help``
command.
Example debugging session
-------------------------
.. code-block:: console
$ ~/go/bin/dlv test github.com/warewulf/warewulf/internal/pkg/node -- -test.v -test.run Test_GetAllNodeInfoDefaults
Type 'help' for list of commands.
(dlv) break node.Test_GetAllNodeInfoDefaults
Breakpoint 1 set at 0x26c0d0 for github.com/warewulf/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51
(dlv) break nodeinfo.go:417
Breakpoint 2 set at 0x267f18 for github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:417
(dlv) continue
=== RUN Test_GetAllNodeInfoDefaults
> github.com/warewulf/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51 (hits goroutine(19):1 total:1) (PC: 0x26c0d0)
46: assert.Contains(t, nodeYaml.Nodes, "test_node")
47: assert.Equal(t, "A single node", nodeYaml.Nodes["test_node"].Comment)
48: }
49:
50:
=> 51: func Test_GetAllNodeInfoDefaults(t *testing.T) {
52: file, writeErr := writeTestConfigFile(`
53: nodes:
54: test_node: {}`)
55: if file != nil {
56: defer os.Remove(file.Name())
(dlv) continue
WARN : Error reading UNDEF/warewulf/defaults.conf: open UNDEF/warewulf/defaults.conf: no such file or directory
> github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:417 (hits goroutine(19):1 total:1) (PC: 0x267f18)
412: defaultNodeConf.NetDevs = nil
413: nodeInfo.SetDefFrom(defaultNodeConf)
414: }
415:
416: // Load normal attributes
=> 417: if nodeConf != nil {
418: // If no profiles are included, automatically include the
419: // default profile.
420: if len(nodeConf.Profiles) == 0 {
421: nodeInfo.Profiles.SetSlice([]string{"default"})
422: } else {
(dlv) next
> github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:420 (PC: 0x267f24)
415:
416: // Load normal attributes
417: if nodeConf != nil {
418: // If no profiles are included, automatically include the
419: // default profile.
=> 420: if len(nodeConf.Profiles) == 0 {
421: nodeInfo.Profiles.SetSlice([]string{"default"})
422: } else {
423: nodeInfo.Profiles.SetSlice(nodeConf.Profiles)
424: }
425:
(dlv) next
> github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:421 (PC: 0x267f3c)
416: // Load normal attributes
417: if nodeConf != nil {
418: // If no profiles are included, automatically include the
419: // default profile.
420: if len(nodeConf.Profiles) == 0 {
=> 421: nodeInfo.Profiles.SetSlice([]string{"default"})
422: } else {
423: nodeInfo.Profiles.SetSlice(nodeConf.Profiles)
424: }
425:
426: nodeInfo.SetFrom(nodeConf)
(dlv) next
> github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:426 (PC: 0x267fec)
421: nodeInfo.Profiles.SetSlice([]string{"default"})
422: } else {
423: nodeInfo.Profiles.SetSlice(nodeConf.Profiles)
424: }
425:
=> 426: nodeInfo.SetFrom(nodeConf)
427: }
428:
429: // Load default attributes for each NetDev
430: if defaultNetDevConf != nil {
431: for _, netdev := range nodeInfo.NetDevs {
(dlv) next
> github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:430 (PC: 0x268000)
425:
426: nodeInfo.SetFrom(nodeConf)
427: }
428:
429: // Load default attributes for each NetDev
=> 430: if defaultNetDevConf != nil {
431: for _, netdev := range nodeInfo.NetDevs {
432: netdev.SetDefFrom(defaultNetDevConf)
433: }
434: }
435:
(dlv) print nodeInfo
github.com/warewulf/warewulf/internal/pkg/node.NodeInfo {
Id: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 1, cap: 1, [
"test_node",
],
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 0, cap: 0, nil,},
Comment: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 0, cap: 0, nil,},
ClusterName: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 0, cap: 0, nil,},
ImageName: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 0, cap: 0, nil,},
Ipxe: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 1, cap: 1, ["default"],},
RuntimeOverlay: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 1, cap: 1, ["generic"],},
SystemOverlay: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 1, cap: 1, ["wwinit"],},
Root: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 1, cap: 1, [
"initramfs",
],},
Discoverable: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 0, cap: 0, nil,},
Init: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 1, cap: 1, [
"/sbin/init",
],},
AssetKey: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 0, cap: 0, nil,},
Kernel: *github.com/warewulf/warewulf/internal/pkg/node.KernelEntry {
Override: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x4000158370),
Args: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001583c8),},
Ipmi: *github.com/warewulf/warewulf/internal/pkg/node.IpmiEntry {
Ipaddr: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6600),
Netmask: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6658),
Port: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b66b0),
Gateway: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6708),
UserName: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6760),
Password: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b67b8),
Interface: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6810),
Write: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6868),
Tags: map[string]*github.com/warewulf/warewulf/internal/pkg/node.Entry [],},
Profiles: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 1, cap: 1, ["default"],
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 1, cap: 1, ["default"],},
PrimaryNetDev: github.com/warewulf/warewulf/internal/pkg/node.Entry {
value: []string len: 0, cap: 0, nil,
altvalue: []string len: 0, cap: 0, nil,
from: "",
def: []string len: 0, cap: 0, nil,},
NetDevs: map[string]*github.com/warewulf/warewulf/internal/pkg/node.NetDevEntry [],
Tags: map[string]*github.com/warewulf/warewulf/internal/pkg/node.Entry [],}

View File

@@ -1,8 +0,0 @@
=============================
Development Environment (Dev Container/VSC)
=============================
Using a Dev Container for development
=====================================================
Visual Studio Code (VSC) can utilize a Dev Container for a self-contained environment that has all the necessary tools and dependencies to build and test Warewulf. The Dev Container is based on the Rocky 9 image and is built using the `devcontainer.json` file in the `.devcontainer` directory of the Warewulf repository. To use this working Docker/Podman and VSC installations are required. To use the Dev Container, click the "Open a Remote Window" button on the bottom left of the editor (`><` icon) and select "Reopen in Container". This will build the container and open a new VSC window with the container as the development environment.

View File

@@ -1,125 +0,0 @@
=============================
Development Environment (KVM)
=============================
Create CentOS 7 development virtual machine under KVM
=====================================================
.. code-block:: bash
# KVM is running on server called master1 which is not my desktop
ssh -X master1
# On master1 server
wget -P /global/downloads/centos http://mirror.mobap.edu/centos/7.8.2003/isos/x86_64/CentOS-7-x86_64-Everything-2003.iso
qemu-img create -o preallocation=metadata -f qcow2 /global/images/centos-7.qcow2 32G
# install wwdev Centos 7 development VM
sudo virt-install --virt-type kvm --name centos7-wwdev --ram 8192 \
--disk /global/images/centos-7.qcow2,format=qcow2 \
--network network=default \
--graphics vnc,listen=0.0.0.0 --noautoconsole \
--os-type=linux --os-variant=rhel7.0 \
--location=/global/downloads/centos/CentOS-7-x86_64-Everything-2003.iso
# Complete installation using virt-manager
# To start virt-manager on non-local server
ssh -X master1
sudo -E virt-manager
# Login to VM and install @development group and go language
ssh root@wwdev
# Disable selinux by modifying /etc/sysconfig/selinux
vi /etc/sysconfig/selinux
SELINUX=disabled
# disable firewall
systemctl stop firewalld
systemctl disable firewalld
Turn off default network dhcp on server master1
===============================================
.. code-block:: bash
# shutdown all VMs
sudo virsh net-destroy default
sudo virsh net-edit default
# remove dhcp lines from XML
sudo virsh net-start default
Build and install Warewulf on wwdev
===================================
.. code-block::
ssh wwdev
# Fedora prerequisites
sudo dnf -y install tftp-server tftp
sudo dnf -y install dhcp
sudo dnf -y install ipmitool
sudo dnf install singularity
sudo dnf install gpgme-devel
sudo dnf install libassuan.x86_64 libassuan-devel.x86_64
sudo dnf golang
sudo dnf nfs-utils
# Centos prerequisites
sudo yum -y install tftp-server tftp
sudo yum -y install dhcp
sudo yum -y install ipmitool
sudo yum install http://repo.ctrliq.com/packages/rhel7/ctrl-release.rpm
sudo yum install singularityplus
sudo yum install gpgme-devel
sudo yum install libassuan.x86_64 libassuan-devel.x86_64
sudo yum install https://packages.endpoint.com/rhel/7/os/x86_64/endpoint-repo-1.7-1.x86_64.rpm
sudo yum install golang
sudo yum install nfs-utils
# Install Warewulf and dependencies
git clone https://github.com/warewulf/warewulf.git
cd warewulf
make all
sudo make install
# Configure the controller
Edit the file /etc/warewulf/warewulf.conf and ensure that you've ser the approprite configuration parameters
# Configure system service automatically
sudo wwctl configure dhcp # Create the default dhcpd.conf file and start/enable service
sudo wwctl configure tftp # Install the base tftp/PXE boot files and start/enable service
sudo wwctl configure nfs # Configure NFS exports
sudo wwctl configure ssh # Build the basic ssh keys to be included by the ssh overlays
# Pull and build the image
sudo wwctl image import docker://ghcr.io/warewulf/warewulf-centos:7 centos-7 --setdefault
# Set up the default node profile
sudo wwctl profile set default -K $(uname -r) -C centos-7
sudo wwctl profile set default --netdev eth0 -M WW_server_subnet_mask -G WW_server_ip
sudo wwctl profile list
# Add a node and build node specific overlays
sudo wwctl node add n0000.cluster --netdev eth0 -I n0000_ip --discoverable
sudo wwctl node list -a n0000
# Review Warewulf overlays
sudo wwctl overlay list -l
sudo wwctl overlay list -ls
sudo wwctl overlay edit default /etc/hello_world.ww
sudo wwctl overlay build -a
# Start the Warewulf daemon
sudo wwctl server &
Boot your node and watch the bash and the output of the Warewulfd process

View File

@@ -1,270 +0,0 @@
=================================
Development Environment (Vagrant)
=================================
Create Rocky Linux 9 virtual machine for Warewulf testbed using Vagrant
Host system requirements
========================
#. CPU supports H/W virtualization.
#. KVM kernel module available and loaded.
CPU H/W Virtualization support
------------------------------
Check CPU virtualization capability using following command.
If your system has Intel CPU, you will see :code:`Intel VT` here, and if your system has AMD CPU, you will see :code:`AMD-V` here.
.. code-block:: bash
lscpu | grep Virtualization
Virtualization: AMD-V
Virtualization type: full
KVM kernel module
-----------------
.. code-block:: bash
lsmod | grep kvm
ccp 118784 1 kvm_amd
kvm 1105920 1 kvm_amd
irqbypass 16384 1 kvm
Setup development environment on Rocky Linux 9
==============================================
Install QEMU, libvirt
---------------------
.. code-block:: bash
# Install packages
sudo dnf install -y libvirt qemu-kvm \
libguestfs virtio-win guestfs-tools libguestfs-inspect-icons virt-win-reg \
virt-install virt-top
# Enable and start libvirtd
sudo systemctl enable --now libvirtd
# Add user to libvirt group
sudo usermod -aG libvirt rocky
Install Cockpit (Optional)
--------------------------
.. code-block:: bash
# Install packages
sudo dnf install -y cockpit cockpit-machines
# Enable and start cockpit (http://localhost:9090)
sudo systemctl enable --now cockpit.socket
Install Vagrant, vagrant-libvirt plug-in and vagrant-reload plug-in
-------------------------------------------------------------------
.. code-block:: bash
sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo dnf install -y vagrant
sudo dnf group install -y "Development tools"
sudo dnf config-manager --set-enabled crb
sudo dnf install -y libvirt-devel
vagrant plugin install vagrant-libvirt
vagrant plugin install vagrant-reload
Vagrant box and Vagrantfile for Warewulf sandbox
================================================
Create Rocky Linux 9.2 vagrant box
----------------------------------
.. code-block:: bash
cat << 'EOF' > box-metadata.json
{
"name" : "rockylinux/9",
"description" : "Rocky Linux 9 2.0.0",
"versions" : [
{
"version" : "2.0.0-20230513.0",
"providers" : [
{
"name" : "libvirt",
"url" : "https://dl.rockylinux.org/pub/rocky/9.2/images/x86_64/Rocky-9-Vagrant-Libvirt-9.2-20230513.0.x86_64.box"
}
]
}
]
}
EOF
vagrant box add box-metadata.json
Vagrantfile
-----------
.. code-block:: bash
mkdir -p ~/warewulf-sandbox
cd ~/warewulf-sandbox
cat << 'EOF' > Vagrantfile
Vagrant.configure("2") do |config|
number_of_node = ENV["NODES"] || 2
branch = ENV["BRANCH"] || "v4.6.0rc3"
config.vm.define :head do |head|
head.vm.box = "rockylinux/9"
head.vm.box_version = "2.0.0-20230513.0"
head.vm.hostname = "warewulf"
head.vm.network "private_network",
ip: "192.168.200.254",
netmask: "255.255.255.0",
libvirt__network_name: "pxe",
libvirt__dhcp_enabled: false
head.vm.synced_folder ".", "/vagrant", type: "nfs", nfs_version: 4, nfs_udp: false
head.vm.provider :libvirt do |libvirt|
libvirt.cpu_mode = "host-passthrough"
libvirt.memory = '8192'
libvirt.cpus = '2'
libvirt.machine_virtual_size = 40
end
head.vm.provision "shell", inline: <<-SHELL
dnf install -y cloud-utils-growpart
growpart /dev/vda 5
xfs_growfs /dev/vda5
SHELL
head.vm.provision "shell", inline: <<-SHELL
dnf groupinstall -y "Development Tools"
dnf install -y epel-release
dnf config-manager --set-enabled crb
dnf install -y golang tftp-server dhcp-server nfs-utils gpgme-devel libassuan-devel
cd /tmp
git clone https://github.com/warewulf/warewulf.git
cd warewulf
git checkout v4.6.0rc3
make clean defaults \
PREFIX=/usr \
BINDIR=/usr/bin \
SYSCONFDIR=/etc \
DATADIR=/usr/share \
LOCALSTATEDIR=/var/lib \
SHAREDSTATEDIR=/var/lib \
MANDIR=/usr/share/man \
INFODIR=/usr/share/info \
DOCDIR=/usr/share/doc \
SRVDIR=/var/lib \
TFTPDIR=/var/lib/tftpboot \
SYSTEMDDIR=/usr/lib/systemd/system \
BASHCOMPDIR=/etc/bash_completion.d/ \
FIREWALLDDIR=/usr/lib/firewalld/services \
WWCLIENTDIR=/warewulf
make all
make install
systemctl disable --now firewalld
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
SHELL
head.vm.provision "reload"
head.vm.provision "shell", inline: <<-SHELL
cat << 'CONF' | sudo tee /etc/warewulf/warewulf.conf
ipaddr: 192.168.200.254
netmask: 255.255.255.0
network: 192.168.200.0
warewulf:
port: 9873
secure: false
update interval: 60
autobuild overlays: true
host overlay: true
dhcp:
enabled: true
range start: 192.168.200.50
range end: 192.168.200.99
systemd name: dhcpd
tftp:
enabled: true
systemd name: tftp
nfs:
enabled: true
export paths:
- path: /home
export options: rw,sync
- path: /opt
export options: ro,sync,no_root_squash
systemd name: nfs-server
CONF
sed -i 's@ExecStart=/usr/bin/wwctl server@ExecStart=/usr/bin/wwctl server -d -v@' /usr/lib/systemd/system/warewulfd.service
systemctl enable --now warewulfd
wwctl configure --all
wwctl image import docker://ghcr.io/warewulf/warewulf-rockylinux:9 rocky-9
wwctl profile set --yes --image rocky-9 "default"
wwctl profile set --yes --netdev eth1 --netmask 255.255.255.0 --gateway 192.168.200.254 "default"
wwctl node add n0001.cluster -I 192.168.200.101 --discoverable true
wwctl node add n0002.cluster -I 192.168.200.102 --discoverable true
SHELL
end
(1..number_of_node).each do |i|
config.vm.define :"n000#{i}", autostart: false do |node|
node.vm.hostname = "n000#{i}"
node.vm.network "private_network",
libvirt__network_name: "pxe"
node.vm.provider :libvirt do |compute|
compute.cpu_mode = 'host-passthrough'
compute.memory = '8192'
compute.cpus = '2'
boot_network = {'network' => 'pxe'}
compute.boot boot_network
end
end
end
end
EOF
Spin up head node
=================
.. code-block:: bash
vagrant up
Spin up compute nodes
=====================
.. code-block:: bash
vagrant up n0001
# Wait until n0001 becomes ready
vagrant up n0002

View File

@@ -1,158 +0,0 @@
====================================
Development Environment (VirtualBox)
====================================
I have VirtualBox running on my desktop.
1. Create a NAT Network (a private vlan) to be used for the Warewlf
Server and compute nodes inside the VirtualBox. Make sure to
turnoff DHCP service within this NAT Network.
.. code-block:: console
# On the host with VirtualBox execute below. In my example using 10.0.8.0/24 as the private vlan for my experiment with Warewulf
VBoxManage natnetwork add --netname wwnatnetwork --network "10.0.8.0/24" --enable --dhcp off
2. Create a Centos 7 development Virtual machine (wwdev) to be used as
the Warewulf Server. Enable two Network adapters one with a
standard NAT and SSH port mapping such that you can access this VM
from the host machine. Assign the second network adapter to the NAT
Network created in step #1. Assign sufficient memory (e.g: 4GB) to
the VM.
.. code-block:: console
# Download a Centos7 or SL7 ISO and mount it to the optical drive to boot and install OS for the wwdev VM.
# Attach Network adapter #1 of the wwdev VM to the standard NAT via VM Settings -> Network option.
# By default VirtualBox puts the Network Adapter into 10.0.2.0/24 network and assigns 10.0.2.15 IP address.
# Also add a rule to the port forwarding table under the standard NAT configuration to allow SSH
# from localhost (127.0.0.1) some high port e.g 2222 to the guest IP 10.0.2.15 port 22 such that
# you can SSH from your host/desktop to the wwdev VM.
# Next attach the second Network adapter #2 to the NAT Network and you should be able to choose
# the 'wwnatnetwork' created above in step #1 from the drop down list.
3. Build and install Warewulf on wwdev
.. code-block::
# Login to wwdev VM and install @development group and go language
ssh localhost -p 2222 #(should prompt for a user account password on wwdev VM)
# Disable selinux by modifying /etc/sysconfig/selinux
vi /etc/sysconfig/selinux
SELINUX=disabled
# Disable firewall
systemctl stop firewalld
systemctl disable firewalld
# Centos prerequisites
sudo yum -y install tftp-server tftp
sudo yum -y install dhcp
sudo yum -y install ipmitool
sudo yum install http://repo.ctrliq.com/packages/rhel7/ctrl-release.rpm
sudo yum install singularityplus
sudo yum install gpgme-devel
sudo yum install libassuan.x86_64 libassuan-devel.x86_64
# Upgrade git to v2+
sudo yum install https://packages.endpoint.com/rhel/7/os/x86_64/endpoint-repo-1.7-1.x86_64.rpm
sudo yum install git
sudo yum install golang
sudo yum install nfs-utils
# Install Warewulf and dependencies
git clone https://github.com/warewulf/warewulf.git
cd warewulf
make all
sudo make install
# Static assign an IP to adapter #2 which is in the wwnatnetwork.
$ Edit the file /etc/sysconfig/networking-scripts/ifcfg-enp0s9 # adapter name at the end might be different for you
# Add lines like to below to assign an ip in 10.0.8.0/24 wwnatnetwork, I choose 10.0.8.4
BOOTPROTO=static
ONBOOT=yes
NAME=enp0s9
DEVICE=enp0s9
IPADDR=10.0.8.4
NETMASK=255.255.255.0
GATEWAY=10.0.8.1
# Bring the enp0s9 interface online and verify ip assignment
# Configure the Warewulf controller
$ Edit the file /etc/warewulf/warewulf.conf and ensure that you've set the approprite configuration parameters.
# My conf file looks like below:
ipaddr: 10.0.8.4
netmask: 255.255.255.0
warewulf:
port: 9873
secure: true
update interval: 60
dhcp:
enabled: true
range start: 10.0.8.150
range end: 10.0.8.200
template: default
systemd name: dhcpd
tftp:
enabled: true
tftproot: /var/lib/tftpboot
systemd name: tftp
nfs:
systemd name: nfs-server
exports:
- /home
- /var/warewulf
# Configure system service automatically
sudo wwctl configure dhcp --persist # Create the default dhcpd.conf file and start/enable service
sudo wwctl configure tftp --persist # Install the base tftp/PXE boot files and start/enable service
sudo wwctl configure nfs --persist # Configure the NFS exports
sudo wwctl configure ssh --persist # Build the basic ssh keys to be included by the SSH overlay
# Pull and build the image
sudo wwctl image import docker://ghcr.io/warewulf/warewulf-centos:7 centos-7 --setdefault
# Set up the default node profile
sudo wwctl profile set default -K $(uname -r) -C centos-7
sudo wwctl profile set default --netdev eth0 -M 255.255.255.0 -G 10.0.8.4
sudo wwctl profile list
# Add a node and build node specific overlays
# IP address of my nodes start from 150 as set in the warewulf.conf file above
sudo wwctl node add n0000.cluster --netdev eth0 -I 10.0.8.150 --discoverable
sudo wwctl node list -a n0000
# Review Warewulf overlays
sudo wwctl overlay list -l
sudo wwctl overlay list -ls
sudo wwctl overlay edit default /etc/hello_world.ww
sudo wwctl overlay build -a
# Start the Warewulf daemon
sudo wwctl server &
4. Create a new guest VM instance inside the VirtualBox to be the
Warewulf client/compute node. Under the system configuration make
sure to select the optical and network options only for the boot
order. The default iPXE used by VirtualBox does not come with
bzImage capability which is needed for Warewulf. Download the
ipxe.iso available at ipxe.org and mount the ipxe.iso to the
optical drive. Enable one Network adapter for this VM and assign it
to the NAT Network created in step #1 above.
.. code-block:: console
# Download ipxe.so available at http://boot.ipxe.org/ipxe.iso
# VM Settings -> System disable Floppy, Hard Disk from Boot order. Enable Optical and Network options.
# VM Settings -> Storage and mount the above download ipxe.so to the Optical Drive.
# VM Settings -> Network Enable adapter #1, attach to 'Nat Network' and choose 'wwnatnetwork' from the drop down list.
Boot your node and watch the console and the output of the Warewulfd
process.

View File

@@ -0,0 +1,97 @@
=======================
Development Environment
=======================
To develop and test the Warewulf server, you need a single system (typically a
virtual machine) to serve as a test server deployment. To actually test
provisioning your development server also needs a dedicated network that it can
run DHCP on. This can typically be provisioned as a virtual network bridge in
virtual machine software.
Options include:
* KVM / Libvirt
* VirtualBox
* VMWare
* UTM
A Warewulf development environment should likely use Rocky Linux 9 or openSUSE
LEAP 15, though there are ongoing development efforts using Debian and Ubuntu as
well.)
Compiling Warewulf for a Development Server
===========================================
.. code-block:: shell
# Rocky Linux 9
dnf -y install git epel-release golang {libassuan,gpgme}-devel unzip tftp-server dhcp-server nfs-utils ipxe-bootimgs-{x86,aarch64}
git clone https://github.com/warewulf/warewulf.git
cd warewulf
env \
PREFIX=/opt/warewulf \
SYSCONFDIR=/etc \
IPXESOURCE=/usr/share/ipxe \
WWPROVISIONDIR=/opt/warewulf/provision \
WWOVERLAYDIR=/opt/warewulf/overlays \
WWCHROOTDIR=/opt/warewulf/chroots \
make all
make install
These paths balance isolation (e.g., installing binaries in
``/opt/warewulf/bin/``) with integration (e.g., storing configuration in
``/etc/warewulf/`` and using local Dracut and iPXE paths).
After making changes to the source, simply running ``make install`` should be
enough to update installed binaries.
You should likely also disable any local firewall. Otherwise, consult the
general installation guide for configuration details.
.. code-block:: shell
systemctl disable --now firewalld
Running the Test Suite
======================
Warewulf includes an ever-growing test suite. Alias targets in the ``Makefile``
support running it quickly, easily, and consistently.
.. code-block:: shell
make test
Additional tests exist as well to perform various checks on the golang source.
These checks are run automatically by GitHub as part of the Warewulf CI process;
but it is a good idea to run them locally before submitting a new PR.
.. code-block:: shell
make vet
make staticcheck
make lint
New code, and code changes, should often be accompanied by updates to the test
suite.
More information:
* `The golang testing package <https://pkg.go.dev/testing>`_
* `Table Driven Tests <https://go.dev/wiki/TableDrivenTests>`_
* `Testift assert <https://pkg.go.dev/github.com/stretchr/testify/assert>`_
* `Warewulf testenv <https://pkg.go.dev/github.com/warewulf/warewulf/internal/pkg/testenv>`_
Using a Dev Container
=====================
Visual Studio Code (VSC) can utilize a Dev Container for a self-contained
environment that has all the necessary tools and dependencies to build and test
Warewulf. The Dev Container is based on the Rocky 9 image and is built using the
`devcontainer.json` file in the `.devcontainer` directory of the Warewulf
repository. To use this working Docker/Podman and VSC installations are
required. To use the Dev Container, click the "Open a Remote Window" button on
the bottom left of the editor (`><` icon) and select "Reopen in Container".
This will build the container and open a new VSC window with the container as
the development environment.

View File

@@ -2,16 +2,10 @@
Documentation Documentation
============= =============
We (like almost all open source software providers) have a You can contribute to the documentation by `raising an issue to suggest an
documentation dilemma… We tend to focus on the code features and improvement <https://github.com/warewulf/warewulf/issues/new>`_ or by sending a
functionality before working on documentation. And there is very good `pull request <https://github.com/warewulf/warewulf/compare>`_ on `our GitHub
reason for this: we want to share the love so nobody feels left out! repository <https://github.com/warewulf/warewulf>`_.
You can contribute to the documentation by `raising an issue to
suggest an improvement
<https://github.com/warewulf/warewulf/issues/new>`_ or by sending a
`pull request <https://github.com/warewulf/warewulf/compare>`_ on
`our repository <https://github.com/warewulf/warewulf>`_.
The current documentation is generated with `Sphinx The current documentation is generated with `Sphinx
<https://www.sphinx-doc.org/>`_. <https://www.sphinx-doc.org/>`_.
@@ -19,4 +13,4 @@ The current documentation is generated with `Sphinx
For more information on using Git and GitHub to create a pull request For more information on using Git and GitHub to create a pull request
suggesting additions and edits to the docs, see the `section on suggesting additions and edits to the docs, see the `section on
contributing to the code <contributing>`_. The procedure is identical contributing to the code <contributing>`_. The procedure is identical
for contributions to the documentation and the code base. for contributions to documentation and code.

View File

@@ -1,28 +0,0 @@
FROM debian
# Disclaimer:
# this is WIP and subject to change, ant feedback is highly appreciated
# squelsh apt-get
ENV DEBIAN_FRONTEND noninteractive
ENV RUNLEVEL 1
# ----- install vital packages -----
# 'dbus' might makes sense as well
RUN apt-get update && apt-get install -y --no-install-recommends \
kmod \
systemd-sysv \
openssh-client \
openssh-server \
isc-dhcp-client \
pciutils \
strace \
nfs-common \
ethtool\
ifupdown \
linux-image-amd64 \
ifmetric \
netbase && \
rm -rf /var/lib/apt/lists/*
ENV DEBIAN_FRONTEND teletype

View File

@@ -1,21 +0,0 @@
# Debian, Buster
## Docker container
### build and push
> PSI specific, change for upstream
change into your docker build directory
```bash
docker build -t docker.psi.ch:5000/debian:buster-slim .
docker push docker.psi.ch:5000/debian:buster-slim
```
### import docker container into Warewulf
```bash
wwctl container import docker://docker.psi.ch:5000/debian:buster-slim debian-10:slim
```

View File

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 91 KiB

View File

@@ -1,7 +1,8 @@
===================================== =================
Debian 12 Quickstart Debian Quickstart
===================================== =================
Deploying Warewulf for Debian 12.
Install the basic services Install the basic services
========================== ==========================
@@ -10,7 +11,6 @@ Install the basic services
sudo apt install firewalld nfs-kernel-server tftpd-hpa isc-dhcp-server sudo apt install firewalld nfs-kernel-server tftpd-hpa isc-dhcp-server
.. note:: .. note::
If you get an error message concerning *isc-dhcp-server.service* you If you get an error message concerning *isc-dhcp-server.service* you
@@ -18,19 +18,15 @@ Install the basic services
will listen to. Run ``sudo dpkg-reconfigure isc-dhcp-server`` and enter will listen to. Run ``sudo dpkg-reconfigure isc-dhcp-server`` and enter
the name of your cluster's private network interface (e.g. enp2s0). After that, you might also need to run ``sudo systemctl enable isc-dhcp-server``. the name of your cluster's private network interface (e.g. enp2s0). After that, you might also need to run ``sudo systemctl enable isc-dhcp-server``.
Install Warewulf and dependencies Install Warewulf and dependencies
================================= =================================
.. code-block:: bash .. code-block:: bash
sudo apt install build-essential curl unzip sudo apt install build-essential curl unzip
sudo apt install git golang libnfs-utils libgpgme-dev libassuan-dev sudo apt install git golang libnfs-utils libgpgme-dev libassuan-dev
mkdir ~/git mkdir ~/git
cd ~/git cd ~/git
git clone https://github.com/warewulf/warewulf.git git clone https://github.com/warewulf/warewulf.git
@@ -38,8 +34,6 @@ Install Warewulf and dependencies
git checkout main # or switch to a tag like 'v4.6.0rc3' git checkout main # or switch to a tag like 'v4.6.0rc3'
make all && sudo make install make all && sudo make install
Configure firewalld Configure firewalld
=================== ===================

View File

@@ -1,6 +1,9 @@
=========================================================== ===========================
Enterprise Linux Quickstart (Rocky Linux, CentOS, and RHEL) Enterprise Linux Quickstart
=========================================================== ===========================
Deploying Warewulf for Rocky Linux, CentOS, RHEL, and other related
distributions.
Install Warewulf Install Warewulf
================ ================
@@ -22,17 +25,27 @@ Install Warewulf from source
If you prefer, you can also install Warewulf from source. If you prefer, you can also install Warewulf from source.
.. code-block:: bash .. code-block:: shell
dnf install git dnf install git
dnf install epel-release dnf install epel-release
dnf install golang {libassuan,gpgme}-devel unzip tftp-server dhcp nfs-utils ipxe-bootimgs-{x86,aarch64} dnf install golang {libassuan,gpgme}-devel unzip tftp-server dhcp-server nfs-utils ipxe-bootimgs-{x86,aarch64}
git clone https://github.com/warewulf/warewulf.git git clone https://github.com/warewulf/warewulf.git
cd warewulf cd warewulf
make all PREFIX=/usr/local make defaults
make install make install
.. note::
Some packages, like ``libassuan-devel`` and ``gpgme-devel``, require either
PowerTools (EL8) or CodeReady Builder (EL9) repositories.
.. code-block::
dnf config-manager --set-enabled PowerTools # EL8
dnf config-manager --set-enabled crb # EL9
Configure firewalld Configure firewalld
=================== ===================

View File

@@ -0,0 +1,103 @@
========
Glossary
========
Cluster network
A dedicated network for the Warewulf cluster. Used for provisioning
communication between cluster nodes and the Warewulf server.
External services
The Warewulf server can configure external services to support the
provisioning process. For example, the Warewulf server typically deploys and
configures a DHCP server (either ISC DHCP or dnsqmasq) and a TFTP server.
Image
The node images that Warewulf manages and provisions. Images may be imported
from OCI image registries, OCI image archives, Apptainer sandboxes, and
manual chroot directories.
Warewulf images are maintained as an uncompressed "virtual node file system"
(VNFS, sometimes also referred to as a "chroot"). These virtual file systems
are then built as single-file images which may be used to provision a node.
Kernel
In addition to an image, Warewulf also requires a kernel (typically a Linux
kernel) in order to provision a node.
Warewulf (after v4.3.0) automatically provisions a kernel detected and
extracted from the image itself. In most cases, kernels may be installed in
the image using normal system packages, and no special consideration is
necessary.
Node
Warewulf nodes are the systems that are being provisioned by Warewulf. The
roles of these systems could be "compute", "storage", "GPU", "IO", etc.
nodes.conf
One of two primary Warewulf configuration files, ``nodes.conf`` is a YAML
document which records all configuration parameters for Warewulf's nodes and
profiles. It does not contain the images or overlays, but refers to them by
name.
This file is sometimes referred to as the "nodes database" or "node
registry."
Overlay
Warewulf overlays provide customization for the provisioned image. Overlays
may be configured on nodes or profiles, as either **system** or **runtime**
overlays.
**System overlays** are applied only once, when a node is first provisioned.
**Runtime overlays** are applied when a node is first provisioned and
periodically during the runtime of the node. (The default period is 1
minute.)
Warewulf includes a number of **distribution overlays**; but additional
**site overlays** can be added to a Warewulf environment.
Profile
Warewulf profiles are abstract nodes that carry the same configuration
attributes but do not provision any specific node. Warewulf nodes may then
refer to one or more such profiles for their configuration. In this way,
profiles provide a simple mechanism for applying configuration to a group of
nodes, and this configuration may be mixed with configuration from other
profiles.
Server, Warewulf
The Warewulf controller runs the Warewulf daemon (``warewulfd``) and is
responsible for the management, control, and administration of the cluster.
This system may also sometimes be referred to as the "master," "head," or
"admin" node.
A typical Warewulf controller also runs a DHCP service and a TFTP service,
and often an NFS service; though these services may be managed separately
and on separate servers.
Two-stage boot
A two-stage boot uses an intermediate image (often called "initrd," or
"initramfs") to initialize hardware and load the final image. This contrasts
with Warewulf's default "single stage" behavior, which effectively uses the
final image as a large initial root file system.
The Warewulf two-stage boot process currently supports Dracut-based images.
warewulf.conf
One of two primary Warewulf configuration files, ``warewulf.conf`` is a YAML
document which records all configuration parameters for the Warewulf server
and its optional subservices.
wwclient
Warewulf adds a ``wwclient`` daemon to provisioned nodes. This daemon is
responsible for periodically fetching and applying runtime overlays.
wwctl
The main administrative interface for Warewulf is the ``wwctl`` command,
which provides commands to manage nodes, profiles, images, overlays,
kernels, and more.
wwinit
Warewulf performs some setup during the provisioning process before control
is passed to the provisioned operating system. This process is referred to
as "wwinit," and is implemented and configured by a script and overlay of
the same name.

View File

@@ -0,0 +1,111 @@
============
Introduction
============
Warewulf is an operating system provisioning platform for Linux clusters. Since
its initial release in 2001, Warewulf has become the most popular open source
and vendor-agnostic provisioning system within the global HPC community.
Warewulf is known for its massive scalability and simple management of stateless
(disk optional) provisioning.
Warewulf leverages a simple administrative model centralizing administration
around virtual node images which are used to provision out to the cluster nodes.
This means you can have hundreds or thousands of cluster nodes all booting and
running on the same node image. As of Warewulf v4, the node image can be managed
using industry-standard container tooling and/or CI/CD pipelines. This can be as
simple as DockerHub or your own private GitLab CI infrastructure. With this
architecture, Warewulf combines the best of High Performance Computing (HPC),
Cloud, Hyperscale, and Enterprise deployment principals to create and maintain
large scalable stateless clusters.
Warewulf is used most prominently in High Performance Computing (HPC) clusters,
but its architecture is flexible enough to be used in most any clustered Linux
environment, including clustered web servers, rendering farms, and even
Kubernetes and cloud deployments.
Warewulf design
===============
Warewulf has had a number of iterations since its inception in 2001, but its
design tenets have always remained the same: a simple, scalable, stateless, and
flexible provisioning system for all types of clusters.
* **Lightweight**: Warewulf provisions stateless operating system images and
then gets out of the way. There are no underlying system dependencies or
requisite changes to the provisioned cluster node operating system.
* **Simple**: Warewulf is used by hobbyists, researchers, scientists, engineers
and systems administrators alike.
* **Flexible**: Warewulf can address the needs of any environment--from a
computer lab with graphical workstations, to under-the-desk clusters, to
supercomputing centers providing HPC services to thousands of users.
* **Agnostic**: From the Linux distribution of choice to the underlying
hardware, Warewulf is agnostic and standards compliant. From ARM to x86, Atos
to Dell, Debian, SUSE, Rocky, CentOS, and RHEL, Warewulf can be used in most
any environment.
* **Secure**: Warewulf support SELinux out-of-the-box. Just install SELinux in
your node image and let Warewulf do the rest!
* **Open Source**: Warewulf is and has always been open source. It can be used
in any environment, whether public, private, non-profit, or commercial. And
the Warewulf project is always welcoming of contribution from its community of
users, with major features often beginning as external contributions.
Warewulf architecture
=====================
Warewulf v4 has a simple but flexible base architecture:
A **Warewulf server** stores information about the cluster and the nodes in it,
and provides a command-line interface (``wwctl``) for managing nodes, their
images, and their overlays.
**Cluster nodes** are defined in a flexible `YAML
<https://en.wikipedia.org/wiki/YAML>`_ file, including their network
configuration and image and overlay assignments.
**Node profiles** provide a flexible abstraction for applying configuration to
multiple nodes.
**Node images** provide a bootable operating system image, including the kernel
that will be used to boot the cluster node. Node images provide a base operating
system and, by default, run entirely in memory. This means that when you
reboot the node, the node retains no information about Warewulf or how it
booted; but it also means that they return to their initial known-good state.
**Overlays** customize the provisioned operating system image with static files
and dynamic templates applied with the node image and, optionally, periodically
at runtime.
Beowulf overview
================
Warewulf is designed to support the original `Beowulf Cluster
<https://en.wikipedia.org/wiki/Beowulf_cluster>`_ concept. (Thus its name, a
soft\ **WARE** implementation of the beo\ **WULF**.) The architecture is
characterized by a group of similar cluster nodes all connected together using
standard commodity equipment on an internal cluster network. The server node
(often historically referred to as the "master" or "head" node) is "dual homed"
(i.e., it has two network interfaces) with one of these network interfaces
attached to an external network and the other connected to the internal cluster
network.
.. image:: beowulf_architecture.png
:alt: Beowulf architecture
This simple topology is the foundation for creating a scalable HPC cluster
resource. Even today, almost 30 years after the inception of this architecture,
this is the baseline architecture that virtually all HPC systems are built to.
An HPC cluster often includes dedicated storage, scheduling and resource
management, monitoring, interactive systems, and other components. For smaller
systems, many of these components can be deployed to a single server node; but,
as the system scales, it may be better to have groups of nodes dedicated to
these different services.
Warewulf is flexible enough to start with a simple "head node" Beowulf style
cluster deployment and to grow as needs for the cluster and its environment
change.

View File

@@ -1,69 +1,47 @@
==================== ================
Control Server Setup Network Planning
==================== ================
Operating System Installation A clustered resource depends on a cluster network. This network can be either
============================= persistent (it is always "up" even after provisioning) or temporary, only used
for provisioning and/or out of band system control and management (e.g., IPMI).
Warewulf has almost no predetermined or required configurations aside The cluster network must be dedicated to the cluster because Warewulf uses
from a base architecture networking layout. Install your Linux network services (particularly DHCP) which may conflict with services on another
distribution of choice as you would like, but do pay attention to the mixed-use network. A dedicated cluster network is also important for security,
cluster's private network configuration. as the cluster network often has an implicit level of trust associated with it.
Network The Warewulf server is often "dual homed," meaning that it has separate network
======= interfaces connected to each of the cluster network and an external network. But
it is also possible for the cluster network to be routable from other, more
general-purpose networks.
A clustered resource depends on a private management network. This Many clusters have more than one internal network. This is common for
network can be either persistent (it is always "up" even after performance critical HPC clusters that implement a high speed and low latency
provisioning) to temporary which might only be used for provisioning network like InfiniBand. In this case, this network is used for high speed data
and/or out of band system control and management e.g. IPMI). transfers for inter-process communication between compute nodes and file system
IO.
It is important for this management network to be private to the Warewulf will need to be configured to use the private cluster management
compute resource because Warewulf requires network services on that network. Warewulf will use this network for booting the nodes over PXE. There
network which may conflict with services on the production/public are three network protocols used to accomplish this DHCP/BOOT, TFTP, and HTTP on
network (e.g. DHCP). It is also important from a security perspective port ``9873``. Warewulf will use the operating system's provided version of DHCP
as the management network for typical HPC systems have an implied (ISC-DHCP) and TFTP for the PXE bootstrap to iPXE, and then iPXE will use
trust level associated with it and generally there is no firewalling Warewulf's internal HTTP services to transfer the larger files for provisioning.
or network monitoring occurring on these networks.
Usually, the control node is "dual homed" which means it has at least
two interface cards, one connected to the private cluster network and
one dedicated to the public network (as the figure above
demonstrates).
.. note::
It is possible to omit the public network interface with a reverse
NAT. Warewulf can operate in this configuration but it extends
beyond the scope of this documentation.
Many clusters have more than one private network. This is common for
performance critical HPC clusters that implement a high speed and low
latency network like InfiniBand. In this case, this network is used
for high speed data transfers for inter-process communication between
compute nodes and file system IO.
Warewulf will need to be configured to use the private cluster
management network. Warewulf will use this network for booting the
nodes over PXE. There are three network protocols used to accomplish
this DHCP/BOOT, TFTP, and HTTP on port ``9873``. Warewulf will use the
operating system's provided version of DHCP (ISC-DHCP) and TFTP for
the PXE bootstrap to iPXE, and then iPXE will use Warewulf's internal
HTTP services to transfer the larger files for provisioning.
Addressing Addressing
========== ==========
The addressing scheme of your private cluster network is 100% up to The addressing scheme of your private cluster network is 100% up to the system
the system integrator, but for large clusters, many organizations like integrator, but for large clusters, many organizations like to organize the
to organize the address allocations. Below is a recommended IP address allocations. Below is a recommended IP addressing scheme which we will
addressing scheme which we will use for the rest of this document. use for the rest of this document.
* ``10.0.0.1``: Private network address IP * ``10.0.0.1``: Private network address IP
* ``255.255.252.0``: Private network subnet mask (``10.0.0.0/22``) * ``255.255.252.0``: Private network subnet mask (``10.0.0.0/22``)
Here is an example of how the cluster's address can be divided for a Here is an example of how the cluster's address can be divided for a 255 node
255 node cluster: cluster:
* ``10.0.0.1 - 10.0.0.255``: Cluster infrastructure including this * ``10.0.0.1 - 10.0.0.255``: Cluster infrastructure including this
host, schedulers, file systems, routers, switches, etc. host, schedulers, file systems, routers, switches, etc.
@@ -75,13 +53,15 @@ Here is an example of how the cluster's address can be divided for a
Multiple networks Multiple networks
================= =================
It is possible to configure several networks not just for the nodes but also for the management of ``dhcpd`` and ``tftp``. It is possible to configure several networks not just for the nodes but also for
There are two ways to achive this: the management of ``dhcpd`` and ``tftp``. There are two ways to achieve this:
1. Add the networks to the templates of ``dhcpd`` and/or the ``dnsmasq`` template directly. * Add the networks to the templates of ``dhcpd`` and/or the ``dnsmasq`` template
2. Add the networks to a dummy node and change the templates of ``dhcp`` and ``dnsmasq`` accordingly. directly.
* Add the networks to a dummy node and change the templates of ``dhcp`` and
``dnsmasq`` accordingly.
As the first solution is trivial only the second way is described in the following lines. The first method is relatively trivial. The second method is described below.
As first the first step, add the dummy node. As first the first step, add the dummy node.
@@ -89,7 +69,7 @@ As first the first step, add the dummy node.
wwctl node add deliverynet wwctl node add deliverynet
Now you will have to add the delivery networks to this node. Add the delivery networks to this node.
.. code-block:: shell .. code-block:: shell
@@ -107,8 +87,9 @@ Now you will have to add the delivery networks to this node.
--nettagadd network=10.0.30.0,dynstart=10.10.30.10,dynend=10.10.30.50 \ --nettagadd network=10.0.30.0,dynstart=10.10.30.10,dynend=10.10.30.50 \
deliverynet deliverynet
The ip address is used as the network address of host in the delivery network and an additional tags is used for definition of the network itself and the dynamic dhcp range. The ip address is used as the network address of host in the delivery network
You can check the result with ``wwctl node list``. and an additional tags is used for definition of the network itself and the
dynamic dhcp range. You can check the result with ``wwctl node list``.
.. code-block:: console .. code-block:: console
@@ -119,7 +100,7 @@ You can check the result with ``wwctl node list``.
deliverynet ImageName default leap15.5 deliverynet ImageName default leap15.5
deliverynet Ipxe -- (default) deliverynet Ipxe -- (default)
deliverynet RuntimeOverlay -- (hosts,ssh.authorized_keys) deliverynet RuntimeOverlay -- (hosts,ssh.authorized_keys)
deliverynet SystemOverlay -- (wwinit,wwclient,fstab,hostname,ssh.host_keys,issue,resolv,udev.netname,systemd.netname,ifcfg,NetworkManager,debian.interfaces,wicked,ignition) deliverynet SystemOverlay -- (wwinit,wwclient,hostname,ssh.host_keys,systemd.netname,NetworkManager)
deliverynet Root -- (initramfs) deliverynet Root -- (initramfs)
deliverynet Init -- (/sbin/init) deliverynet Init -- (/sbin/init)
deliverynet Kernel.Args -- (quiet crashkernel=no net.ifnames=1) deliverynet Kernel.Args -- (quiet crashkernel=no net.ifnames=1)
@@ -142,7 +123,6 @@ You can check the result with ``wwctl node list``.
deliverynet NetDevs[deliver1].Tags[dynstart] -- 10.10.20.10 deliverynet NetDevs[deliver1].Tags[dynstart] -- 10.10.20.10
Now the templates of ``dhcpd`` and/or ``dnsmasq`` must be modified. Now the templates of ``dhcpd`` and/or ``dnsmasq`` must be modified.
You can edit the configuration files.
.. code-block:: shell .. code-block:: shell
@@ -181,4 +161,5 @@ and for the ``dnsmasq`` the following lines should be added
{{- end }} {{- end }}
{{- end }} {{- end }}
Note that the ``{{- if eq $node.Id.Get "deliverynet" }}`` is used to identify the dummy host which carries the network information. Note that the ``{{- if eq $node.Id.Get "deliverynet" }}`` is used to identify
the dummy host which carries the network information.

View File

@@ -0,0 +1,93 @@
====================
Cluster Provisioning
====================
Clusters have many scalability factors to consider. Often overlooked among them
is "administrative scaling"-- the systems administration overhead of a person or
team maintaining a large number of systems. While homogeneous configurations do
improve administrative scaling, each installed server is still subject to
version and configuration drift, eventually becoming a point of discrete
administration and debugging. The larger the cluster, the harder this problem is
to solve.
This is the problem that Warewulf was created solve.
Provisioning Overview
=====================
Provisioning is the process of preparing a system for use, typically by
providing and configuring an operating system. There are many ways to accomplish
this, from copying hard drives, to scripted installs, to automated installs.
Each has its place, and there are many tools available to facilitate each
method.
Before dedicated cluster provisioning systems, administrators would visit each
cluster node and install it from scratch, with an ISO, CD, or USB flash drive.
This is obviously not scalable. Because the nodes in a cluster environment are
typically identical, it is much more efficient to group sets of nodes together
to be provisioned in bulk.
Why Stateless Provisioning
==========================
Warewulf further improves on the automated provisioning process by skipping the
installation completely; it boots directly into the runtime operating system
without ever doing an installation.
Stateless provisioning means you never have to install another compute node.
Think of it like booting a LiveOS or LiveISO on nodes over the network. This
means that no node requires discrete administration, but rather the entire
cluster is administrated as a single unit. There is no version drift, because it
is not possible for nodes to fall out of sync. Every reboot makes it exactly the
same as its neighbors.
Cluster Node Requirements
=========================
The only requirement to provision a node with Warewulf is that the node is set
to PXE boot. You may need to change the boot order if there is a local disk
present and bootable. This is a configuration change you will have to make in
the BIOS of the cluster node.
This configuration is different for each vendor platform. For more information,
consult your system documentation or contact your hardware vendor support.
.. note::
Hardware vendors are often able to preconfigure your cluster nodes with
values of your choosing. Ask them to provide a text file that includes all of
the network interface MAC addresses of the clusters nodes in the order they
are racked--this simplifies the process of adding nodes to Warewulf.
The Provisioning Process
========================
When a cluster node boots from Warewulf, the following process occurs:
#. The system firmware (either BIOS or UEFI) initializes hardware, including
local network interfaces.
#. The system uses an in-firmware PXE client to obtain a BOOTP/DHCP address from
the network.
#. The DHCP server (hosted either on the Warewulf server or externally) responds
with an address suitable for provisioning, along with a "next-server" option
directing the cluster node to download (via TFTP) and execute a bootloader
(either iPXE or GRUB) with a Warewulf-provided configuration.
#. The bootloader configuration directs the cluster node to download and
bootstrap the configured kernel, image, and overlays from the Warewulf (HTTP)
server.
* In a single-stage provisioning configuration, the desired image and
overlays are combined and provisioned immediately by the bootloader as the
kernel's initial root file system. This is straightfoward, but does not
work in all environments: some systems have memory layouts that are not
handled properly by either iPXE or GRUB for sufficiently large image sizes,
leading to strange, unpredictable results.
* In a two-stage provisioning configuration, a small initial root fs (created
by dracut) is provisioned first, and this image uses the provisioned Linux
kernel to retrieve and deploy the full image and overlays. Perhaps
counter-intuitively, the two-stage provisioning process is often quicker
than the single-stage process, because the Linux environment is more I/O
efficient than the bootloader itself.
#. Optionally included in a configured overlay, ``wwclient`` is left resident on
the cluster node and periodically refreshes configured runtime overlays.

View File

@@ -1,6 +1,8 @@
==================================== ===============
openSUSE Leap and SLES 15 Quickstart SUSE Quickstart
==================================== ===============
Deploying Warewulf for openSUSE Leap and SLES 15.
Install Warewulf and dependencies Install Warewulf and dependencies
================================= =================================

469
userdocs/images/images.rst Normal file
View 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.

View File

@@ -1,14 +1,13 @@
================= =============
Kernel Management Image Kernels
================= =============
Warewulf nodes require a Linux kernel to boot. As of Warewulf v4.6, the kernel 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 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 provisions the kernel automatically for any node configured to use that image.
image.
You can see what kernels are available in imported images by using the You can see what kernels are available in imported images by using the ``wwctl
``wwctl image kernels`` command: image kernels`` command.
.. code-block:: console .. code-block:: console

View 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``.

View 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.

View File

@@ -6,52 +6,69 @@ Welcome to the Warewulf User Guide!
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Contents :caption: Getting Started
Introduction <contents/introduction> Introduction <getting-started/introduction>
Background <contents/background> The Provisioning Process <getting-started/provisioning>
Stateless Provisioning <contents/stateless> Network Planning <getting-started/network>
Control Server Setup <contents/setup> Enterprise Linux Quickstart (Rocky Linux, CentOS, and RHEL) <getting-started/el-quickstart>
Warewulf Installation <contents/installation> SUSE Quickstart (openSUSE Leap and SLES) <getting-started/suse-quickstart>
Warewulf Configuration <contents/configuration> Debian Quickstart <getting-started/debian-quickstart>
Upgrading Warewulf <contents/upgrade> Glossary <getting-started/glossary>
Controlling Warewulf (wwctl) <contents/wwctl>
Warewulf Initialization <contents/initialization>
Image Management <contents/images>
Kernel Management <contents/kernel>
Boot Management <contents/boot-management>
Node Configuration <contents/nodeconfig>
Node Profiles <contents/profiles>
Warewulf Overlays <contents/overlays>
Node Provisioning <contents/provisioning>
IPMI <contents/ipmi>
Disk Management <contents/disks>
Security <contents/security>
Templating <contents/templating>
dnsmasq <contents/dnsmasq>
Troubleshooting <contents/troubleshooting>
Known issues <contents/known-issues>
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Quickstart :caption: Server
Enterprise Linux (Rocky Linux, CentOS, and RHEL) <quickstart/el> Server Installation <server/installation>
openSUSE Leap and SLES 15 <quickstart/suse15> Controlling Warewulf (wwctl) <server/wwctl>
Debian 12 <quickstart/debian12> Server Configuration <server/configuration>
Using dnsmasq <server/dnsmasq>
Security <server/security>
Bootloaders <server/bootloaders>
Upgrading Warewulf <server/upgrade>
.. toctree::
:maxdepth: 2
:caption: Nodes and Profiles
Cluster Nodes <nodes/nodes>
Node Profiles <nodes/profiles>
Network <nodes/network>
IPMI <nodes/ipmi>
Disks <nodes/disks>
.. toctree::
:maxdepth: 2
:caption: Images
Node Images <images/images>
Image Kernels <images/kernel>
Syncuser <images/syncuser>
SELinux <images/selinux>
.. toctree::
:maxdepth: 2
:caption: Overlays
Overlays <overlays/overlays>
Templating <overlays/templates>
.. toctree::
:maxdepth: 2
:caption: troubleshooting
Troubleshooting <troubleshooting/troubleshooting>
Known issues <troubleshooting/known-issues>
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Contributing :caption: Contributing
Contributing <contributing/contributing> Contributing <contributing/contributing>
Debugging <contributing/debugging> Development Environment <contributing/development-environment>
Documentation <contributing/documentation> Documentation <contributing/documentation>
Development Environment (Dev Container/VSC) <contributing/development-environment-devcontainer> Debugging <contributing/debugging>
Development Environment (Vagrant) <contributing/development-environment-vagrant>
Development Environment (KVM) <contributing/development-environment-kvm>
Development Environment (VirtualBox) <contributing/development-environment-vbox>
Glossary <contents/glossary>
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1

147
userdocs/nodes/disks.rst Normal file
View File

@@ -0,0 +1,147 @@
==================
Provisioning disks
==================
As a tech preview, Warewulf provides structures to define disks, partitions, and
file systems. These structures can generate a configuration for `Ignition`_ to
provision partitions and file systems dynamically on cluster nodes.
.. _Ignition: https://coreos.github.io/ignition/
Ignition can, for example, create ``swap`` partitions or ``/scratch`` file
systems.
.. note::
Warewulf is not currently able to provision the node image onto an explicitly
provisioned root file system.
Requirements
============
Partition and file system creation requires both ``ignition`` and ``sgdisk`` to
be installed in the image.
Rocky Linux
-----------
.. code-block:: shell
dnf install ignition gdisk
.. note::
Packages for Ignition are not currently available for Rocky Linux 8, but it
is available for Rocky Linux 9 as part of "appstream."
openSuse Leap
-------------
.. code-block:: shell
zypper install ignition gptfdisk
Disks and partitions
====================
A node or profile can have several disks. Each disk is identified by the path to
its block device. Each disk holds a map to its partitions and a ``bool`` switch
to indicate if an existing, non-matching partition table should be overwritten.
Each partition is identified by its label. The partition number can be omitted,
but specifying it is recommended as Ignition may fail without it. Partition
sizes should also be set (specified in MiB), except for the last partition: if
no size is given, the maximum available size is used. Each partition has the
switches ``should_exist`` and ``wipe_partition_entry`` which control the
partition creation process. When omitting a partition number the
`wipe_partition_entry` should be true, as this allows ignition to replace the
existing partition.
.. code-block:: shell
wwctl node set n1 \
--diskname /dev/vda --diskwipe \
--partname scratch --partcreate --partnumber 1
File systems
============
File systems are identified by their underlying block device, preferably using
the ``/dev/by-partlabel`` format. Except for a ``swap`` partition, an absolute
path for the mount point must be specified for each file system. Depending on
the image used, valid formats are ``btrfs``, ``ext3``, ``ext4``, and ``xfs``.
Each file system has the switch ``wipe_filesystem`` to control whether an
existing file system is wiped.
.. code-block:: shell
wwctl node set n1 \
--diskname /dev/vda --partname scratch \
--fsname scratch --fsformat btrfs --fspath /scratch
Boot-time configuration
=======================
Ignition uses systemd, as the underlying ``sgdisk`` command relies on dbus
notifications.
1. ``ignition-disks-ww4.service`` uses Ignition to create the specified
partitions and file systems.
2. ``ww4-disks.target`` depends on a matching ``.mount`` unit for each
mounted file system.
3. Each ``.mount`` creates the necessary mount points in the root file system
and mounts the provisioned file systems during boot.
These services and mount units are generated by the ``ignition`` overlay and
depend on the existence of the file ``/warewulf/ignition.json``, also generated
by the ``ignition`` overlay.
Example disk configurations
===========================
This command formats a btrfs file system on a "scratch" partion of
"vda" and mounts it at ``/scratch``.
.. code-block:: shell
wwctl node set n1 \
--diskname /dev/vda --diskwipe \
--partname scratch --partcreate --partnumber 1 \
--fsname scratch --fsformat btrfs --fspath /scratch
This command adds a swap partition to the "vda" disk.
.. code-block:: shell
wwctl node set n1 \
--diskname /dev/vda \
--partname swap --partsize=1024 --partnumber 2 \
--fsname swap --fsformat swap --fspath swap
Re-using or wiping disks
========================
For empty disks the desired configuration is created and the filesystems are
mounted. If partitions or file systems already exist on the disk, ``ignition``
tries to reuse existing file systems by default.
To ignore existing file systems and provision fresh file systems on each boot,
specify the ``--fswipe``` flag for that filesystem, and ``--diskwipe`` for the
disk, as necessary.
If you would like to re-use existing partitions but want to replace existing
file systems once, you may
* wipe the existing data with tools like ``wipefs`` or `dd` [#]_; or
* set the ``--fswipe`` flag and remove it after one reboot.
.. [#] With ``wipefs`` you have to remove the filesystem *and* parition
information. E.g., use ``wipefs -fa /dev/vda*`` to remove all file system
information and partition information.
See the `upstream ignition documentation`_ for additional information.
.. _upstream ignition documentation: https://coreos.github.io/ignition/operator-notes/#filesystem-reuse-semantics

139
userdocs/nodes/ipmi.rst Normal file
View File

@@ -0,0 +1,139 @@
.. _ipmi:
====
IPMI
====
Warewulf can use IPMI to control cluster node power state or to connect to a
serial console.
Configuration
=============
Typically, common settings for IPMI interfaces are set on a profile, leaving
only the IP address set per-node.
If ``--ipmiwrite`` is set to `true`, the ``wwinit`` overlay will write the
desired IPMI configuration to the node's BMC during boot.
.. code-block::
wwctl profile set default \
--ipminetmask=255.255.255.0 \
--ipmiuser=admin \
--ipmipass=passw0rd \
--ipmiinterface=lanplus \
--ipmiwrite
wwctl node set n1 \
--ipmiaddr=192.168.2.1
``wwctl node list`` has a specific overview for IPMI settings.
.. code-block:: console
# wwctl node list --ipmi
NODE IPMI IPADDR IPMI PORT IPMI USERNAME IPMI INTERFACE
---- ----------- --------- ------------- --------------
n1 192.168.1.11 -- hwadmin lanplus
n2 192.168.1.12 -- hwadmin lanplus
n3 192.168.1.13 -- hwadmin lanplus
n4 192.168.1.14 -- hwadmin lanplus
Power
=====
The ``wwctl power`` command can query and set the current power state of cluster
nodes.
.. code-block:: console
wwctl power status n1 # query the current power status
wwctl power off n1 # power off a cluster node
wwctl power on n1 # power on a cluster node
wwctl power reset n1 # forcibly reboot a node
wwctl power soft n1 # ask a node to shut down gracefully
wwctl power cycle n1 # power a cluster node off, then back on
Node ranges are supported; e.g., ``n[1-10]``.
Console
=======
If your node is setup to use serial over lan (SOL), Warewulf can connect a
console to the node.
.. code-block:: console
# wwctl node console n1
Customization
=============
Warewulf doesn't manage IPMI interfaces directly, but uses ``ipmitool``. This is
configured with a template which defines Warewulf's IPMI behavior.
.. code-block::
{{/* used command to access the ipmi interface of the nodes */}}
{{- $escapechar := "~" }}
{{- $port := "623" }}
{{- $interface := "lan" }}
{{- $args := "" }}
{{- if .EscapeChar }} $escapechar = .EscapeChar {{ end }}
{{- if .Port }} {{ $port = .Port }} {{ end }}
{{- if .Interface }} {{ $interface = .Interface }} {{ end }}
{{- if eq .Cmd "PowerOn" }} {{ $args = "chassis power on" }} {{ end }}
{{- if eq .Cmd "PowerOff" }} {{ $args = "chassis power off" }} {{ end }}
{{- if eq .Cmd "PowerCycle" }} {{ $args = "chassis power cycle" }} {{ end }}
{{- if eq .Cmd "PowerReset" }} {{ $args = "chassis power reset" }} {{ end }}
{{- if eq .Cmd "PowerSoft" }} {{ $args = "chassis power soft" }} {{ end }}
{{- if eq .Cmd "PowerStatus" }} {{ $args = "chassis power status" }} {{ end }}
{{- if eq .Cmd "SDRList" }} {{ $args = "sdr list" }} {{ end }}
{{- if eq .Cmd "SensorList" }} {{ $args = "sensor list" }} {{ end }}
{{- if eq .Cmd "Console" }} {{ $args = "sol activate" }} {{ end }}
{{- $cmd := printf "ipmitool -I %s -H %s -p %s -U %s -P %s -e %s %s" $interface .Ipaddr $port .UserName .Password $escapechar $args }}
{{ $cmd }}
A different template can be used to change the IPMI behavior using the
``--ipmitemplate`` field. Referenced templates must be located in
``warewulf.conf:Paths.Datadir`` (``/usr/lib/warewulf/bmc/``).
All IPMI specific fields are accessible in the template:
+---------------------+--------------------+
| Parameter | Template variable |
+=====================+====================+
| ``--ipmiaddr`` | ``.Ipaddr`` |
+---------------------+--------------------+
| ``--ipminetmask`` | ``.Netmask`` |
+---------------------+--------------------+
| ``--ipmiport`` | ``.Port`` |
+---------------------+--------------------+
| ``--ipmigateway`` | ``.Gateway`` |
+---------------------+--------------------+
| ``--ipmiuser`` | ``.UserName`` |
+---------------------+--------------------+
| ``--ipmipass`` | ``.Password`` |
+---------------------+--------------------+
| ``--ipmiinterface`` | ``.Interface`` |
+---------------------+--------------------+
| ``--ipmiwrite`` | ``.Write`` |
+---------------------+--------------------+
| ``--ipmiescapechar``| ``.EscapeChar`` |
+---------------------+--------------------+
| ``--ipmitemplate`` | ``.Template`` |
+---------------------+--------------------+
Additionally, the ``.Cmd`` variable includes the relevant ``wwctl power``
subcommand.
* ``PowerOn``
* ``PowerOff``
* ``PowerCycle``
* ``PowerReset``
* ``PowerSoft``
* ``PowerStatus``
* ``SDRList``
* ``SensorList``
* ``Console``

View File

@@ -0,0 +1,96 @@
.. _node-network:
==================
Network Interfaces
==================
By default, network configurations are applied to a "default" network interface.
.. code-block:: shell
wwctl node set n1 \
--netdev=eno1 \
--hwaddr=00:00:00:00:00:01 \
--ipaddr=10.0.2.1 \
--netmask=255.255.255.0
Each cluster node can have multiple network interfaces, differentiated by
specifying ``--netname``.
.. code-block:: shell
wwctl node set n1 \
--netname=infiniband \
--netdev=ib1 \
--ipaddr=10.0.3.1 \
--netmask=255.255.255.0
.. warning::
Due to the way network interface names are assigned by the Linux kernel, and
later reassigned by udev and systemd, the use of ``eth0``, ``eth1``, etc. as
interface is strongly discouraged. We recommend the use of the original
predictable names assigned to the interfaces (e.g., ``eno1``), as otherwise
an interface may fail to be named correct if its desired name conflicts with
the kernel-assigned name of another interface during the boot process.
Bonding
=======
Support for bonded / link aggregation network interfaces depends on the network overlay being used.
The ``ifcfg`` and ``NetworkManager`` overlays can configure a network bond like this:
.. code-block:: yaml
network devices:
bond0:
type: Bond
device: bond0
ipaddr: 192.168.3.100
netmask: 255.255.255.0
en1:
device: en1
hwaddr: e6:92:39:49:7b:03
tags:
master: bond0
en2:
device: en2
hwaddr: 9a:77:29:73:14:f1
tags:
master: bond0
VLAN
====
You can set the type also to ``vlan``.
Some network configuration systems use the network device name
(e.g., of the form ``eno1.100``)
to configure VLANs.
Other network systems need additional network tags:
- ``vlan_id``: configures the VLAN ID of the interface
- ``parent_device``: configures which physical interface to use
.. code-block:: shell
wwctl node set \
--netdev vlan42 \
--ipaddr 10.0.42.1 \
--netmask 255.255.252.0 \
--netname iband \
--type vlan \
--nettagadd "vlan_id=42,parent_device=eth0" \
n001
Static Routes
=============
The included Warewulf network overlays support the configuration of static routes
using a network tag of the form ``route<N>=<dest>,<gateway>``.
.. code-block:: shell
wwctl node set n001 \
--nettagadd "route1=192.168.2.0/24,192.168.1.254"

201
userdocs/nodes/nodes.rst Normal file
View File

@@ -0,0 +1,201 @@
=============
Cluster Nodes
=============
Warewulf cluster node configuration is persisted in ``nodes.conf`` (also known
as the "node registry" or "node database"). Editing this file directly is
supported; but it is often better to manage it using the ``wwctl`` command.
.. note::
The ``nodes.conf`` file is YAML document that can be edited directly or
managed with configuation management; but its internal structure is
technically undocumented and subject to change between versions. After
Warewulf v4.6.0, the ``wwctl upgrade nodes`` command can be used to update a
``nodes.conf`` from a previous Warewulf v4 version.
.. warning::
When ``nodes.conf`` is edited directly, ``warewulfd`` must be restarted to reflect the changes.
.. code-block:: shell
systemctl restart warewulfd.service
Adding a Cluster Node
=====================
Adding a cluster node is as simple as running ``wwctl node add``.
.. code-block:: console
# wwctl node add n1 --ipaddr=10.0.2.1
Added node: n1
Several nodes can be added with a node range. In this case, the provided IP
address is automatically incremented.
.. code-block:: console
# wwctl node add n[2-4] --ipaddr=10.0.2.2
Added node: n2
Added node: n3
Added node: n4
# wwctl node list --net n[1-4]
NODE NETWORK HWADDR IPADDR GATEWAY DEVICE
---- ------- ------ ------ ------- ------
n1 default -- 10.0.2.1 <nil> --
n2 default -- 10.0.2.2 <nil> --
n3 default -- 10.0.2.3 <nil> --
n4 default -- 10.0.2.4 <nil> --
Listing Nodes
=============
Once you have configured one or more nodes, you can list them and their
attributes with ``wwctl node list``.
.. code-block:: console
# wwctl node list n[1-5]
NODE NAME PROFILES NETWORK
--------- -------- -------
n1 default --
n2 default --
n3 default --
n4 default --
n5 default --
You can also see the node's full attribute list by specifying ``--all``.
.. code-block:: console
# wwctl node list --all n1
NODE FIELD PROFILE VALUE
---- ----- ------- -----
n1 Profiles -- default
n1 Comment default This profile is automatically included for each node
n1 Ipxe default default
n1 RuntimeOverlay default hosts,ssh.authorized_keys
n1 SystemOverlay default wwinit,wwclient,fstab,hostname,ssh.host_keys,issue,resolv,udev.netname,systemd.netname,ifcfg,NetworkManager,debian.interfaces,wicked,ignition
n1 Kernel.Args default quiet,crashkernel=no
n1 Init default /sbin/init
n1 Root default initramfs
n1 Resources[fstab] default [{"file":"/home","mntops":"defaults,nofail","spec":"warewulf:/home","vfstype":"nfs"},{"file":"/opt","mntops":"defaults,noauto,nofail,ro","spec":"warewulf:/opt","vfstype":"nfs"}]
Setting Node Fields
===================
Node fields are set using the ``wwctl node set`` command. A list of all
available fields is available with ``wwctl node set --help``.
You can also edit nodes as YAML data in an interactive editor using ``wwctl node
edit``.
List values
-----------
Some node fields, such as overlays and kernel aruments, accept a list of values.
These may be specified as a comma-separated list or as multiple arguments.
To include an explicit comma in the value, enclose the value in inner-quotes.
.. code-block:: shell
wwctl node set n1 \
--kernelargs 'quiet,crashkernel=no,nosplash' \
--kernelargs='"console=ttyS0,115200"'
Un-setting Node Fields
----------------------
To un-set a field value, set the value to ``UNDEF``.
.. code-block:: shell
wwctl node set n1 \
--image=UNDEF
Configuring an Image
====================
One of the main things to configure for a cluster node is the image that it
should provision.
.. code-block:: shell
wwctl node set n1 \
--image=rockylinux-9
Images are covered in more detail :ref:`in their own section. <images>`
Configuring the Network
=======================
By default, network configurations are applied to a "default" network interface.
.. code-block:: shell
wwctl node set n1 \
--netdev=eno1 \
--hwaddr=00:00:00:00:00:01 \
--ipaddr=10.0.2.1 \
--netmask=255.255.255.0
Network interface configuration is covered in more detail :ref:`in its own
section. <node-network>`
Node Discovery
==============
The MAC / hardware address (``--hwaddr``) of a cluster node can be automatically
discovered by marking the node ``--discoverable``. If a node attempts to
provision against Warewulf using an interface that is unknown to Warewulf, its
hardware address becomes associated with the first discoverable node. (Multiple
discoverable nodes are sorted lexically, first by cluster, then by ID.)
Once a node has been discovered its "discoverable" field is automatically
cleared.
Tags
====
Cluster nodes support multiple key-value pair tags. Tags may be applied to the
node directly, to network interfaces, and even to IPMI interfaces.
.. code-block:: shell
wwctl node set n1 --tagadd="localtime=UTC"
wwctl node set n1 --nettagadd="DNS1=1.1.1.1"
Resources
=========
Cluster nodes support generic "resources" that may hold arbitrarily complex YAML
data. This data, along with tags, may be used by both distribution and site
overlays.
.. code-block:: yaml
nodeprofiles:
default:
resources:
fstab:
- spec: warewulf:/home
file: /home
vfstype: nfs
mntops: defaults
freq: 0
passno: 0
- spec: warewulf:/opt
file: /opt
vfstype: nfs
mntops: defaults,ro
freq: 0
passno: 0
Resources can only be managed with ``wwctl node edit``.

145
userdocs/nodes/profiles.rst Normal file
View File

@@ -0,0 +1,145 @@
=============
Node Profiles
=============
Node profiles provide a way to scalably group node configurations together.
Instead of redundant configurations for each node, you can set common fields in
a profile and then apply one or more profiles to each node.
Profiles may, themselves, reference other profiles, supporting complex mixtures
of profile configuration and negation.
The Default Profile
===================
A default Warewulf installation will come with a single "default" profile
pre-defined in ``nodes.conf``.
.. code-block:: console
# wwctl profile list
PROFILE NAME COMMENT/DESCRIPTION
------------ -------------------
default This profile is automatically included for each node
If the default profile exists, each new node automatically includes it when it
is added.
You can view the fields of a profile with ``wwctl profile --all``.
.. code-block:: console
# wwctl profile list default --all
PROFILE FIELD VALUE
------- ----- -----
default Profiles --
default Comment This profile is automatically included for each node
default ClusterName --
default ImageName --
default Ipxe default
default RuntimeOverlay hosts,ssh.authorized_keys
default SystemOverlay wwinit,wwclient,fstab,hostname,ssh.host_keys,issue,resolv,udev.netname,systemd.netname,ifcfg,NetworkManager,debian.interfaces,wicked,ignition
default Kernel.Version --
default Kernel.Args quiet,crashkernel=no
default Init /sbin/init
default Root initramfs
default PrimaryNetDev --
default Resources[fstab] [{"file":"/home","mntops":"defaults,nofail","spec":"warewulf:/home","vfstype":"nfs"},{"file":"/opt","mntops":"defaults,noauto,nofail,ro","spec":"warewulf:/opt","vfstype":"nfs"}]
``wwctl node list --all`` indicates which profile defines each field.
.. code-block:: console
# wwctl node list n1 --all
NODE FIELD PROFILE VALUE
---- ----- ------- -----
n1 Profiles -- default
n1 Comment default This profile is automatically included for each node
n1 Ipxe default default
n1 RuntimeOverlay default hosts,ssh.authorized_keys
n1 SystemOverlay default wwinit,wwclient,fstab,hostname,ssh.host_keys,issue,resolv,udev.netname,systemd.netname,ifcfg,NetworkManager,debian.interfaces,wicked,ignition
n1 Kernel.Args default quiet,crashkernel=no
n1 Init default /sbin/init
n1 Root default initramfs
n1 Resources[fstab] default [{"file":"/home","mntops":"defaults,nofail","spec":"warewulf:/home","vfstype":"nfs"},{"file":"/opt","mntops":"defaults,noauto,nofail,ro","spec":"warewulf:/opt","vfstype":"nfs"}]
Setting Profile Fields
======================
(Almost) any node fields can be set on a profile, but some fields don't really
make sense anywhere but a node (e.g., ``--hwaddr`` and ``--ipaddr``).
.. code-block:: shell
wwctl profile set default \
--image=rockylinux-9 \
--netmask=255.255.255.0
Multiple Profiles
=================
It's possible to create multiple profiles, and even to apply multiple profiles
to each node.
.. code-block:: shell
wwctl profile add net
wwctl profile set net --netmask=255.255.255.0
wwctl profile add image
wwctl profile set image --image=rockylinux-9
wwctl node set n1 --profile="default,net,image"
.. note::
If two profiles set the same field, the right-most profile in the node's list
takes precedence. Field values set directly on nodes take precedence over
profile field values.
.. code-block:: console
# wwctl node list n1 --all
NODE FIELD PROFILE VALUE
---- ----- ------- -----
n1 Profiles -- default,net,image
n1 Comment default This profile is automatically included for each node
n1 ImageName image rockylinux-9
n1 Ipxe default default
n1 RuntimeOverlay default hosts,ssh.authorized_keys
n1 SystemOverlay default wwinit,wwclient,fstab,hostname,ssh.host_keys,issue,resolv,udev.netname,systemd.netname,ifcfg,NetworkManager,debian.interfaces,wicked,ignition
n1 Kernel.Args default quiet,crashkernel=no
n1 Init default /sbin/init
n1 Root default initramfs
n1 NetDevs[default].Netmask net 255.255.255.0
n1 Resources[fstab] default [{"file":"/home","mntops":"defaults,nofail","spec":"warewulf:/home","vfstype":"nfs"},{"file":"/opt","mntops":"defaults,noauto,nofail,ro","spec":"warewulf:/opt","vfstype":"nfs"}]
Using multiple profiles makes it easy to work with multiple, heterogeneous
groups of cluster nodes and to test new configurations on smaller subsets of
nodes. For example, you can use this method to run a different kernel on only a
subset or group of cluster nodes without changing any other node attributes.
Negating Profiles
=================
Profiles may be negated by later profiles. For example, a profile list
``p2,~p1`` adds the profile ``p2`` to a node and removes a previously-applied
``p1`` profile from a node.
Using Profiles Effectively
==========================
There are a lot of ways to use profiles to facilitate complex cluster
configurations; but they are not required. It is completely possible to not use
profiles at all, and to simply set all fields directly on cluster nodes.
If you do use profiles, some fields lend themselves most naturally to being set
on profiles. Network subnet masks (``--netmask``) and gateways (``--gateway``)
are common profile fields, as is ``--image``. Most :ref:`IPMI <ipmi>` fields
make sense on a profile, and it is also common to configure tags and resources
on a profile for easy application to multiple nodes.
Node-specific information, like HW/MAC addresses (``--hwaddr``) and IP addresses
(``--ipaddr``, ``--ipmiaddr``) should always be put in a node configuration
rather than a profile configuration.

View File

@@ -0,0 +1,329 @@
========
Overlays
========
Warewulf supplements provisioned node images with an "overlay" system. Overlays
are collections of files and :ref:`templates` that are rendered
and built per-node and then applied over the image during the provisioning
process.
Overlays are the primary mechanism for adding functionality Warewulf. Much of
even core functionality in Warewulf is implemented as distribution overlays, and
this flexibility is also available for local, custom overlays. By combining
templates with tags, network tags, and resources, the node registry
(``nodes.conf``) can become an expressive metadata store for arbitrary cluster
node configuration.
You can list the available overlays with ``wwctl overlay list``, and the files
within the overlays with ``wwctl overlay list --all``.
.. code-block:: console
# wwctl overlay list --all fstab
OVERLAY NAME FILES/DIRS SITE
------------ ---------- ----
fstab etc/ false
fstab etc/fstab.ww false
Structure
=========
An overlay is a directory that is applied to the root of a cluster node's
runtime file system. The overlay source directory should contain a single
``rootfs`` directory which represents the actual root directory for the overlay.
.. code-block:: none
/usr/share/warewulf/overlays/issue
└── rootfs
└── etc
└── issue.ww
Adding Overlays to Nodes
========================
A node or profile can configure an overlay in two different ways:
* An overlay can be configured to apply only during boot, along with the node
image. These overlays are called **system overlays**.
* An overlay can be configured to also apply periodically while the system is
running. These overlays are called **runtime overlays**.
.. code-block:: shell
wwctl profile set default \
--system-overlays="wwinit,,wwclient,fstab,hostname,ssh.host_keys,systemd.netname,NetworkManager" \
--runime-overlays="hosts,ssh.authorized_keys"
Multiple overlays can be applied to a single node, and overlays from multiple
profiles are appended together when applied to a single node.
Building Overlays
=================
Overlays are built (e.g., with ``wwctl overly build``) into compressed overlay
images for distribution to cluster nodes. These images typically match these two
use cases: system and runtime. As such, each cluster node typically has two
overlay images.
.. code-block:: console
# wwctl overlay build
Building system overlay image for n1
Created image for n1 system overlay: /var/lib/warewulf/provision/overlays/n1/__SYSTEM__.img
Compressed image for n1 system overlay: /var/lib/warewulf/provision/overlays/n1/__SYSTEM__.img.gz
Building runtime overlay image for n1
Created image for n1 runtime overlay: /var/lib/warewulf/provision/overlays/n1/__RUNTIME__.img
Compressed image for n1 runtime overlay: /var/lib/warewulf/provision/overlays/n1/__RUNTIME__.img.gz
Overlay images for multiple node are built in parallel. By default, each CPU in
the Warewulf server will build overlays independently. The number of workers can
be specified with the ``--workers`` option.
Warewulf will attempt to build/update overlays as needed (configurable in the
``warewulf.conf``); but not all cases are detected, and manual overlay builds
are often necessary.
Creating and Modifying Overlays
===============================
You can add a new overlay to Warewulf with ``wwctl overlay create``.
.. code-block:: shell
wwctl overlay create issue
A new overlay is just an empty directory. For it to be useful it needs to
contain some files.
For example, ``wwctl overlay import`` imports files from the Warewulf server
into the overlay.
.. code-block:: shell
wwctl overlay import --parents issue /etc/issue
This imports ``/etc/issue`` from the Warewulf server into the new ``issue``
overlay.
.. note::
The ``issue`` overlay already existed as a distribution overlay. Creating one
shadows the distribution overlay with a new site overlay, allowing for local
modification.
Any modification to a distribution overlay first transparently creates a new
site overlay and applies any changes there: distribution overlays should
always remain unmodified.
You can also edit a new or existing overlay file in an interactive editor.
.. code-block:: shell
wwctl overlay edit issue /etc/issue
Use ``wwctl overlay show`` to inspect the content of an overlay file.
.. code-block:: shell
wwctl overlay show issue /etc/issue
Overlay files that end with ``.ww`` are templates. You can use ``wwctl overlay
show --render=<node>`` to show how a given template file would be rendered for
distribution to a given cluster node.
.. code-block:: shell
wwctl overlay delete issue /etc/issue
wwctl overlay import issue /etc/issue /etc/issue.ww
wwctl overlay show issue /etc/issue.ww --render=n1
More information about templates is available in :ref:`its own section
<templates>`.
The content of the file for the given overlay is displayed with this command.
With the ``--render`` option a template is rendered as it will be rendered for
the given node. The node name is a mandatory argument to the ``--render`` flag.
Additional information for the file can be suppressed with the ``--quiet``
option.
.. note::
It is not possible to delete files with an overlay.
Permissions
-----------
Overlay files are distributed to cluster nodes with the same user, group, and
mode that they have on the Warewulf server. Use ``wwctl overlay chown`` and
``wwctl overlay chmod`` to adjust them as necessary.
.. code-block:: shell
wwctl overlay chown issue /etc/issue.ww root root
wwctl overlay chmod issue /etc/issue.ww 0644
Distribution Overlays
=====================
Warewulf distinguishes between **distribution** overlays, which are included
with Warewulf, and **site** overlays, which are created or added locally. A site
overlay always takes precedence over a distribution overlay with the same name.
Any modification of a distribution overlay with ``wwctl`` actually makes changes
to an automatically-generated **site** overlay cloned from the distribution
overlay.
Site overlays are often stored at ``/var/lib/warewulf/overlays/``. Distribution
overlays are often stored at ``/usr/share/warewulf/overlays/``. But these paths
are dependent on compilation, distribution, packaging, and configuration
settings.
wwinit
------
The **wwinit** overlay performs initial configuration of the Warewulf node. Its
`wwinit` script runs before ``systemd`` or other init is called and contains all
configurations which are needed to boot.
In particular:
- Configure the loopback interface
- Configure the BMC based on the node's configuration
- Update PAM configuration to allow missing shadow entries
- Relabel the file system for SELinux
Other overlays may place additional scripts in ``/warewulf/init.d/`` to affect
node configuration in this pre-boot environment.
wwclient
--------
All configured overlays are provisioned initially along with the node image
itself; but **wwclient** periodically fetches and applies the runtime overlay to
allow configuration of some settings without a reboot.
Network interfaces
------------------
Warewulf ships with support for many different network interface configuration
systems. All of these are applied by default; but the list may be trimmed to
the desired system.
- ifcfg
- NetworkManager
- debian.interfaces
- wicked
Warewulf also configures both systemd and udev with the intended names of
configured network interfaces, typically based on a known MAC address.
- systemd.netname
- udev.netname
Several of the network configuration overlays support netdev tags to further
customize the interface:
- **``DNS[0-9]*``:** one or more DNS servers
- **``DNSSEARCH``:** domain search path
- **``MASTER``:** the master for a bond interface
NetworkManager
^^^^^^^^^^^^^^
- **``parent_device``:** the parent device of a vlan interface
- **``vlan_id``:** the vlan id for a vlan interface
- **``downdelay``, ``updelay``, ``miimon``, ``mode``, ``xmit_hash_policy``:**
bond device settings
Basics
------
The **hostname** overlay sets the hostname based on the configured Warewulf
node name.
The **hosts** overlay configures ``/etc/hosts`` to include all Warewulf nodes.
The **issue** overlay configures a standard Warewulf status message for display
during login.
The **resolv** overlay configures ``/etc/resolv.conf`` based on the value of
"DNS" nettags. (In most situations this should be unnecessary, as the network
interface configuration should handle this dynamically.)
fstab
-----
The **fstab** overlay configures ``/etc/fstab`` based on the data provided in the "fstab"
resource. It also creates entries for file systems defined by Ignition.
.. code-block:: yaml
nodeprofiles:
default:
resources:
fstab:
- spec: warewulf:/home
file: /home
vfstype: nfs
- spec: warewulf:/opt
file: /opt
vfstype: nfs
ssh
---
Two SSH overlays configure host keys (one set for all node in the cluster) and
``authorized_keys`` for the root account.
- ssh.authorized_keys
- ssh.host_keys
syncuser
--------
The **syncuser** overlay updates ``/etc/passwd`` and ``/etc/group`` to include
all users on both the Warewulf server and from the image.
To function properly, ``wwctl image syncuser`` (or the ``--syncuser`` option
during ``import``, ``exec``, ``shell``, or ``build``) must have also been run on
the image to synchronize its user and group IDs with those of the server.
If a ``PasswordlessRoot`` tag is set to "true", the overlay will also insert a
"passwordless" root entry. This can be particularly useful for accessing a
cluster node when its network interface is not properly configured.
ignition
--------
The **ignition** overlay defines partitions and file systems on local disks.
debug
-----
The **debug** overlay is not intended to be used in configuration, but is
provided as an example. In particular, the provided `tstruct.md.ww` demonstrates
the use of most available template metadata.
.. code-block:: shell
wwctl overlay show --render=<nodename> debug tstruct.md.ww
host
----
Configuration files used for the configuration of the Warewulf host /
server are stored in the **host** overlay. Unlike other overlays, it
*must* have the name ``host``. Existing files on the host are copied
to backup files with a ``wwbackup`` suffix at the first
run. (Subsequent use of the host overlay won't overwrite existing
``wwbackup`` files.)
The following services get configuration files via the host overlay:
* ssh keys are created with the scrips ``ssh_setup.sh`` and
``ssh_setup.csh``
* hosts entries are created by manipulating ``/etc/hosts`` with the
template ``hosts.ww``
* nfs kernel server receives its exports from the template
``exports.ww``
* the dhcpd service is configured with ``dhcpd.conf.ww``

View File

@@ -0,0 +1,207 @@
.. _templates:
=========
Templates
=========
Templates (denoted in overlays with a ``.ww`` suffix) allow you to create
dynamic configuration specifically for the node that it is applied to. Templates
have access to all metadata from the node registry (``nodes.conf``) and much of
the server configuration (``warewulf.conf``), and can also reference and import
files from the server file system.
Warewulf uses the ``text/template`` engine to facilitate implementing dynamic
content. This template format is documented at `pkg.go.dev/text/template.
<https://pkg.go.dev/text/template>`_
.. note::
When the template is rendered within a built overlay image, the ``.ww`` will
be dropped, so ``/etc/hosts.ww`` will end up being ``/etc/hosts``.
Non-Overlay Templates
=====================
Most Warewulf templates are included in overlays, but there are a few
non-overlay templates as well.
* ``/etc/warewulf/ipxe/``: includes iPXE script templates to direct iPXE during
the network boot process.
* ``/etc/warewulf/grub/``: includes GRUB script templates to direct GRUB during
the network boot process.
* ``/usr/share/warewulf/bmc/``: includes templates to generate BMC control
commands for the ``wwctl power``, ``wwctl sensor``, and ``wwctl console``
commands.
Template functions
==================
Warewulf templates have access to a number of functions that assist in creating
more dynamic and expressive templates.
Default functions
-----------------
``text/template`` includes a number of `default functions
<https://pkg.go.dev/text/template#hdr-Functions>`_ that are available during
Warewulf template processing.
Sprig
-----
Supplementing the default functions, Warewulf templates also have access to
`Sprig functions.`_
.. _Sprig functions.: https://masterminds.github.io/sprig/
Include
-------
Reads content from the given file into the template. If the file does not begin
with ``/`` it is considered relative to ``Paths.Sysconfdir``.
.. code-block::
{{ Include "/root/.ssh/authorized_keys" }}
IncludeFrom
-----------
Reads content from the given file from the given image into the template.
.. code-block::
{{ IncludeFrom $.ImageName "/etc/passwd" }}
IncludeBlock
------------
Reads content from the given file into the template, stopping when the provided
abort string is found.
.. code-block::
{{ IncludeBlock "/etc/hosts" "# Do not edit after this line" }}
ImportLink
----------
Causes the processed template file to become a symlink to the same target as the
referenced symlink.
.. code-block::
{{ ImportLink "/etc/localtime" }}
basename
--------
Returns the base name of the given path.
.. code-block::
{{- range $type, $name := $.Tftp.IpxeBinaries }}
if option architecture-type = {{ $type }} {
filename "/warewulf/{{ basename $name }}";
}
{{- end }}
file
----
Write the content from the template to the specified file name. May be specified
more than once in a template to write content to multiple files.
.. code-block::
{{- range $devname, $netdev := .NetDevs }}
{{- $filename := print "ifcfg-" $devname ".conf" }}
{{ file $filename }}
{{/* content here */}}
{{- end }}
softlink
--------
Causes the processed template file to become a symlink to the referenced target.
.. code-block::
{{ printf "%s/%s" "/usr/share/zoneinfo" .Tags.localtime | softlink }}
readlink
--------
Equivalent to ``filepath.EvalSymlinks``. Returns the target path of a named
symlink.
.. code-block::
{{ readlink /etc/localtime }}
IgnitionJson
------------
Generates JSON suitable for use by Ignition to create
abort
-----
Immediately aborts processing the template and does not write a file.
.. code-block::
{{ abort }}
nobackup
--------
Disables the creation of a backup file when replacing files with the current
template.
.. code-block::
{{ nobackup }}
UniqueField
-----------
UniqueField returns a filtered version of a multi-line input string. input is
expected to be a field-separated format with one record per line (terminated by
`\n`). Order of lines is preserved, with the first matching line taking
precedence.
For example, the following template snippet has been used in the ``syncuser`` overlay
to generate a combined ``/etc/passwd``.
.. code-block::
{{
printf "%s\n%s"
(IncludeFrom $.ImageName "/etc/passwd" | trim)
(Include (printf "%s/%s" .Paths.Sysconfdir "passwd") | trim)
| UniqueField ":" 0 | trim
}}
Examples
========
Many example templates are included in the distribution overlays. The ``debug``
template also includes a ``tstruct.ww`` template that includes much of the
available metadata.
.. code-block:: shell
wwctl overlay show debug tstruct.ww
wwctl overlay show debug tstruct.ww --render=n1
Node-Specific Files
-------------------
Sometimes there is the need to have specific files for each cluster node which
can't be generated by a template (e.g., a per-node Kerberos keytab). You can
include these files with following template:
.. code-block::
{{ Include (printf "/srv/%s/%s" .Id "payload") }}

View File

@@ -1,16 +1,20 @@
=============== ===========
Boot Management Bootloaders
=============== ===========
Warewulf uses iPXE to for network boot by default. As a tech preview, support Warewulf uses iPXE as its default network bootloader. As a tech preview, support
for GRUB is also available, which adds support for secure boot. for GRUB is also available, which adds support for secure boot.
Also as a tech preview, Warewulf may also use iPXE to boot a dracut Also as a tech preview, Warewulf may also use iPXE or GRUB to boot a dracut
initramfs as an initial stage before loading the image. initramfs as an initial stage before loading the image. This is called a
two-stage boot.
Booting with iPXE Booting with iPXE
================= =================
The ``/etc/warewulf/ipxe/`` directory contains *text/templates* that are used by
the Warewulf configuration process to configure the ``ipxe`` service.
.. graphviz:: .. graphviz::
digraph G{ digraph G{
@@ -49,10 +53,13 @@ to load the full OS image, avoiding the issue entirely.
Building iPXE locally Building iPXE locally
--------------------- ---------------------
By default (as of v4.5.0) Warewulf packages use iPXE from the host operating system rather than bundling iPXE binaries with Warewulf. By default (as of v4.5.0) Warewulf packages use iPXE from the host operating
However, sometimes the specific build included in the host OS has bugs or missing features, and a local build of iPXE is necessary. system rather than bundling iPXE binaries with Warewulf. However, sometimes the
specific build included in the host OS has bugs or missing features, and a local
build of iPXE is necessary.
The Warewulf project provides a `build-ipxe.sh`_ script to simplify the process of building iPXE locally. The Warewulf project provides a `build-ipxe.sh`_ script to simplify the process
of building iPXE locally.
.. _build-ipxe.sh: https://github.com/warewulf/warewulf/blob/main/scripts/build-ipxe.sh .. _build-ipxe.sh: https://github.com/warewulf/warewulf/blob/main/scripts/build-ipxe.sh
@@ -69,8 +76,11 @@ The Warewulf project provides a `build-ipxe.sh`_ script to simplify the process
Running build-ipxe.sh Running build-ipxe.sh
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
The script, by default, builds iPXE for x86_64 BIOS, x86_64 EFI, and arm64 EFI from the master branch on the iPXE project GitHub and stores the resultant builds in ``/usr/local/share/ipxe/``. The script, by default, builds iPXE for x86_64 BIOS, x86_64 EFI, and arm64 EFI
(These parameters can be adjusted by setting ``TARGETS``, ``IPXE_BRANCH``, and ``DESTDIR`` environment variables, with the current values shown in the ``-h`` output for reference.) from the master branch on the iPXE project GitHub and stores the resultant
builds in ``/usr/local/share/ipxe/``. (These parameters can be adjusted by
setting ``TARGETS``, ``IPXE_BRANCH``, and ``DESTDIR`` environment variables,
with the current values shown in the ``-h`` output for reference.)
.. code-block:: console .. code-block:: console
@@ -89,8 +99,9 @@ The script, by default, builds iPXE for x86_64 BIOS, x86_64 EFI, and arm64 EFI f
Build options Build options
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
By default, ``build-ipxe.sh`` enables support for `ZLIB`_ and `GZIP`_ images, as well as commands for managing `VLANs`_ and the `framebuffer console`_. By default, ``build-ipxe.sh`` enables support for `ZLIB`_ and `GZIP`_ images, as
The x86_64 build also enables support for the `serial console`_. well as commands for managing `VLANs`_ and the `framebuffer console`_. The
x86_64 build also enables support for the `serial console`_.
.. _ZLIB: https://ipxe.org/buildcfg/image_zlib .. _ZLIB: https://ipxe.org/buildcfg/image_zlib
@@ -142,13 +153,17 @@ For example, the ``imgextract`` command can be `explicitly enabled`_.
.. note:: .. note::
``IMG_ARCHIVE_CMD`` is already enabled by default in the iPXE master branch, but only takes effect when at least one archive image format is configured. ``IMG_ARCHIVE_CMD`` is already enabled by default in the iPXE master branch,
This is the case in the default state of ``build-ipxe.sh``, which enables support for ZLIB and GZIP archive image formats. but only takes effect when at least one archive image format is configured.
This is the case in the default state of ``build-ipxe.sh``, which enables
support for ZLIB and GZIP archive image formats.
Configuring Warewulf (≥ v4.5.0) Configuring Warewulf (≥ v4.5.0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In Warewulf v4.5.0, Warewulf can be configured to use these files using the ``tftp.ipxe`` and ``paths.ipxesource`` configuration parameters in ``warewulf.conf``. In Warewulf v4.5.0, Warewulf can be configured to use these files using the
``tftp.ipxe`` and ``paths.ipxesource`` configuration parameters in
``warewulf.conf``.
.. code-block:: yaml .. code-block:: yaml
@@ -162,8 +177,10 @@ In Warewulf v4.5.0, Warewulf can be configured to use these files using the ``tf
paths: paths:
ipxesource: /usr/local/share/ipxe ipxesource: /usr/local/share/ipxe
Restart ``warewulfd`` following the change to ``warewulf.conf``. Restart ``warewulfd`` following the change to ``warewulf.conf``. Then remove any
Then remove any previously-provisioned files from ``/var/lib/tftpboot/warewulf/`` and use ``wwctl configure tftp`` and ``wwctl configure dhcp`` to re-provision the TFTP files and update the DHCP configuration. previously-provisioned files from ``/var/lib/tftpboot/warewulf/`` and use
``wwctl configure tftp`` and ``wwctl configure dhcp`` to re-provision the TFTP
files and update the DHCP configuration.
.. code-block:: console .. code-block:: console
@@ -179,9 +196,11 @@ Then remove any previously-provisioned files from ``/var/lib/tftpboot/warewulf/`
Configuring Warewulf (< v4.5.0) Configuring Warewulf (< v4.5.0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Prior to v4.5.0, Warewulf packages included bundled builds of iPXE and did not provide a mechanism for configuring which iPXE to use. Prior to v4.5.0, Warewulf packages included bundled builds of iPXE and did not
To use a custom iPXE before v4.5.0, replace the bundled builds included with Warewulf. provide a mechanism for configuring which iPXE to use. To use a custom iPXE
After that, remove any previously-provisioned files from ``/var/lib/tftpboot/warewulf/`` and use ``wwctl configure tftp`` to re-provision the TFTP files. before v4.5.0, replace the bundled builds included with Warewulf. After that,
remove any previously-provisioned files from ``/var/lib/tftpboot/warewulf/`` and
use ``wwctl configure tftp`` to re-provision the TFTP files.
.. code-block:: console .. code-block:: console
@@ -257,10 +276,9 @@ Secure boot
If secure boot is enabled at every step a signature is checked and the boot If secure boot is enabled at every step a signature is checked and the boot
process fails if this check fails. The shim typically only includes the key for process fails if this check fails. The shim typically only includes the key for
a single operating system, which means that each distribution needs separate a single operating system, which means that each distribution needs separate
`shim` and `grub` executables. Warewulf extracts these binaries from the `shim` and `grub` executables. Warewulf extracts these binaries from the images.
images. If the node is unknown to Warewulf or can't be identified during If the node is unknown to Warewulf or can't be identified during the TFTP boot
the TFTP boot phase, the shim/grub binaries of the host in which Warewulf is phase, the shim/grub binaries of the host in which Warewulf is running are used.
running are used.
Install shim and efi Install shim and efi
-------------------- --------------------
@@ -279,11 +297,11 @@ booted by GRUB.
These packages must also be installed on the Warewulf server host to enable These packages must also be installed on the Warewulf server host to enable
node discovery using GRUB. node discovery using GRUB.
http boot HTTP boot
--------- ---------
Modern EFI systems have the possibility to directly boot per http. The flow diagram Modern EFI systems have the possibility to directly boot per http. The flow
is the following: diagram is the following:
.. graphviz:: .. graphviz::
@@ -306,20 +324,18 @@ directly from the node's assigned image.
Booting with dracut Booting with dracut
=================== ===================
Some systems, typically due to limitations in their BIOS or EFI Some systems, typically due to limitations in their BIOS or EFI firmware, are
firmware, are unable to load image of a certain size unable to load image of a certain size directly with a traditional bootloader,
directly with a traditional bootloader, either iPXE or GRUB. As a either iPXE or GRUB. As a workaround for such systems, Warewulf can be
workaround for such systems, Warewulf can be configured to load a configured to load a dracut initramfs from the image and to use that initramfs
dracut initramfs from the image and to use that initramfs to load to load the full image.
the full image.
Warewulf provides a dracut module to configure the dracut initramfs to Warewulf provides a dracut module to configure the dracut initramfs to load the
load the image. This module is available in the image. This module is available in the ``warewulf-dracut`` subpackage, which
``warewulf-dracut`` subpackage, which must be installed in the must be installed in the image.
image.
With the ``warewulf-dracut`` package installed, you can build an With the ``warewulf-dracut`` package installed, you can build an initramfs
initramfs inside the image. inside the image.
.. code-block:: shell .. code-block:: shell
@@ -328,9 +344,9 @@ initramfs inside the image.
.. note:: .. note::
In some systems, such as ``rockylinux:8``, it may be In some systems, such as ``rockylinux:8``, it may be necessary to remove
necessary to remove ``/etc/machine-id`` for dracut to properly generate ``/etc/machine-id`` for dracut to properly generate the initramfs in the
the initramfs in the location that Warewulf is expecting. location that Warewulf is expecting.
To direct iPXE to fetch the node's initramfs image and boot with dracut To direct iPXE to fetch the node's initramfs image and boot with dracut
semantics, set an ``IPXEMenuEntry`` tag for the node. semantics, set an ``IPXEMenuEntry`` tag for the node.
@@ -366,14 +382,12 @@ dracut semantics, set a ``GrubMenuEntry`` tag for the node.
The ``GrubMenuEntry`` variable may be set at the node or profile level. The ``GrubMenuEntry`` variable may be set at the node or profile level.
During boot, ``warewulfd`` will detect and dynamically serve an During boot, ``warewulfd`` will detect and dynamically serve an initramfs from a
initramfs from a node's image in much the same way that it node's image in much the same way that it can serve a kernel from an image. This
can serve a kernel from an image. This image is loaded by image is loaded by iPXE (or GRUB) which directs dracut to fetch the node's image
iPXE (or GRUB) which directs dracut to fetch the node's image
during boot. during boot.
The wwinit module provisions to tmpfs. By default, tmpfs is permitted The wwinit module provisions to tmpfs. By default, tmpfs is permitted to use up
to use up to 50% of physical memory. This size limit may be adjustd to 50% of physical memory. This size limit may be adjusted using the kernel
using the kernel argument `wwinit.tmpfs.size`. (This parameter is argument `wwinit.tmpfs.size`. (This parameter is passed to the `size` option
passed to the `size` option during tmpfs mount. See ``tmpfs(5)`` for during tmpfs mount. See ``tmpfs(5)`` for more details.)
more details.)

View File

@@ -0,0 +1,345 @@
====================
Server Configuration
====================
By default, the Warewulf server configuration is located at
``/etc/warewulf/warewulf.conf``. This is a YAML-formatted configuration file
used by to configured the Warewulf server itself and its external services.
An initial ``warewulf.conf`` is packaged with Warewulf. Each section is covered
in detail below.
Once Warewulf has been installed and configured:
* run ``wwctl configure --all`` to reconfigure external services
* run ``systemctl restart warewulfd`` to apply the configuration to the Warewulf
server
Re-run both of these commands when making changes to ``warewulf.conf``.
.. code-block:: yaml
ipaddr: 192.168.1.1
netmask: 255.255.255.0
network: 192.168.1.0
warewulf:
port: 9873
secure: true
update interval: 60
autobuild overlays: true
host overlay: true
grubboot: false
dhcp:
enabled: true
template: default
systemd name: dhcpd
tftp:
enabled: true
tftproot: /var/lib/tftpboot
systemd name: tftp
ipxe:
00:0B: arm64-efi/snponly.efi
"00:00": undionly.kpxe
"00:07": ipxe-snponly-x86_64.efi
"00:09": ipxe-snponly-x86_64.efi
nfs:
enabled: true
systemd name: nfsd
ssh:
key types:
- ed25519
- ecdsa
- rsa
- dsa
image mounts:
- source: /etc/resolv.conf
dest: /etc/resolv.conf
paths:
bindir: /usr/bin
sysconfdir: /etc
localstatedir: /var/lib
cachedir: /var/cache
ipxesource: /usr/share/ipxe
srvdir: /var/lib
firewallddir: /usr/lib/firewalld/services
systemddir: /usr/lib/systemd/system
datadir: /usr/share
wwoverlaydir: /var/lib/warewulf/overlays
wwchrootdir: /var/lib/warewulf/chroots
wwprovisiondir: /var/lib/warewulf/provision
wwclientdir: /warewulf
warewulf
========
.. code-block:: yaml
ipaddr: 192.168.1.1
netmask: 255.255.255.0
network: 192.168.1.0
warewulf:
port: 9873
secure: true
update interval: 60
autobuild overlays: true
host overlay: true
grubboot: false
* ``ipaddr``: The Warewulf server address on the cluster network. This
configuration must match the server's IP address.
If ``ipaddr`` is specified as a CIDR address, ``netmask`` and ``network`` may
be omitted.
* ``netmask``: The netmask for the cluster network.
* ``network``: The address of the cluster network itself.
* ``warewulf:port``: This is the port that the Warewulf web server will be
listening on. It is recommended not to change this so there is no misalignment
with node's expectations of how to contact the Warewulf service.
* ``warewulf:secure``: When ``true``, this limits the Warewulf server to only
respond to runtime overlay requests originating from a privileged port. This
prevents non-root users from requesting the runtime overlay, which may contain
sensitive information.
When ``true``, ``wwclient`` uses TCP port 987 by default. (A different port
can be specified at ``wwclient:port``.)
Changing this option requires rebuilding node overlays and rebooting compute
nodes to configure them to use a privileged port for `wwclient`.
* ``warewulf:update interval``: This defines the frequency (in seconds) with
which the Warewulf client on the compute node fetches overlay updates.
* ``warewulf:autobuild overlays``: Controls whether per-node overlays will
automatically be rebuilt. (e.g., when an underlying overlay is changed)
Overlay autobuild is not 100% reliable; but it is particularly useful for
building overlays for new nodes.
* ``warewulf:host overlay``: Controls whether the special ``host`` overlay is
applied to the Warewulf server during configuration. (The host overlay is used
to configure external services.)
* ``warewulf::grubboot``: Controls whether iPXE (default) or GRUB is used as the
network bootloader.
dhcp
====
The DHCP external service can be configured explicitly with ``wwctl configure
dhcp``. This (re)writes the DHCP configuration and enables and (re)starts the
DHCP service.
.. code-block:: yaml
dhcp:
enabled: true
template: default
systemd name: dhcpd
* ``dhcp:enabled``: Whether Warewulf should configure a DHCP server on the
cluster network. Set to ``false`` when managing DHCP separately.
* ``dhcp:template`` An optional DHCP template variable to control the
generation of the DHCP template.
Specifying ``template: static`` populates ``dhcpd.conf`` with static leases
for each host, bypassing the DHCP range. (Run ``wwctl configure dhcp`` to
update ``dhcpd.conf`` when nodes are added, removed, or changed.)
* ``dhcp:range start`` and ``dhcp:range end``: Defines a dynamic DHCP range to
use when provisioning cluster nodes. This address range must exist in the
cluster network defined above. (Otherwise, the DHCP server will fail to
start).
This range should not overlap with IP addresses assigned to nodes in
``nodes.conf``.
* ``dhcp:systemd name``: Identifies the systemd service that manages the DHCP
service. Used during ``wwctl configure dhcp`` to restart the service.
tftp
====
The TFTP external service can be configured explicitly with ``wwctl configure
tftp``. This writes the appropriate bootloader executables to the TFTP root
directory and enables the TFTP service.
.. code-block:: yaml
tftp:
enabled: true
tftproot: /var/lib/tftpboot
systemd name: tftp
ipxe:
00:0B: arm64-efi/snponly.efi
"00:00": undionly.kpxe
"00:07": ipxe-snponly-x86_64.efi
"00:09": ipxe-snponly-x86_64.efi
* ``tftp:enabled``: Whether Warewulf should configure a TFTP server on the
cluster network. Set to ``false`` when managing TFTP separately.
* ``tftp:tftproot``: Identifies the local path being served by the managed TFTP
server. Warewulf creates a ``warewulf/`` subdirectory and copies iPXE and/or
GRUB bootloader files to this location depending on the server configuration.
* ``systemd name``: Identifies the systemd service that manages the TFTP
service. Used during ``wwctl configure tftp`` to restart the service.
* ``ipxe``: A map of DHCP option architecture-types to the iPXE binary that
should be used for that architecture. iPXE binaries are searched for in
``paths:ipxesource``. By default, these paths correspond to the location of
the correct iPXE binary for each architecture in the distribution iPXE
packages; but they can be specified explicitly when providing a local iPXE
build.
nfs
===
The NFS external service can be configured explicitly with ``wwctl configure
nfs``. This configures the NFS server (particularly ``/etc/exports``) on the
Warewulf server and enables and starts the NFS service.
.. code-block:: yaml
nfs:
enabled: true
export paths:
- path: /home
export options: rw,sync
- path: /opt
export options: ro,sync,no_root_squash
systemd name: nfsd
* ``nfs:enabled``: Whether Warewulf should configure an NFS server on the
cluster network. Set to ``false`` when not required or when managing NFS
separately.
* ``nfs:export paths``: A list of NFS exports to configure on the Warewulf
server. Each export defines a ``path`` to be exported and the ``export
options`` for that export.
* ``systemd name``: Identifies the systemd service that manages the NFS
service. Used during ``wwctl configure nfs`` to restart the service.
ssh
===
*New in Warewulf v4.5.1*
SSH key types to generate during ``wwctl configure ssh``. This create the
appropriate host keys (stored in ``/etc/warewulf/keys/``) and authentication
keys for passwordless ``ssh`` to cluster nodes. It also installs shell profiles
``/etc/profile.d/ssh_setup.csh`` and ``/etc/profile.d/ssh_setup.sh`` to
initialize authentication keys for new users if and when they log into the
Warewulf server.
.. code-block:: yaml
ssh:
key types:
- ed25519
- ecdsa
- rsa
- dsa
* ``ssh:key types``: Warewulf generate host keys for each listed key type.
The first listed key type is used to generate authentication ssh keys.
image mounts
============
A list of paths to temporarily mount from the Warewulf server into an image
during ``wwctl image exec`` and ``wwctl image shell``, typically to allow them
to operate in the host environment prior to deployment.
.. code-block:: yaml
image mounts:
- source: /etc/resolv.conf
dest: /etc/resolv.conf
* ``image mounts:source``: The path on the Warewulf server to mount into the
image.
* ``image mounts:dest``: The path in the image to use for the mount.
* ``image mounts::readonly``: Whether the mount should be read-only (``true``)
or allow writes into the server path (``false``).
* ``image mounts::copy``: When ``true``, copy files into the image rather than
mount. This is useful for initializing files with a starting value from the
Warewulf server that should then be maintained as part of the image.
paths
=====
*New in Warewulf v4.5.0*
Override paths to images, overlays, and other Warewulf components.
.. code-block:: yaml
paths:
sysconfdir: /etc
cachedir: /var/cache
ipxesource: /usr/share/ipxe
datadir: /usr/share
wwoverlaydir: /var/lib/warewulf/overlays
wwchrootdir: /var/lib/warewulf/chroots
wwprovisiondir: /var/lib/warewulf/provision
wwclientdir: /warewulf
* ``paths:sysconfdir``: The parent directory for the ``warewulf`` configuration
directory, which stores ``warewulf.conf`` and ``nodes.conf``.
* ``paths::cachedir``: The parent directory for the ``warewulf`` cache of OCI
images during ``wwctl image import``.
* ``paths:ipxesource``: Where to get iPXE binaries. These files are copied to
``warewulf.conf:tftp:tftproot`` by ``wwctl configure tftp``.
* ``datadir``: Parent directory for distribution overlays and BMC templates.
* ``paths:wwoverlaydir``: Parent directory for site overlays.
* ``paths:wwchrootdir``: Parent directory for Warewulf images.
* ``paths:wwprovisiondir``: The destination for built images and overlay images.
* ``paths:wwclientdir``: Where ``wwclient`` looks for its configuration on a
provisioned node.
wwclient
========
Configuration for the ``wwclient`` service on cluster nodes.
.. code-block:: yaml
wwclient:
port: 987
* ``wwclient:port``: The source port used by ``wwclient``. By default an
ephemeral port is selected; but ``warewulf.conf:warewulf:secure: true``
requires a known privileged port.
``wwclient`` will use the TCP port "987" by default if ``secure: true``; but,
if that port is otherwise in use, a different port may be specified.
hostfile
========
There are no explicit "hostfile" configuration options in ``warewulf.conf``; but
``wwctl configure hostfile`` updates the Warewulf server's ``/etc/hosts`` file
to include expected configuration for the server itself as well as the known
names of the cluster nodes and thier interfaces.
Entries from the Warewulf server's ``/etc/hosts`` file are distributed to
cluster nodes by the "hosts" overlay.

View File

@@ -0,0 +1,63 @@
=============
Using dnsmasq
=============
As an experimental feature, it is possible to use ``dnsmasq`` instead of the ISC
``dhcpd`` server and ``TFTP`` server.
In order to keep the file ``/etc/dnsmasq.d/ww4-hosts.conf`` is created and must
be included in the main ``dnsmasq.conf`` via the ``conf-dir=/etc/dnsmasq.d``
option.
Installation
============
Before the installation, make sure that ``dhcpd`` and ``tftp`` are disabled.
You can do that with the commands:
.. code-block:: shell
systemctl disable --now dhcpd
systemctl disable --now tftp
Now you can install ``dnsmasq``.
.. code-block:: shell
# Rocky Linux
dnf install dnsmasq
# SUSE
zypper install dnsmasq
After the installation, instruct ``warewulf`` to use ``dnsmasq`` as its
``dhcpd`` and ``tftp`` service. This is done in the server configuration file,
typically at ``/etc/warewulf/warewulf.conf``:
.. code-block:: yaml
tftp:
systemd name: dnsmasq
dhcp:
systemd name: dnsmasq
The configuration of ``dnsmasq`` often doesn't need to be changed, as the
default configuration includes all files with following pattern
``/etc/dnsmasq.d/*conf`` into its configuration. This configuration is created
by the overlay template ``host:/etc/dnsmasq.d/ww4-hosts.conf.ww``.
.. note::
In certain distributions, such as Rocky Linux 9, ``dnsmasq`` is configured to
listen locally via the ``interface=lo`` option by default. Replace this entry
in ``/etc/dnsmasq.conf`` with the interface associated with your Warewulf
network, or remove/comment out the interface option entirely to enable
listening on all interfaces.
Once the Warewulf configuration has been updated, re-deploy the configuration
and restart ``warewulfd``.
.. code-block:: shell
wwctl configure --all
systemctl restart warewulfd.service

View File

@@ -0,0 +1,145 @@
===================
Server Installation
===================
There are multiple methods to install a Warewulf server. This page describes
some of those methods.
Binary RPMs
===========
The Warewulf project builds binary RPMs as part of its CI/CD process. You can
obtain them from the `GitHub releases`_ page.
.. _GitHub releases: https://github.com/warewulf/warewulf/releases
Rocky Linux 9
-------------
.. code-block:: console
# dnf install https://github.com/warewulf/warewulf/releases/download/v4.6.0rc2/warewulf-4.6.0rc2-1.el9.x86_64.rpm
openSuse Leap
-------------
.. code-block:: console
# zypper install https://github.com/warewulf/warewulf/releases/download/v4.6.0rc2/warewulf-4.6.0rc2-1.suse.lp155.x86_64.rpm
Container images
================
Warewulf can be built in a Linux container. This can be especially useful for
testing and development, or to replace traditional package installation. It is
also possible to only use the container for building and the install it in the
host system afterwards. For that look at the INSTALL, UNINSTALL and PURGE labels
inside the `Dockerfile`_
.. _Dockerfile: https://github.com/warewulf/warewulf/blob/main/Dockerfile
Docker
------
.. code-block:: console
# docker build -t warewulf .
# docker run -d --replace --name warewulf-test --privileged --net=host -v /:/host -v /etc/warewulf:/etc/warewulf -v /var/lib/warewulf/:/var/lib/warewulf/ -e NAME=warewulf-test -e IMAGE=warewulf warewulf
Systemd-nspawn
--------------
Warewulf runs multiple services inside one single container and uses systemd as
init system. As such, it might be better to use `systemd-nspawn`_, which was
explicitly made to run containers with a full init system.
.. _systemd-nspawn: https://www.freedesktop.org/software/systemd/man/latest/systemd-nspawn.html
.. code-block:: console
# docker build -t warewulf .
# mkdir warewulf-nspawn
# docker export "$(docker create --name warewulf-test warewulf true)" | tar -x -C warewulf-nspawn
# systemd-nspawn -D warewulf-nspawn/ passwd
# systemd-nspawn -D warewulf-nspawn/ --boot
Compiled from Source
====================
Before you build the Warewulf source code you will first need to install the
build dependencies:
* ``make``: This should be available via your Linux distribution's package
manager (e.g. ``dnf install make``)
* ``go``: Golang is also available on most current Linux distributions, but you
can also install `the most recent version. <https://golang.org/dl/>`_
* Depending on your Linux Distribution, you may need to install other
development packages. Typically it is recommended to install the entire
development group.
.. code-block::
dnf groupinstall "Development Tools"
Once these dependencies are installed, you can obtain and build the source code.
Release Tarball
---------------
The Warewulf project releases source distributions alongside its binary RPMs.
You can obtain them from the `GitHub releases`_ page.
Select the version you wish to install and download the tarball to any
location on the server, then follow these directions making the
appropriate substitutions:
.. code-block:: bash
curl -LO https://github.com/warewulf/warewulf/releases/download/v4.6.0rc2/warewulf-4.6.0rc2.tar.gz
tar -xf warewulf-4.6.0rc2.tar.gz
cd warewulf-4.6.0rc2
make all && sudo make install
Git
---
You can install different versions of Warewulf from its Git tags or branches.
The ``main`` branch is where most active development occurs, so if you want to
obtain the latest and greatest version of Warewulf, this is where to go. But be
forewarned, using a snapshot from ``main`` is not guaranteed to be stable or
generally supported for production.
If you are building for production, it is best to download a release tarball
from the main site, the GitHub releases page, or from a Git tag.
.. code-block:: bash
git clone https://github.com/warewulf/warewulf.git
cd warewulf
git checkout main # or switch to a tag like 'v4.6.0rc2'
make all && sudo make install
Runtime Dependencies
--------------------
In its default configuration, Warewulf requires some operating system provided
services. Generally these are provided by your distribution.
* ``dhcp-server``
* ``tftp-server``
* ``nfs-utils``
If you are using an Enterprise Linux compatible distribution you can install
them with ``dnf install dhcp-server tftp-server nfs-utils``.
Starting warewulfd
==================
The Warewulf installation registers the Warewulf service with systemd, so it
should be as easy to start/stop/check as any other systemd service:
.. code-block:: console
# systemctl enable --now warewulfd

View File

@@ -0,0 +1,84 @@
========
Security
========
While certain parallelization and high performance library capabilities still
require lowering the security threshold within a cluster, Warewulf strives to
support good security practices within the cluster wherever possible.
Provisioning Security
=====================
Provisioning is, by default, a relatively "insecure" process: there is generally
nothing preventing a user on a cluster node from spoofing a provision request
and downloading the node image and overlays for inspection. If any of these
include secrets (e.g., private keys) they are at risk of exposure.
There are multiple ways to secure the Warewulf provisioning process:
* The best way to secure the provisioning process is to dedicate a vLAN
specifically for provisioning, and then not make that vLAN available in the
provisioned environment. Warewulf can be used in such an environment (without
``wwclient``) but you must consult your switch documentation and features to
implement a default vLAN for provisioning and to ensure that the runtime
operating system is configured for a different tagged vLAN once booted.
* Warewulf can leverage hardware "asset tags" which almost all vendors support.
This is a configurable firmware string that is accessible only via root or
physical access. During provisioning (as well as post provisioning via
``wwclient``) Warewulf sends the detected asset tag to the Warewulf server as
a "shared secret" token. If the node is also configured with an ``asset key``
on the Warewulf server (e.g., via ``wwctl node set --assetkey "..."``), the
Warewulf server will only respond to requests with a matching asset tag.
* If the Warewulf server is configured with ``warewulf:secure: true``, then it
will only provide the runtime overlay to a ``wwclient`` communicating from a
privileged (< 1024) TCP port. This prevents unprivileged cluster users from
being able to retrieve the runtime overlay.
* When the nodes are booted via `shim` and `grub` Secure Boot can be enabled.
This means that the nodes only boot the kernel which is provided by the
distributor and also custom complied modules can't be loaded.
SELinux
=======
The Warewulf server can be run with SELinux enabled in "targeted" and
"enforcing" mode.
For more information about running SELinux-enabled cluster node images, see
:ref:`SELinux-Enabled Images <selinux_images>`.
firewalld
=========
If the Warewulf server is running ``firewalld``, the following services must be
added for them to function:
.. code-block:: console
firewall-cmd --permanent --add-service=warewulf
firewall-cmd --permanent --add-service=dhcp
firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-service=tftp
firewall-cmd --reload
.. note::
The DHCP, TFTP, and NFS services may be managed manually, apart from the
Warewulf server. In that case, they may be omitted from the ``firewalld``
configuration on the Warewulf server; but they must be accessible from where
they are served.
nftables
========
If the Warewulf server is running ``nftables`` directly, without ``firewalld``,
ensure that TCP port ``9873`` must be permitted for cluster nodes to communicate
with the Warewulf server.
.. code-block:: console
nft add rule inet filter input tcp dport 9873 accept
nft list ruleset >/etc/nftables.conf
systemctl restart nftables

View File

@@ -0,0 +1,22 @@
==================
Upgrading Warewulf
==================
New versions of Warewulf might introduce changes to ``warewulf.conf`` and
``nodes.conf``. The ``wwctl upgrade`` command can help ease the transition
between versions.
.. note::
``wwctl upgrade`` will back up any files before it changes them (to
``<name>-old``) but it is good practice to back up your configuration
manually.
.. code-block:: console
# wwctl upgrade config
# wwctl upgrade nodes --add-defaults --replace-overlays
Both upgrade commands support specifying ``--output-path=-`` to print the
upgraded configuration file to standard out for inspection before replacing the
configuration files.

58
userdocs/server/wwctl.rst Normal file
View File

@@ -0,0 +1,58 @@
====================
Controlling Warewulf
====================
Warewulf's command-line interface is based primarily around the ``wwctl``
command. This command has sub-commands for each major component of Warewulf's
functionality.
* ``configure``: configures the Warewulf server and its external services
* ``node``: manages nodes in the cluster
* ``profiles``: defines common sets of node configuration which can be applied
to multiple nodes
* ``image``: configures (node) images
* ``overlays``: manages overlays
``wwctl`` also provides additional helpers for interacting with cluster nodes
over SSH and IPMI.
* ``power``: turns nodes on and off
* ``ssh``: provides basic parallel ssh functionality
All of these subcommands (and their respective sub-subcommands) have
built-in help with either ``wwctl help`` or ``--help``.
Hostlists
=========
Many of the commands (e.g., ``wwctl node list`` support a "hostlist"
syntax for referring to multiple nodes at once. Hostlist expressions
support both ranges and comma-separated numerical lists.
For example:
* ``node[1-2]`` expands to ``node1 node2``
* ``node[1,3]`` expands to ``node1 node3``
* ``node[1,5-6]`` expands to ``node1 node5 node6``
Node status
===========
During the whole provisioning process of your nodes, you can check their status
through the following command :
.. code-block:: console
# wwctl node status
NODENAME STAGE SENT LASTSEEN (s)
================================================================================
n1 RUNTIME_OVERLAY __RUNTIME__.img.gz 16
For each node, there are 4 different stages:
* **IPXE**
* **KERNEL**
* **SYSTEM_OVERLAY**
* **RUNTIME_OVERLAY**
You can use the ``wwctl node status`` to check communication between the
Warewulf server (``warewulfd``) and the Warewulf client (``wwclient``).

View File

@@ -0,0 +1,101 @@
============
Known issues
============
SELinux and IPMI Write not Working When Using Two-Stage Boot
============================================================
The dracut implementation of two-stage boot in versions of Warewulf prior to
v4.6.0 bypasses the ``wwinit`` process by default, invoking the image's init
system directly. While cluster nodes will often still boot mostly successfully
this way, features implemented by wwinit will not complete. In particular,
SELinux relabeling and IPMI write are not executed.
To ensure that dracut runs the full ``wwinit`` process, pass ``init=/init`` or
``init=/warewulf/wwinit`` on the kernel command line.
.. code-block:: shell
wwctl profile set default --kernelargs="init=/init"
Images are Read-Only
====================
Warewulf v4.5 uses the permissions on an image's ``rootfs/`` to determine a
"read-only" state of the image: if the root directory of the image is ``u-w``,
it will be mounted read-only during ``wwctl image <exec|shell``, preventing
interactive changes to the image.
In the past, the root directory was ``u+w``, but Enterprise Linux 9.5 (including
Red Hat, Rocky, _et al._) includes an update to the ``filesystem`` package that
marks the root directory ``u-w``. This causes Warewulf images to be "read only"
by default.
To mark a Warewulf image as writeable, use `chmod u+w`.
.. code-block:: shell
chmod u+w $(wwctl image show rockylinux-9.5)
This behavior is changed in v4.6 to use an explicit ``readonly`` file stored
outside of ``rootfs/``.
Image Sockets Cause Build Failures
==================================
If an image source directory includes persistent sockets, these sockets may
cause the import operation to fail.
.. code-block::
Copying sources...
ERROR : could not import image: lchown ./rockylinux-8/run/user/0/gnupg/d.kg8ijih5tq41ixoeag4p1qup/S.gpg-agent: no such file or directory
To resolve this, remove the sockets from the source directory.
.. code-block:: shell
find ./rockylinux-8/ -type s -delete
This issue was fixed in an upstream library and `should be resolved in Warewulf
v4.6.0. <https://github.com/warewulf/warewulf/issues/892>`_
Image Size Considerations
=========================
Node images can grow quickly as packages and other files are added to them. Even
these larger images are often not an issue in modern environments; but some
architectural limits exist that can impede the use of images larger than a few
gigabytes. Workarounds exist for these issues in most circumstances:
* Warewulf's :ref:`two-stage boot support <booting with dracut>` effectively
eliminates this problem by handling the bulk of the image management within
Linux. This feature is currently in preview, and is subject to change; but it
is likely to become the default boot method in a future release.
* Systems booting in legacy / BIOS mode, being a 32-bit environment, cannot boot
an image that requires more than 4GB to decompress. This means that the
compressed image and the decompressed image together must be < 4GB. This is
typically reported by the system as "No space left on device
(https://ipxe.org/34182006)."
The best work-around for this limitation is to switch to UEFI. UEFI is 64-bit
and should support booting significantly larger images, though sometimes
system-specific implementation details have led to artificial limitations on
image size.
* The Linux kernel itself can only decompress an image up to 4GB due to the use
of 32-bit integers in critical sections of the kernel initrd decompression
code.
The best work-around for this limitation is to use an iPXE with support for
`imgextract <https://ipxe.org/cmd/imgextract>`_. This allows iPXE to
decompress the image rather than the kernel.
* Some BIOS / firmware retain a "memory hole" feature for legacy devices, e.g.,
reserving a 1MB block of memory at the 15MB-16MB address range. this feature
can interfere with booting stateless node images.
If you are still getting "Not enough memory" or "No space left on device"
errors, try disabling any "memory hole" features or updating your system BIOS
or firmware.

View File

@@ -0,0 +1,188 @@
===============
Troubleshooting
===============
warewulfd
=========
The Warewulf server (``warewulfd``) sends logs to the systemd journal.
.. code-block::
journalctl -u warewulfd.service
To increase the verbosity of the log, specify either ``--verbose`` or
``--debug`` in the warewulfd OPTIONS.
.. code-block::
echo "OPTIONS=--debug" >>/etc/default/warewulfd
systemctl restart warewulfd.service
iPXE
====
If you're using iPXE to boot (the default), you can get a command prompt by
pressing with C-b during boot.
From the iPXE command prompt, you can run the same commands from `default.ipxe`_
to troubleshoot potential boot problems.
.. _default.ipxe: https://github.com/warewulf/warewulf/blob/main/etc/ipxe/default.ipxe
For example, the following commands perform a (relatively) normal Warewulf boot.
(Substitute your Warewulf server's IP address in place of 10.0.0.1, update the
port number if you have changed it from the default of 9873, and substitute your
cluster node's MAC address in place of 00:00:00:00:00:00.)
.. code-block::
set uri http://10.0.0.1:9873/provision/00:00:00:00:00:00
kernel --name kernel ${uri}?stage=kernel
imgextract --name image ${uri}?stage=image&compress=gz
imgextract --name system ${uri}?stage=system&compress=gz
imgextract --name runtime ${uri}?stage=runtime&compress=gz
boot kernel initrd=image initrd=system initrd=runtime
- The ``uri`` variable points to ``warewulfd`` for future reference. This
includes the cluster node's MAC address so that Warewulf knows what image and
overlays to provide.
- The ``kernel`` command fetches a kernel for later booting.
- The ``imgextract`` command fetches and decompresses the images that will make
up the booted noe image. In a typical environment this is used to load a
minimal "initial ramdisk" which, then, boots the rest of the system. Warewulf,
by default, loads the entire image as an initial ramdisk, and also loads the
system and runtime overlays at this time time.
- The ``boot`` command tells iPXE to boot the system with the given kernel and
ramdisks.
.. note::
This example does not provide ``assetkey`` information to ``warewulfd``. If
your nodes have defined asset tags, provide it in the ``uri`` variable for
the node you are trying to boot.
For example, you may want to try booting to a pre-init shell with debug logging
enabled. To do so, substitute the ``boot`` command above.
.. code-block::
boot kernel initrd=image initrd=system initrd=runtime rdinit=/bin/sh
.. note::
You may be more familiar with specifying ``init=`` on the kernel command
line. ``rdinit`` indicates "ramdisk init." Since Warewulf, by default, boots
the node image as an initial ramdisk, we must use ``rdinit=`` here.
GRUB
====
If you're using GRUB to boot, you can get a command prompt by pressing "c" when
prompted during boot.
From the GRUB command prompt, you can enter the same commands that you would
otherwise find in `grub.cfg.ww`_.
.. _grub.cfg.ww: https://github.com/warewulf/warewulf/blob/main/etc/grub/grub.cfg.ww
For example, the following commands perform a (relatively) normal Warewulf boot.
(Substitute your Warewulf server's IP address in place of 10.0.0.1, and update
the port number if you have changed it from the default of 9873.)
.. code-block::
uri="(http,10.0.0.1:9873)/provision/${net_default_mac}"
linux "${uri}?stage=kernel" wwid=${net_default_mac}
initrd "${uri}?stage=image&compress=gz" "${uri}?stage=system&compress=gz" "${uri}?stage=runtime&compress=gz"
boot
- The ``uri`` variable points to ``warewulfd`` for future reference.
``${net_default_mac}`` provides Warewulf with the MAC address of the booting
node, so that Warewulf knows what image and overlays to provide it.
- The ``linux`` command tells GRUB what kernel to boot, as provided by
``warewulfd``. The ``wwid`` kernel argument helps ``wwclient`` identify the
node during runtime.
- The ``initrd`` command tells GRUB what images to load into memory for boot. In
a typical environment this is used to load a minimal "initial ramdisk" which,
then, boots the rest of the system. Warewulf, by default, loads the entire
image as an initial ramdisk, and also loads the system and runtime overlays at
this time time.
- The ``boot`` command tells GRUB to boot the system with the previously-defined
configuration.
.. note::
This example does not provide ``assetkey`` information to ``warewulfd``. If
your nodes have defined asset tags, provide it in the ``uri`` variable for
the node you are trying to boot.
For example, you may want to try booting to a pre-init shell with debug logging
enabled. To do so, substitute the ``linux`` command above.
.. code-block::
linux "${uri}?stage=kernel" wwid=${net_default_mac} debug rdinit=/bin/sh
.. note::
You may be more familiar with specifying ``init=`` on the kernel command
line. ``rdinit`` indicates "ramdisk init." Since Warewulf, by default, boots
the node image as an initial ramdisk, we must use ``rdinit=`` here.
Dracut
======
By default, dracut simply panics and terminates when it encounters an issue.
Dracut looks at the kernel command line for its configuration. You can configure
it for additional logging and to switch to an interactive shell on error:
.. code-block::
wwctl profile set default --kernelargs=rd.shell,rd.debug,log_buf_len=1M
For more information on debugging Dracut problems, see `the Fedora dracut
problems guide.`_
.. _the Fedora dracut problems guide.: https://docs.fedoraproject.org/en-US/quick-docs/debug-dracut-problems/
Ignition
========
If partition creation doesn't work as expected you have a few options to
investigate:
- Add ``systemd.log_level=debug`` and or ``rd.debug`` to the kernelArgs of the
node you're working on.
- After the next boot you should be able to find verbose information on the node
with ``journalctl -u ignition-ww4-disks.service``.
- You could also check the content of ``/warewulf/ignition.json``.
- You could try to tinker with ``/warewulf/ignition.json`` calling
.. code-block:: shell
/usr/lib/dracut/modules.d/30ignition/ignition \
--platform=metal \
--stage=disks \
--config-cache=/warewulf/ignition.json \
--log-to-stdout
after each iteration on the node directly until you find the settings you
need. (Make sure to unmount all partitions if ``ignition`` was partially
successful.)
- Sometimes you need to add ``should_exist: "true"`` for the swap partition as
well.
Running Containers on Cluster Nodes
===================================
Some container runtimes, notably Podman, require file system features that are
not available in ``initrootfs``. Cluster nodes using Podman (and some other
container runtimes) should be configured with ``--root=tmpfs``.