Repository navigation
[Backport release-1.6] fix(opensearch-operator): let a permanently yellow cluster restart - #5074
Merged
myasnikovdaniil merged 5 commits intoOct 23, 2026
Conversation
The operator restarts a node only when its health gate opens, and the gate wanted green, or yellow caused by the observability index alone. A cluster whose replicas can never be assigned reaches neither: on a single data node any index with a replica is yellow for good, and the operator itself turns on the audit log that creates one on the first audited event. From then on nothing that needs a restart was ever rolled out, a version upgrade and the move of the HTTP listener onto the cert-manager chain included. Upstream rewrote the gate to let a yellow cluster through once allocation is enabled, every data node has joined and no shard is moving, and to refuse instead to restart a node that holds the only active copy of a shard meant to have others. No released operator carries that change, so it is carried here as a patch against the pinned version, together with the upstream tests for it. Backport: the Dockerfile header keeps release-1.6's trace paragraph, placed after the new one as on main. Signed-off-by: Aleksei Sviridkin <[email protected]> Assisted-by: LLM (cherry picked from commit d9fbeab) Signed-off-by: Myasnikov Daniil <[email protected]>
…nish The yellow restart gate carried in the previous patch lets a permanently yellow cluster through, and with three or more nodes packages/apps/opensearch turns drainDataNodes on. The restart then reaches PreparePodForDelete, which excludes the candidate from allocation before it can know whether the drain will finish. On the cluster that made the gate wait it never finishes: a shard on that node has nowhere else to go, which is the same condition holding the cluster yellow. The exclusion is withdrawn only after a pod is really deleted, so a data node stays out of allocation for as long as the restart is stuck, shedding its shards onto the rest of the cluster and buying nothing. Ask the allocator before excluding anything, and only while nothing is moving, so a drain that is making progress costs nothing. A started shard answering can_move_to_other_node: no means the drain cannot finish, and then no exclusion is written and one left by an earlier pass is withdrawn. The two-data-node path keeps its behaviour, because it never waits for a full drain. Checking after the fact instead would flap: the next reconcile, ten seconds later, would exclude the node again. Upstream as opensearch-project/opensearch-k8s-operator#1585, fixed there by #1586; the patch goes away with the first release carrying it. Backport: the Dockerfile header keeps release-1.6's trace paragraph, placed between the new ones as on main. Assisted-by: LLM Signed-off-by: IvanHunters <[email protected]> (cherry picked from commit 28195d3) Signed-off-by: Myasnikov Daniil <[email protected]>
… build
The patches under images/opensearch-operator/patches carry their own tests and
nothing runs them. The build compiles main.go, and go-unit-tests in the root
Makefile covers this repository's own Go tree, so a test file that had stopped
compiling still produced an image:
printf 'func Broken() { this is not go }' >> restart_gate_test.go
go build -a -o manager main.go # exit 0
Run go test over the two package trees the patches touch before building the
binary. Both run without a cluster, and the stage takes about eight minutes on
an arm64 builder, most of it the module download the build needs anyway.
Assisted-by: LLM
Signed-off-by: IvanHunters <[email protected]>
(cherry picked from commit 000e2e3)
Signed-off-by: Myasnikov Daniil <[email protected]>
Upstream gives the operator's calls to a cluster no deadline of any kind. The transport it builds carries no dial, handshake or response-header timeout, no http.Client is configured, the calls the client makes on its own behalf pass context.Background(), and the ones that take a context from the caller are handed one with no deadline on it. A cluster that accepts a connection and then says nothing holds such a call for as long as the process lives, and with one worker per controller that single call stops every OpenSearchCluster from being reconciled. The deletion that then waits out its whole termination timeout is the visible end of it. The bound goes on the RoundTripper, the one level every request passes through, the ones opensearch-go builds for itself included: before a client's first request the library runs a product check that carries a context.Background() of its own and decodes the body of the answer, and a client is built per reconcile, so that check runs on every one. The deadline cannot be released when RoundTrip returns, because the body goes back to the caller still open; it rides on the body and is released by Close, the way http.Client applies its own Timeout. That bounds one attempt. opensearch-go retries a request up to three more times on 502, 503 and 504 and the transport's deadline starts over on each, so the calls carry a deadline a second time for the series: through requestContext where the call decodes the answer before it returns, and through performRequest where the still-open body goes back to the caller. The dial and the TLS handshake keep a shorter bound of their own, so an unreachable node fails in a third of the budget with an error that names what went wrong. Each of those bounds has a test that fails when it is removed. Signed-off-by: IvanHunters <[email protected]> (cherry picked from commit 1a2c876) Signed-off-by: Myasnikov Daniil <[email protected]>
The timeout tests drive a listener from one goroutine and inspect what it accepted from another. The plain run passes an unsynchronised access there, so nothing in this repository would catch one. The builder image carries cgo and gcc, and the package images are built natively on x86-64 runners, so the detector is supported where this runs. Signed-off-by: IvanHunters <[email protected]> (cherry picked from commit 48058dc) Signed-off-by: Myasnikov Daniil <[email protected]>
Contributor
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
myasnikovdaniil
marked this pull request as ready for review
October 23, 2026 15:00
myasnikovdaniil
deleted the
backport/4317-opensearch-operator-release-1.6
branch
October 23, 2026 15:00
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 PR does
Backport of #4317, #4323 and #4341 to release-1.6.
drainDataNodeson for every release (main limits it to clusters with more than two data nodes, a change that came with feat(opensearch)!: issue HTTP and Dashboards certificates from cert-manager #2682 and is not on this line), so a single-node cluster still cannot finish a rolling restart here. The release note below is adjusted for that.Screenshots
Not a UI change.
Downstream repositories
Release note