Skip to content

OCPBUGS-83863: Dockerfile: remove rhel8, use rhel9 as base, add rhel10 support#228

Open
sdodson wants to merge 4 commits into
mainfrom
OCPBUGS-83863-remove-rhel8-add-rhel10
Open

OCPBUGS-83863: Dockerfile: remove rhel8, use rhel9 as base, add rhel10 support#228
sdodson wants to merge 4 commits into
mainfrom
OCPBUGS-83863-remove-rhel8-add-rhel10

Conversation

@sdodson
Copy link
Copy Markdown
Member

@sdodson sdodson commented Apr 28, 2026

Summary

  • Remove the rhel8 build stage (RHEL 8 is EOL) and switch the windows builder to the rhel-9 image
  • Use rhel9-built binaries as the canonical /usr/src/plugins/bin/ and populate rhel9/bin/ via hardlinks instead of a duplicate COPY
  • Add rhel10/bin/ directory populated with hardlinks to the rhel9 binaries, assuming compatibility for now
  • Strip symbols and debug info from Linux binaries via -ldflags "-s -w" to reduce image size

Test plan

  • Verify the container image builds successfully
  • Verify /usr/src/plugins/bin/ contains the expected CNI plugin binaries
  • Verify /usr/src/plugins/rhel9/bin/ and /usr/src/plugins/rhel10/bin/ contain hardlinks to the same binaries
  • Verify /usr/src/plugins/windows/bin/ contains the Windows binaries
  • Verify no rhel8/ directory exists in the final image
  • Verify Linux binaries are stripped (no symbol table or DWARF debug info)

🤖 Generated with Claude Code

sdodson added 3 commits April 28, 2026 15:25
RHEL 8 is end-of-life. Remove the rhel8 build stage, switch the
windows builder to the rhel-9 image, and use rhel9-built binaries
as the default in /usr/src/plugins/bin/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
The rhel9/bin/ directory contains the same binaries as bin/. Use
hardlinks to avoid duplicating them in the image layer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
Add a rhel10/bin/ directory populated with hardlinks to the rhel9
binaries. For now the rhel9 binaries are assumed to be compatible
with rhel10.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Apr 28, 2026
@openshift-ci-robot
Copy link
Copy Markdown
Contributor

@sdodson: This pull request references Jira Issue OCPBUGS-83863, which is valid.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.0.0) matches configured target version for branch (5.0.0)
  • bug is in the state POST, which is one of the valid states (NEW, ASSIGNED, POST)

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

Summary

  • Remove the rhel8 build stage (RHEL 8 is EOL) and switch the windows builder to the rhel-9 image
  • Use rhel9-built binaries as the canonical /usr/src/plugins/bin/ and populate rhel9/bin/ via hardlinks instead of a duplicate COPY
  • Add rhel10/bin/ directory populated with hardlinks to the rhel9 binaries, assuming compatibility for now

Test plan

  • Verify the container image builds successfully
  • Verify /usr/src/plugins/bin/ contains the expected CNI plugin binaries
  • Verify /usr/src/plugins/rhel9/bin/ and /usr/src/plugins/rhel10/bin/ contain hardlinks to the same binaries
  • Verify /usr/src/plugins/windows/bin/ contains the Windows binaries
  • Verify no rhel8/ directory exists in the final image

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot added the jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. label Apr 28, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

Walkthrough

The Dockerfile removes the rhel8 Linux builder stage, stops producing rhel8 artifacts, updates the windows build stage to use rhel-9-golang-1.24-openshift-4.21, and creates /usr/src/plugins/rhel10/bin/ while using symlinks to distribute Linux binaries from the rhel9 stage.

Changes

