Skip to content

Conversation

@naemono
Copy link
Contributor

@naemono naemono commented Oct 22, 2025

Fixes #8429

What is changing?

This ensure that the master StatefulSets are always upgraded last when doing a version upgrade of Elasticsearch.

Validation

  1. Manual testing
  2. Unit test for behavior
  3. e2e test validating behavior

@prodsecmachine
Copy link
Collaborator

prodsecmachine commented Oct 22, 2025

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Licenses 0 0 0 0 0 issues
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@botelastic botelastic bot added the triage label Oct 22, 2025
Signed-off-by: Michael Montgomery <[email protected]>
Signed-off-by: Michael Montgomery <[email protected]>
@naemono
Copy link
Contributor Author

naemono commented Oct 29, 2025

buildkite test this -f p=kind,t=TestNonMasterFirstUpgradeComplexTopology -m s=9.1.2

Signed-off-by: Michael Montgomery <[email protected]>
Signed-off-by: Michael Montgomery <[email protected]>
…/cloud-on-k8s into fix-sts-upgrade-issue-recreation
@naemono
Copy link
Contributor Author

naemono commented Oct 29, 2025

buildkite test this -f p=kind,t=TestHandleUpscaleAndSpecChanges_VersionUpgradeDataFirstFlow -m s=9.1.2

Signed-off-by: Michael Montgomery <[email protected]>
Signed-off-by: Michael Montgomery <[email protected]>
Signed-off-by: Michael Montgomery <[email protected]>
Signed-off-by: Michael Montgomery <[email protected]>
Signed-off-by: Michael Montgomery <[email protected]>
@naemono naemono changed the title WIP: Upgrade masters last when upgrading ES clusters Upgrade masters last when upgrading ES clusters Oct 29, 2025
@naemono naemono marked this pull request as ready for review October 29, 2025 23:21
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a non-master-first upgrade strategy for Elasticsearch clusters. The key change ensures that during version upgrades, non-master nodes (data, ingest, coordinating nodes) are upgraded before master nodes, which helps maintain cluster stability during upgrades.

  • Adds logic to separate master and non-master StatefulSets during version upgrades
  • Implements upgrade order validation to ensure non-master nodes complete their upgrades first
  • Adds comprehensive unit and e2e tests to verify the upgrade flow

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
pkg/controller/elasticsearch/driver/upgrade.go Adds check to identify new clusters vs upgrades by checking if status version is empty
pkg/controller/elasticsearch/driver/upscale.go Implements non-master-first upgrade logic with resource separation and upgrade status checking
pkg/controller/elasticsearch/driver/upscale_test.go Adds comprehensive unit test for version upgrade flow and minor formatting fixes
test/e2e/es/non_master_first_upgrade_test.go Adds e2e test that validates non-master-first upgrade behavior with a watcher

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return
}

// Check if any master StatefulSet has it's version higher than any non-master StatefulSet
Copy link

Copilot AI Oct 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'it's' to 'its' (possessive form, not contraction).

Suggested change
// Check if any master StatefulSet has it's version higher than any non-master StatefulSet
// Check if any master StatefulSet has its version higher than any non-master StatefulSet

Copilot uses AI. Check for mistakes.
Signed-off-by: Michael Montgomery <[email protected]>
@barkbay barkbay added the >bug Something isn't working label Nov 3, 2025
@botelastic botelastic bot removed the triage label Nov 3, 2025
Comment on lines +263 to +264
// If the StatefulSet is not at the target version, it is not upgraded
// so don't even bother looking at the state/status of the StatefulSet.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is possible to enter a kind of "deadlock" when the master role is added to an existing nodeSet.
In that case:

  • The updated sts is detected here as a "not (yet) master sst"
  • But it is never going to be upgraded because it is considered as a masterResources in adjusted

Simple manifest to replicate the deadlock:

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: elasticsearch-sample
spec:
  version: 9.1.6
  nodeSets:
  - name: ns1
    config:
      node.roles: ["master","data"]
      node.store.allow_mmap: false
    count: 1
  - name: ns2
    config:
      node.roles: ["data", "ingest", "ml"]
      node.store.allow_mmap: false
    count: 3

Then upgrade to 9.2.0 with:

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: elasticsearch-sample
spec:
  version: 9.2.0
  nodeSets:
  - name: ns1
    config:
      node.roles: ["master","data"]
      node.store.allow_mmap: false
    count: 1
  - name: ns2
    config:
      node.roles: ["master", "data", "ingest", "ml"]
      node.store.allow_mmap: false
    count: 3

Copy link
Contributor

@barkbay barkbay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also have a problem when we increase the master replicas:

Initial manifest

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: elasticsearch-sample
spec:
  version: 9.1.6
  nodeSets:
  - name: ns1
    config:
      node.roles: ["master"]
      node.store.allow_mmap: false
    count: 1
  - name: ns2
    config:
      node.roles: ["data", "ingest", "ml"]
      node.store.allow_mmap: false
    count: 3

Updated manifest

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: elasticsearch-sample
spec:
  version: 9.2.0
  nodeSets:
  - name: ns1
    config:
      node.roles: ["master"]
      node.store.allow_mmap: false
    count: 3
  - name: ns2
    config:
      node.roles: ["data", "ingest", "ml"]
      node.store.allow_mmap: false
    count: 3

Operator is stuck in:

    inProgressOperations:
      downscale:
        lastUpdatedTime: "2025-11-03T10:04:05Z"
      upgrade:
        lastUpdatedTime: "2025-11-03T10:04:05Z"
      upscale:
        lastUpdatedTime: "2025-11-03T10:13:51Z"
        nodes:
        - message: Creating master node
          name: elasticsearch-sample-es-ns1-1
          status: EXPECTED
        - message: Limiting master nodes creation to one at a time
          name: elasticsearch-sample-es-ns1-2
          status: PENDING
    observedGeneration: 3
    phase: ApplyingChanges
    version: 9.1.6

Comment on lines +273 to +291
// Check if this StatefulSet has pending updates
if statefulSet.Status.UpdatedReplicas != statefulSet.Status.Replicas {
return false, nil
}

// Check if there are any pods that need to be upgraded
pods, err := es_sset.GetActualPodsForStatefulSet(client, k8s.ExtractNamespacedName(&statefulSet))
if err != nil {
return false, err
}

for _, pod := range pods {
// Check if pod revision matches StatefulSet update revision
if statefulSet.Status.UpdateRevision != "" && sset.PodRevision(pod) != statefulSet.Status.UpdateRevision {
// This pod still needs to be upgraded
return false, nil
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this whole logic assumes that the StatefulSet controller has updated the status, which is not necessarily true from my experiments. I hit several cases where the StatefulSet spec has been updated but not its status. A non master sts is then detected as reconciled while it is not the case.

}

// Check if all non-master StatefulSets have completed their upgrades before proceeding with master StatefulSets
if len(masterResources) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering in which cases we are expecting this to be false?

Suggested change
if len(masterResources) > 0 {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

>bug Something isn't working v3.3.0 (next)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] ECK should only Update Elasticsearch StatefulSet version when attempting to upgrade the StatefulSet Pods

3 participants