Observability

Alert To Runbook Map

Keep this table synchronized with your PrometheusRule package. Alert annotations should link to the matching page or heading. Use the Observability Change Checklist when adding, removing, or changing alerts, alert annotations, runbook links, dashboard links, or actionable Events.

Alerts

AlertPrimary runbookFirst checks
BloodravenOperatorDownOperator unavailableDeployment, leader election, logs
BloodravenNoWritableSiteEmergency manual promotion or Total site lossActive site, pod reachability, fencing
BloodravenFailoverOccurredFailoverDNS, app writes, old primary state
BloodravenDivergentTransactionsDivergent old primary recovery or Divergent replicaEvents (DataLossDetected / DivergentReplicaDetected), status.sites[].divergenceDetectedBy, GTIDs, old primary fenced
BloodravenReplicationLaggingReplication lag highlag metric, MySQL replica status
BloodravenReplicationDownReplication lag high; sites awaiting a post-restore reclone are excluded by design (Peer replication during a full-instance restore)bloodraven_replication_running, bloodraven_restore_reclone_pending, MySQL replica status
BloodravenRestoreReclonesHeldPeer reclones after a full-instance restorestatus.restoreReclones, status.restoreInPlace.message, the primary's data before choosing what to keep
BloodravenBackupStaleFailed backuplatest MysqlBackup, Job logs
BloodravenBackupArtifactCleanupFailing (increase(bloodraven_backup_artifact_cleanup_failures_total[6h]) > 0)Artifact cleanupArtifactCleanup condition on Terminating MysqlBackups, cleanup Job termination message, S3 credentials or claim
BloodravenBackupVerificationStaleBackup Verificationverification CRs, restore logs
BloodravenPITRArchiveLaggingBackup And Restorearchiver metrics, object storage, PITRArchiveReady reason and status.pitr.archive (an archive identity refusal stops uploads)
BloodravenDNSUpdateFailedDNS failover stuckDNSEndpoint, external-dns logs
BloodravenSplitBrainDetectedSplit-brain recoverywritable sites, app traffic, GTIDs
BloodravenDragonflySiteDownDragonfly degradedstatus.dragonfly.sites[], Dragonfly pods, active Service endpoints
BloodravenDragonflyPromotionFailedDragonfly degradedplanned-failover Dragonfly status, Events, Redis client impact
BloodravenDragonflySessionsLostDragonfly degradedstatus.dragonfly.replTakeoverSupported, DragonflySessionsLost Events, image pin
BloodravenDragonflyManagerPanicDragonfly degradedoperator logs, panic counter, current status.dragonfly
BloodravenKeyringNotSealedData-at-rest encryptionstatus.encryptionAtRest.sites[].phase and .message, escrow Secret exists, sidecar /keyring/status
BloodravenKeyringEscrowFailingData-at-rest encryptionbloodraven_keyring_escrow_pushes_total{outcome="failure"}, sidecar logs, operator /keyring/escrow rejections
BloodravenUnencryptedTablespacesData-at-rest encryptionbloodraven_encryption_unencrypted_tablespaces, whether the group was adopted with partial coverage
BloodravenLicenseUpdatesExpiringLicensingbloodraven_license_updates_expiry_timestamp_seconds. Renewal reminder only — the operator does not gate or change behavior when the timestamp is in the past.

Kubernetes Events

Event categoryExpected operator actionRunbook
Planned failover requested/started/completedDrain writes, promote target, update DNSPlanned Failover
PlannedFailoverFailed with outcome SourceLeftFencedNothing was written to the target; the source stays read-only. The operator re-asserts an attributable fence on its own; some causes are manualPlanned failover left the source fenced
PlannedFailoverPromotionConfirmationFailedNames the target as the last failover target without a cooldown; emergency failover may promote the fenced sourcePromoted but unconfirmed
PlannedFailoverManualRecoveryRequired / PlannedFailoverHoldPersistedHolds automatic failover for the group (AutomaticFailoverHeld=True) until a human acknowledges it. PagePlanned failover automation hold
PlannedFailoverStalledManagerAbsent / PlannedFailoverStatusStalledNo topology manager, or status writes failing, while a planned failover holds its claim; the run ends after 5 or 2 minutes (10 seconds once its promotion is recorded and published)Planned failover
PlannedFailoverDeferred with DeploymentHoldInspect blocking operation, instance, and admission.retryTime; prefer completion/release or expiry over interruptionDeployment coordination
DeploymentLeaseRevokedStop deployment heartbeat and further DDL; check topologyGeneration, revocation reason, and post-DDL recovery requirementsDeployment coordination
Emergency failover started/completedPromote best candidate, taint old site, update DNSFailover
Reclone started/completed/failedRebuild replica from active primaryDivergent old primary recovery
Backup started/completed/failedCreate/update MysqlBackup Job and statusFailed backup
ArtifactCleanupFailed / ArtifactCleanupBlocked / ArtifactCleanupNothingFoundRetry or block artifact cleanup of a deleted MysqlBackup; the CR stays TerminatingArtifact cleanup
ArtifactCleanupStalledProducerStopDeleting an abandoned backup waits for its producing Job's pods to stop; one has not after 10 min. Once its node is confirmed down, force-delete the podArtifact cleanup
ArtifactCleanupDeferred / RetentionDeferredKeep a backup a verification is reading; informational unless it persists after the run endedBackup verification
Restore started/completed/failedGate bootstrap or restore workflowFailed restore
Verification started/completed/failedRestore backup into ephemeral MySQLBackup Verification
PITRArchiveNotReady with an Archive* reason (ArchiveLegacy, ArchiveForeign, ArchiveCopy, ArchiveDescriptorMissing, ArchiveEncryptionMismatch, ArchiveKeyMismatch, ArchiveVersionUnsupported, ArchiveStoreUnsupported)A site refused the archive's identity and uploads nothing; usually point PITR at a new prefix and take a full backupArchive identity
PITRArchiveUnsafeHistoryDetectedA site set its permanent history-integrity marker after an out-of-band change; undo it, new prefix plus full backup. The marker removes every restore target that needs that site's bytes, including earlier onesUnsafe history marker
PITRMysqlConfRefusedThe operator left a PITR-unsafe spec.mysqlConf option (filter, binlog_format, binlog_row_image) out of my.cnf; PITRMysqlConfAccepted=False names it. Remove the key, or disable PITR if the setting is requiredOperator-owned MySQL settings
PITRArchiveReissueRiskDetectedA site with divergent or quarantined archive rows was promoted; if it was recloned after a lossy failover, start a new prefix and take a full backupReissue risk after a reclone
PITRArchiveEncryptionChangeRefused / PITRArchiveKeyChangeRefusedA passphrase or encryption change on a profile whose archive is in use was refused; pods keep the accepted key snapshot and archiving continues. Revert the edit, or rotate by moving to a new prefixRotation
PITRArchiveKeyMaterialLostA Bound binding's key snapshot is missing or wrong; MySQL keeps running, the archiver fails closed. Restore the Secret from a backup of it, or set a profile to the original passphrase so the operator re-creates a missing one. Never delete a snapshot that is present: it may hold the only copy of the keyKey snapshots
PITRArchiveBindingRefusedA binding was refused (wrong key, foreign, copy, legacy, missing archive) or pre-binding Deployments (any site Deployment without a decodable render annotation) are deferred; the group holds its last accepted render, restores wait or failArchive encryption bindings
PITRArchiveBindingLimitReached16 entries that stay (Bound or used by a target) exist; release unused ones by idReleasing a binding
PITRArchiveBindingReleaseRefused / PITRArchiveBindingReleaseRejectedA release is waiting for its binding to be unused, or its annotation was malformed and removedReleasing a binding
PITRArchiveKeySourceRemoved / PITRArchiveKeySnapshotRecreated / PITRArchiveKeySnapshotReadFailed / BackupScheduleRefusedInformational: the profile's Secret is gone (snapshot still serves), a snapshot was re-created, an acceptance annotation is malformed (never used, never deleted), or a schedule targets a read-only profileArchive encryption bindings
PITRDivergentHistoryExcludedA restore or verification excluded transactions outside the target history; confirm the excluded set is the lost, errant or other-branch history you meant to dropTarget history and excludeGtids
PITROnHistoryTransactionsExcludedAn excluded transaction on the target history precedes replayed ones; the result is not certified for it, so check the affected rowsOn-history exclusions
PITRReplayTruncatedallowPartial restored to the archive head instead of the requested target; confirm the earlier point meets the recovery objectivePartial outcomes
PITR restore or verification refused (status.restore.reason or the Verified reason is a PITR* token)Read the token and its message: identity, dump, frontier, divergent history, gap, order or replayRestore refusals
PITRArchiveRefused (MysqlStandbyCluster)The DR standby refused the source archive; the dump is published without a PITR windowRestoring from a replicated archive
DNS update created/failedWrite DNSEndpoint for external-dnsDNS failover stuck
Split-brain or recovery pendingFence losers or wait for manual recoverySplit-brain recovery
Dragonfly promotion/sync/upgrade eventsPreserve or restore cache/session continuity while MySQL remains authoritativeDragonfly degraded
KeyringPhaseChanged / KeyringUnsealedInformational — a site is moving through the keyring lifecycleData-at-rest encryption
KeyringEscrowMissing / KeyringEscrowCorruptUrgent. A sealed site's only copy of its keys is gone or altered; do not restart that podData-at-rest encryption
KeyringNotReadOnly / KeyringDigestMismatchInvestigate the rendering — the site is not actually protectedData-at-rest encryption
KeyringEscrowTimedOutA site has not escrowed its keyring within keyring.escrowTimeout and is Failed; it stays unsealed and the operator keeps retrying. Check the sidecar's /keyring/status and its logsData-at-rest encryption
KeyringRotationRejected / EncryptionAdoptionRefusedFollow the supported rotation or adoption procedureData-at-rest encryption
KeyringPromotionSkipped / KeyringPromotionRefusedA rotating site is not a promotion target. If the group has no primary, finish the rotation (there is no cancel); then failover proceeds on the next pollData-at-rest encryption
LicenseInvalidNone required for availability. Check the token string and kid. Operator behavior is unchanged.Licensing
LicenseVerifiedInformationalLicensing

Minimum alert annotations

Each alert should include:

  • summary with the failing group and namespace.
  • description with immediate user impact.
  • runbook_url pointing to this docs site.
  • dashboard_url pointing to the relevant Grafana dashboard.

If an alert intentionally has no runbook or dashboard link, the change must include a specific operational rationale in the pull request. Do not use a bare N/A.