Repository navigation
Commit 89f97fd
committed
[SPARK-59694] Do not treat an unanswered request as a permanent failure
### What changes were proposed in this pull request?
This PR makes `ReconcilerUtils.isTransientError` classify the failures fabric8 reports without a
response status, and makes `shouldBackoffBeforeRetry` delay before retrying them.
`KubernetesClientException.getCode()` returns `-1`, not `0`, when no response status was received,
so the existing `case 0` never matched anything the client produces. This bug was introduced by the following.
- #530
https://github.com/apache/spark-kubernetes-operator/blob/957d4bc2919abe7c863cace3f4dd773f0ade5fe3/spark-operator/src/main/java/org/apache/spark/k8s/operator/utils/ReconcilerUtils.java#L306-L308
A new `NO_RESPONSE_CODE` constant carries that value, and a new private `brokeOnTheWayToTheApiServer` decides whether such a
failure left the request unanswered. It is written as the complement of the failures that repeating
cannot change — an unparsable answer, a handshake rejected over a certificate, and a rejection
raised before sending, which carries no cause at all — so it does not depend on the HTTP client in
use. That matters because the pinned client reports a connection the peer closes mid-response with
a type of its own that is not even an `IOException`.
`shouldBackoffBeforeRetry` gains the same code: an unanswered request carries no `Status` and so
can never supply the `Retry-After` hint that is the only other way to earn a delay.
### Why are the changes needed?
No failure ever reported code `0`, so every failure that did not reach a healthy API server was
treated as a decision by that API server. Verified against the pinned client by pointing a real
`KubernetesClient` at local sockets:
| Failure | `getCode()` | Innermost cause | Classified |
| --- | --- | --- | --- |
| Connection refused | `-1` | `java.net.ConnectException` | transient |
| Connect timeout | `-1` | `io.netty.channel.ConnectTimeoutException` | transient |
| Read timeout | `-1` | `io.vertx.core.impl.NoStackTraceTimeoutException` | transient |
| Connection reset | `-1` | `java.net.SocketException` | transient |
| Peer closed mid-response | `-1` | `io.vertx.core.http.HttpClosedException` | transient |
| DNS failure | `-1` | `java.net.UnknownHostException` | transient |
| Unparsable response body | `-1` | `com.fasterxml.jackson.databind.exc.MismatchedInputException` | permanent |
| Rejected before sending | `-1` | none | permanent |
The misclassification reached every caller:
| Caller | Before | After |
| --- | --- | --- |
| `getOrCreateSecondaryResource` | rethrew on the first attempt, skipping the `GET` that avoids a duplicate create, which `AppInitStep` turns into a terminal `SchedulingFailure` under the default `RestartPolicy.Never` | retries with backoff |
| `getResourceStrictly` | reported an unanswered read as a refusal | reports it as one the create path settles |
| `StatusRecorder.persistStatus` | wrote a `StatusUpdateFailed` event per blip, adding load to the server that caused it | stays quiet |
| `KueueWorkloadUtils.retryAfterRequestFailure` | warning event plus the default requeue interval | the short interval, no event |
The classification also holds in the other direction: an unparsable response and a rejection raised
before sending no longer pass as transient, so they keep their warning event and longer requeue
instead of being retried forever in silence.
### Does this PR introduce _any_ user-facing change?
Yes. A `SparkApplication` that loses its connection to the API server while requesting driver
resources is now retried with backoff instead of failing on the first attempt, and such failures no
longer emit `Warning` events. Retries stay bounded by
`spark.kubernetes.operator.api.secondaryResourceCreateMaxAttempts` (3 by default), so exhausting
them still ends in `SchedulingFailure`. `SparkCluster` master and worker resources are created
through `serverSideApply()` rather than `getOrCreateSecondaryResource()`, so they are unaffected; a
`SparkCluster` benefits through its status updates and its Kueue admission requests.
### How was this patch tested?
Pass the CIs.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Opus 5
Closes #860 from dongjoon-hyun/SPARK-59694.
Authored-by: Dongjoon Hyun <dongjoon@apache.org>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>1 parent 957d4bc commit 89f97fd
6 files changed
Lines changed: 372 additions & 26 deletions
File tree
- docs
- spark-operator/src
- main/java/org/apache/spark/k8s/operator
- config
- utils
- test/java/org/apache/spark/k8s/operator
- reconciler/reconcilesteps
- utils
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
10 | | - | |
| 9 | + | |
| 10 | + | |
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
570 | 570 | | |
571 | 571 | | |
572 | 572 | | |
573 | | - | |
574 | | - | |
575 | | - | |
576 | | - | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
577 | 578 | | |
578 | 579 | | |
579 | 580 | | |
| |||
584 | 585 | | |
585 | 586 | | |
586 | 587 | | |
587 | | - | |
588 | | - | |
589 | | - | |
590 | | - | |
591 | | - | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
592 | 595 | | |
593 | 596 | | |
594 | 597 | | |
| |||
807 | 810 | | |
808 | 811 | | |
809 | 812 | | |
810 | | - | |
811 | | - | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
812 | 816 | | |
813 | 817 | | |
814 | 818 | | |
| |||
818 | 822 | | |
819 | 823 | | |
820 | 824 | | |
821 | | - | |
822 | | - | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
823 | 828 | | |
824 | 829 | | |
825 | 830 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
34 | 37 | | |
35 | 38 | | |
36 | 39 | | |
37 | 40 | | |
| 41 | + | |
| 42 | + | |
38 | 43 | | |
39 | 44 | | |
40 | 45 | | |
| |||
57 | 62 | | |
58 | 63 | | |
59 | 64 | | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
60 | 79 | | |
61 | 80 | | |
62 | 81 | | |
| |||
144 | 163 | | |
145 | 164 | | |
146 | 165 | | |
147 | | - | |
| 166 | + | |
148 | 167 | | |
149 | 168 | | |
150 | 169 | | |
| |||
279 | 298 | | |
280 | 299 | | |
281 | 300 | | |
282 | | - | |
| 301 | + | |
| 302 | + | |
283 | 303 | | |
284 | 304 | | |
285 | 305 | | |
| |||
297 | 317 | | |
298 | 318 | | |
299 | 319 | | |
300 | | - | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
301 | 323 | | |
302 | 324 | | |
303 | | - | |
| 325 | + | |
304 | 326 | | |
305 | 327 | | |
306 | | - | |
307 | 328 | | |
308 | | - | |
309 | | - | |
| 329 | + | |
| 330 | + | |
310 | 331 | | |
311 | 332 | | |
312 | 333 | | |
313 | 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 | + | |
314 | 373 | | |
315 | 374 | | |
316 | 375 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
| |||
989 | 990 | | |
990 | 991 | | |
991 | 992 | | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + | |
992 | 1044 | | |
993 | 1045 | | |
994 | 1046 | | |
| |||
0 commit comments