Cap the kops-controller bootstrap retry backoff, and verify the e2e upgrade actually rolls - #18675
Conversation
RetryWithBackoff never read wait.Backoff.Cap, and the bootstrap client paired that with Factor 2 and Steps 100, so the retry interval doubled without limit: attempt 11 lands 17 minutes in, attempt 12 at 34 minutes. A node whose control plane is slow to become reachable therefore stops retrying at any useful rate. In one Azure run the scale set create stalled long enough to delay the role assignments the VMs need to read their nodeup config. By the time kops-controller was serving, the nodes were asleep: the first bootstrap request arrived 23 seconds after cluster validation had already given up, and succeeded on its first try. Honor Cap in RetryWithBackoff and set a 30s cap on the bootstrap client. Every other caller uses between 4 and 20 steps, where the unbounded growth is already bounded in practice, and none of them set Cap.
|
Skipping CI for Draft Pull Request. |
a2569a9 to
477eee7
Compare
|
/test all |
A cluster that was never rolled validates cleanly, so an upgrade that silently did nothing still reports green. That is how a broken Azure rolling update went unnoticed for three weeks: reconcile printed "No rolling-update required" for both phases, every node stayed on the old kubelet, and the job went red only when an unrelated addon rollout happened to still be in flight when validation ran. Assert that every node's kubelet reports the target version, so that case fails for the right reason. K8S_VERSION_B is rewritten into a release-dev URL when it is "ci", so compare on its last path segment, which is what kubelet reports.
477eee7 to
af93dc3
Compare
|
/test all |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: hakman The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Two fixes found while working through the
kops-azureTestGrid after #18604. Neither is Azure-specific in its fix, though both were surfaced by Azure runs.1. Cap the kops-controller bootstrap retry backoff
vfs.RetryWithBackoffnever readwait.Backoff.Cap, andpkg/kopscontrollerclientpaired that withFactor: 2andSteps: 100. The interval doubles without limit, so attempt 11 lands 17 minutes in and attempt 12 at 34 minutes — a node whose control plane is slow to become reachable stops retrying at any useful rate.Seen on
e2e-kops-azure-conformance-1-34/2080139096432316416: the VMSS create stalled ~17.5 minutes, which delayed the role assignments the VMs need in order to read their nodeup config, so every worker spent that window failing withAuthorizationPermissionMismatch. kops-controller began serving at 04:21:29, but the first bootstrap request did not arrive until 04:34:25 — 23 seconds after cluster validation had already given up — and succeeded on its first try:All 4 workers were
provisioningState: Succeededin Azure but never joined; validation failed onmachine "..." has not yet joined cluster. Nothing else was wrong — the eventual success proves NSG, NAT gateway, LB rule 3988 and attestation were all fine.RetryWithBackoffnow honorsCap, and the bootstrap client sets a 30s cap. Every other caller uses between 4 and 20 steps, where the unbounded growth is already bounded in practice, and none of them setCap— so this is the only call site whose behavior changes.2. Assert the A→B upgrade actually rolled the nodes
A cluster that was never rolled validates cleanly, so an upgrade that silently did nothing still reports green.
That is exactly what was happening on
e2e-kops-azure-upgrade-dns-none, which failed 6 of 17 runs. In all six, both rolling-update phases printedNo rolling-update requiredand every node stayed on the old kubelet version — the upgrade never happened. The job only went red because an addon rollout happened to still be in flight when validation ran; had it settled twenty seconds earlier, the run would have passed on an un-upgraded cluster, and some of the eleven "passing" runs may have been exactly that.The underlying cause was fixed in #18669, so this PR does not re-fix it. It adds the guard that would have caught it in July instead of letting it hide behind an intermittent validation failure for three weeks: every node's kubelet must report
K8S_VERSION_B.An earlier revision of this PR also added
--wait 15mto thevalidate clustercall. That was wrong and has been dropped — as @hakman pointed out in review, the cluster should already be stable at that point, since a rolling update's last action is a full cluster validation (pkg/instancegroups/instancegroups.go:262).e2e-kops-aws-upgrade-dns-noneis 52/52 on the barevalidate cluster, and waiting would have masked the very regression class this PR is meant to catch.Testing
New unit tests in
util/pkg/vfs/context_test.gocover the cap clamping.go build ./...and the affected package tests pass. The scenario change is only exercised by the periodic upgrade jobs.Draft because I have not run
make ci/verify-golangci-lintlocally yet./kind bug
/cc @hakman