feat(alerting): cluster event log alert rules for docker clusters - #1301
Draft
boddumanohar wants to merge 1 commit into
Draft
feat(alerting): cluster event log alert rules for docker clusters#1301boddumanohar wants to merge 1 commit into
boddumanohar wants to merge 1 commit into
Conversation
Adds `sbctl cluster event-alerts <cluster-id>`, which provisions eight Grafana alert rules that read the cluster event log through /api/v2/clusters/<id>/logs instead of the Thanos metrics the rules in alerting/alert_rules.yaml read. Ports the rules from simplyblock-operator#474, which does the same for the Helm chart. The event log carries the transition an entity made, not only the state it ended in, so these rules can tell an operator's shutdown apart from a fault that ended in the same state, and can report three conditions no metric carries: a device removal and the two journal-compression conditions. Opt-in, because the rules need a REST data source and therefore a Grafana plugin the deployed image does not carry and downloads once (~74 MB). The command works on a running cluster, which on docker is every cluster there will be: it writes the two provisioning files into the directories Grafana already bind-mounts -- on every management node, since Grafana is constrained to managers and may be rescheduled to any of them -- and then recreates the Grafana task so it re-reads them. Paths are read off the running service rather than computed from this package's location. Not wired into `cluster create` or the compose file on purpose: nothing on the create path changes, so an upgrade cannot alter the behaviour of a cluster whose operator does not run the command. Five of the eight overlap a rule in alert_rules.yaml, three of which can only ever fire via noDataState today (the metrics exporter skips any node that is not ONLINE and any device that is not online/read_only/ cannot_allocate, so snode_status_code is always 0 and device_status_code never carries unavailable). Retiring those is a separate change. 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.
Ports simplyblock-operator#474 to docker-based clusters.
Adds
sbctl cluster event-alerts <cluster-id>, which provisions eight Grafana alert rules that read the cluster event log through/api/v2/clusters/<id>/logsinstead of the Thanos metrics the rules inalerting/alert_rules.yamlread.The event log carries the transition an entity made, not only the state it ended in. That is what lets these rules tell an operator's shutdown apart from a fault that ended in the same state, and lets them report three conditions no metric carries: a device removal and the two journal-compression conditions.
How it works
Run once, from any management node. The command:
monitoring_grafanaservice, rather than computing them from this package's location;event_alert_rules.yamlanddatasource-events.ymlfor this cluster;node.role == managerand may be rescheduled to any of them, and these are host paths);--force, adding the plugin env and the data source mount, so Grafana re-reads provisioning.Opt-in because the rules need a REST data source, and therefore a Grafana plugin the deployed image does not carry and downloads once (~74 MB) into the
grafana_datavolume.--plugin-preinstalledcovers an air-gapped install.Deliberately not wired into
cluster createordocker-compose-swarm-monitoring.yml: nothing on the create path changes, so an upgrade cannot alter the behaviour of a cluster whose operator does not run the command. It also means this works on clusters that already exist, which for docker is all of them.The rules
StorageNode_left_onlineonline/in_creationin_shutdown,in_removal,pending_removalorremovedDevice_became_unavailableunavailableonlineDevice_removedremovedin the last 24hCluster_became_degradeddegradedCluster_became_suspendedsuspendedCluster_capacity_reachedJM_records_threshold_exceededJM_compression_errorEach rule returns one row per entity that is currently wrong, so healing is structural: the reverting event removes the row, and
noDataState: OKturns an empty result into resolved.Known gaps, for the reviewer
alert_rules.yaml, and both sets route to the same contact point withgroup_by: ['grafana_folder','alertname'], so those conditions notify twice. Retiring the duplicates is a separate change.StorageNode_status_online_to_down,..._to_unreachable,Device_status_online_to_unavailable) can only ever fire vianoDataStatetoday:simplyblock_web/api/v1/metrics.py:141skips any node that is notONLINEand:201any device that is notonline/read_only/cannot_allocate, sosnode_status_codeis always0anddevice_status_codenever carriesunavailable(3) orremoved(4). Worth fixing on its own — it also makes those values wrong in every dashboard.JM_records_threshold_exceededclears on a one-hour timer, not on recovery.check_jm_compression_backloglogs the downward crossing but writes no event, so there is nothing for the fold to see. ~10 lines to emit one, then the rule can heal structurally.storage-node restart/suspendstill notifies, sincein_restartandsuspendedare not in the operator-requested set.device_events.py:23setsnode_idto the device id, andget_logsexposes no owning node), so a device failure on another node within 120s of a node going down is suppressed too.Testing
tox run-parallel -e lint,typesandtox run -e unitare green, with one pre-existing unrelated failure (test_leaderless_warning_is_rate_limited, which reproduces onorigin/main— its rate limiter uses0.0as a sentinel againsttime.monotonic()).Not yet exercised against a live cluster — that is what this draft is for. On a real cluster, worth checking:
then trigger a device removal and a node fault and confirm both the firing and the healing, and that a clean
storage-node shutdownstays quiet.🤖 Generated with Claude Code