Skip to content

Conversation

@jbtrystram
Copy link
Member

Instead of deploying the container to the tree then copy all the contents to the disk image, use bootc to directly manage the installation to the target filesystems.

Right now this requires to use the image as the buildroot so this requires python (for osbuild). This is tracked in [1].

[1] bootc-dev/bootc#1410 Requires osbuild/osbuild#2149

@openshift-ci
Copy link

openshift-ci bot commented Jul 17, 2025

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces changes to use bootc install to deploy the container, which simplifies the image build process. There are a few critical issues in the YAML manifest related to copy-paste errors that lead to incorrect configurations for the 4k image builds and missing options for loopback devices. These issues need to be addressed.

@dustymabe
Copy link
Member

dustymabe commented Jul 17, 2025

I switched the CI on this to run against rawhide (contains python) so we could actually test the change.

@dustymabe
Copy link
Member

A few diffs picked up by cosa diff --metal from #4226

cosa-diff-metal.txt

We should probably profile each diff (maybe in coreos/fedora-coreos-tracker#1827) and evaluate whether it's a change we want to make or not.

@dustymabe
Copy link
Member

I can't get a built qemu image to boot. I suspect probably the root= and boot= UUIDs added on the kernel command line?

@jbtrystram
Copy link
Member Author

I can't get a built qemu image to boot. I suspect probably the root= and boot= UUIDs added on the kernel command line?

do you mind sharing more logs ? What I am getting locally is ignition failing on coreos/fedora-coreos-tracker#1250

@dustymabe
Copy link
Member

Ahh. I see that too now:

[    4.726843] ignition[875]: Ignition failed: failed to create users/groups: failed to configure users: failed to create user "core": exit status 10: Cmd: "useradd" "--root" "/sysroot" "--create-home" "--password" "*" "--comment" "CoreOS Admin" "--groups" "adm,sudo,systemd-journal,wheel" "core" Stdout: "" Stderr: "useradd: cannot lock /etc/group; try again later.\n"

@jbtrystram

This comment was marked as outdated.

@jbtrystram

This comment was marked as outdated.

@jbtrystram
Copy link
Member Author

I can't get a built qemu image to boot. I suspect probably the root= and boot= UUIDs added on the kernel command line?

looks like removing those make the boot process go further (ignition completes), and out of the initramfs but fail to mount the boot partition.

@jbtrystram
Copy link
Member Author

Blocked on bootc-dev/bootc#1441

@jbtrystram
Copy link
Member Author

ok this works with the following PRs :

for the bootc PR, it can be built then added into the image through overrides/rootfs. Make sure to build rawhide.

@jbtrystram
Copy link
Member Author

follow-up : either find a way to get the boot components inside cosa, or change the bootc code to call bootupd from the deployed root . I think the latter is preferable.
I filed bootc-dev/bootc#1455

@jbtrystram
Copy link
Member Author

jbtrystram commented Jul 29, 2025

follow-up : either find a way to get the boot components inside cosa, or change the bootc code to call bootupd from the deployed root . I think the latter is preferable. I filed bootc-dev/bootc#1455

Made bootc-dev/bootc#1460
With this, we no longer require to use the container as the buildroot, cosa works, so we could do that on all streams.

@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch 4 times, most recently from bb4270f to 310bd60 Compare July 30, 2025 07:38
@jbtrystram
Copy link
Member Author

Alright, marking this as ready for review as all the bits are in place.
I guess i need to update the osbuild manifest or the other arches as well, but I'll do that after a review to reduce the amount of back and forth.

This will need a release of bootc.

@jbtrystram jbtrystram marked this pull request as ready for review July 30, 2025 07:44
Copy link
Member

@dustymabe dustymabe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments.

I think there are a few things we need to iron out before we can really move forward with this:

  1. supporting both old and new paths at the same time

Do we need to? Usually when we make a change this large we roll it out slowly, which means we have to support both ways for some time.

This PR is ignoring that fact, but TBH looking at OSBuild configs that support both would be pretty intimidating, so I'm not excited about trying to do that either. I'd be interested in @jlebon or @travier's thoughts.

  1. We need to make sure any/every diff that exists between images generated this way and the old way are considered and acknowleged as acceptable before we'd make this change.

@dustymabe
Copy link
Member

Thank you for your patience here JB. I don't see anything too alarming in the patch set here. Mostly small stuff.

I do want to spend some time with this change testing it out locally and poking around the built images. I'll try to do so tomorrow.

@dustymabe
Copy link
Member

A couple of things:

  1. Trying to build the live media failed with:
Verifying that repacked image matches digest                                                                                                                                                                                                                                  
Packing successful!                                                                                                                                                                                                                                                           
Kernel binary linked: /run/osbuild/tree/tmp_1cwx4nh/tmp-rootfs-dir/boot/vmlinuz-6.17.0-0.rc7.250924gcec1e6e5d1ab3.58.fc44.x86_64                                                                                                                                              
Kernel HMAC linked: /run/osbuild/tree/tmp_1cwx4nh/tmp-rootfs-dir/boot/.vmlinuz-6.17.0-0.rc7.250924gcec1e6e5d1ab3.58.fc44.x86_64.hmac                                                                                                                                          
Creating erofs with -zlzma,level=6 -Eall-fragments,fragdedupe=inode -C1048576 --quiet                                                  
Traceback (most recent call last):                                                                                                     
  File "/run/osbuild/bin/org.osbuild.coreos.live-artifacts.mono", line 967, in <module>                                                
    r = main(workdir=tmdir,                                                                                                            
             tree=args["tree"],                                                                                                        
             inputs=args["inputs"],                                                                                                    
             options=args["options"],                                                                                                  
             loop_client=remoteloop.LoopClient("/run/osbuild/api/remoteloop"))                                                         
  File "/run/osbuild/bin/org.osbuild.coreos.live-artifacts.mono", line 929, in main                                                    
    blsentry_kargs, osname = mkrootfs_metal(paths, workdir, img_metal, fstype, fsoptions, loop_client)                                 
                             ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                 
  File "/run/osbuild/bin/org.osbuild.coreos.live-artifacts.mono", line 638, in mkrootfs_metal                                          
    with open(os.path.join(tmp_rootfs_dir, ALEPH_FILENAME), encoding='utf8') as f:                                                     
         ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                           
FileNotFoundError: [Errno 2] No such file or directory: '/run/osbuild/tree/tmp_1cwx4nh/tmp-rootfs-dir/.aleph-version.json'
  1. The metal diff did show some differences (attached from-metal-ls-diff.txt and to-metal-ls-diff.txt).
  • ./.aleph-version.json and the corresponding ./.coreos-aleph-version.json symlink are now just ./.bootc-aleph.json.
  • There are ./boot/efi/EFI/fedora/bootuuid.cfg and ./boot/grub2/bootuuid.cfg that I think in the past we generate on first boot for CoreOS, is that right?
  • ./boot/grub2/locale is missing a bunch of files that were there before (not sure if this is important).
  • A bunch of new files in ./ostree/bootc/storage/
  • The ref for the container seems to now include more information (i.e. about the pullspec) ./ostree/repo/refs/heads/ostree/container/image/docker_3A__2F__2F_quay_2E_io -> ./ostree/repo/refs/heads/ostree/container/image/docker_3A__2F__2F_ostree-image-signed_3A_docker_3A__2F__2F_quay_2E_io

from-metal-ls-diff.txt
to-metal-ls-diff.txt

@jbtrystram
Copy link
Member Author

A couple of things:
....

Thank you so much for looking into this Dusty ! another set of eyes is really helpful.
I'll try to address these this week

@jbtrystram
Copy link
Member Author

jbtrystram commented Oct 21, 2025

There are ./boot/efi/EFI/fedora/bootuuid.cfg and ./boot/grub2/bootuuid.cfg that I think in the past we generate on first boot for CoreOS, is that right?

See #4224 (comment)

./.aleph-version.json and the corresponding ./.coreos-aleph-version.json symlink are now just ./.bootc-aleph.json

We'll have to re-add this symlink in a postprocess I guess. I can change stages/org.osbuild.ostree.aleph to have it take an argument that only does the symlink if the aleph already exist. Note that this aleph is generated by bootc and have different content than ours.
I guess I need to dig into what we use this for

A bunch of new files in ./ostree/bootc/storage/

Looks like this is a leaked overlay mount, see this todo

@jbtrystram
Copy link
Member Author

jbtrystram commented Oct 21, 2025

Added a commit that fixes the missing aleph file symlink. This also fixes the live artifact build

Requires osbuild/osbuild#2226

The log disk usage message comming every 10 seconds is quite noisy,
hide it when we are in a shell in osbuild.

I aslo added a couple of helpful tips in comments given by @dustymabe
to work with osbuild.
Bootc is looking for the prepare-root config file in the buildroot
environnement because the main assumption is that it's run from the
target container.
However, in osbuild, it's run from te buildroot, because podman inside
bwrap (inside supermin in our case) causes issues.
It's fine for RHCOS and SCOS where we use the target container as the
buildroot but we cannot do that for FCOS because we require python in
the buildroot.

For now, insert a prepare-root file in the supermin VM (use as the
buildroot for osbuild) until either :
- bootc learn to look into the container for it [1]
- we ship python in our images and can use them as buildroot.

Another approach would be to layer python and the osbuild dependencies
on top of our image and use that as the buildroot, but that would create
room for packages drift (what was in the repos at build time?). At least
using COSA it's easier to keep track of versions.

[1] bootc-dev/bootc#1410
@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch from bcb4d05 to 096dc64 Compare October 27, 2025 15:54
@jbtrystram
Copy link
Member Author

jbtrystram commented Oct 27, 2025

@dustymabe : Rebased and updated. I included a manifest knob and a env var to make use of the bootc manifest.

* `./boot/grub2/locale` is missing a bunch of files that were there before (not sure if this is important).

It looks like those come from running grub-mkconfig but our boot partition should be populated with bootupd, so I don't understand how that differ. I could not find any lead in the bootupd code.

* The `ref` for the container seems to now include more information (i.e. about the pullspec) `./ostree/repo/refs/heads/ostree/container/image/docker_3A__2F__2F_quay_2E_io` -> `./ostree/repo/refs/heads/ostree/container/image/docker_3A__2F__2F_ostree-image-signed_3A_docker_3A__2F__2F_quay_2E_io`

Do you know any code that rely on the output of ostree refs ? A quick search didn't yield much

@jbtrystram
Copy link
Member Author

jbtrystram commented Oct 27, 2025

It looks like those come from running grub-mkconfig but our boot partition should be populated with bootupd, so I don't understand how that differ. I could not find any lead in the bootupd code.

OK i dug more on this and it's another instance of bootc-dev/bootc#1559
In the previous manifest we were using a chroot before calling bootupd which made sure bootupd (and by extension grub2) would pull content from the target root. I fixed the missing grub static config in bootupd by manually pulling them when --src-root is passed, but the locale aren't present in the build root so they are not copied.

It would be nicer to have bootc actually chroot before calling bootupd, because it would have the added benefit to use the bootupd (and other) binaries that will ship on the image rather than what is in the buildroot.

Another way would be to use our image as the buildroot, but once again, we don't ship python.

jbtrystram added a commit to jbtrystram/coreos-assembler that referenced this pull request Oct 28, 2025
this rpm provides locales under `/usr/share/locale`.
grub2 install these files inside the /boot partition using what
exist on the host. Mooving to bootc install results in an empty
folder because those files don't exist in the buildroot, so add them.

In the previous manifest we were using a chroot before calling bootupd
which made sure bootupd (and by extension grub2) would pull content
from the target root.

It would be nicer to have bootc install also chroot before calling
bootupd, it would have the added benefit to use the bootupd (and other)
binaries that are shipped on the image rather than what is in the buildroot.

Again, this is a complication coming from not having python in the image
so we can't use ourselves as the buildroot, which would alleviate a lot
of pain.

See coreos#4224 (comment)
And bootc-dev/bootc#1559
@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch from 2b1ca62 to fdadef3 Compare October 28, 2025 15:11
jbtrystram added a commit to jbtrystram/coreos-assembler that referenced this pull request Oct 28, 2025
this rpm provides locales under `/usr/share/locale`.
grub2 install these files inside the /boot partition using what
exist on the host. Mooving to bootc install results in an empty
folder because those files don't exist in the buildroot, so add them.

In the previous manifest we were using a chroot before calling bootupd
which made sure bootupd (and by extension grub2) would pull content
from the target root.

It would be nicer to have bootc install also chroot before calling
bootupd, it would have the added benefit to use the bootupd (and other)
binaries that are shipped on the image rather than what is in the buildroot.

Again, this is a complication coming from not having python in the image
so we can't use ourselves as the buildroot, which would alleviate a lot
of pain.

See coreos#4224 (comment)
And bootc-dev/bootc#1559
@jbtrystram
Copy link
Member Author

jbtrystram commented Oct 28, 2025

Ok I cleaned up the commits and addressed everything.
I started a full test run with a COSA image containing this PR and the manifest config knob in the staging pipeline

Prep work to add a knob for using bootc install in osbuild.
Refactor the override logic in a helper function so we can easily add
those knobs down the line.
@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch from fdadef3 to f672aff Compare October 28, 2025 16:05
jbtrystram added a commit to jbtrystram/coreos-assembler that referenced this pull request Oct 28, 2025
this rpm provides locales under `/usr/share/locale`.
grub2 install these files inside the /boot partition using what
exist on the host. Mooving to bootc install results in an empty
folder because those files don't exist in the buildroot, so add them.

In the previous manifest we were using a chroot before calling bootupd
which made sure bootupd (and by extension grub2) would pull content
from the target root.

It would be nicer to have bootc install also chroot before calling
bootupd, it would have the added benefit to use the bootupd (and other)
binaries that are shipped on the image rather than what is in the buildroot.

Again, this is a complication coming from not having python in the image
so we can't use ourselves as the buildroot, which would alleviate a lot
of pain.

See coreos#4224 (comment)
And bootc-dev/bootc#1559
Instead of deploying the container to the tree then copy all the contents
to the disk image, use bootc to directly manage the installation to the
target filesystems.

Right now this requires to use the image as the buildroot so this
requires python (for osbuild). This is tracked in [1].
As we have python in rawhide now I duplicated the manifest and added a
switch in the osbuild wrapper script.

We can keep the manifest duplicated until we are confident to roll this
to all streams.

[1] bootc-dev/bootc#1410

Requires:
bootc-dev/bootc#1460
bootc-dev/bootc#1451
osbuild/osbuild#2149
osbuild/osbuild#2152

All of which have landed in osbuild-159 and bootc 1.6
@jbtrystram
Copy link
Member Author

Ok I cleaned up the commits and addressed everything. I started a full test run with a COSA image containing this PR and the manifest config knob in the staging pipeline

a few tests are failing, i'll look into it tomorrow

@jbtrystram
Copy link
Member Author

jbtrystram commented Oct 29, 2025

Next up is bootc-dev/bootc#1710 ( we want to set sysroot.bls-append-except-default in the ostree repo config) and also /sysroot is not labeled correctly

Create symlinks to the aleph file created by bootc so our tests and
tooling find the aleph at the expected path.

Shipping the osbuild patches until [1] is merged.

[1]: osbuild/osbuild#2226
this rpm provides locales under `/usr/share/locale`.
grub2 install these files inside the /boot partition using what
exist on the host. Mooving to bootc install results in an empty
folder because those files don't exist in the buildroot, so add them.

In the previous manifest we were using a chroot before calling bootupd
which made sure bootupd (and by extension grub2) would pull content
from the target root.

It would be nicer to have bootc install also chroot before calling
bootupd, it would have the added benefit to use the bootupd (and other)
binaries that are shipped on the image rather than what is in the buildroot.

Again, this is a complication coming from not having python in the image
so we can't use ourselves as the buildroot, which would alleviate a lot
of pain.

See coreos#4224 (comment)
And bootc-dev/bootc#1559
Properly label the filesystem mount points before calling bootc,
otherwise `/sysroot` and `/boot` end up being `unlabeled_t`
@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch from f672aff to 01b2a13 Compare October 29, 2025 11:53
@jbtrystram
Copy link
Member Author

Fixed the labels issue in the last commit

@jbtrystram
Copy link
Member Author

jbtrystram commented Oct 29, 2025

Failing tests :

ext.config.kdump.crash
ext.config.butane.grub-users
ext.config.ignition.remote
 kdump.crash.ssh
ext.config.networking.ifname-karg.everyboot-systemd-link-file
 kdump.crash.nfs
 ext.config.networking.rd-net-timeout-carrier
multipath.day1
ext.config.ignition.kargs

Except ext.config.butane.grub-users which is due to a missing ostree repo config, all of these failing tests are failing due to the /boot/grub2/bootuuid.cfg :

From what I understand, during the boot, coreos-gpt-setup.service assigns a new UUID to the partition, and coreos-boot-edit.service writes that new uuid to /boot/grub2/bootuuid.cfg.
However, when ignition needs to reboot (e.g. for applying a karg), the reboot happens between the two. So the UUID that bootc had written is no longer valid, preventing the reboot.

This does not happen in the non-bootc case because that bootuuid.cfg does not exist at first boot, trigerring grub to look for the boot label and not the partition uuid.

@openshift-ci

This comment was marked as off-topic.

@jbtrystram
Copy link
Member Author

Failing tests :

ext.config.kdump.crash
ext.config.butane.grub-users
ext.config.ignition.remote
 kdump.crash.ssh
ext.config.networking.ifname-karg.everyboot-systemd-link-file
 kdump.crash.nfs
 ext.config.networking.rd-net-timeout-carrier
multipath.day1
ext.config.ignition.kargs

Except ext.config.butane.grub-users which is due to a missing ostree repo config, all of these failing tests are failing due to the /boot/grub2/bootuuid.cfg :

From what I understand, during the boot, coreos-gpt-setup.service assigns a new UUID to the partition, and coreos-boot-edit.service writes that new uuid to /boot/grub2/bootuuid.cfg. However, when ignition needs to reboot (e.g. for applying a karg), the reboot happens between the two. So the UUID that bootc had written is no longer valid, preventing the reboot.

This does not happen in the non-bootc case because that bootuuid.cfg does not exist at first boot, trigerring grub to look for the boot label and not the partition uuid.

alright I was able to work around this with the following changes in our initrd services in FCOS :

diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-gpt-setup.service b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-gpt-setup.service
index 629bb60f..f2d9c134 100644
--- a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-gpt-setup.service
+++ b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-gpt-setup.service
@@ -28,3 +28,6 @@ OnFailureJobMode=isolate
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=/usr/sbin/coreos-gpt-setup /dev/disk/by-label/boot
+# MountFlags=slave is so the umount of /boot is guaranteed to happen.
+# /boot will only be mounted for the lifetime of the unit.
+MountFlags=slave
diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-gpt-setup.sh b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-gpt-setup.sh
index 11cebd34..8042b735 100755
--- a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-gpt-setup.sh
+++ b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-gpt-setup.sh
@@ -26,6 +26,19 @@ if [ "${PTUUID:-}" != "$UNINITIALIZED_GUID" ]; then
     exit 0
 fi
 
+
+# Mount /boot. Note that we mount /boot but we don't unmount it because we
+# are run in a systemd unit with MountFlags=slave so it is unmounted for us.
+bootmnt=/mnt/boot_partition/
+bootdev=/dev/disk/by-label/boot
+mount -o rw ${bootdev} ${bootmnt}
+# Make sure we delete any pre-existing bootuuid.cfg
+# bootc install stamps it during the disk image creation
+# since we are changing the uuid here we want to remove this file
+# otherwise it will prevent a reboot
+rm -f ${bootmnt}/grub2/bootuuid.cfg
+
+
 echo "Randomizing disk GUID"
 sgdisk --disk-guid=R --move-second-header "$PKNAME"
 udevadm settle || :

I'll push a container and start the test suite

@jbtrystram
Copy link
Member Author

jbtrystram commented Oct 29, 2025

hmmm ok 1 last test failure : ext.config.boot.grub2-install
Which would be solved if bootc was chrooting before the bootupd invocation.

Pipeline run : https://jenkins-fedora-coreos-pipeline.apps.ocp.stg.fedoraproject.org/blue/organizations/jenkins/jbtrystram-build/detail/jbtrystram-build/8/pipeline

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants