Boot-service is a new service generated by Fabrica and created to replace BSS. But why create a new service to handle boot configurations? Intially, we used BSS for serving our boot configs to nodes whenever a DHCP request was made to boot an image. And it worked…fine. However, inheriting BSS meant that we would have to deal with the technical debt that accumulated over the years whenever we needed to change things. In other words, modifying BSS was becoming a huge burden!
Before diving into how boot-service works itself, I would recommend taking a look at the blog post about Fabrica and explore the Fabrica repository on GitHub first. It isn’t critical, but the basic idea is that Fabrica is a new API service generator which is used to generate new services. Understanding this should help to understand a bit more about how boot-service works internally and where some issues may occur when troubleshooting.
This post will briefly cover how to set up and use boot-service in place of BSS.
Swapping out the two services is simple and only requires a few steps. You can also run both services side-by-side behind a gateway if you want to have some way to maintain compatibility with BSS, but it isn’t necessary with the new boot-service’s legacy API. The API lets you make requests to BSS-like endpoints under /boot/v1 with similar enough behavior for boot-service to serve as a drop-in replacement (for the most part).
First, let’s start by creating a new INI file similar the BSS one. This would typically saved somewhere like /etc/containers/systemd/boot-service.container.
[Unit]
Description=The boot-service container
PartOf=openchami.target
# Ensure SMD has started already
Wants=smd.service
After=smd.service
[Container]
ContainerName=boot-service
HostName=boot-service
Image=ghcr.io/openchami/boot-service:v0.1.0
# Networks for the Container to use
Network=openchami-internal.network
# Proxy settings
PodmanArgs=--http-proxy=false
[Service]
Restart=alwaysThis file defines the quadlet that generates a Systemd unit file. The dependency on SMD is not necessary here since boot-service has another mechanism for adding nodes with a file. However, we want to use SMD to pull node information like we’re currently doing with BSS.
Then, if you need to make changes and test out a custom image, you can clone the respository and build with podman build using the Dockerfile.standalone file.
git clone https://github.com/OpenCHAMI/boot-service
cd boot-service
# build new podman image
sudo podman build \
-f Dockerfile.standalone \
--build-arg VERSION=v0.1.0 \
--build-arg COMMIT=$(git rev-parse --short HEAD) \
--build-arg DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
-t ghcr.io/openchami/boot-service:v0.1.0 \
-v /opt/workdir/tokensmith:/tokensmith \
-v /opt/workdir/fabrica:/fabrica \
--env BOOT_SERVICE_HSM_URL=http://smd:27779 .Confirm that it was built. You should see an image with the tag you used in the above command.
sudo podman imagesAnd the output of the command.
REPOSITORY TAG IMAGE ID CREATED SIZE
ghcr.io/openchami/boot-service v0.1.0 9fbb27a9d754 8 days ago 19.5 MBReload the Systemd daemon and start the service.
sudo systemctl daemon-reload
sudo systemctl start --enable boot-serviceYou can view the logs to make sure the container is running with podman.
sudo podman logs -f boot-serviceIf we wanted to use boot-service sans SMD, we can tell it about our nodes manually using the CLI and a JSON file.
Copy the contents of the JSON file below to nodes.yaml somewhere.
{
"xname": "x1000c0s0b0n0",
"nid": 1,
"bootMac": "52:54:00:be:ef:01",
"role": "Compute",
"subRole": "Worker",
"hostname": "compute1",
"interfaces": [
{
"mac": "52:54:00:be:ef:01",
"ip": "172.16.0.1",
"type": "management"
}
],
"groups": [
"compute"
]
}Then, we can use the client to upload the node information to the server.
cat nodes.yaml | boot-service-client node create --server https://demo.openchami.cluster:8443Now, we just need to give boot-service a boot config to serve the nodes. Copy the contents below to compute-rocky9.yaml and modify the params, kernel, and initrd params accordingly (assuming you already have images built).
{
"macs": [
"52:54:00:be:ef:01",
"52:54:00:be:ef:02",
"52:54:00:be:ef:03",
"52:54:00:be:ef:04",
"52:54:00:be:ef:05"
],
"params": "nomodeset ro root=live:http://172.16.0.254:9000/boot-images/compute/debug/rocky9.6-compute-debug-rocky9 ip=dhcp overlayroot=tmpfs overlayroot_cfgdisk=disabled apparmor=0 selinux=0 console=ttyS0,115200 ip6=off cloud-init=enabled ds=nocloud-net;s=http://172.16.0.254:8081/cloud-init",
"kernel": "http://172.16.0.254:9000/boot-images/efi-images/compute/debug/vmlinuz-5.14.0-570.26.1.el9_6.x86_64",
"initrd": "http://172.16.0.254:9000/boot-images/efi-images/compute/debug/initramfs-5.14.0-570.26.1.el9_6.x86_64.img",
}At this point, you should be able to boot your nodes whether they are virtual or real. You can view the logs with sudo podman logs -f boot-service like before to see the requests coming from your nodes!
Some of the steps here in this post are also included as changes to the OpenCHAMI tutorial in sections 2.5 and 2.6.
Specifically, the way we add the boot configs for the nodes is different and uses a different client generated by Fabrica instead of ochami by default. There are plans to adapt ochami to work with boot-service, but that has not been done yet as the time of this blog post.
The tutorial also covers how to integrate what we’ve done here with the gateway. If you haven’t done so already, I would strongly encourage you to review the tutorial and get a full picture view on how to use OpenCHAMI!