Take a restarting Kibana replica out of the proxy rotation - #128
Merged
Merged
Conversation
The docker env runs two Kibana replicas behind kbn-proxy. The upstream block had no connect timeout and no failover, so while one replica restarted - which Kibana-config.cy.ts makes it do, and which `restart: always` on kbn-ror exists for - half of every request went to a container that was not listening. A stopped container drops the packets rather than refusing them, so those requests hung instead of failing. nginx waited its default 60s connect timeout, which is longer than every Cypress timeout, so the browser gave up first, the failure never counted against the peer, and the peer stayed in the rotation. Cypress retries did not help: all three attempts hit the same alternation. Measured on a two-replica reproduction with one replica stopped. before: 000 200 000 200 000 200 000 200 000 200 (50% lost, each hanging to the client's limit) after: 200/2.00s 200/0.0005s 200/0.0005s ... (one failover, then the peer is out) Sustained for 30s with the peer down: 110 requests, 0 failures, 3 over 0.5s (the 10s re-probe), worst 2.0s - inside every Cypress timeout. The replica returns to the rotation on its own when it answers again. This fits the evidence: the failures only ever appear on the `docker` legs, never on `eck`, and eck runs a single Kibana (kind-cluster/ror/base/kbn.yml, count: 1) with no proxy in front. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This comment was marked as off-topic.
This comment was marked as off-topic.
This was referenced Sep 12, 2026
Merged
The first version of this change set max_fails=1 fail_timeout=10s, and it made the suite worse: the 9.5.3 docker leg failed 10 of 27 specs, every one of them on `502: Bad Gateway`, with `no live upstreams while connecting to upstream` in the nginx log. Ejection cannot work here. There are two peers, and a settings change restarts Kibana, so BOTH answer 503 for a few seconds. One 503 each ejects both, nginx has no peer left, and every request gets a 502 — including for ten seconds after the replicas are healthy again. Measured on a two-replica reproduction with controllable backends, 24 requests per case: scenario max_fails=1 max_fails=0 one peer stopped 24 ok 24 ok one peer answering 503 24 ok 24 ok both peers 503 0 ok, 23x 502, 1x 503 0 ok, 24x 503 both recover first 200 at 10.49s first 200 at 0.01s http_503 stays in proxy_next_upstream. Taking it out looked like the fix at first, and it is not: with one replica restarting and the other healthy it turned 0 failures into 12 of 24, because the 503 is then served to the client instead of being retried on the peer that can answer. What is left is failover without ejection. A peer that cannot take a request costs that request one failover, and a peer that recovers is used again on the next request. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This comment was marked as outdated.
This comment was marked as outdated.
… suite fails Temporary, to be reverted. On the red 9.4.6 docker legs the kbn-ror containers restart with exit code 0 during Tenancy, Test-settings and User-settings; on the green legs they never restart. The EXIT trap tears the stack down before any later step can look, so this prints `docker events` and the shutdown-related Kibana log lines from inside the failure path. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
…when the suite fails" This reverts commit 664fdba.
This comment was marked as outdated.
This comment was marked as outdated.
coutoPL
reviewed
Sep 14, 2026
Each comment states what the directive does and why the value is set. Measurements and change history stay in the PR description. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
The
9.4.6, dockerleg has been failing on nearly every pull request, on different specs each time, and passing on a re-run. I treated it as a flaky spec. It is not — it is the proxy in front of Kibana.The mechanism
environments/elk-ror/base.docker-compose.ymlruns two Kibana replicas, andkbn-proxyround-robins across them.Kibana-config.cy.tschanges ROR settings, which restarts Kibana —restart: alwaysonkbn-rorcarries a comment saying that is exactly why it is there.While a replica restarts, half of every request goes to a container that is not listening. A stopped container drops the packets rather than refusing them, so those requests hang instead of failing. The old config set no
proxy_connect_timeout, so nginx waited its default 60 seconds — longer than every Cypress timeout (defaultCommandTimeout20s,requestTimeout10s). The browser gave up first, the failure never reached nginx to be counted against the peer, and the peer stayed in the rotation.Cypress's
retries: 2did not help. Three attempts, same alternation.That accounts for every symptom:
dockerlegs only, nevereckkind-cluster/ror/base/kbn.yml,count: 1) with no proxySample failures, all timeouts on unrelated things:
The change
Three directives on the
location, and the defaultmax_fails/fail_timeoutwritten out on the peer so the intent is on the page:proxy_connect_timeout 2s— the important one. It turns a hung connect into a countable failure long before the client gives up. Two seconds is far above a healthy connect on the container network and far below the 10s Cypress spends incy.wait().proxy_next_upstream error timeout http_502 http_503 http_504— send the request to the other replica.http_503is in the list because a Kibana that is listening but still starting answers 503, which nginx does not treat as an error by default.proxy_next_upstream_tries 2— there are two replicas.Measured
Two-replica reproduction, one replica stopped, same config shape:
Sustained for 30s with the peer down: 110 requests, 0 failures, 3 over 0.5s (the 10s re-probe), worst case 2.0s — inside every Cypress timeout. When the replica answers again nginx takes it back on its own, verified.
nginx -tpasses on the real file.What I did not test
The
http_503path is reasoned, not measured: I reproduced the dropped-packet case, which is what a restarting Kibana does, and not the "listening but answering 503" case. It is a standard directive and costs nothing if that state never occurs.I also left
proxy_read_timeoutandproxy_send_timeoutat their 60s defaults. Lowering them would catch a replica that hangs after accepting the request, butReporting.cy.tscan legitimately wait a long time on a response, and I would rather not trade this flake for a new one.Base branch
master, perdocs/dev/branching.mdcase 3 — a fix for a test that fails against the released plugins, and a flaky test counts.🤖 Generated with Claude Code
Summary by CodeRabbit