feat(datanode): delegate OpenSearch roles across node groups - #114
Open
monrax wants to merge 3 commits into
Open
feat(datanode): delegate OpenSearch roles across node groups#114monrax wants to merge 3 commits into
monrax wants to merge 3 commits into
Conversation
Add opt-in role delegation so larger clusters can dedicate StatefulSets to specific OpenSearch roles (cluster_manager, data, ingest, remote_cluster_client, search) instead of every Data Node carrying all roles. - The top-level datanode block is the primary node group (legacy unsuffixed names). datanode.roles (default []) sets its OpenSearch roles and is inherited as the default by every extra group; empty keeps the Data Node default and its automatic search-role-on-snapshot behavior. - datanode.extraNodeGroups is a map keyed by group name; each value overrides the inherited datanode.* values. Keys may be hyphenated. Cross-values-file deep merge and unique names come for free. - graylog.datanode.groups enriches every group with derived fields (fullname, configmapName, pdbName, groupLabel, data/nativeLibs storage class), so the StatefulSet, ConfigMap and PDB templates iterate with `.`/`$` and never pass (root, group) dicts. The StatefulSet, ConfigMap and PDB become per-group; the headless Service and Secret stay shared, and discovery seed hosts span all groups. - Group labels (graylog-datanode-group) are emitted only when extra groups exist, so a plain install keeps today's unlabeled selector and upgrades in place. When groups are added, the primary is labeled `default` and every StatefulSet gets a distinct selector (no controller overlap). NOTE: this relabels the primary selector, which is immutable — first-time adoption requires recreating the graylog-datanode StatefulSet (documented in values.yaml). - graylog.datanode.replicas sums replicas across groups; drop the `| default N` fallbacks from graylog.replicas / graylog.datanode.replicas so values.yaml is authoritative and an explicit replicas: 0 is no longer coerced. Verified: back-compat renders identically to main (modulo random secrets and config checksum); map mode renders primary + extras with distinct selectors, per-group roles/heap/storage, group-spanning seed hosts, and falsy overrides (persistence.data.enabled: false). 66 unit tests pass; helm lint clean. Guardrails (fail without a cluster_manager group, warn on missing data role or a search group without a repo) follow in a separate commit. Co-Authored-By: Claude Opus 4.8 (1M context)[EMAIL_ADDRESS_REDACTED]om>
Add validation on top of the extraNodeGroups role delegation: - Hard fail (graylog.datanode.validate, included from the datanode StatefulSet) when no node group is eligible to be a cluster_manager, i.e. every group sets explicit roles and none includes cluster_manager. Groups with empty roles use the Data Node default (which includes cluster_manager), so the all-defaults install never trips it. - NOTES.txt warning when no group is eligible to hold data (every group sets explicit roles and none includes data). - NOTES.txt warning when a group declares the search role but no snapshot repository is configured (datanode.config.s3ClientDefault*), listing the affected groups; suppressed once a repo is set. Warnings follow the chart's existing NOTES.txt convention (fsGroup, MongoDB worker count). 7 unit tests cover the fail path, both warnings, and their negative cases via failedTemplate / matchRegexRaw; 73 tests pass, lint clean. Co-Authored-By: Claude Opus 4.8 (1M context) <[EMAIL_ADDRESS_REDACTED]>
Add docs/datanode-node-roles.md covering the role list, the primary group + extraNodeGroups map, a hot+search example, the guardrails, the search-tier snapshot-repository requirement, and the flat->groups migration. The migration recreates the primary StatefulSet by deleting it and upgrading in one chained step, so helm creates (not patches) the immutable selector and never errors; PVCs are retained and the primary pods restart once. Documents the role-narrowing / data-path and dedicated-manager rebuild caveats. Link the guide from the README Usage section and the DataNode values reference, and trim the values.yaml comments to a short pointer. Migration verified live on EKS: adding a data-capable group to a running flat install migrates cleanly (PVCs retained, cluster stays green as one cluster). Co-Authored-By: Claude Opus 4.8 (1M context) <[EMAIL_ADDRESS_REDACTED]>
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.
This is a first pass at the DataNode roles issue. While it has been validated against a live EKS cluster, it has not been tested thoroughly.
Summary
Allow Data Nodes to be dedicated to specific OpenSearch roles so larger clusters can delegate responsibilities (e.g. a dedicated search/warm tier or dedicated cluster-manager nodes) instead of every Data Node carrying all roles.
Details
datanodeblock is now the primary node group;datanode.roles(default[]= Data Node default set of roles) sets its OpenSearch roles and is inherited as the default by extra groups.datanode.extraNodeGroupsmap (keyed by group name) — each entry renders its own StatefulSet, ConfigMap and PDB, inheriting everydatanode.*value and overriding only what it declares. The headless Service and Secret stay shared; discovery seed hosts span all groups so they form a single OpenSearch cluster.graylog.datanode.groupshelper normalizes + enriches each group (fullname, configmap/pdb names, storage classes, group label) so templates iterate with./$.graylog-datanode-group) are emitted only when extra groups exist, so a plain install keeps today's unlabeled selector and upgrades in place.cluster_manager-eligible; NOTES.txt warnings when no group isdata-eligible or when asearchgroup has no snapshot repository configured.| default Nfallbacks fromgraylog.replicas/graylog.datanode.replicasvalues.yaml is authoritative; explicitreplicas: 0is no longer coerced);graylog.datanode.replicasnow sums across groups.docs/datanode-node-roles.mdguide (roles, node groups, guardrails, search-tier repository requirement, flat→groups migration), linked from the README and values reference.Linked issues
This fixes #107
PR Checklist
Please check the items that apply to your change.
Testing Checklist
Static Validation
helm lint ./charts/grayloghelm template graylog ./charts/graylog --validateInstallation
helm unittest charts/graylog(73 tests)Functional (if applicable)
CONNECTED/AVAILABLE, indexer cluster green)Upgrade (if applicable)
Specific to this PR
Verified live on EKS (fresh EKS cluster,
provider=aws):cluster_manager-only + adata,ingest,remote_cluster_clientgroup. Each pod's generatedopensearch.ymlcarried exactly the delegatednode.roles; the two StatefulSets had distinct selectors (no cross-adoption); all datanodes registered in one cluster; indexer health green with 0 unassigned shards.helm upgrade --dry-runwhen no group iscluster_manager-eligible; NOTES warnings render for the no-data / search-without-repo cases.extraNodeGroupson a running flat install fails an in-place upgrade on the immutable StatefulSet selector; the documentedkubectl delete statefulset graylog-datanode && helm upgraderecreates it (PVCs retained) and the cluster returns green as one cluster. The role-narrowing / dedicated-manager rebuild caveats are documented in the guide.Notes for reviewers
🤖 Generated with Claude Code