Skip to content

[Question]: Upgrade implementation vs recommendations in docs #363

Open

Description

@ivareri

Ask a question

Hi

I've been meaning to provide feedback on the upgrade functionality for quite some time, but life have gotten in the way. Maybe this should have been multiple issues, and I've might have missed some details or points, but it is what is it.

Latest elastic docs and the implemented process have some differences:

  • Stopping ML nodes is not implemented.
  • Docs says "cluster.routing.allocation.enable": "primaries" vs implemented none
  • Docs recommends upgrading tier-by-tier (frozen-cold-warm-hot)

Things I have observed during testing:

  • Wait period for a cluster to return to Green status is not always long enough
  • Sometimes cluster never returns to Green status as there are no eligible nodes for the replica shards
  • If a node fails, the entire play should abort. Currently it just drops the node that failed, and keeps running for the rest of the nodes.

Questions:
Is the "cluster.routing.allocation.enable" based on earlier recommendations, or is there another reason to choose none over primaries?

My biggest blocker currently is that the cluster remains in a yellow state when there are replicas with no eligible nodes. The Docs says to proceed with the upgrade in these cases. This means we would have to check init and relo columns in _cat/health?v=true. This might either be trivial or far-from-trivial, not sure to be honest.

Regarding failing entire play vs node, this might be something in my ansible setup, or something in my playbook. I've not had time to give this a hard look yet.

Adding a task to start/stop ML nodes should be trivial, I might drop a PR for this if/when I find the time.

Activity

  1. ivareri commented on Jan 27, 2025

    @ivareri
    ContributorAuthor

    Ok, so by replacing this test

    with

     until:
            - "response.json.relocating_shards == 0"
            - "response.json.initializing_shards == 0"
            - "response.json.status == 'green' or
               response.json.status == 'yellow'"
    

    it solved the deadlock with no eligble nodes. It should probably verify this status a couple of times before procceding.

    @widhalmt: Do you want PRs for this against main or #349

  2. widhalmt commented on Feb 4, 2025

    @widhalmt
    Member

    Hi,

    As you know from our collaboration "life getting in the way" Is a thing just know all too well. Your contributions are very welcome and I'm personally extremely thankful for the work you put into it.

    To be honest, the "old implementation" came from a very old documentation where updates where done mostly manually. Until now we have not encountered a problem with the update procedure. That doesn't mean I don't believe it exists, we only work with a limited count of different setups.

    Please provide PRs against #349 as this will be the new way for updates/upgrades.

    I haven't encountered an upgrade where the system was left without eligible nodes. My personal approach would be that this is an fatal exception and needs manual interaction. On the other hand with your code you provided I don't see a problem with using it in the future. All the more since you can support the idea of proceeding with official documentation.

  3. afeefghannam89 commented on Aug 21, 2026

    @afeefghannam89
    Member

    Related question that came up while fixing #546: should the logstash, kibana and beats roles get
    the same fresh-install guard that the elasticsearch role now has on its package tasks?

    They should not. The guard is only safe in the elasticsearch role because there is an
    alternative path - a blocked plain install falls through to elasticsearch-rolling-upgrade.yml.
    The other three roles have no such path, so the plain package: state=present task is their
    upgrade mechanism. Guarding it would mean the package is installed once and then never updated
    again, and raising elasticstack_version would silently do nothing.

    What those roles are missing instead is ordering. The upgrade docs put ingest components after
    the cluster:

    Once you've successfully upgraded your deployment, you can upgrade your ingest components,
    such as Logstash, Elastic Agent, or Beats.

    Nothing currently makes sure the Elasticsearch rolling upgrade has finished before logstash,
    kibana and beats are upgraded. If it aborts halfway, the other components are upgraded anyway
    and end up ahead of the cluster.

    For logstash there is a second, smaller point: with more than one instance they all restart at
    the same time, which pauses ingest for that window. Beats buffer and track offsets, so this is
    an availability dip rather than data loss, but serializing it the way the elasticsearch role
    does would avoid it.

  4. afeefghannam89 commented on Aug 24, 2026

    @afeefghannam89
    Member

    Two additions after comparing the current implementation with the docs.

    The until change proposed above matches the documentation. The
    rolling upgrade guide
    says to proceed once the shards have settled, not once the cluster is green:

    You can proceed once there are no initializing or relocating shards.

    and it expects yellow during the upgrade, because of the mixed-version rule on the same page:

    Primary shards assigned to a node running the new version cannot have their replicas assigned
    to a node with the old version.

    If it is not possible to assign the replica shards to another node (there is only one upgraded
    node in the cluster), the replica shards remain unassigned and status stays yellow.

    So waiting for green between nodes cannot succeed in a small cluster, it can only time out.

    One gap that is not in the list above: node order. Per
    Upgrade Elasticsearch
    the upgrade runs in three groups - data nodes tier by tier (data_frozen, data_cold,
    data_warm, data_hot, then the remaining data nodes), then the nodes that are neither data nor
    master-eligible (ml, ingest, transform, remote_cluster_client, coordinating-only), then
    master-eligible last:

    Upgrade the master-eligible nodes last.

    Upgraded nodes can join a cluster with an earlier version master, but earlier version nodes
    cannot always join a cluster with an upgraded master.

    tasks/main.yml loops over groups[elasticstack_elasticsearch_group_name], so the position of a
    master-eligible node in the inventory decides when it is upgraded. If it goes first, every
    remaining old node has to join an upgraded master, which the docs say may fail.

    The role already builds elasticsearch_role_master / _data / _other with group_by, but only
    uses them to count masters and to render cluster.initial_master_nodes - the upgrade loop could
    use the same groups. One caveat: that block is gated on elasticsearch_node_types is defined, so
    with the default configuration (no node.roles written, so
    every node is master-eligible)
    the groups do not exist and the elected master would have to be read from _cat/master instead.

    The tier order has its own reason, also from the guide:

    Upgrade the data nodes first, tier-by-tier, starting with the frozen tier, then the cold tier,
    then the warm tier, then the hot tier.

    This ensures ILM can continue to move data through the tiers during the upgrade.

    For reference: #349 in its current state moves the tasks into separate files but keeps both
    points, "cluster.routing.allocation.enable": "none" and until: response.json.status == 'green'.

  5. added this to the 1.0.0 milestone on Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions