Skip to content

test(e2e): make the in-sandbox Talos image cache reachable by tenant workers - #3254

Merged
IvanHunters merged 2 commits into
mainfrom
fix/e2e-talos-image-cache-tenant-egress
Jul 9, 2026
Merged

test(e2e): make the in-sandbox Talos image cache reachable by tenant workers#3254
IvanHunters merged 2 commits into
mainfrom
fix/e2e-talos-image-cache-tenant-egress

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What this PR does

The in-sandbox Talos image cache added in #3244 is unreachable by the tenant workers it was meant to serve, so it makes the kubernetes-latest / kubernetes-previous e2e tests fail deterministically instead of relieving the intermittent public-factory flake it targets (#3231). Every branch off current main inherits this — for example #3240 has failed its tenant-Kubernetes e2e repeatedly for this reason alone, despite being unrelated (it only touches host boot assets).

Root cause: tenant namespaces run under a default-deny Cilium egress installed by the tenant chart. A worker's CDI importer is allowed to reach the outside world (so the public factory works) and kube-dns (so the name resolves), but nothing permits egress to an arbitrary kube-system Service. The importer therefore resolves talos-image-cache.kube-system.svc yet its TCP connect to the ClusterIP is silently dropped (dial tcp <clusterip>:80: i/o timeout), the DataVolume import never starts, the worker VM stays DataVolumeError, and no tenant node joins within the 12-minute deadline. #3244's readiness gate never caught this because it probed the server over localhost inside the serve Pod, which passes regardless of cross-Pod reachability.

Two changes:

  • Ship a tightly-scoped CiliumClusterwideNetworkPolicy that lets importer Pods in tenant-test egress to the mirror Pod in kube-system. Cilium unions allow rules, so this only adds a hole; scoping it to a namespace that is already default-deny egress means it never flips another namespace's posture, and the mirror Pod needs no ingress rule because no ingress policy selects it. The policy is applied at point-of-use (not with the rest of the mirror manifest, which is applied before Cilium's CRDs exist).
  • Replace the localhost range-probe with one that faces the exact same network path as a real importer: a throwaway Pod in the tenant namespace, labelled cdi.kubevirt.io=importer, that fetches the seeded image from the Service ClusterIP with a Range request and must get a 206. Tenants are pointed at the mirror only when that end-to-end check passes; otherwise the harness falls back to the public factory. This restores the invariant feat(apps/kubernetes): overridable Talos image factory URL + in-sandbox e2e mirror #3244 intended — the mirror can only help, never make CI worse.

Not a retry/timeout bump: it fixes the real network path and adds a genuine reachability gate.

Screenshots

N/A — CI-only change, no user-facing surface.

Release note

test(e2e): make the in-sandbox Talos image cache reachable by tenant Kubernetes workers, fixing deterministic kubernetes-* e2e failures (#3231)

Summary by CodeRabbit

  • New Features
    • Updated Talos image cache e2e selection to run a tenant-scoped reachability probe to the local mirror and require HTTP byte-range support (206) before using it.
    • If the probe fails or does not confirm byte-range behavior, the flow now reliably falls back to the public Talos image source.
    • Added CI-only tenant egress controls to allow importer Pods to reach the mirror Service.
  • Documentation
    • Expanded e2e guidance to clarify the mirror is best-effort and that fallback happens at probe time.
  • Tests
    • Added a new Bats suite covering manifest splitting, policy wiring, probe overrides, and strict 206 gating/fallback scenarios.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1601a4ff-cd2a-4b78-a90b-792f0b7ba6e2

📥 Commits

Reviewing files that changed from the base of the PR and between c57b685 and 1a0680b.

📒 Files selected for processing (3)
  • hack/e2e-install-cozystack.bats
  • hack/e2e-talos-image-cache.yaml
  • hack/talos-image-cache_test.bats
🚧 Files skipped from review as they are similar to previous changes (3)
  • hack/e2e-talos-image-cache.yaml
  • hack/talos-image-cache_test.bats
  • hack/e2e-install-cozystack.bats

📝 Walkthrough

Walkthrough

Changes the Talos image factory mirror selection to use a tenant-namespace reachability probe validating HTTP 206 byte-range support against the mirror's Service ClusterIP, replacing a localhost-based range check. Adds a Cilium egress policy, updated manifest/test documentation, and a new Bats test suite covering the probe and manifest split.

Changes

Tenant Egress Reachability Probe

Layer / File(s) Summary
Cilium egress policy and manifest documentation
hack/e2e-talos-image-cache.yaml, hack/e2e-install-cozystack.bats
Adds CiliumClusterwideNetworkPolicy allowing CDI importer egress to the mirror pod, updates manifest and install test comments describing the tenant probe requirement and manifest splitting.
Probe helper functions: policy apply, overrides, success detection
hack/e2e-apps/talos-image-cache.sh
Adds config variables and functions to apply the policy, build restricted probe pod overrides, and strictly detect code=206.
Tenant reachability probe and resolver integration
hack/e2e-apps/talos-image-cache.sh
Adds the tenant-namespace probe pod flow and updates mirror selection to require a successful 206 probe before using the local factory URL.
Test suite for manifest split and probe logic
hack/talos-image-cache_test.bats
New Bats tests validate manifest partitioning, label/namespace consistency, 206 gate behavior, and probe override JSON contents.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • cozystack/cozystack#3244: Both PRs modify the same Talos image-cache e2e harness and 206/byte-range gating logic in hack/e2e-apps/talos-image-cache.sh.

Suggested labels: area/kubernetes

Suggested reviewers: kvaps, lllamnyp, androndo, sircthulhu, IvanHunters

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: making the in-sandbox Talos image cache reachable to tenant workers in e2e.
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.
✨ 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 fix/e2e-talos-image-cache-tenant-egress

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.

@github-actions github-actions Bot added area/testing Issues or PRs related to testing (e2e, bats, unit tests) size/L This PR changes 100-499 lines, ignoring generated files labels Jul 9, 2026
@lexfrei
Aleksei Sviridkin (lexfrei) force-pushed the fix/e2e-talos-image-cache-tenant-egress branch 4 times, most recently from 5966b98 to 1c779cf Compare July 9, 2026 12:30
@lexfrei
Aleksei Sviridkin (lexfrei) marked this pull request as ready for review July 9, 2026 12:44
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses deterministic failures in e2e tests caused by network reachability issues between tenant workers and the in-sandbox Talos image cache. By implementing a targeted network policy and a more accurate reachability probe, the changes ensure that the mirror is only utilized when it is fully accessible, falling back to the public factory otherwise to maintain CI stability.

Highlights

  • Cilium Network Policy: Introduced a CiliumClusterwideNetworkPolicy to explicitly allow tenant CDI importer Pods to access the in-sandbox Talos image cache, resolving connectivity issues caused by default-deny egress policies.
  • Reachability Verification: Replaced the localhost-based readiness check with a robust end-to-end probe that mimics a real CDI importer, ensuring the mirror is only used when it is genuinely reachable from the tenant namespace.
  • Testing: Added comprehensive unit tests in hack/talos-image-cache_test.bats to validate the manifest partitioning and the integrity of the reachability probe logic.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dosubot dosubot Bot added area/ci Issues or PRs related to CI workflows, GitHub Actions, automation kind/bug Categorizes issue or PR as related to a bug labels Jul 9, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request enhances the E2E Talos image cache mechanism by verifying reachability from the tenant namespace before using the mirror. It introduces a CiliumClusterwideNetworkPolicy to allow tenant CDI importer Pods to egress to the mirror, applies this policy dynamically once Cilium is up, and runs a tenant-scoped probe Pod to verify end-to-end connectivity (specifically checking for a 206 Partial Content response). Additionally, it adds comprehensive unit tests in hack/talos-image-cache_test.bats to validate the manifest splitting and probe logic. The reviewer suggested performing the probe Pod deletion asynchronously using --wait=false to avoid blocking the E2E test runner.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread hack/e2e-apps/talos-image-cache.sh Outdated
The in-sandbox Talos image mirror was pointed at by tenant Kubernetes
CRs whenever its Deployment was Available, but "Available" only proves
the seed finished and the server answers on localhost. It does not
prove a worker's CDI importer can reach the Service. Tenant namespaces
run under a default-deny Cilium egress that permits the outside world
and kube-dns but not an arbitrary kube-system Service, so the importer
resolves the name yet its TCP connect to the ClusterIP is silently
dropped. The disk import then never starts, no tenant node joins within
the 12-minute deadline, and the kubernetes-* tests fail
deterministically -- worse than the intermittent public-factory flake
the mirror was meant to relieve.

Replace the localhost range-probe with one that faces the exact same
network path as a worker importer: a throwaway Pod in the tenant
namespace, labelled cdi.kubevirt.io=importer, that fetches the seeded
image from the Service ClusterIP with a Range request and expects a
206. Point tenants at the mirror only when that end-to-end check
passes; otherwise fall back to the public factory, restoring the
guarantee that the mirror can only help, never make CI worse. The
resolver also installs the importer egress allow at point-of-use,
because Cilium's CRDs do not exist yet when the mirror manifest is
first applied before install.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
@lexfrei
Aleksei Sviridkin (lexfrei) force-pushed the fix/e2e-talos-image-cache-tenant-egress branch from 1c779cf to c57b685 Compare July 9, 2026 12:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 `@hack/talos-image-cache_test.bats`:
- Around line 124-137: The overrides builder test only verifies part of the
restricted PSA security context, so it can miss regressions in
_talos_image_cache_probe_overrides. Update the test in the talos-image-cache
probe overrides suite to assert the remaining restricted fields emitted by the
builder, including runAsUser = 1000, seccompProfile.type = RuntimeDefault, and
capabilities.drop containing ALL, alongside the existing image, command,
runAsNonRoot, and allowPrivilegeEscalation checks.
🪄 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: 68f9cc93-5a6b-4ed1-bae6-0b6e255eed55

📥 Commits

Reviewing files that changed from the base of the PR and between f91841f and 1c779cf.

📒 Files selected for processing (4)
  • hack/e2e-apps/talos-image-cache.sh
  • hack/e2e-install-cozystack.bats
  • hack/e2e-talos-image-cache.yaml
  • hack/talos-image-cache_test.bats

Comment thread hack/talos-image-cache_test.bats
Tenant namespaces run under a default-deny Cilium egress installed by
the tenant chart, which lets a worker's CDI importer reach the outside
world and kube-dns but nothing in kube-system. The in-sandbox image
mirror is a kube-system Service, so without an explicit allow the
importer's connect to its ClusterIP is dropped and the worker disk
import never starts.

Ship a tightly-scoped CiliumClusterwideNetworkPolicy in the mirror
manifest that lets importer Pods in tenant-test egress to the mirror
Pod in kube-system. Cilium unions allow rules, so this only adds a
hole; scoping it to tenant-test (already under default-deny egress)
means it never flips another namespace's posture, and the mirror Pod
needs no ingress rule because it is selected by no ingress policy. The
policy is kept out of the pre-install apply because that runs before
Cilium's CRDs exist; the resolver in hack/e2e-apps/talos-image-cache.sh
applies it at point-of-use once Cilium is up.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
@lexfrei
Aleksei Sviridkin (lexfrei) force-pushed the fix/e2e-talos-image-cache-tenant-egress branch from c57b685 to 1a0680b Compare July 9, 2026 12:56
myasnikovdaniil added a commit that referenced this pull request Jul 9, 2026
Supersedes the earlier kube-system probe on this branch, which shared the
original localhost probe's flaw: it ran OUTSIDE the tenant egress policy, so
it would report the ClusterIP reachable while a real importer in tenant-test
stayed blocked (a false positive that would not have prevented the failure).

Root cause (from #3254 by @lexfrei, verified against the failing run's
crust-gather snapshot): tenant namespaces run a default-deny Cilium egress
(allow-internal/external-communication + the <tenant>-egress CCNP) that
permits the world entity and the tenant tree but NOT an arbitrary kube-system
Service, so the CDI importer's TCP connect to the cache ClusterIP is silently
dropped and no worker disk imports.

Port of #3254 to the Chainsaw layout (hack/e2e-chainsaw/_lib/):
- ship a tightly-scoped CiliumClusterwideNetworkPolicy (importer pods in
  tenant-test -> mirror pod in kube-system), applied at point-of-use once
  Cilium CRDs exist; excluded from the pre-Cilium install apply via yq.
- replace the readiness probe with a throwaway pod in tenant-test labelled
  cdi.kubevirt.io=importer that curls the ClusterIP with a range request and
  must get 206 - the exact egress path a real importer faces.
- port the unit test pinning the manifest split, the probe/policy label
  agreement, the strict 206 gate, and the --overrides JSON builder.

Kept from this branch's prior commit: the (a2) DataVolume import-stage
diagnostics in the node-join failure block (importer logs + a ClusterIP
re-probe via talos_image_cache_diagnose), complementary to #3254.

Assisted-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
myasnikovdaniil added a commit that referenced this pull request Jul 9, 2026
)

The in-sandbox Talos image mirror (#3244) is unreachable by the tenant
workers it serves, so the kubernetes-* e2e tests fail deterministically at
the 12m node-join wait instead of relieving the public-factory flake (#3231).

Root cause (from #3254 by @lexfrei, verified against the failing run's
crust-gather snapshot): tenant namespaces run a default-deny Cilium egress
(allow-internal/external-communication + the <tenant>-egress CCNP) that
permits the world entity and the tenant tree but NOT an arbitrary kube-system
Service, so a worker's CDI importer resolves talos-image-cache.kube-system.svc
yet its TCP connect to the ClusterIP is silently dropped and no disk imports.
#3244's gate never caught this because it probed the server over localhost
inside the serve pod, which passes regardless of cross-pod reachability.

Port of #3254 to the Chainsaw layout (hack/e2e-chainsaw/_lib/):
- ship a tightly-scoped CiliumClusterwideNetworkPolicy (importer pods in
  tenant-test -> mirror pod in kube-system), applied at point-of-use once
  Cilium CRDs exist; excluded from the pre-Cilium install apply via yq.
- replace the readiness probe with a throwaway pod in tenant-test labelled
  cdi.kubevirt.io=importer that curls the ClusterIP with a range request and
  must get 206 - the exact egress path a real importer faces; tenants use the
  mirror only when that end-to-end check passes, else fall back to the public
  factory, so it can only help, never make CI worse.
- unit test pinning the manifest split, probe/policy label agreement, the
  strict 206 gate, and the --overrides JSON builder.

Also adds (a2) DataVolume import-stage diagnostics to the node-join failure
block in run-kubernetes.sh (importer logs + a ClusterIP re-probe via
talos_image_cache_diagnose) so the import-stage failure mode is legible.

Assisted-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
@IvanHunters
IvanHunters merged commit ca93adc into main Jul 9, 2026
16 of 19 checks passed
@IvanHunters
IvanHunters deleted the fix/e2e-talos-image-cache-tenant-egress branch July 9, 2026 17:18
myasnikovdaniil added a commit that referenced this pull request Jul 10, 2026
Reconciles the talos-image-cache conflicts created when #3254 merged to
main: keep the Chainsaw _lib/ port (hack/e2e-chainsaw/_lib/talos-image-cache.sh,
a superset of #3254's logic + the node-join diagnose helper), drop the
BATS-era hack/e2e-apps/talos-image-cache.sh, and keep the _lib/-path
versions of the mirror manifest, install bats, and unit test. Also picks
up main's zizmor action-pinning (#3223, unblocks pre-commit/zizmor) and
Talos v1.13.6 (#3240).

Assisted-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ci Issues or PRs related to CI workflows, GitHub Actions, automation area/testing Issues or PRs related to testing (e2e, bats, unit tests) kind/bug Categorizes issue or PR as related to a bug size/L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants