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

lib/deploy: Add support for overlay initrds #2155

Merged
merged 3 commits into from
Oct 2, 2020

Conversation

jlebon
Copy link
Member

@jlebon jlebon commented Jul 24, 2020

In FCOS and RHCOS, the need to configure software in the initramfs has
come up multiple times. Sometimes, using kernel arguments suffices.
Other times, it really must be a configuration file. Rebuilding the
initramfs on the client-side however is a costly operation. Not only
does it add complexity to the update workflow, it also erodes a lot of
the value obtained from using the baked "blessed" initramfs from the
tree itself.

One elegant way to address this is to allow specifying multiple
initramfses. This is supported by most bootloaders (notably GRUB) and
results in each initrd being overlayed on top of each other.

This patch allows libostree clients to leverage this so that they can
avoid regenerating the initramfs entirely. libostree itself is agnostic
as to what kind and how much data overlay initrds contain. It's up to
the clients to enforce such boundaries.

To implement this, we add a new option to the deploy APIs called
overlay_initrds: this is an array of filepaths to CPIO archives. We
copy these files into /boot and add them to the BLS as another
initrd entry.

jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Jul 24, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs. This
will be useful for configuring services involved in bringing up the root
block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Checking out tree 9a817d7... done
Writing OSTree commit... done
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                BaseCommit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar
                  Unlocked: development

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94
@jlebon jlebon marked this pull request as draft July 25, 2020 14:31
jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Jul 25, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs. This
will be useful for configuring services involved in bringing up the root
block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Checking out tree 9a817d7... done
Writing OSTree commit... done
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                BaseCommit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar
                  Unlocked: development

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94
@cgwalters
Copy link
Member

There's no use case I can think of for a "pristine" ostree shipping multiple initramfses. So what if instead

  • We just taught the bootconfig parser to correctly preserve multiple initramfs fields (done in this code)
  • Downstream, projects like rpm-ostree could create e.g. /boot/rpm-ostree/custom-initramfs-foo.img and generate a new deployment using it.

