Commit 1d4b5e5
Fix FBGD stale-state bugs on aborted transitions (#3)
## TL;DR
Fixes three bugs in `FlinkBlueGreenDeployment` that compound to leave a
transition silently restoring from a stale savepoint:
| # | Bug | Fix |
|---|-----|-----|
| 1 | `savepointTriggerId` not cleared on abort → next deploy stuck
FAILING+IGNORE | Clear it in `abortDeployment` (mirrors upstream
[a00bf27](apache@a00bf27))
|
| 2 | `setLastReconciledSpec` runs before `startTransition` → failed
spec marked reconciled, retries no-op | Stamp only on success (mirrors
upstream
[apache#1072](apache#1072))
|
| 3 | Suspended child carries stale `status.upgradeSavepointPath` → JM
restores from old savepoint on retry | Delete the failed child in
`abortDeployment` so the next transition fresh-creates it |
Verified in unit test and end-to-end on `data-stg` — see
[Validation](#Staging-validation-on-data-stg) below.
## Issue 1 — `savepointTriggerId` not cleared on abort
`abortDeployment` left `status.savepointTriggerId` in place. The next
reconcile tried to re-fetch the trigger from the active side's JM, which
had TTL-evicted it (~300s), threw `Could not fetch savepoint with
triggerId: X`, and left FBGD stuck in FAILING + IGNORE. Required a
`restartNonce` bump to escape.
## Issue 2 — `setLastReconciledSpec` stamped before `startTransition`
returns
In `checkAndInitiateDeployment`, `setLastReconciledSpec` ran *before*
`startTransition`. If `startTransition` threw (e.g., from Issue 1), the
failed spec was already marked reconciled, so the next reconcile saw
`specDiff = IGNORE` and silently did nothing until another spec change
came in.
## Issue 3 — Stale `status.upgradeSavepointPath` shadows fresh
`spec.initialSavepointPath`
`AbstractJobReconciler.restoreJob()` reads
`status.jobStatus.upgradeSavepointPath`, not
`spec.initialSavepointPath`, in the `terminal && !isHaMetadataAvailable`
upgrade branch. A suspended child retained its stale
`upgradeSavepointPath` from the previous failed deploy. On retry, FBGD
wrote a fresh
`spec.initialSavepointPath`, but `createOrReplace` does not touch the
status subresource — so the stale status value won and the JM restored
from an arbitrarily old savepoint while the transition appeared
successful.
Upstream
[apache#1073](apache#1073)
does NOT fix this: its `!isHaMetadataAvailable || isJmAccessible` gate
is satisfied with empty HA, so the operator still routes through the
stale-status path.
**Fix**: `abortDeployment` now deletes the failed child instead of
suspending it. The next transition fresh-creates the child via
`createOrReplace`'s POST path, with no status to be stale. Falls back to
`suspendFlinkDeployment` if the delete call fails, to avoid an
inconsistent state.
## Tests
- `verifyFailedChildDeletedOnAbort` (new): forces a failed transition,
asserts the failed child is gone, then asserts the retry fresh-creates
GREEN with the fresh savepoint in spec and no carry-over status.
- `verifyFailureDuringTransition` /
`verifyFailureBeforeFirstDeployment`: updated to assert the failed child
is absent (not SUSPENDED) after abort.
- `verifySavepointFetchFailureRecovery`: asserts the failed spec is NOT
present in `lastReconciledSpec` (Issue 2).
## Test plan
- [x] `FlinkBlueGreenDeploymentControllerTest` → 60/60 pass
- [x] `*ControllerTest` → 148/148 pass (no regressions in
FlinkDeployment / SessionJob / StateSnapshot)
- [x] Deployed to `data-stg`; forced abort + retry on `beamperfk8s1`;
verified all three fixes ([details
below](#Staging-validation-on-data-stg))
## Staging validation on data-stg
Forced a failed transition on `beamperfk8s1` with a bad image tag, then
retried with a good image.
| Time (UTC) | Event |
|------------|-------|
| 15:08:40 | First transition: triggerId `5d75a09efb99...`, savepoint
`6966a02076a5` → new GREEN |
| 15:09:42 | `Aborting deployment 'beamperfk8s1-green', rolling B/G
deployment back to ACTIVE_BLUE` |
| 15:09:44 | GREEN audit: `Status[Job] \| Error \| DELETED \|
ErrImagePull` |
| 15:11:40 | Retry: NEW triggerId `5f1d597953fe...` (different from
first) |
| 15:11:55 | Fresh savepoint `b0d173acab2e` → fresh GREEN |
| 15:12:56 | GREEN JM log: `Starting job ... from savepoint
.../savepoint-4d93e8-b0d173acab2e` |
| 15:13:23 | Old BLUE deleted (normal post-transition cleanup) |
- **1**: retry used a new triggerId, not the TTL-evicted first one
- **2**: retry transition actually ran (would have been IGNORE'd if the
failed spec had been stamped)
- **3**: failed GREEN was DELETED (not suspended); fresh GREEN's JM
restored from the fresh `b0d173acab2e`, not the prior attempt's
`6966a02076a5`
## Production incident this resolves
May 7 `demandingestion`: a transient deploy failure left stale
`savepointTriggerId` and `status.upgradeSavepointPath` on a suspended
GREEN; the failed spec was stamped as reconciled, freezing retries; when
the trigger TTL evicted and a deploy went through, the JM silently
restored from a 9-day-old savepoint. Full RCA: [Deploy Failure
Investigation](https://docs.google.com/document/d/1rwN2TABe-3VtkHWBttLbLlW_P6Q-TMs0cuAs6fd-cQA/edit).
---------
Co-authored-by: jennifer-xiong25 <jennifer.xiong@shopify.com>1 parent eb99c5a commit 1d4b5e5
2 files changed
Lines changed: 131 additions & 16 deletions
File tree
- flink-kubernetes-operator/src
- main/java/org/apache/flink/kubernetes/operator/controller/bluegreen
- test/java/org/apache/flink/kubernetes/operator/controller
Lines changed: 25 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
137 | | - | |
138 | 137 | | |
139 | | - | |
140 | | - | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
141 | 149 | | |
142 | 150 | | |
143 | 151 | | |
| |||
551 | 559 | | |
552 | 560 | | |
553 | 561 | | |
554 | | - | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
555 | 575 | | |
556 | 576 | | |
557 | 577 | | |
558 | 578 | | |
| 579 | + | |
559 | 580 | | |
560 | 581 | | |
561 | 582 | | |
| |||
Lines changed: 106 additions & 12 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
297 | 297 | | |
298 | 298 | | |
299 | 299 | | |
300 | | - | |
301 | 300 | | |
302 | 301 | | |
303 | 302 | | |
304 | 303 | | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
305 | 307 | | |
306 | | - | |
| 308 | + | |
307 | 309 | | |
308 | 310 | | |
309 | 311 | | |
310 | 312 | | |
311 | 313 | | |
312 | | - | |
313 | | - | |
314 | | - | |
315 | | - | |
316 | | - | |
317 | | - | |
318 | 314 | | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
319 | 318 | | |
320 | 319 | | |
321 | 320 | | |
| |||
325 | 324 | | |
326 | 325 | | |
327 | 326 | | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
328 | 417 | | |
329 | 418 | | |
330 | 419 | | |
| |||
389 | 478 | | |
390 | 479 | | |
391 | 480 | | |
| 481 | + | |
392 | 482 | | |
393 | | - | |
394 | | - | |
395 | | - | |
396 | | - | |
| 483 | + | |
397 | 484 | | |
398 | 485 | | |
399 | 486 | | |
| |||
537 | 624 | | |
538 | 625 | | |
539 | 626 | | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
540 | 634 | | |
541 | 635 | | |
542 | 636 | | |
| |||
0 commit comments