Add Podman quadlet .image file support#501
Conversation
|
Do you intend to resolve #277 with this? |
I'm wondering if we can leverage the built in Also not sure if you can use |
As we stated before, tieing ourselves to an RPM laying down some base container will slow us down as any time it requires a change we have to wait for the RPM to cycle and it would split the base from any overrides. I think we would end up just deploying everything via overrides. Just feel like friction right now. I did think about this and here is an alternative using this concept: Updated ProposalPlace .image files alongside .container files in /etc/containers/systemd/, using quadlet's native drop-in mechanism for overrides. Layout: /etc/containers/systemd/ Precedence (last wins):
Numbered prefixes enforce ordering with gaps for future layers. What this eliminates:
What stays the same:
|
This is what I had in mind.
This is IMHO the big benefit. |
|
i like this approach too and will change my PR to only have the feature addition but no changes to image locations. looking forward to this getting merged 🙂 |
|
Being able to override the container images easily would be really beneficial for development. If we eventually have containers built from PRs much like packit does with RPMs today, you could just drop those in. Or, when we need to test new versions of Pulp, we could simply drop that new Pulp container in (theforeman/pulp-oci-images#13). |
| @@ -1,6 +1,5 @@ | |||
| --- | |||
| iop_advisor_frontend_container_image: "quay.io/iop/advisor-frontend" | |||
| iop_advisor_frontend_container_tag: "foreman-3.18" | |||
There was a problem hiding this comment.
Unrelated, but shouldn't this follow nightly?
9b0d041 to
2f9968f
Compare
| Image=quay.io/foreman/foreman:nightly | ||
| ``` | ||
|
|
||
| **User's own registry:** The user creates a `90-user.conf` drop-in to point at their own registry. This overrides the base layer: |
There was a problem hiding this comment.
This particular use case may be easier with containers-registries.conf. From reading the docs I think adding the following to /etc/containers/registries.conf should work:
[[registry]]
prefix = "quay.io/theforeman"
location = "katello.example.com/Default_Organization"| post_tasks: | ||
| - name: Pull an image | ||
| containers.podman.podman_image: | ||
| - name: Deploy core image units |
There was a problem hiding this comment.
From what i understand is this only writes .image files to /etc/containers/systemd/ and does a daemon_reload but does that actually pulls a image? i mean does it download the images that can be used without re-pulling in deploy?
There was a problem hiding this comment.
https://docs.podman.io/en/latest/markdown/podman-image.unit.5.html#usage-summary says enerating a systemd .service that runs podman image pull. is confusing, does it pull by default or on start of .service
There was a problem hiding this comment.
I think it generates a .service (like foreman.image.service) file but it requires someone/something to start it. Whether that's a user running systemctl or another service depending on it (I'd expect foreman.service to).
In this case I'd expect foremanctl pull-images to ensure the service is started, but some questions that pop up:
- What if the service (like
foreman.image.service) was already started? Is it a noop or does it run again? - What happens if an updated image is pulled? Does it restart dependent services?
Looking at the docs Policy influences this.
There was a problem hiding this comment.
The quadlet generator makes each .image unit a Type=oneshot service. When a container starts, systemd activates its image service dependency, which runs podman image pull (or no-ops if the image already exists), then exits. The service transitions active → inactive when the oneshot finishes.
This strategy has lots of benefits and one small downside, on systemctl start foreman.target:
- Each container Requires its image service
- Since the image services are inactive (they completed as oneshots), systemd re-runs them
- Each one checks whether the image exists, which is fast if it's cached — but with 20 image services being re-checked concurrently on a busy system, it adds latency
Because of this I had to increase the foreman.target retries when we test start/stop/restart of it.
There was a problem hiding this comment.
The docs mention Policy=always and that implies it always connects over the network. Perhaps we should use Policy=missing so it's only a local operation after the first installation?
Then we do need an explicit process to update images, but we already have an update and upgrade guide. Perhaps that's good anyway? Otherwise you can unexpectedly pull in z-streams after a reboot.
There was a problem hiding this comment.
When a container starts, systemd activates its image service dependency, which runs podman image pull
so technically it happens when containers start not when we run foremanctl pull-images? thats seems odd with what we expect from pull-images, as a user i can pull-images and then deploy which reduces the deployment time as i already have latest images.
or i am interpreting wrong?
2f9968f to
e392b79
Compare
| dest: "{{ images_quadlet_dir }}/{{ images_definition.name }}.image" | ||
| mode: "0644" | ||
|
|
||
| - name: Create drop-in directory for {{ images_definition.name }} |
There was a problem hiding this comment.
we don't deploy anything here, right? it's just "so it's there so someone else can do it"?
There was a problem hiding this comment.
Yes. So, arguably, I can drop this here and just let whatever needs to do this create them (e.g. downstreams with different images or upstream release RPMs). Thoughts?
There was a problem hiding this comment.
I thought packages would not touch it here anyway but use /usr/lib?
There was a problem hiding this comment.
/usr/share but yes you are correct. This override directory would be used for these two scenarios:
- development / testing image overrides (e.g. developers being able to do Pulp upgrade container for development pulp-oci-images#13 and then drop it in and test it)
- "hotfix" or modified containers with a different name:tag
One argument is these are specialized and thus the directory should be created at the time of use. This adds a step the user or developer has to remember. Whereas, having the directory allows quick and easy drop in with less overhead remembering two steps.
What do you think?
There was a problem hiding this comment.
One argument is these are specialized and thus the directory should be created at the time of use. This adds a step the user or developer has to remember. Whereas, having the directory allows quick and easy drop in with less overhead remembering two steps.
IMHO you can't count on things existing just because Ansible created it so I'd prefer the tools to be robust by having a mkdir -p in there. So my suggestion is to remove the drop-in directory from Ansible.
e392b79 to
f0e2546
Compare
| @@ -0,0 +1,15 @@ | |||
| --- | |||
| - name: Generate image file for {{ images_definition.name }} | |||
| containers.podman.podman_image: | |||
There was a problem hiding this comment.
Following up on #501 (comment): I think we should set Policy=missing so it doesn't automatically update on every reboot/restart.
Then we can use podman auto-update to force updates.
Introduce .image quadlet units to decouple image sourcing from container definitions. Container roles now reference Image=<name>.image instead of full registry URLs, and a new images role handles deployment with a three-tier precedence model: admin overrides (/etc/foremanctl/images.d/) > vendor RPMs (/usr/share/foremanctl/images.d/) > generated defaults. Resolves: theforeman#277 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
f0e2546 to
6057acc
Compare
| quadlet_file_mode: "0644" | ||
| quadlet_options: | ||
| - "Policy=missing" | ||
| - "Environment=REGISTRY_AUTH_FILE={{ images_registry_auth_file }}" |
There was a problem hiding this comment.
Per containers/ansible-podman-collections#1034 (comment) you can use authfile:
| - "Environment=REGISTRY_AUTH_FILE={{ images_registry_auth_file }}" | |
| authfile: "{{ images_registry_auth_file }}" |
There was a problem hiding this comment.
Nope. This will set AuthFile and this will enforce the existence of this file. What we want is to set the environment variable like we do in puppet-iop.
|
I'm not yet sure what change in the design is not leading to the failure. I will need to follow up with deeper investigation. |
| quadlet_file_mode: "0644" | ||
| quadlet_options: | ||
| - "Policy=missing" | ||
| - "Environment=REGISTRY_AUTH_FILE={{ images_registry_auth_file }}" |
There was a problem hiding this comment.
| - "Environment=REGISTRY_AUTH_FILE={{ images_registry_auth_file }}" | |
| - "AUTH_FILE={{ images_registry_auth_file }}" |
we can't use Environment or REGISTRY_AUTH_FILE directly in [Image] section as thats not one of the valid options(https://docs.podman.io/en/latest/markdown/podman-image.unit.5.html#options)
we could use REGISTRY_AUTH_FILE but not directly in .image file https://docs.podman.io/en/latest/markdown/podman-image.unit.5.html#authfile-path
There was a problem hiding this comment.
and mostly CI is also failing because of same reason
systemd[1]: Reloading.
May 20 09:47:23 quadlet.example.com quadlet-generator[34868]: converting "postgresql.image": unsupported key 'Environment' in group 'Image' in /etc/containers/systemd/postgresql.image
May 20 09:47:23 quadlet.example.com quadlet-generator[34868]: processing encountered some errors
May 20 09:47:23 quadlet.example.com systemd-rc-local-generator[34879]: /etc/rc.d/rc.local is not marked executable, skipping.
May 20 09:47:23 quadlet.example.com systemd[34865]: /usr/lib/systemd/system-generators/podman-system-generator failed with exit status 1.
Why are you introducing these changes? (Problem description, related links)
Container image references were embedded directly in each service role as variable defaults, making it difficult to override images for product builds, disconnected installs, or developer testing without modifying foremanctl-managed files.
Resolves: #277
What are the changes introduced in this pull request?
imagesrole withdeploy_image.yamlthat generates a.imagequadlet unit file and.image.d/drop-in directory for each container image usingcontainers.podman.podman_image(state: quadlet)image.yamltask that calls theimagesrole with its image name and tag, removing per-role image variable defaultsImage=<name>.imageinstead of full registry URLs, binding image pull to the quadlet unit lifecycle managed by systemdpull-imagesplaybook updated to deploy image units and rundaemon_reloadrather than pulling images directly; actual pulls happen on first service start/usr/share/containers/systemd/<name>.image.d/10-product.conf,20-archive.conf,/etc/containers/systemd/<name>.image.d/90-user.conf) allows RPM vendors, ISO extraction, and users to override images without modifying foremanctl-generated filesimages_registry_auth_filedefaults to/etc/foreman/registry-auth.json; users with authenticated registries runpodman login <registry> --authfile=/etc/foreman/registry-auth.jsonbefore deployingtests/images_test.pyfor core image files, drop-in directories, and systemd service existence; IOP image tests intests/iop/images_test.pyHow to test this pull request
Steps to reproduce:
./foremanctl deploy.imagefiles exist under/etc/containers/systemd/for each service<name>-imagesystemd services exist./forge testand confirmimages_test.pypasses/etc/containers/systemd/foreman.image.d/90-user.confwith an alternate image tag, runsystemctl daemon-reload, and confirm the override takes precedenceChecklist