Cohort / File(s) Summary
Dockerfile Build Configuration
Dockerfile
Removed rhel8 builder stage and rhel8 artifact copies; updated windows build stage to use rhel-9-golang-1.24-openshift-4.21; final image now creates /usr/src/plugins/rhel10/bin/ and uses symlinks to populate /usr/src/plugins/rhel9/bin/ and /usr/src/plugins/rhel10/bin/ from the rhel9 build artifacts.
Linux build script
build_linux.sh
go build invocations for non-windows plugins now include linker flags -s -w, stripping symbol/debug info while keeping output paths the same.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 12
✅ Passed checks (12 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: removing rhel8 support, using rhel9 as the base, and adding rhel10 support, which align with the Dockerfile and build script modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed PR modifies only build infrastructure files (Dockerfile, build_linux.sh) without changing any Ginkgo test files, making it not applicable to the test names stability check.
Test Structure And Quality ✅ Passed This pull request does not modify any Ginkgo test files. Changes are limited to Dockerfile and build_linux.sh, which are non-test files. The custom check reviews Ginkgo test code quality, so it is not applicable here.
Microshift Test Compatibility ✅ Passed This PR does not add any new Ginkgo e2e tests; modifications are exclusively to infrastructure and build files (Dockerfile and build_linux.sh).
Single Node Openshift (Sno) Test Compatibility ✅ Passed This PR only modifies build and container configuration files (Dockerfile and build_linux.sh) and does not introduce any new Ginkgo e2e tests.
Topology-Aware Scheduling Compatibility ✅ Passed PR modifies only Dockerfile and build script—purely build-time artifacts with no Kubernetes scheduling constraints or topology-dependent logic.
Ote Binary Stdout Contract ✅ Passed PR modifies infrastructure files without changing OTE binary code, process-level entry points, or stdout-writing code, so the custom check is not violated.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed This pull request does not add any new Ginkgo e2e tests. The changes are exclusively to build configuration and infrastructure files: the Dockerfile and build_linux.sh. Since the custom check is for new Ginkgo e2e tests and this PR contains no new test code, the check passes by default.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch OCPBUGS-83863-remove-rhel8-add-rhel10

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

@openshift-ci openshift-ci Bot requested review from dougbtv and s1061123 April 28, 2026 19:26
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 28, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: sdodson
Once this PR has been reviewed and has the lgtm label, please assign dougbtv for approval. For more information see the Code Review Process.

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

Details 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

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 the current code and only fix it if needed.

Inline comments:
In `@Dockerfile`:
- Around line 24-26: The two separate RUN layers creating hardlinks should be
combined into a single RUN so the hardlinks share the same inode; update the
Dockerfile so the ln operations that link /usr/src/plugins/bin/* into
/usr/src/plugins/rhel9/bin/ and /usr/src/plugins/rhel10/bin/ are executed in one
RUN instruction (i.e., run both ln commands together in the same shell
invocation) to avoid duplicate file data across layers and preserve inode
identity.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 5cdb716f-6ea1-43d1-9996-e288ff5a7acc

📥 Commits

Reviewing files that changed from the base of the PR and between 747ad66 and c536523.

📒 Files selected for processing (1)
  • Dockerfile

Comment thread Dockerfile
Comment on lines +24 to +26
RUN ln /usr/src/plugins/bin/* /usr/src/plugins/rhel9/bin/
# For now assume rhel9 binaries are compatible with rhel10
RUN ln /usr/src/plugins/bin/* /usr/src/plugins/rhel10/bin/
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

engine="podman"
command -v podman >/dev/null 2>&1 || engine="docker"

$engine build -t cni-hardlink-check -f Dockerfile .

$engine run --rm cni-hardlink-check sh -ec '
for f in /usr/src/plugins/bin/*; do
  b=$(basename "$f")
  i_bin=$(stat -c "%d:%i" "$f")
  i_r9=$(stat -c "%d:%i" "/usr/src/plugins/rhel9/bin/$b")
  i_r10=$(stat -c "%d:%i" "/usr/src/plugins/rhel10/bin/$b")
  if [ "$i_bin" != "$i_r9" ] || [ "$i_bin" != "$i_r10" ]; then
    echo "hardlink mismatch: $b -> bin=$i_bin rhel9=$i_r9 rhel10=$i_r10"
    exit 1
  fi
done
echo "all hardlinks match"
'

Repository: openshift/containernetworking-plugins

Length of output: 128


🏁 Script executed:

# First, let's see the full Dockerfile context around the flagged lines
fd -t f -name "Dockerfile" | head -5

Repository: openshift/containernetworking-plugins

Length of output: 312


🌐 Web query:

Docker overlayfs hardlink inode preservation across layers RUN

💡 Result:

No, Docker's overlayfs (specifically overlay2, the current default) does not preserve the same inode numbers for hardlinks created in a RUN instruction across different image layers. Hardlinks created within the same RUN layer (single layer) share the same inode and are preserved correctly during layer commit, as shown in examples where ls -li reports the same inode and link count >1 intra-layer. However, when creating hardlinks in subsequent RUN instructions to files from previous layers, the inode is not preserved across layers: the new hardlink gets a new inode in the current layer's diff directory, resulting in separate storage (duplication of file data in the layer tarball), increased layer size, and different inode numbers when inspected in the final image. This is due to how layers are committed to tar archives—tar only preserves hardlinks if both links are in the same layer's changes; cross-layer references cannot be maintained as inodes are layer-local. Official Docker docs confirm layers contain "hard links to data shared with lower layers" at the storage driver level for mounting, but this does not extend to preserving identical inodes for user-created hardlinks across committed layers. Recent issues (2024) confirm this behavior persists with BuildKit.

Citations:


🌐 Web query:

overlayfs copy-on-write hardlink behavior separate layers

💡 Result:

In OverlayFS, hard links do not span across separate layers (upper and lower). The merged view presents files from either the upper or lower layer, but since upper and lower are distinct filesystem trees (often on the same underlying fs but treated separately), hard links cannot connect inodes across layers. When a write operation triggers copy-up of a file from the lower layer to the upper layer, OverlayFS creates a new independent file in the upper layer. If the original lower file had multiple hard links (nlink > 1), this copy-up "breaks" those links by default: the upper copy is a separate inode, so changes to it do not propagate to other lower hard link names, and vice versa. The kernel documentation explicitly states: "If this feature [inode index] is disabled and a file with multiple hard links is copied up, then this will 'break' the link. Changes will not be propagated to other names referring to the same inode." Creating a new hard link in the overlay (to a lower file) also triggers copy-up of the target file to the upper layer before linking. The "index=on" mount option (inodes index feature) preserves hard link semantics during copy-up by creating an index entry (a hard link in a hidden index directory to the upper inode, keyed by the lower file handle). This ensures consistent lookup of the same upper inode for all lower hard links, maintaining the union nlink count. Without index=on, hard links are broken on copy-up. Sources confirm hard links do not work across layers natively, and copy-up creates separate inodes unless indexing is used.

Citations:


🏁 Script executed:

cat -n Dockerfile | head -40

Repository: openshift/containernetworking-plugins

Length of output: 1619


Combine both hardlink operations in a single RUN layer to preserve inode identity and avoid storage duplication.

Lines 24 and 26 create hardlinks in separate Docker layers. Due to how overlayfs manages layer composition, each subsequent RUN instruction creates a new inode for hardlinked files, resulting in duplicate file data stored in each layer's tarball. Consolidating both ln commands into one RUN layer ensures all hardlinks reference the same inode across bin, rhel9/bin, and rhel10/bin.

Proposed fix
-RUN ln /usr/src/plugins/bin/* /usr/src/plugins/rhel9/bin/
-# For now assume rhel9 binaries are compatible with rhel10
-RUN ln /usr/src/plugins/bin/* /usr/src/plugins/rhel10/bin/
+# For now assume rhel9 binaries are compatible with rhel10
+RUN ln /usr/src/plugins/bin/* /usr/src/plugins/rhel9/bin/ && \
+    ln /usr/src/plugins/bin/* /usr/src/plugins/rhel10/bin/
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
RUN ln /usr/src/plugins/bin/* /usr/src/plugins/rhel9/bin/
# For now assume rhel9 binaries are compatible with rhel10
RUN ln /usr/src/plugins/bin/* /usr/src/plugins/rhel10/bin/
# For now assume rhel9 binaries are compatible with rhel10
RUN ln /usr/src/plugins/bin/* /usr/src/plugins/rhel9/bin/ && \
ln /usr/src/plugins/bin/* /usr/src/plugins/rhel10/bin/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` around lines 24 - 26, The two separate RUN layers creating
hardlinks should be combined into a single RUN so the hardlinks share the same
inode; update the Dockerfile so the ln operations that link
/usr/src/plugins/bin/* into /usr/src/plugins/rhel9/bin/ and
/usr/src/plugins/rhel10/bin/ are executed in one RUN instruction (i.e., run both
ln commands together in the same shell invocation) to avoid duplicate file data
across layers and preserve inode identity.

Pass -ldflags "-s -w" to go build to reduce binary size by
stripping the symbol table and DWARF debug information.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 28, 2026

@sdodson: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/security 2bde2a8 link false /test security

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants