运维自动化
EnerOS 内置完整的运维自动化能力,覆盖 On-call 排班、Runbook 自动执行、自动扩缩容、备份恢复等场景,减少对人工运维的依赖,提升电力生产环境的稳定性。运维自动化由 eneros-ops crate 提供,与告警系统、健康检查、安全网关深度集成。
自动化架构
┌──────────────────────────────────────────────────────────┐
│ 监控与告警源 │
│ Prometheus / Health Probe / IDS / SLO 违反 │
└──────────────────────┬───────────────────────────────────┘
│
┌──────────────────────▼───────────────────────────────────┐
│ 自动化决策层 │
│ Alert Router ─▶ Runbook Engine ─▶ Approval Gate │
│ │ │
│ ┌────────┴────────┐ │
│ ▼ ▼ │
│ Action Executor On-call Notifier │
└──────────────────────┬───────────────────────────────────┘
│
┌──────────────────────▼───────────────────────────────────┐
│ 执行与回滚层 │
│ Service Restart / Scale Up-Down / Backup / Restore │
│ 所有动作落入 WORM 审计链 │
└──────────────────────────────────────────────────────────┘
| 模块 | 职责 | 触发方式 |
|---|---|---|
| On-call Schedule | 排班与升级 | 告警触发 |
| Runbook Engine | 自动化手册执行 | 告警 / 定时 |
| Autoscaler | 资源扩缩容 | 指标阈值 |
| Backup Manager | 备份与恢复 | 定时 / 手动 |
| Health Monitor | 健康探测与自愈 | 周期 / 事件 |
| Report Scheduler | 定时报表 | 定时 |
On-call 管理
支持多团队、多级别的排班与升级策略:
use eneros_ops::oncall::{OncallSchedule, Rotation, EscalationPolicy, Day, Time};
use std::time::Duration;
let schedule = OncallSchedule::new()
.rotation(Rotation::weekly()
.members(vec!["alice", "bob", "carol"])
.handoff(Day::Monday, Time::from_hms(9, 0, 0)))
.escalation(EscalationPolicy::new()
.level(1, Duration::from_secs(5 * 60)) // 5 分钟无响应 → L2
.level(2, Duration::from_secs(15 * 60)) // 15 分钟 → L3
.level(3, Duration::from_secs(30 * 60))) // 30 分钟 → L4
.timezone("Asia/Shanghai")
.follow_the_sun(true) // 跟随太阳模式
.override(OncallOverride::new()
.user("dave")
.start("2026-07-10T09:00:00+08:00")
.end("2026-07-15T18:00:00+08:00"));
schedule.activate().await?;
Escalation 级别说明
| 级别 | 触发条件 | 通知渠道 | 响应目标 |
|---|---|---|---|
| L1 | 告警产生 | 钉钉 / 企业微信 | 5 分钟 |
| L2 | L1 无响应 5 分钟 | 短信 + 钉钉 | 15 分钟 |
| L3 | L2 无响应 15 分钟 | 电话呼叫 | 30 分钟 |
| L4 | L3 无响应 30 分钟 | 电话 + 邮件主管 | 60 分钟 |
Runbook 自动化
将运维手册转化为可执行的 Runbook,告警触发时自动执行。Runbook 支持条件分支、并行步骤、人工审批节点。
use eneros_ops::runbook::{Runbook, Step, Trigger, Condition, Action};
let runbook = Runbook::new("high-cpu-agent")
.trigger(Trigger::alert("agent_cpu_90"))
.step(Step::check(health_check, "服务健康检查"))
.step(Step::collect_diagnostic()
.snapshot(Snapshot::heap_profile())
.snapshot(Snapshot::thread_dump())
.snapshot(Snapshot::metrics_window(Duration::from_secs(300))))
.step(Step::conditional(
Condition::cpu_high_for(Duration::from_secs(60)),
Step::sequence(vec![
Step::restart_service("agent-runtime"),
Step::wait(Duration::from_secs(30)),
Step::verify(ServiceHealth::healthy()),
]),
))
.step(Step::approval(
"执行紧急扩容需主管审批",
Duration::from_secs(300),
Approver::role("ops_lead"),
))
.step(Step::notify_oncall()
.channel(NotifyChannel::DingTalk));
runbook.register(&ops).await?;
Runbook 库
| Runbook | 触发条件 | 动作链 | 预计耗时 |
|---|---|---|---|
| high-cpu | CPU > 90% 持续 5min | 诊断 → 重启 → 验证 | 2 分钟 |
| disk-full | 磁盘 > 85% | 清理日志 → 告警 | 30 秒 |
| agent-crash | Agent 进程退出 | 重启 → 通知 → 收集 core dump | 5 秒 |
| tsdb-slow | 查询 P99 > 1s | 重建索引 → 切换只读副本 | 5 分钟 |
| cert-expire | 证书 30 天到期 | 续签 → 重载 → 验证 | 30 秒 |
| memory-leak | 内存持续增长 > 1h | 转储 → 重启 → 通知 | 1 分钟 |
| tls-handshake-fail | mTLS 失败率 > 5% | 检查 CA → 重载证书 | 1 分钟 |
| replica-lag | 副本延迟 > 10s | 重置复制 → 通知 | 2 分钟 |
Runbook 配置参数
| 参数 | 默认值 | 说明 |
|---|---|---|
| timeout | 300s | 单 Runbook 执行超时 |
| step_timeout | 60s | 单步执行超时 |
| retry | 3 次 | 失败重试次数 |
| parallel_steps | 4 | 最大并行步骤 |
| require_approval | false | 是否需要人工审批 |
| collect_diagnostic | true | 自动收集诊断信息 |
自动扩缩容
基于多维度指标自动调整资源,支持 Predictive(预测式)与 Reactive(响应式)两种策略:
use eneros_ops::autoscale::{Autoscaler, Rule, Strategy};
let scaler = Autoscaler::new()
.target("agent-runtime")
.min_instances(2)
.max_instances(10)
.strategy(Strategy::reactive())
.rule(Rule::cpu(70, 90)) // CPU 70% 扩容,90% 紧急扩容
.rule(Rule::memory(80, 95))
.rule(Rule::queue_depth(1000, 5000))
.rule(Rule::custom("inflight_requests", 500, 2000))
.cooldown(Duration::from_secs(300))
.scale_up_step(2) // 每次扩容 2 个实例
.scale_down_step(1)
.grace_period(Duration::from_secs(60));
scaler.activate().await?;
预测式扩缩容
基于历史负载预测提前扩容:
use eneros_ops::autoscale::predictive::{PredictiveScaler, ForecastModel};
let predictive = PredictiveScaler::new()
.model(ForecastModel::prophet()
.history(Duration::from_secs(86400 * 30)) // 30 天历史
.horizon(Duration::from_secs(3600)) // 1 小时预测
.confidence(0.95))
.lookahead(Duration::from_secs(600)) // 提前 10 分钟
.min_confidence(0.80);
predictive.activate().await?;
扩缩容规则参数
| 规则 | 扩容阈值 | 缩容阈值 | 评估窗口 |
|---|---|---|---|
| cpu | > 70% | < 30% | 5 分钟 |
| memory | > 80% | < 40% | 5 分钟 |
| queue_depth | > 1000 | < 200 | 1 分钟 |
| latency_p99 | > 500ms | < 100ms | 5 分钟 |
| inflight_requests | > 500 | < 100 | 1 分钟 |
实时域不参与自动扩缩容
实时域资源在部署时静态绑定,避免动态调度破坏确定性。扩缩容只针对通用域。实时域扩容需手动审批后执行。
备份与恢复
支持全量、增量与持续备份,所有备份加密后写入对象存储:
use eneros_ops::backup::{BackupManager, BackupSpec, BackupTarget, KeyId, Verification};
let backup = BackupManager::new()
.schedule("daily-full", BackupSpec::full()
.target(BackupTarget::S3("s3://eneros-backup"))
.encryption(KeyId::from("backup-key"))
.compression(Compression::Zstd { level: 9 })
.retention(Duration::from_secs(86400 * 30))
.verify(Verification::checksum()))
.schedule("5min-incremental", BackupSpec::incremental()
.target(BackupTarget::S3("s3://eneros-backup"))
.retention(Duration::from_secs(86400 * 7)))
.schedule("continuous-wal", BackupSpec::continuous_wal()
.target(BackupTarget::S3("s3://eneros-backup/wal"))
.retention(Duration::from_secs(86400)));
backup.start().await?;
恢复操作
use eneros_ops::backup::{Restore, RestoreTarget, RestorePoint};
let restore = Restore::new()
.from(RestorePoint::latest())
.to(RestoreTarget::NewCluster("staging-restore"))
.include(vec!["topology", "timeseries", "agents"])
.verify(Verification::data_integrity())
.verify(Verification::service_health());
restore.execute().await?;
恢复演练
定期自动执行恢复演练,验证备份有效性:
backup.drill()
.restore_to("staging")
.verify(Verification::data_integrity())
.verify(Verification::service_health())
.verify(Verification::slo_met(99.9))
.schedule(Duration::from_secs(86400 * 7)) // 每周
.notify_on_failure(vec!["ops@grid.com"])
.run().await?;
备份策略对比
| 策略 | 频率 | RPO | 存储 | 适用 |
|---|---|---|---|---|
| 全量 | 每日 | 24h | 高 | 长期归档 |
| 增量 | 每 5 分钟 | 5min | 低 | 日常恢复 |
| WAL 持续 | 实时 | ≈0 | 中 | 灾难恢复 |
| 跨区域复制 | 实时 | ≈0 | 高 | DR 场景 |
健康检查与自愈
多维度健康探测与自动自愈:
use eneros_ops::health::{HealthMonitor, Probe, ProbeType};
let monitor = HealthMonitor::new()
.probe(Probe::http("agent-runtime", "/health", 200)
.interval(Duration::from_secs(10))
.timeout(Duration::from_secs(2))
.failure_threshold(3))
.probe(Probe::tcp("realtime-domain", 6080)
.interval(Duration::from_secs(5)))
.probe(Probe::custom("tsdb", check_tsdb_health)
.interval(Duration::from_secs(30)))
.probe(Probe::grpc("kernel", "/grpc.health.v1.Health/Check")
.interval(Duration::from_secs(10)))
.on_unhealthy(|service, status| async move {
match status.failures {
1..=2 => SelfHealing::restart(service).await,
3..=5 => SelfHealing::replace(service).await,
_ => SelfHealing::escalate(service).await,
}
});
monitor.start().await?;
自愈动作矩阵
| 失败次数 | 动作 | 影响 |
|---|---|---|
| 1-2 | 重启服务 | 短暂中断 |
| 3-5 | 替换实例 | 流量切换 |
| 6+ | 上报人工 | 进入维护模式 |
性能指标
| 操作 | 延迟 | 备注 |
|---|---|---|
| Runbook 触发到执行 | < 1s | 含告警路由 |
| 自动扩容决策 | < 5s | 含指标聚合 |
| 增量备份(1GB 数据) | < 30s | 压缩加密后 |
| 全量恢复(100GB) | < 10min | 含验证 |
| 自愈重启 Agent | < 3s | 含健康检查 |
| On-call 通知送达 | < 5s | 钉钉 / 短信 |
| 健康检查执行 | < 100ms | 单 Probe |
| 恢复演练启动 | < 30s | 含资源申请 |
通知渠道
| 渠道 | 适用 | 延迟 | 重试 |
|---|---|---|---|
| 邮件 | 非紧急 | 30s | 3 次 |
| 短信 | 高优先级 | 5s | 3 次 |
| 钉钉 / 企业微信 | 团队协同 | 2s | 5 次 |
| Webhook | 集成外部系统 | 1s | 5 次 |
| 电话呼叫 | L3 级告警 | 10s | 直到接听 |
| Slack | 国际团队 | 2s | 3 次 |
与其他能力的关系
- 高可用增强:运维自动化是高可用保障的执行层,详见 高可用增强
- 多租户隔离:运维动作按租户隔离,详见 多租户与隔离
- 安全守卫:运维命令也过安全网关,详见 安全守卫
- 零信任:所有运维动作落入审计链,详见 零信任与安全增强
- AIOps:告警聚类与根因分析驱动 Runbook 触发