Skip to content

container: merge grout and FRR into a single image#616

Merged
rjarry merged 4 commits into
DPDK:mainfrom
rjarry:merge-containers
May 19, 2026
Merged

container: merge grout and FRR into a single image#616
rjarry merged 4 commits into
DPDK:mainfrom
rjarry:merge-containers

Conversation

@rjarry
Copy link
Copy Markdown
Collaborator

@rjarry rjarry commented May 13, 2026

The FRR dplane_grout plugin is tightly coupled with grout. Delivering them as separate container images can cause API/ABI mismatches between the plugin and the daemon. Merge everything into a single Containerfile to ensure both are always aligned.

The default entrypoint starts grout. A /usr/bin/frr helper script is provided to start FRR daemons separately. For example:

podman run -d --name grout --privileged quay.io/grout/grout
podman exec grout frr

Container image consolidation

Merged grout and FRR builds into a single Containerfile; removed the FRR-specific build and Containerfile.grout to prevent API/ABI mismatches between the dplane_grout plugin and the FRR daemon by keeping both components built and versioned in one image.

CI / release workflow changes (.github/workflows/publish.yml)

  • Single upload pipeline: added a version step that queries RPM artifacts and exports grout and frr VERSIONs as outputs.
  • Docker metadata: meta step now emits both grout_version and frr_version labels from steps.version.outputs.
  • Single image build/push: removed the separate meta-frr and Containerfile.frr build; docker/build-push-action invoked once using Containerfile to build/push linux/amd64 and linux/arm64 images for quay.io/${{ vars.REGISTRY_NAMESPACE || 'grout' }}/grout.
  • Release publishing: removed pyTooling releaser for edge; replaced with explicit gh release steps—an “Update edge pre-release” (delete/recreate edge pre-release with container run instructions) and a “Create release” step for version tags that creates releases including container run instructions.

Containerfile changes (multi-stage build → unified image)

  • Builder stage: COPY *.rpm /tmp (all RPM artifacts copied into build context) and use dnf --installroot to install packages and the copied RPM(s) into a prepared installroot.
  • FRR configuration: sets /tmp/null/etc/frr/daemons to include zebra_options="-A 127.0.0.1 --log stdout -M dplane_grout" so the dplane_grout plugin is enabled in the packaged FRR.
  • FRR helper: installs /usr/bin/frr in the image as a shell wrapper that sources /usr/libexec/frr/frrcommon.sh and execs /usr/libexec/frr/watchfrr $(daemon_list) to allow starting FRR daemons independently (e.g., via podman exec).
  • Entrypoint/command and init: final image assembled from scratch, copies prepared installroot, sets STOPSIGNAL SIGRTMIN+3, ENTRYPOINT to ["/usr/libexec/catatonit/catatonit", "--"], and default CMD to ["/usr/bin/grout"] so the container starts grout by default while providing an explicit helper for running FRR.

Deleted file

  • Containerfile.grout: removed the previous CentOS Stream 10 multi-stage builder and scratch assembly (replaced by the unified Containerfile).

Deployment examples and systemd/podman unit helpers (docs/quadlets)

  • Added docs/quadlets README and quadlet unit files:
    • grout.container: quadlet to run quay.io/grout/grout:edge with privileged runtime, hugepages, vfio, PCI sysfs, device additions and post-start grcli against /etc/grout.init.
    • frr.container: quadlet to run FRR container joined to grout's network namespace and mounting /etc/frr/frr.conf.
    • grout-metrics.container: quadlet that runs an alpine/socat container to expose grout's openmetrics UNIX socket on TCP port 9111, sharing /run with grout container.
    • grout-netns.service: oneshot unit to create/remove a grout network namespace and bring up loopback.
    • grout-bind and grout-unbind scripts plus grout-bind@.service: idempotent bind/unbind helpers to move/claim network devices for DPDK use (resolve PCI address, detect current driver, bind to vfio-pci or move mlx5 interfaces into grout netns), with a parameterized oneshot service to bind specific interfaces.