IOW we think of this more like kernel arguments (which don't affect the commit checksum).

jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Aug 13, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs. This
will be useful for configuring services involved in bringing up the root
block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Checking out tree 9a817d7... done
Writing OSTree commit... done
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                BaseCommit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar
                  Unlocked: development

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94
@jlebon jlebon force-pushed the pr/add-initrds branch 2 times, most recently from 5dc1f01 to 58b1f03 Compare August 13, 2020 21:32
jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Aug 13, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs (or
even a new OSTree commit). This will be useful for configuring services
involved in bringing up the root block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar
                  Unlocked: development

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94
@jlebon
Copy link
Member Author

jlebon commented Aug 13, 2020

OK, updated this now based on feedback and coreos/rpm-ostree#2170 (comment). We no longer look for the additional initramfses in the tree; it's instead passed via the new deploy APIs, checksummed, copied into /boot, and added into the BLS entry. The end result is that this is now an even more lightweight operation for clients!

jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Aug 14, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs (or
even a new OSTree commit). This will be useful for configuring services
involved in bringing up the root block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar
                  Unlocked: development

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94
@jlebon jlebon changed the title lib/deploy: Add support for additional initrds lib/deploy: Add support for overlay initrds Aug 14, 2020
@jlebon
Copy link
Member Author

jlebon commented Aug 17, 2020

Split out the trivial/prep patches into #2172.

openshift-merge-robot added a commit that referenced this pull request Aug 17, 2020
@jlebon
Copy link
Member Author

jlebon commented Sep 28, 2020

Added an installed tests and marked ready for review!

Requires: #2204

Edit: I also updated coreos/rpm-ostree#2170 to show how the new APIs are used.

jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Sep 28, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs (or
even a new OSTree commit). This will be useful for configuring services
involved in bringing up the root block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94
Prep for actually teaching the rest of the codebase about this.

We keep the primary initrd in the `options` hash table for backwards
compatibility.
And make the `override_kernel_argv` one of those options. This is mostly
a mechanical move here, no functional change otherwise.

Prep for adding a new option.
In FCOS and RHCOS, the need to configure software in the initramfs has
come up multiple times. Sometimes, using kernel arguments suffices.
Other times, it really must be a configuration file. Rebuilding the
initramfs on the client-side however is a costly operation. Not only
does it add complexity to the update workflow, it also erodes a lot of
the value obtained from using the baked "blessed" initramfs from the
tree itself.

One elegant way to address this is to allow specifying multiple
initramfses. This is supported by most bootloaders (notably GRUB) and
results in each initrd being overlayed on top of each other.

This patch allows libostree clients to leverage this so that they can
avoid regenerating the initramfs entirely. libostree itself is agnostic
as to what kind and how much data overlay initrds contain. It's up to
the clients to enforce such boundaries.

To implement this, we add a new ostree_sysroot_stage_overlay_initrd
which takes a file descriptor and returns a checksum. Then users can
pass these checksums when calling the deploy APIs via the new array
option `overlay_initrds`. We copy these files into `/boot` and add them
to the BLS as another `initrd` entry.
@jlebon
Copy link
Member Author

jlebon commented Sep 30, 2020

Rebased this now that #2204 is merged!

Copy link
Member

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

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

One comment, otherwise I think this is looking good!

for (char **it = overlay_initrds; it && *it; it++)
{
const char *basename = glnx_basename (*it);
if (strlen (basename) != (_OSTREE_SHA256_STRING_LEN + strlen (".img")))
Copy link
Member

Choose a reason for hiding this comment

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

It'd be nice to allow people to have a "short name" for their overlay initrd to describe its purpose without needing to unpack it to look.

Basically we append the checksum to the name they provide?

Copy link
Member

Choose a reason for hiding this comment

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

IOW it's /boot/ostree/initramfs-overlays/kdump-41af286dc0b172ed2f1ca934fd2278de4a1192302ffa07087cea2682e7d372e3.img and not just /boot/ostree/initramfs-overlays/41af286dc0b172ed2f1ca934fd2278de4a1192302ffa07087cea2682e7d372e3.img

Copy link
Member

Choose a reason for hiding this comment

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

If you prefer we can do this as a followup too.

Copy link
Member Author

@jlebon jlebon Oct 2, 2020

Choose a reason for hiding this comment

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

Are you suggesting expanding the overlay initrd staging API as e.g.:

diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h
index 3a3b6a77..ef5a353c 100644
--- a/src/libostree/ostree-sysroot.h
+++ b/src/libostree/ostree-sysroot.h
@@ -189,6 +189,7 @@ gboolean ostree_sysroot_write_deployments_with_options (OstreeSysroot     *self,
 _OSTREE_PUBLIC
 gboolean ostree_sysroot_stage_overlay_initrd (OstreeSysroot  *self,
                                               int             fd,
+                                              const char      short_id,
                                               char          **out_checksum,
                                               GCancellable   *cancellable,
                                               GError        **error);

?

Hmm, or maybe we could change the semantics of OstreeSysrootDeployTreeOpts.overlay_initrds to have the checksum be optionally prefixed by an ID? (E.g. my-id:<sha256>).

🤔 Honestly, while the code here does support multiple overlays, I think in practice it's not something that will be used often. E.g. in the rpm-ostree use case, there is just a single "initramfs-etc" initrd, and my hope is that it's the one way through which users interact with this feature.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I'd vote for leaving the API simple and we can do the second approach mentioned above if it comes up? (Because the first approach would obviously be an API break.)

Copy link
Member

Choose a reason for hiding this comment

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

OK, fine by me!

Copy link
Member

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

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

/lgtm

@openshift-ci-robot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: cgwalters, jlebon

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-robot openshift-merge-robot merged commit 06a77bf into ostreedev:master Oct 2, 2020
jlebon added a commit to jlebon/ostree that referenced this pull request Oct 6, 2020
This is a basic `.packit.yaml` integration file which will allow us have
continuous builds of OSTree in cosa and upstream CI. If things go well,
we'll likely deploy this in other build tools like rpm-ostree.

Prompted by wanting to get ostreedev#2155 out to unblock
coreos/rpm-ostree#2170.
@jlebon jlebon mentioned this pull request Oct 6, 2020
jlebon added a commit to jlebon/ostree that referenced this pull request Oct 6, 2020
This is a basic `.packit.yaml` integration file which will allow us have
continuous builds of OSTree in cosa and upstream CI. If things go well,
we'll likely deploy this in other build tools like rpm-ostree.

Prompted by wanting to get ostreedev#2155 out to unblock
coreos/rpm-ostree#2170.
jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Oct 18, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs (or
even a new OSTree commit). This will be useful for configuring services
involved in bringing up the root block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94
jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Oct 21, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs (or
even a new OSTree commit). This will be useful for configuring services
involved in bringing up the root block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94
jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Oct 21, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs (or
even a new OSTree commit). This will be useful for configuring services
involved in bringing up the root block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94
jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Oct 23, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs (or
even a new OSTree commit). This will be useful for configuring services
involved in bringing up the root block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94

Closes: coreos#1930
openshift-merge-robot pushed a commit to coreos/rpm-ostree that referenced this pull request Oct 29, 2020
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs (or
even a new OSTree commit). This will be useful for configuring services
involved in bringing up the root block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94

Closes: #1930
@jlebon jlebon deleted the pr/add-initrds branch April 24, 2023 02:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants