The raw-disk-with-object, osd-with-metadata-device, and pvc canary jobs
used loopback devices to supply an extra block device beyond the single
spare disk a GitHub runner provides. Loop devices behave differently
from real block devices -- Rook gates them behind
ROOK_CEPH_ALLOW_LOOP_DEVICES and special-cases them in the OSD daemon --
so exercising core scenarios on them is less realistic than using real
SCSI disks.
Provision the extra device(s) over iSCSI (LIO) instead, reusing the
existing create_extra_disk helper: it now creates N LUNs, the new
find_extra_block_devs and find_second_block_dev helpers enumerate them,
and deploy_cluster gains a two_raw_disks mode. The three jobs now run
entirely on real disks, and the canary CI no longer creates loop devices
or relies on the loop-device test helpers.
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
CephMgrSuite (ceph_mgr_test.go) exercised the Rook orchestrator mgr
module through `ceph orch` commands. Remove the suite together with its
GitHub Actions workflow (integration-test-mgr-suite.yaml), whose sole
purpose was to run this suite, gated behind the run-mgr-suite label and
a nightly cron.
No other code references the deleted suite. Its helpers (logBytesInfo,
the defaultTries constant, and the host/service/serviceStatus types)
were all local to the file, so nothing is left orphaned.
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
The reusable canary workflow declares a default ceph_images value that is never used: both callers always pass an explicit image list. A stale default is a drift hazard because a new caller could silently exercise the wrong image. Drop the default and mark the input required so callers must choose deliberately.
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
Canary jobs upload their logs under an artifact named by job and ceph image, but the job matrix also varies kubernetes-version. When more than one kubernetes version is exercised the upload-artifact step fails on a duplicate artifact name. Append the kubernetes version so each matrix cell produces a unique artifact.
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
The validate-rgw-endpoint step gave each validation loop only 15
seconds. A single attempt of the external script can exceed that
budget when the RGW is slow to respond right after the object store
was created, killing the step before any retry could happen. This
showed up as sporadic canary job failures with exit code 124 and no
diagnostics.
Validation failures are also reported on stderr while the script exits
0, so the until loop never actually retried them. Retry until the
script succeeds with no stderr output, give the loops a generous
timeout, and print the captured stderr when validation does not
succeed in time.
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
actionlint only understands workflow files, so the .github/actionlint.yaml
ignore keeps the composite action definitions out of `make lint.workflows`.
Apply the same shellcheck fixes there anyway, found by running shellcheck over
their run: blocks directly:
- quote unquoted variable expansions (SC2086): the $GITHUB_ENV writes in
collect-logs, tmate_debug and upterm_debug, and ${ARCH} in the cri-dockerd
install in integration-test-setup-cluster-resources
- split `export BLOCK=$(...)` into a separate assignment and export so a
failing command substitution is not masked (SC2155) in
encryption-pvc-kms-ibm-kp
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
Resolve the shellcheck findings actionlint reports so that
`make lint.workflows` passes:
- quote unquoted variable expansions (SC2086) and command substitutions
(SC2046)
- split `export VAR=$(...)` into a separate assignment and export so a
failing command substitution is not masked by export's exit status
(SC2155)
- double-quote kubectl jsonpath arguments inside `sh -c '...'` loops so
the single quotes no longer break out of the wrapper (SC1083)
- annotate intentional deferred-expansion `sh -c '...'` bodies and the
intentional `for ... in $sockets` word splitting with targeted
`# shellcheck disable` directives (SC2016, SC2086)
- drop unused command-output captures (SC2034), simplify a `\! -z` test
(SC2236) and fix nested same-type quoting (SC2140)
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
Run actionlint over the workflow files through the `make lint.workflows`
target (added in PR 17795) so the check behaves identically when run
locally and in CI, and narrow the workflow's path filter to the
lint-relevant files.
Add .github/actionlint.yaml to ignore the composite action definitions
under .github/workflows/<name>/action.{yml,yaml}: actionlint only
understands workflow files and otherwise mis-parses composite actions as
malformed workflows.
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
Several callers pass a github-token input to composite actions that do not declare it, so it is silently ignored and emits a runner warning at run time. The integration-test-setup-cluster-resources action (called from the nightly jobs and the keystone-auth suite) and the encryption-pvc-kms-ibm-kp action (called from the canary suite) declare only their real inputs. Remove the dead github-token from every such call. If a token is ever needed it should be declared and consumed by the action itself.
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
The workflow already sets defaults.run.shell, yet several steps in the rgw-multisite-testing and two-object-one-zone jobs re-declare the identical shell. Remove the per-step overrides; the workflow default already applies to every run step.
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
It is intended that the CI test the latest patch release of each
kubernetes version that is tested.
The canary integration test tested v1.35.0 however, while
the latest v1.35 patch releaase is v1.35.5.
This change updates the integration-test CI workflow
to test k8s v1.35.5 instead of v1.35.0 to match the intention.
Signed-off-by: Michael Adam <obnox@samba.org>
Rook supports six versions of kubernetes but we only want to spend CI
resources for testing four of them.
In order to align with this commitment, this change lets rook run
integration test suites on kubernetes v1.34 instead of v1.33 for release
testing.
As a result, the latest patch releases of kubernetes v1.31, v1.32,
v1.34, and v1.35 are tested for rook releases.
In addition, k8s version specification is made more systematic to
use the pattern v1.3X.Y instead of 1.3X.Y.
Signed-off-by: Michael Adam <obnox@samba.org>
The CephUpgradeSuite workflow failed ~31% of PR runs vs the ~19%
broken-PR baseline of the other integration suites. Classifying the
failing step of every failed run from the last ~400 PR runs and the
logs of every failure on non-dependabot branches shows the excess
comes from a handful of too-tight waits, unretried network fetches,
and environment races rather than from the upgrade logic itself:
- The biggest class (21 of 44 genuine test-phase failure runs):
"giving up waiting for deployment(s) with label
app=rook-ceph-{rgw,osd},ceph-version!=..." during the
Squid->Tentacle upgrade. The operator updates daemons sequentially
(mons, mgr, osds with PG health gates between them, mds, rgw), so
each later daemon's fixed 275s wait also absorbs the time spent on
every daemon before it; rgw, last in the sequence, failed most
often. The mon wait was already extended for slow image pulls in
98bd03a42; extend the same retry count to all the daemon waits.
- ~7 runs: "snapshot controller is not ready" in the Helm upgrade
path. WaitForSnapshotController(30) allows only 150s, and the logs
show the deployment still converging (readyreplicas 1 < replicas 2)
on the final poll. Raise to 90 retries.
- InstallOrUpgradeHelmRepoChart ran helm with no retry; an observed
failure fetched the ceph-csi-drivers chart tarball from GitHub
release assets and got a 504. Retry up to 5 times, as
InstallLocalHelmChart already does.
- Raise the go test timeouts (2400s->3600s rook, 1800s->2700s helm).
Failed runs ended in "panic: test timed out" during teardown, which
aborts cleanup and log collection; the longer daemon waits above
also need the headroom.
- The "setup cluster resources" composite action (shared by all
suites) accounted for half of all failed jobs. The one steady class
there (8 distinct runs across 7 different days): minikube exits with
K8S_FAIL_CONNECT (code 40) when the requested kubernetes version is
missing from its bundled version list, because it then validates the
version with an anonymous GitHub API request (GITHUB_TOKEN is not
honored on that code path), and anonymous requests from shared
runner IPs are regularly rate-limited. minikube 1.38.x predates
v1.35.5, so only the v1.35.5 jobs hit this class. Pass --force to
minikube start to skip that check: the kubernetes versions used in
CI are pinned constants already validated by the PRs that bump
them, and an invalid version would still fail fast at the kubeadm
download. Also seen twice: dpkg failing on a corrupt cri-dockerd .deb
because curl ran without --fail and saved an HTTP error page as the
package; add --fail and retries.
- On runners without the /mnt resource disk, the fallback OSD disk is
an iSCSI (LIO) device and use_local_disk_for_integration_test
returned early on those runners, skipping the udev nowatch
workaround for the device re-probe storms of rook issue 8975. A burn-in
failure on this PR captured the consequence with full kernel
forensics: ~100 udev change events on the OSD disk, and ceph-volume
activate wedged in uninterruptible sleep on the block device lock
(blkdev_llseek -> rwsem_down_write_slowpath) for 18+ minutes during
the ceph version upgrade while the cluster's only OSD stayed down.
Install the nowatch rule before the early return so it applies to
every runner type, and before the disk is first written rather than
after.
- One burn-in round failed before the upgrade even began: the
pre-upgrade PVC create on the Helm path expired WaitUntilPVCIsBound
(RetryLoop, 275s) while the CSI provisioner pods were still
starting. Set RETRY_MAX=110 for this workflow to double the
framework's base wait budget, instead of extending individual waits
one flake at a time.
- minikube also exits with GUEST_START (code 80) when its internal 6
minute node-ready wait expires on slow runners (5 runs in the
dataset, two more observed while burning in this PR, one of them on
another suite). Pass --wait-timeout=15m to minikube start.
Not addressed (small or episodic classes): OSDs never coming up on
initial deploy (3 runs, possibly the same udev/iSCSI wedge), the
filesystem not becoming active (2 runs), and several day-clustered
minikube incidents (exit codes 65/67/90).
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
Multus CI failures on master pushes from 2026-04-08 to 2026-06-10 were
dominated by a race in setup-multus.sh: 'kubectl wait' was invoked on a
pod label selector immediately after 'kubectl create' of a daemonset,
and it exits with "error: no matching resources found" when the
daemonset controller has not created any pods yet. This caused 9 of the
10 genuine multus flakes across the standalone multus workflow and the
canary multus-public-and-cluster job (the two share setup-multus.sh).
- setup-multus.sh: wait with 'kubectl rollout status' on the daemonsets
instead of 'kubectl wait' on pod label selectors. The daemonset
object exists as soon as 'kubectl create' returns, and rollout status
correctly waits for all desired pods to be created and become ready.
The old selector wait also silently under-waited: pods created after
its initial LIST were never waited on at all. The stricter wait
revealed that full multi-node convergence can exceed 2 minutes on
busy runners, so the wait timeout is raised to 5 minutes (the waits
return as soon as the rollouts are ready, so this costs nothing on
healthy runs).
- Wait for the host-net-config daemonset rollout in both workflows
before proceeding; it configures the host routing that the multus
public network depends on and was previously not waited on at all.
Pin its jonlabelle/network-tools image.
- test_multus_connections: retry the osd dump / fs dump network checks
for up to 2 minutes. Daemons register their addresses in the mon maps
asynchronously after the cluster reports ready; one canary failure
(2026-04-29) ran the MDS check at fsmap epoch 1, before any MDS had
registered.
- Dump cluster state (pods, daemonsets, events, multus logs) when the
multus workflow job fails; the workflow previously had no failure
diagnostics at all.
Also remove the unused NUMBER_OF_COMPUTE_NODES env var from the multus
workflow (kind-config.yaml creates 3 workers; nothing consumes it).
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
The rgw-multisite-testing canary job has been chronically flaky
(roughly a third of recent canary runs, including on master and
release branches). Job logs and collected artifacts show two recurring
mechanisms, neither of which is addressed by bumping timeouts:
1. Every recent failure of the "write an object" step died within
~16s: the very first "s3cmd mb" against the primary zone got
ECONNREFUSED three times across the 10s retry window. The RGW
process never crashed; RGWs pause their HTTP frontends to reload
the realm whenever the RGW configuration period changes ("rgw
realm reloader: Pausing frontends for realm update..."), which
keeps happening shortly after the second zone joins the zonegroup,
exactly when the test starts writing. While paused, the readiness
probe also times out, the endpoint is removed from the Service, and
connections to the ClusterIP are refused.
2. The "kubectl wait --for=condition=available deployment/..."
barrier added previously is a no-op for these deployments: with one
replica and maxUnavailable=1, the availability threshold is zero
ready pods, so the condition is always true.
Changes:
- Wait on RGW pod readiness instead of deployment availability.
- Add a "wait for multisite sync to be established" step that polls
"radosgw-admin sync status" on both clusters until metadata and
data sync report caught up, mirroring the checkpoints ceph's own
multisite QA performs before asserting replication.
- Probe both RGW endpoints over HTTP until several consecutive
requests succeed before writing, to ride out realm-reload pauses.
- Replace the fixed 3-attempt s3cmd retries with time-budgeted
retries.
- Replace the s3cmd read polling loop and its SIGUSR1 timer (which was
never cancelled on success, silently shrinking the second
direction's time budget) with "radosgw-admin bucket sync
checkpoint", the marker-based barrier used by ceph QA, followed by
a single get and diff.
- Dump multisite diagnostics (pod state, RGW logs, sync status,
period) when the job fails.
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
The CephObjectSuite ran both the TLS and non-TLS object store tests in a
single job via `-run CephObjectSuite`, executing TestWithTLS and
TestWithoutTLS sequentially. Split every invocation of the suite so the two
variants run as independent jobs, using `-run CephObjectSuite/TestWithoutTLS`
and `-run CephObjectSuite/TestWithTLS`, matching the existing CephUpgradeSuite
split pattern.
Each workflow that runs the suite now has two jobs, one per variant, in the
same file:
- integration-test-object-suite.yaml (PR): TestCephObjectSuite and
TestCephObjectSuiteTLS
- integration-tests-on-release.yaml (push): TestCephObjectSuite and
TestCephObjectSuiteTLS
- daily-nightly-jobs.yml (nightly): object-suite-ceph-main and
object-suite-tls-ceph-main
The TestCephObjectSuite job name is preserved so the existing required
status check is unchanged.
No Go changes are required; ObjectSuite already separates the two methods.
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>
Not all of he CI workflows that test on kubernetes tested on the latest
patch release so far.
This change updates the CI to always test on the latest patch release
when testing on kubernetes.
More explicitly, this changes thew CI to use:
* v1.35.5 instead of v1.35.4
* v1.33.12 instead of v1.33.11
As a result, the kubernetes versions tested in the CI are now:
* v1.31.14
* v1.32.13
* v1.33.12
Signed-off-by: Michael Adam <obnox@samba.org>