bitflicker64 commented on PR #3132:
URL: https://github.com/apache/hugegraph/pull/3132#issuecomment-5612092139

   ## Correction and follow-up: the `/v1/ready` default is not safe on a 
pre-1.8.0 PD image
   
   In the campaign comment above I listed this as a gap:
   
   > the claim that a pre-#3185 image would never turn Ready on `/v1/ready` is 
derived, not
   > shown, because no such image exists in this campaign.
   
   I went and built one. **The claim is false, and the README says the opposite 
of what
   happens.** That seemed worth correcting quickly rather than leaving in place.
   
   ### The control
   
   `bed2e457` is the parent of the #3185 merge, so it carries #3187 but neither 
#3185 nor
   #3189: a single variable. Built as `hugegraph/pd:pre3185` and swapped in for 
PD only, chart
   defaults untouched. A stamped revision label proves nothing about a jar, so 
the control was
   validated by the **absence of `hg_raft_*` metrics** on the running pod, 
those being #3185's
   own, and by its layer set differing from the merged build.
   
   ### What the README promises
   
   > a PD image that predates the fix: `/v1/ready` does not exist there, so the 
PD never turns
   > Ready and Stores never leave Init. Set both values back to `/v1/health` on 
such an image.
   
   A loud, blocking, self-correcting failure.
   
   ### What happens
   
   **All three PD pods reported `Ready=True`. Not one probe failed.**
   
   | Path | pre-#3185 (`bed2e457`) | merged master (`60c8803d`) |
   |---|---|---|
   | `/v1/health` | 200, empty body, real handler | 200 |
   | `/v1/ready` | **200**, body `{"error":"Unauthorized!","status":-1}` | 200, 
real quorum-aware handler |
   | `/v1/thispathdoesnotexist` | **200**, same Unauthorized body | **401** |
   | `/v1/ready/alsobogus` | **200**, same body | **401** |
   | `hg_raft_*` metrics | 0 | 3 |
   
   `/v1/ready` on the old image is not an endpoint. It is **B5**: the pre-#3189 
interceptor
   writes its error body and returns without setting a status, so *every* 
unmapped path under
   `/v1/` answers 200. The arbitrary nonsense path answering 200 identically is 
what proves it.
   On merged master those same paths correctly return 401, which is #3189 
working, and that is
   the only reason this is invisible on current images.
   
   **Why this is worse than the documented failure.** The documented one is 
safe: nothing
   starts, the operator reads Limitations, sets `/v1/health`. The real one is 
silent: the
   cluster comes up, every PD claims Ready unconditionally, and readiness 
conveys nothing. It
   is strictly worse than the `/v1/health` it replaced, which at least reflects 
the listener,
   and under a quorum loss such a PD keeps reporting Ready, which is #3183 
reintroduced by the
   new default on old images. This reaches released **1.7.0**, and this PR 
defaults
   `tag: latest`.
   
   The remedy in the README works. The problem is that nothing tells an 
operator to apply it.
   Suggested wording, no code change: say that on a PD image predating #3189 
every unmapped
   `/v1/` path returns 200, so `/v1/ready` **silently always passes** and 
readiness becomes
   meaningless; therefore both paths **must** be set to `/v1/health` on such an 
image, and
   there is no symptom to warn you. The 1.8.x pin this PR already promises also 
resolves it.
   
   ### The rest of the follow-up run
   
   Same merged master, so nothing that already passed was re-run. Ten of the 
eleven gaps I
   listed are now closed.
   
   | Gap | Now |
   |---|---|
   | **Clean single-node PD leader partition with a write oracle** | 
**PASS-hardening.** All three earlier confounds fixed: victim from 
`/v1/members`, cut inside the Pod netns between the leader and its peers only, 
teardown via the Pod **sandbox** PID. `/v1/ready` went 503 at T0+2s; 
**`/v1/health` stayed 200 on 200 of 200 samples**; leadership moved; 0 
restarts; healed unaided |
   | **EndpointSlice ready-condition membership** | **Closed.** The partitioned 
PD's address flips to `ready=False` at T0+27s, tracking the pod condition 
exactly |
   | **`hg_raft_has_leader` reaching 0** | **Measured**, 1.0 to 0.0 at T0+3s. 
No longer carried |
   | **S11's last link** | **Measured.** `-t 10` takes exactly 10 s and `-t 30` 
exactly 30 s, both printing `The operation timed out(Ns)`. A dead pid returns 
in 0 s, so raising 120 s to 450 s does not slow crash detection |
   | **kubescape** | **Run.** NSA 87.0 on the tested tree and 87.5 on this PR, 
MITRE 100.0 on both. Three failing NSA controls, all already-documented 
decisions |
   | **Store majority loss** | **PASS-hardening.** 7 of 40 writes timed out, 
full recovery at T+209s, data intact, PVCs rebound |
   | **Cross-namespace REST** | **PASS.** Auth holds across the boundary; 401 / 
401 / 200 on both Server and PD |
   | **Node freeze** | **PASS-hardening.** NotReady at T+55s, 2 of 50 writes 
lost, rejoined 10 s after unfreeze |
   | **The N1 fix** | **Verified.** Lint clean, renders unchanged at 19/17/20, 
63 tests pass, and one patch applies cleanly to both branches |
   | Upgrade from a released chart version | **Still NOT-RUN.** Re-checked: 
latest release is 1.7.0, no 1.8.x tag, Docker Hub has only `latest`, 
`helm-dev`, `1.7.0` |
   
   **One cost the partition exposed.** Recovery from a *partitioned* leader is 
bounded by
   `raft.rpc-timeout`, default 10000 ms (`PDConfig.java:187`, wired at
   `RaftEngine.java:136-138`), not by the election timeout: a blackhole sends 
no RST, so every
   attempt to reach the unreachable ex-leader blocks for the full timeout. 
Measured **67 s**
   leaderless, against **5 s** for a `kill -9` of the leader, and for **47 s** 
of it the
   `pd-client` Service had zero ready endpoints because all three PDs correctly 
answered 503.
   Worth a docs line; the chart does not expose that value.
   
   ### Corrections to my own method, since two of them nearly became numbers 
here
   
   - My first scanner run measured **the wrong tree**. `git worktree add 
feat/hstore-helm-chart`
     resolved to an older branch of that name on a different remote, which 
renders 13/11/13.
     Caught only because it did not match the 16/14/16 I had measured earlier. 
The right head
     comes from `git fetch origin pull/3132/head`.
   - A Store majority-loss sampler reported `3/3` ready throughout, which is 
false: a
     StatefulSet recreates deleted pods under the same names, so counting rows 
never dips. Only
     uid and start time show the replacement.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to