Jing Hung created FLINK-41373:
---------------------------------

             Summary: Blue/Green: after an aborted transition, the next deploy 
restores from a stale savepoint
                 Key: FLINK-41373
                 URL: https://issues.apache.org/jira/browse/FLINK-41373
             Project: Flink
          Issue Type: Bug
          Components: Kubernetes Operator
    Affects Versions: 1.16.0, 1.14.0, 1.15.0
            Reporter: Jing Hung


h3. Summary:

FlinkBlueGreenDeployment restores from a stale savepoint after an aborted 
transition because the suspended child keeps 
status.jobStatus.upgradeSavepointPath
h3. Problem

When a Blue/Green transition is aborted, {{abortDeployment()}} suspends the 
failed child FlinkDeployment. It does not delete it. The suspended child keeps 
{{status.jobStatus.upgradeSavepointPath}} from its last deployment.

On the next transition, the B/G controller takes a fresh savepoint and writes 
it to the child's {{{}spec.job.initialSavepointPath{}}}. Because the child 
already exists, the reconciler handles it as a restore of a suspended job, and 
{{AbstractJobReconciler.restoreJob()}} reads 
{{{}status.jobStatus.upgradeSavepointPath{}}}. The fresh 
{{initialSavepointPath}} is ignored, and the job restores from the old 
savepoint.

The transition reports success, so the problem is silent. In our production 
incident the job restored from a savepoint 9 days old, and the state between 
the two savepoints was lost.
h3. Steps to reproduce
 # Create a FlinkBlueGreenDeployment with {{{}upgradeMode: savepoint{}}}. Wait 
for ACTIVE_BLUE.
 # Change the spec with an image that does not exist. The controller takes 
savepoint S1 and creates GREEN from S1.
 # Wait for the abort. GREEN is suspended with 
{{{}status.jobStatus.upgradeSavepointPath = S1{}}}.
 # Change the spec again with a valid image. The controller takes savepoint S2 
and sets GREEN {{{}initialSavepointPath = S2{}}}.

*Expected:* GREEN restores from S2.
*Actual:* GREEN restores from S1.

FLINK-39270 and FLINK-40470 do not fix this. The FLINK-39270 gate passes when 
HA metadata is empty, and FLINK-40470 applies only when the spec and status 
savepoint paths are equal.

h3. Proposed fix

In {{{}abortDeployment(){}}}, delete the failed child instead of suspending it, 
and fall back to suspend if the delete fails. The next transition then creates 
the child again with no status, so the reconciler uses 
{{{}spec.job.initialSavepointPath{}}}. This keeps the fix in the B/G controller 
and does not change FlinkDeployment restore semantics.

Behavior change: after an abort, the failed child no longer remains as 
SUSPENDED. The abort reason stays in the FlinkBlueGreenDeployment status.error 
and events.

Alternatives considered:
* Patch the child's {{status.jobStatus.upgradeSavepointPath}} to match the new 
{{initialSavepointPath}} in {{prepareFlinkDeployment()}}. This has a race with 
the FlinkDeployment reconciler, which can read the status before the patch 
arrives.
* Clear the child status on abort. Our tests showed this causes a stateless 
start (state loss).
* Make {{restoreJob()}} prefer {{spec.job.initialSavepointPath}} when it 
differs from status. This changes core FlinkDeployment semantics for all users, 
so would prefer to fix it in the B/G controller.






--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to