Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

01bootetc: introduce module for updating dracut etc #792

Closed
wants to merge 2 commits into from

Conversation

darkmuggle
Copy link
Contributor

This provides support for updating '/etc/' in the initramfs using
'bootetc='. If the device has the path '/initrd-etc', then the
tree is copied into the initramfs.

The purpose of bootetc is to aide immutable operating systems like
Fedora and Red Hat CoreOS that ship static initrds with a path for
user-provided configuration. Example use cases include udev rules, iSCSI
and multipath configuration, fips and Network Manager configurations.

@centos-ci
Copy link
Collaborator

Can one of the admins verify this patch?

@darkmuggle
Copy link
Contributor Author

@cgwalters this is the end result of the idea to support /etc coming from boot.

#!/bin/sh
. /lib/dracut-lib.sh

bootetc=$(getarg bootetc=)
Copy link
Contributor

Choose a reason for hiding this comment

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

OK, so we require an explicit opt-in karg like bootetc=1; and you see us changing FCOS to pass that by default? Or it only gets injected when e.g. dm-multipath is in use?

Copy link
Contributor Author

@darkmuggle darkmuggle Apr 16, 2020

Choose a reason for hiding this comment

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

It's more like bootetc=LABEL=..... I envision this being an opt-in. We could use it for FCOS, but I'm particularly keen on not making that decision today.

touch /run/bootetc.done

if [ -z "$DRACUT_SYSTEMD" ]; then
systemctl try-restart dracut-cmdline.service
Copy link
Contributor

Choose a reason for hiding this comment

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

This part is probably the most unfortunate. I don't know all of what's going on in dracut-cmdline.service but it'll need to be prepared to be killed at arbitrary points.

Can't we have this bit run Before=dracut-cmdline.service?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, I looked at the boot-path. dracut-cmdline.service is run before Udev. we need udev to find the boot device.


if [ -z "$DRACUT_SYSTEMD" ]; then
systemctl try-restart dracut-cmdline.service
systemctl try-restart systemd-udev-trigger.service
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, why does udev need to be retriggered?

Copy link
Contributor

Choose a reason for hiding this comment

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

probably so the device that contains the boot partition can be found?

Copy link
Contributor

Choose a reason for hiding this comment

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

oh re-triggered.. not sure

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Udev rules :)

@cgwalters
Copy link
Contributor

cgwalters commented Apr 16, 2020

At a high level, I think the original idea was just that we support e.g. /boot/etc/multipath.conf, which would be checked if e.g. rd.multipath=1 is set or so and used for the rootfs mounting path. This would be less flexible, but would avoid any need to restart any parts of dracut.

@jlebon
Copy link
Contributor

jlebon commented Apr 16, 2020

I think the approach here has potential. A few questions/comments:

  • Do we have any concerns here about trying to wait for /boot early on and holding up boot?
  • We're modifying boot configuration while booting, which means we'll race with any other code which is reading those files. I agree it probably covers a lot of use case, though it doesn't seem as complete as the approaches discussed in Support rpm-ostree initramfs --enable-overlay coreos/rpm-ostree#1930. Would you agree?

@cgwalters
Copy link
Contributor

though it doesn't seem as complete as the approaches discussed in coreos/rpm-ostree#1930. Would you agree?

Well I was pushing back against using initramfs mutation for this because it conflicts with any approach to signing, it's mixing code and configuration. The initramfs is code that should be parsing configuration from e.g. the kernel cmdline. The problem with multipath is that its configuration is too big for the cmdline.

@darkmuggle
Copy link
Contributor Author

  • Do we have any concerns here about trying to wait for /boot early on and holding up boot?

Its a pretty-fast failure and its opt-in only. Since its run after udev, it fairly quick.,

  • We're modifying boot configuration while booting, which means we'll race with any other code which is reading those files. I agree it probably covers a lot of use case, though it doesn't seem as complete as the approaches discussed in coreos/rpm-ostree#1930. Would you agree?

Sort of. I think they are orthogonal. Support in rpm-ostree is one question. This could be used for traditional systems and CoreOS now, while support in coreos/rpm-ostree#1930 is done. But the bigger question is first boot, for things like multipath or things that are needed to install the system in the first place.

@darkmuggle
Copy link
Contributor Author

darkmuggle commented Apr 16, 2020

Well I was pushing back against using initramfs mutation for this because it conflicts with any approach to signing, it's mixing code and configuration. The initramfs is code that should be parsing configuration from e.g. the kernel cmdline. The problem with multipath is that its configuration is too big for the cmdline.

Multipath configuration can't be used on the commandline. The configuration must originate from /etc/multipath.conf. The only way to narrowly scope it to multipath would be to bind it to the multipath module; that felt a bit too hacky. I had to step back and realize that Dracut is scoped to Linux et al, not just CoreOS. CoreOS may need this support for one thing, but other Linux's could use it for other things.

This PR is a general solution for general Linux. And having been a support engineer, I would have killed for the features that this enables such as the ability to change the configuration in the initramfs without having to play the regeneration of the initramfs (because everyone loves the bind mount, chroot, regenerate, reboot game).

Something else to consider: it was requested that this idea be put in Dracut. If this is too much for CoreOS, then we should carry the narrowly scoped module in our own trees for building CoreOS.

@cgwalters
Copy link
Contributor

The only way to narrowly scope it to multipath would be to bind it to the multipath module; that felt a bit too hacky.

Right, we also have the iSCSI case which is similar. But any dracut module that wants to use this shares all the bits of mounting /boot - the difference just comes in that the individual modules would cherry-pick their own config files; IOW:

dm-multipath-pre.service

ConditionKernelCmdline=boot
RequiresMountsFor=/boot
ExecStartPre=/bin/cp /boot/etc/multipathd.conf /etc
...

iscsid-pre.service:

ConditionKernelCmdline=boot
RequiresMountsFor=/boot
ExecStartPre=/bin/cp /boot/etc/iscsid.conf /etc

etc. (Written as a systemd unit instead of the shell, but the same idea applies in both).

I agree it's a good idea to find solutions that will apply to traditional systems too! And nothing about the "narrow" approach excludes that - IOW once that change landed at some point e.g. Anaconda could be changed for "traditional" Fedora systems to set up dm-multipath that way instead of regenerating the initrd. But..the motivation for doing that is a lot lower if one is always regenerating the initrd locally anyways.

Or to rephrase this, either way something different is happening; CoreOS uses initrd-etc and traditional doesn't, or CoreOS uses /boot/etc/multipath.conf and traditional doesn't.

@cgwalters
Copy link
Contributor

To ensure this is all xref'd; Lennart suggested using EFI variables (my followup) but it just doesn't work for us because e.g. AWS is BIOS only and we need a uniform mechanism (not to mention e.g. needs to work on s390x too etc.).

@cgwalters
Copy link
Contributor

Another angle on this code/configuration thing; as this stands today someone could write an /boot/initrd-etc/systemd/system/mycustom.service (and I don't think it would work because systemd would already have loaded the configuration, i.e. something would need to systemctl daemon-reload) - but systemd units are arbitrary code that are being injected into the initramfs in this approach. Whereas if individual services know to look for just their configuration, we avoid the injected code.

@darkmuggle
Copy link
Contributor Author

Another angle on this code/configuration thing; as this stands today someone could write an /boot/initrd-etc/systemd/system/mycustom.service (and I don't think it would work because systemd would already have loaded the configuration, i.e. something would need to systemctl daemon-reload) - but systemd units are arbitrary code that are being injected into the initramfs in this approach. Whereas if individual services know to look for just their configuration, we avoid the injected code.

That's why I didn't do a daemon-reload. I considered that part of the idea. And no, it doesn't work. I tested that.

Given the strong distaste for this PR, I'll rework this.

@cgwalters
Copy link
Contributor

Given the strong distaste for this PR, I'll rework this.

Well, we can see what the other drauct devs think too!

@darkmuggle
Copy link
Contributor Author

xref to coreos/ignition-dracut#154 and the commend that inspired this PR coreos/ignition-dracut#154 (comment) for background

@jlebon
Copy link
Contributor

jlebon commented Apr 16, 2020

I guess one other concern I have with having configs in /boot in general is that now we'd have two sources of truth: /etc (where dracut sources configs from today) and /boot/initrd-etc.

If we constrain this to just solving the firstboot case, I think doing something similar to coreos/fedora-coreos-config#346 could make sense. (I.e. apply in initrd, propagate to real root, delete directory). Would that solve the multipath scenario?

@cgwalters
Copy link
Contributor

If we constrain this to just solving the firstboot case, I think doing something similar to coreos/fedora-coreos-config#346 could make sense. (I.e. apply in initrd, propagate to real root, delete directory). Would that solve the multipath scenario?

We need to find the multipath configuration on every boot.

@darkmuggle
Copy link
Contributor Author

I guess one other concern I have with having configs in /boot in general is that now we'd have two sources of truth: /etc (where dracut sources configs from today) and /boot/initrd-etc.

For an RHCOS in the scope of OCP, there is no easy mechanism to regenerate the initrd.

The two-sources of truth concern, IMO, is mitigated by the fact that this is an opt-in (off-by-default) option. Turning it is explicitly stating you want to use the mechanism.

If we constrain this to just solving the firstboot case, I think doing something similar to coreos/fedora-coreos-config#346 could make sense. (I.e. apply in initrd, propagate to real root, delete directory). Would that solve the multipath scenario?

No. Not at all. If root is on a multipath, then it has to be enabled in the initramfs before root is mounted. If the root is mounted first, then the multipath is not activated. So you have to regenerate the initramfs. I didn't pursue using the MCO to trigger an initramfs regeneration because the MCO can't deliver payloads on a node level; multipath configuration can be/often-is a node-level configuration.

If:

  • appending or regenerating the initrd is out (due to desires to sign, don't want to mutate it)
  • reading the files from /boot alternative path is out
  • opening the root device and fetching a while-list is worse, especially in the case of LUKS (open, read files, close LUKS, bounce a few things, re-open....)

Then multipath, iSCSI and other complicated disk setups can't be supported by CoreOS.

@darkmuggle
Copy link
Contributor Author

I fear that we might wear our welcome here by debating CoreOS specific concerns here.

@jlebon @cgwalters @dustymabe let's take the debate to coreos/fedora-coreos-tracker#464 And the Dracut Developers are more than welcome to come to our space.

I'm inclined to close until a decision is made at the CoreOS level. If the idea wouldn't be merged into CoreOS's own codebase, why ask Dracut to consider it?

@cgwalters
Copy link
Contributor

I don't think this problem domain is solely CoreOS specific - it applies to any "image based" system which wants to ship a server-side generated initramfs, right? And it's good if solutions we come up with can be adopted by other distributions using non-OSTree mechanisms.

@darkmuggle
Copy link
Contributor Author

darkmuggle commented Apr 17, 2020

I don't think this problem domain is solely CoreOS specific - it applies to any "image based" system which wants to ship a server-side generated initramfs, right?

Agreed. And that's what I tried to do with this, and why I liked your suggestion to cargo-cult in /boot/etc. And it was your suggestion that I submitted here first.

And it's good if solutions we come up with can be adopted by other distributions using non-OSTree mechanisms.

I suggested that we move the discussion because the scope of conversation had become one about OSTree needs. I had proposed the general solution and it quickly rabbit holed. I would be happy to consider discussing the best implementation for the feature within the scope of the generic Linux community for image-based workflows. CoreOS' needs were indeed the opening justification, but it has dominated the discussion. I'd rather we have our myopic discussions in our own space.

To be clear -- your counter idea of targeted and per-module overrides makes sense, and there's merit to it. As does the merits of Jonathan's concerns about not having N sources of truth (although, having 18 ways to the same thing is a thing in Linux). The solution as proposed puts the power in the hands of the user by allowing for easy side-loading. The tension between the target path and this solution is really whether we want a side-loading functionality for users and to which degree. Not debating OSTree specific concerns.

My position is that once we enable Multipath and iSCSI sideloads, someone else will want it for something else. In looking at the full-scope of the problem domain, I concluded that a general side-loading mechanism is pro-user and gives a good balance between image base workloads against user tensions. My argument is that reducing friction for users will increase adoptions while image masters do their arcane and byzantine dark magic. The typical image based workloads would normally require re-mastering the image or using kargs; this solves those pain points. If adopted the wider Dracut world outside of Fedora/Red Hat and CoreOS could use that and its why I did the most generic method possible.

I do think that we should continue the debate for CoreOS in the Fedora CoreOS. Trust me, had I submitted it to Fedora CoreOS or Ignition Dracut this would have looked very different. The general side loading of /etc is a starting point and something that the Dracut community can decide; CoreOS is a member of the Dracut community, too. The danger I am trying to avoid is having a change that only suits our needs or having an exclusively CoreOS discussion.

With that, let's continue the debate on the generic solution here. And then figure it how/if/what to use in our ivory towers.

This provides support for updating '/etc/' in the initramfs using
'bootetc=<DEVICE>'. If the device has the path '/initrd-etc', then the
tree is copied into the initramfs.

The purpose of bootetc is to aide immutable operating systems like
Fedora and Red Hat CoreOS that ship static initrds with a path for
user-provided configuration. Example use cases include udev rules, iSCSI
and multipath configuration, fips and Network Manager configurations.
@darkmuggle
Copy link
Contributor Author

darkmuggle commented Apr 17, 2020

@haraldh Can I bother you to weigh in here? There's a lot going on in the conversation, and without understanding how the Dracut Community feels, this idea is pretty much dead in my opinion.

@darkmuggle darkmuggle closed this Apr 20, 2020
@haraldh
Copy link
Collaborator

haraldh commented Apr 20, 2020

For the reference.. @darkmuggle and I chatted in private.

I opted for either a unsecure-config source, which has to be treated carefully and/or a signed config source (signed by the Machine Owner Key or similar).

IMHO, ideally it would be a signed config cpio, which could be checked by grub, so we would avoid any reload of systemd services.

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.

6 participants