Runtime impact / usage

  • Container default: catatonit launches /usr/bin/grout (grout runs by default).
  • To run FRR daemons separately inside the running container, use the provided /usr/bin/frr helper (example: podman exec frr).

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Caution

Review failed

Pull request was closed or merged during review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR consolidates the container build into a single Containerfile, updates the publish workflow to extract grout and frr RPM VERSIONs and label the grout image with grout_version and frr_version, and replaces prior releaser steps with explicit gh release commands. The Containerfile now stages all *.rpm files, adds /usr/bin/frr as a wrapper, and changes the final image ENTRYPOINT to /usr/libexec/catatonit/catatonit -- with CMD /usr/bin/grout. It also adds docs/quadlets with podman/systemd quadlets and helper scripts for device bind/unbind and a metrics proxy.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/publish.yml:
- Line 48: The workflow step is defined as id: frr-version but subsequent
references use steps.version, causing missing outputs; rename the step id from
frr-version to version (update the step with id: frr-version -> id: version) so
that the existing references to steps.version and outputs (used for image
labels/publish) resolve correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1d5bff72-55c8-4be4-be80-45f5c96bc415

📥 Commits

Reviewing files that changed from the base of the PR and between 0ab251b and 0f642f7.

📒 Files selected for processing (3)
  • .github/workflows/publish.yml
  • Containerfile
  • Containerfile.grout
💤 Files with no reviewable changes (1)
  • Containerfile.grout

Comment thread .github/workflows/publish.yml Outdated
@rjarry
Copy link
Copy Markdown
Collaborator Author

rjarry commented May 13, 2026

@zeeke what do you think?

@zeeke
Copy link
Copy Markdown
Contributor

zeeke commented May 13, 2026

@zeeke what do you think?

I'm ok with these changes. I'm not sure where and how the images are used right now.
The only one consumer I know is

which currently consume released RPMs files

@rjarry rjarry force-pushed the merge-containers branch from 0f642f7 to 98a7a1b Compare May 13, 2026 11:57
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
.github/workflows/publish.yml (1)

48-48: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix broken step output reference used by Docker labels.

Line 48 defines id: frr-version, but Lines 66-67 read from steps.version.outputs.*. That key is undefined, so metadata label values cannot resolve correctly.

Suggested fix
-        id: frr-version
+        id: version

Also applies to: 66-67

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish.yml at line 48, The workflow defines the step id
as frr-version but later reads steps.version.outputs.*, which is undefined;
update the references so they match — either rename the step id from frr-version
to version (targeting the step that generates outputs) or change all usages of
steps.version.outputs.* to steps.frr-version.outputs.* (including the Docker
labels usage), ensuring the id in the producing step (frr-version) and the
consuming references are identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In @.github/workflows/publish.yml:
- Line 48: The workflow defines the step id as frr-version but later reads
steps.version.outputs.*, which is undefined; update the references so they match
— either rename the step id from frr-version to version (targeting the step that
generates outputs) or change all usages of steps.version.outputs.* to
steps.frr-version.outputs.* (including the Docker labels usage), ensuring the id
in the producing step (frr-version) and the consuming references are identical.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 253d20ac-5dc5-4f34-bf52-f060c397e877

📥 Commits

Reviewing files that changed from the base of the PR and between 0f642f7 and 98a7a1b.

📒 Files selected for processing (3)
  • .github/workflows/publish.yml
  • Containerfile
  • Containerfile.grout
💤 Files with no reviewable changes (1)
  • Containerfile.grout

rjarry added 2 commits May 19, 2026 23:45
The executable is at /usr/libexec/catatonit/catatonit.

Fixes: d1a19cf ("packaging: use catatonit instead of tini")
Signed-off-by: Robin Jarry <rjarry@redhat.com>
The FRR dplane_grout plugin is tightly coupled with grout. Delivering
them as separate container images can cause API/ABI mismatches between
the plugin and the daemon. Merge everything into a single Containerfile
to ensure both are always aligned.

The default entrypoint starts grout. A /usr/bin/frr helper script is
provided to start FRR daemons separately. For example:

  podman run -d --name grout --privileged quay.io/grout/grout
  podman exec grout frr

Signed-off-by: Robin Jarry <rjarry@redhat.com>
@rjarry rjarry force-pushed the merge-containers branch from 98a7a1b to cc5a713 Compare May 19, 2026 21:47
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/publish.yml:
- Line 68: The workflow is using a mutable tag for the GitHub Action ("uses:
docker/build-push-action@v7"); replace that with a pinned immutable reference by
updating the "uses" entry for docker/build-push-action to the action's
repository at a specific commit SHA (e.g.,
docker/build-push-action@<commit-sha>) so the workflow references a fixed
commit; locate the line containing "docker/build-push-action@v7" and swap the
tag for the chosen commit SHA from the upstream repo's releases/commits.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9c62ee65-ac3b-4989-951b-9636294ed625

📥 Commits

Reviewing files that changed from the base of the PR and between 98a7a1b and cc5a713.

📒 Files selected for processing (3)
  • .github/workflows/publish.yml
  • Containerfile
  • Containerfile.grout
💤 Files with no reviewable changes (1)
  • Containerfile.grout

labels: |
frr_version=${{steps.version.outputs.frr}}
grout_version=${{steps.version.outputs.grout}}
- uses: docker/build-push-action@v7
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 19, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# List workflow actions not pinned to a 40-char commit SHA
rg -nP '^\s*-\s+uses:\s+\S+@(?![0-9a-f]{40}\b)\S+' .github/workflows

Repository: DPDK/grout

Length of output: 1692


Pin this GitHub Action to a commit SHA.

The action uses a mutable tag (@v7), which can be retargeted by the upstream repository and exposes the workflow to supply-chain risk.

🧰 Tools
🪛 zizmor (1.25.2)

[error] 68-68: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish.yml at line 68, The workflow is using a mutable
tag for the GitHub Action ("uses: docker/build-push-action@v7"); replace that
with a pinned immutable reference by updating the "uses" entry for
docker/build-push-action to the action's repository at a specific commit SHA
(e.g., docker/build-push-action@<commit-sha>) so the workflow references a fixed
commit; locate the line containing "docker/build-push-action@v7" and swap the
tag for the chosen commit SHA from the upstream repo's releases/commits.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

isn't this the case for all third party actions?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@rjarry, yes, you're correct — the same concern applies to all third-party actions in the workflow (actions/checkout@v6, actions/download-artifact@v8, docker/setup-qemu-action@v4, docker/setup-buildx-action@v4, docker/login-action@v4, docker/metadata-action@v6). The static analysis tool flagged only the line in the diff, but the supply-chain risk is consistent across the entire file and is pre-existing rather than introduced by this PR.

Would you like me to open a separate issue to track pinning all workflow actions to commit SHAs?

rjarry added 2 commits May 20, 2026 00:14
pyTooling/Actions/releaser is deprecated. Replace it with direct gh CLI
calls. On pushes to main, recreate a rolling "edge" pre-release. On
version tags, create a proper release with auto-generated notes. Include
container image usage instructions in the release notes.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
Provide example systemd/podman quadlet files to run grout and FRR as
containers. The grout container runs in privileged mode with no network
namespace, and FRR joins it via NetworkNS to share interfaces. A third
container runs socat to expose grout's openmetrics unix socket over TCP
port 9111 in its own network namespace. All three containers share /run
via an anonymous volume on the grout container.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
@rjarry rjarry merged commit 7d359af into DPDK:main May 19, 2026
12 of 14 checks passed
@rjarry rjarry deleted the merge-containers branch May 19, 2026 23:19
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.

2 participants