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

WIP: Use podman pull to fetch containers #215

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

cgwalters
Copy link
Collaborator

@cgwalters cgwalters commented Dec 3, 2023

Tracker: #20


Prep in #214


WIP: Use podman pull to fetch containers

See #147 (comment)

With this bootc starts to really gain support for a different backend
than ostree. Here we basically just fork off podman pull to
fetch container images into an alternative root in
/ostree/container-storage,
(Because otherwise basic things like podman image prune would
delete the OS image)

This is quite distinct from our use of skopeo in the ostree-ext project
because suddenly now we gain support for things
implemented in the containers/storage library like zstd:chunked and
OCI crypt.

However...today we still need to generate a final flattened
filesystem tree (and an ostree commit) in order to maintain
compatibilty with stuff in rpm-ostree. (A corrollary to this is
we're not booting into a podman mount overlayfs stack)
Related to this, we also need to handle SELinux labeling.

Hence, we implement "layer squashing", and then do some final
"postprocessing" on the resulting image matching the same logic
that's done in ostree-ext such as etc -> usr/etc and handling /var.

Note this also really wants
ostreedev/ostree#3106
to avoid duplicating disk space.


@cgwalters
Copy link
Collaborator Author

Demo:

$ env RUST_LOG=debug /run/hostsrv/src/github/containers/bootc/target/release/bootc switch --backend container quay.io/cgwalters/ostest
DEBUG Re-executing current process for _ostree_unshared
DEBUG Already in a mount namespace
DEBUG Current security context is unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
DEBUG Copying self to temporary file for re-exec
DEBUG Label for /tmp/.tmpnua4Vn is system_u:object_r:install_exec_t:s0
DEBUG Created "/tmp/.tmpnua4Vn"
DEBUG Re-executing _bootc_selinuxfs_mounted="/tmp/.tmpnua4Vn" "/tmp/.tmpnua4Vn" "switch" "--backend" "container" "quay.io/cgwalters/ostest"
DEBUG Already in a mount namespace
DEBUG Current security context is unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
DEBUG Removing temporary file
DEBUG Pulling docker://quay.io/cgwalters/ostest
Trying to pull quay.io/cgwalters/ostest:latest...
Getting image source signatures
Copying blob 797644653c72 skipped: already exists  
Copying blob 797644653c72 skipped: already exists  
Copying blob ef5675472650 skipped: already exists  
...
Writing manifest to image destination
DEBUG Creating temporary container for c864f541834eaef553a6e49d5a7da8f91a7fec26a7fdd9ce492a004499a4eef6
DEBUG Mounting 6674154c085cda1abf3f17b28c1fede55e74f975ad1acb0ec2d03252c2de340e
DEBUG Merging layer: ostree/container-storage/overlay/1cc5fa9dff7d8c9ce68cb1a635aede85960085b7bf5c6bce2ff91527fa0fb5ac/diff
DEBUG Merging layer: ostree/container-storage/overlay/f16810ac59f484691c15a8f186df29e54ac378e801972e3ca8416896bc882814/diff
DEBUG Merging layer: ostree/container-storage/overlay/705dd7ffd5fea45eee3dbe85688091c696f918746576419d1a22dfa2d666e8b3/diff
...
DEBUG Writing ostree commit
829754790d5c947c4816e15c3e07a11db72c7e64928e5620fa32b9a36f6c8409
Queued for next boot: ostree-image-signed:docker://quay.io/cgwalters/ostest
  Version: 39.20231123.1
  Digest: sha256:f7afa32ff5a924a9660c7ebd0c567cd37d9d85c6598ea08784961e13477d24e8
$

Now, we can also expose every single podman command but operating on our internal root, like:

$ /run/hostsrv/src/github/containers/bootc/target/release/bootc internal-podman images
REPOSITORY                TAG         IMAGE ID      CREATED       SIZE
quay.io/cgwalters/ostest  latest      c864f541834e  27 hours ago  1.24 GB
$

And also for example, we can optimize pushes and pulls between the bootc storage and the default containers-storage in /var/lib/containers. (Particularly if they're on the same filesystem); i.e. we want something like a handy bootc push-to-podman as well as bootc pull-from-podman as sugar for effectively skopeo copy containers-storage:[overlay@/ostree/containers-storage]:foo containers-storage:foo.

Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

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

@rhatdan PTAL
FYI @giuseppe

lib/src/podman.rs Outdated Show resolved Hide resolved
lib/src/podman.rs Show resolved Hide resolved
lib/src/podman_ostree.rs Show resolved Hide resolved
@cgwalters cgwalters force-pushed the podman-pull branch 5 times, most recently from 91856eb to 0415f12 Compare December 4, 2023 22:28
@cgwalters cgwalters mentioned this pull request Apr 6, 2024
7 tasks
@@ -0,0 +1,72 @@
//! # Copy of the ostree authfile bits as they're not public
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OK, #581 merged

@github-actions github-actions bot added the area/install Issues related to `bootc install` label Jun 5, 2024
@jeckersb
Copy link
Contributor

jeckersb commented Jun 5, 2024

Ok, I've pushed my rebased and seemingly-working fork onto the original here so I can continue to iterate here instead of off in my own world. I know there are things that are still half-done or hacked-around that needs cleaned up, but this is at least something people can look at and build and play around with.

@@ -138,41 +153,62 @@ pub(crate) fn create_imagestatus(

/// Given an OSTree deployment, parse out metadata into our spec.
#[context("Reading deployment metadata")]
fn boot_entry_from_deployment(
async fn boot_entry_from_deployment(
Copy link
Contributor

Choose a reason for hiding this comment

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

This whole function should probably be reworked, it's really hard to follow.

ImageState::from(*ostree_container::store::query_image_commit(repo, &csum)?)
}
};
//let cached = imgstate.cached_update.map(|cached| {
Copy link
Contributor

Choose a reason for hiding this comment

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

I ignored this while moving things around, needs to be addressed properly.

.map(|d| boot_entry_from_deployment(sysroot, d))
.transpose()
.context("Rollback deployment")?;
let staged = if let Some(d) = deployments.staged.as_ref() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't love how this changed, but I couldn't figure out a better way to do it since await snuck in here and it doesn't play as well with the chaining+closures.

@@ -439,7 +454,7 @@ async fn upgrade(opts: UpgradeOpts) -> Result<()> {
}
}
} else {
let fetched = crate::deploy::pull(sysroot, imgref, opts.quiet).await?;
let fetched = crate::deploy::pull(sysroot, spec.backend, imgref, opts.quiet).await?;
Copy link
Contributor

Choose a reason for hiding this comment

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

In the branch above here where we handle --check, it doesn't know how to store cached updates properly for the podman backend. This in turn means we don't have a good way to represent that in bootc status (it will always just be None currently)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We have a lot of choice for how to represent this; it strongly relates to the question of image GC though. I think today, podman and c/storage generally handle this by creating containers which hold references to images.

Copy link
Contributor

Choose a reason for hiding this comment

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

This also feels like more reason re: your previous comment to switch to using skopeo instead of podman, since we could use skopeo inspect to only fetch the metadata in the --check case. If I'm following correctly from the way ostree does it today it's similar in that it's just saving the manifest/config.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yep

@jeckersb
Copy link
Contributor

jeckersb commented Jun 25, 2024

Something else that needs fixed:

ERROR Status: Computing status: Booted deployment: Reading deployment metadata: Reading manifest data from commit: Missing ostree.manifest-digest metadata on merge commit

I get that if I do a hack/Containerfile build, podman-bootc run that, then bootc switch --backend container quay.io/fedora/fedora-bootc:40, then reboot and finally bootc status.

Nevermind this was just me being temporarily dumb. Of course if I switch to the latest fedora image and then boot into it, the bootc binary there isn't going to know how to handle the podman backend properly.

lib/src/status.rs Outdated Show resolved Hide resolved
cgwalters and others added 5 commits July 2, 2024 11:36
We'll use this even in cases where we don't have the `install`
feature.

Signed-off-by: Colin Walters <walters@verbum.org>
See containers#147 (comment)

With this bootc starts to really gain support for a different backend
than ostree.  Here we basically just fork off `podman pull` to
fetch container images into an *alternative root* in
`/ostree/container-storage`,
(Because otherwise basic things like `podman image prune` would
 delete the OS image)

This is quite distinct from our use of `skopeo` in the ostree-ext project
because suddenly now we gain support for things
implemented in the containers/storage library like `zstd:chunked` and
OCI crypt.

*However*...today we still need to generate a final flattened
filesystem tree (and an ostree commit) in order to maintain
compatibilty with stuff in rpm-ostree.  (A corrollary to this is
we're not booting into a `podman mount` overlayfs stack)
Related to this, we also need to handle SELinux labeling.

Hence, we implement "layer squashing", and then do some final
"postprocessing" on the resulting image matching the same logic
that's done in ostree-ext such as `etc -> usr/etc` and handling `/var`.

Note this also really wants
ostreedev/ostree#3106
to avoid duplicating disk space.

Signed-off-by: Colin Walters <walters@verbum.org>
Signed-off-by: John Eckersberg <jeckersb@redhat.com>
Signed-off-by: John Eckersberg <jeckersb@redhat.com>
@vrothberg
Copy link
Member

Trying to catch up: Which items are open in this PR?

@jeckersb
Copy link
Contributor

jeckersb commented Jul 8, 2024

Trying to catch up: Which items are open in this PR?

Colin and I discussed this a bit last week before the holiday, the first thing I want to land is a prep change that adds the machinery for multiple backends, which initially will have just one implemented backend (the current "OstreeContainer" backend). This will force the backend API to get fleshed out, as well as help decouple the backend bits from everything else so I can (hopefully) spend less time rebasing this as things change around it. I'm going to draft a proposed backend API in a new PR that I will link here, and we can debate the design over there.

Once that's in, we finish cleaning up the ideas here into the second backend implementation. This PR as-is implements the backend via podman pull, however above discussions indicate we probably want to swap that out for skopeo copy/inspect instead. I think ideally those skopeo bits would live either in a reimagined containers-image-proxy-rs or a new sibliing containers-storage-proxy-rs library or similar. For the short-term, in bootc we'll probably just exec out to skopeo similar to how this draft execs podman. Switching to skopeo lets us handle caching update metadata via skopeo inspect without pulling down the payload the same way the current ostree backend works.

There's also the opaque directory issue noted above, which I haven't given any thought to.

I think that covers the known outstanding issues?

cgwalters added a commit to cgwalters/bootc that referenced this pull request Jul 30, 2024
Closes: containers#721

- Initialize a containers-storage: instance at install time
  (that defaults to empty)
- Open it at the same time we open the ostree repo/sysroot
- Change bound images to use this

We are *NOT* yet changing the base bootc image pull to use this.
That's an obvious next step (xref
containers#215 ) but will come later.

Signed-off-by: Colin Walters <walters@verbum.org>
cgwalters added a commit to cgwalters/bootc that referenced this pull request Jul 31, 2024
Closes: containers#721

- Initialize a containers-storage: instance at install time
  (that defaults to empty)
- Open it at the same time we open the ostree repo/sysroot
- Change bound images to use this

We are *NOT* yet changing the base bootc image pull to use this.
That's an obvious next step (xref
containers#215 ) but will come later.

Signed-off-by: Colin Walters <walters@verbum.org>
@vrothberg
Copy link
Member

vrothberg commented Aug 19, 2024

I dreamed of getting rid of skopeo from bootc images. That would drop ~30MB from the image.

Am I reading the comments correctly that the intend of keeping skopeo is being able to remote inspect an image?

@cgwalters
Copy link
Collaborator Author

I dreamed of getting rid of skopeo from bootc images. That would drop ~30MB from the image.

Honestly what's probably the most practical thing is to vendor the skopeo (and while we're here, buildah) code into podman, with a podman-all-tools package that ships those as symbolic links or so...

@vrothberg
Copy link
Member

Friendly ping. Are we on track to get this in before RHEL 10?

@cgwalters
Copy link
Collaborator Author

Friendly ping. Are we on track to get this in before RHEL 10?

To be clear the thing that has me feeling a bit stuck is in which order we try to do things. We could switch over to basically forking podman pull or skopeo copy into the existing "plain overlay" backend and then post-processing it as this PR is doing.

What'd be more work is vendoring c/storage and trying to get patches in to do some things more intelligently. Even more work: Try to aim for a unified composefs-oriented storage.

This latter is what I personally find the most interesting and exciting because I care more about "sealing" then I do zstd:chunked basically.

OTOH there's other knock-on huge benefits to having the bootc image in c/storage such as being able to seamlessly push and build on it.

The thing that hurts my head is that if we do c/storage first before aiming for composefs then we will very likely need to do another storage transition later. But that's also true for the default /var/lib/containers/storage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/install Issues related to `bootc install` do-not-merge/work-in-progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants