Selva-git-22/Advanced-Observability-and-Incident-Response-platform

GitHub: Selva-git-22/Advanced-Observability-and-Incident-Response-platform

该平台将 Prometheus 指标、OpenSearch 日志和 Jaeger 分布式追踪统一集成,帮助运维团队快速定位跨服务故障并支持自动修复。

Stars: 0 | Forks: 0

# 可观测性与事件响应平台 ![Prometheus](https://img.shields.io/badge/Prometheus-E6522C?style=flat&logo=prometheus&logoColor=white) ![Grafana](https://img.shields.io/badge/Grafana-F46800?style=flat&logo=grafana&logoColor=white) ![OpenSearch](https://img.shields.io/badge/OpenSearch-005EB8?style=flat&logo=opensearch&logoColor=white) ![Jaeger](https://img.shields.io/badge/Jaeger-66CFE3?style=flat&logo=jaeger&logoColor=white) ![AWS](https://img.shields.io/badge/AWS-232F3E?style=flat&logo=amazonaws&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-2496ED?style=flat&logo=docker&logoColor=white) 我们总是被打个措手不及。服务会降级,用户会抱怨,而我们在每次事件发生的前 40 分钟里,只能试图弄清楚问题到底出在*哪里*——在单个 EC2 实例上跟踪日志,猜测哪个服务出了问题,手动在三个不同的工具间关联时间戳。 所以我构建了这个平台。目标不是使用每一个花哨的工具,而是将 metrics、logs 和 traces 集中到一个地方,让你在凌晨 2 点系统出问题时能够真正快速地在它们之间切换。 ## 问题所在 AWS 上的三个微服务(Node.js API、Python backend、Go worker)。没有集中式日志记录。只有在 CPU 达到 100% 时才触发的告警——而此时损害已经造成。没有分布式追踪,因此当请求失败时,我们根本不知道它是死在 API、backend,还是两者之间的某个地方。 对于任何非简单的事件,平均解决时间都徘徊在 **45–60 分钟**左右。这段时间大部分都花在了排查上,而不是修复上。 ## 架构 | 组件 | 角色 | |---|---| | **Prometheus** | 抓取并存储时间序列 metrics | | **Grafana** | 用于查看 metrics、logs 和 traces 的统一仪表盘 | | **Fluent Bit** | 从所有服务收集并发送 logs | | **OpenSearch** | 集中式日志存储和搜索 | | **Jaeger** | 通过 OpenTelemetry 实现跨服务分布式追踪 | | **Alertmanager** | 将告警路由到 Slack 和 AWS SNS | | **AWS Lambda** | 针对已知故障模式的自动修复 | 部署在 **AWS EC2 (t3.xlarge)** 上,Prometheus metrics 在本地保留 30 天,并通过 Thanos 发送到 S3 进行长期存储。 ## 快速开始 ### 前置条件 - Docker `>= 24.x` 和 Docker Compose `>= 2.x` - 已配置 AWS CLI (`aws configure`) - 最少 4 vCPU / 16 GB RAM ### 克隆仓库 ``` git clone https://github.com/your-username/observability-platform.git cd observability-platform ``` ### 启动核心栈 ``` docker compose up -d ``` ### 添加日志和追踪 ``` docker compose up -d opensearch opensearch-dashboards fluent-bit jaeger ``` ### 验证一切是否运行正常 ``` docker compose ps ``` ## 服务 URL | 服务 | URL | 凭据 | |---|---|---| | Grafana | `http://localhost:3000` | `admin / admin123` | | Prometheus | `http://localhost:9090` | — | | Alertmanager | `http://localhost:9093` | — | | Jaeger UI | `http://localhost:16686` | — | | OpenSearch Dashboards | `http://localhost:5601` | — | | OpenSearch API | `http://localhost:9200` | — | | Node Exporter | `http://localhost:9100/metrics` | — | ## 📊 Metrics — Prometheus + Grafana Prometheus 每 `15s` 抓取一次应用的 `/metrics` endpoint。Node Exporter 负责处理主机级别的 metrics —— CPU、内存、磁盘、网络。 **CPU 使用率 %** ``` 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) ``` **p95 响应延迟** ``` histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) ``` **错误率 %** ``` sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100 ``` **SLO 消耗率** - 高于 `1` 的值意味着错误预算将在月底前耗尽 ``` (1 - job:http_success_rate:ratio_rate1h) / (1 - 0.999) ``` **可导入 Grafana 的社区仪表盘:** | 仪表盘 | ID | |---|---| | Node Exporter Full | `1860` | | Prometheus 2.0 Overview | `3662` | ## 🪵 Logging - Fluent Bit + OpenSearch Fluent Bit 会追踪 Docker 容器日志和应用日志文件,使用 `hostname` 和 `environment` 元数据丰富它们,并发送到 OpenSearch。日志被索引到每日索引 (`app-logs-YYYY.MM.DD`) 中,并通过 ISM 生命周期策略在 **30 天**后自动删除。 `fluent-bit/fluent-bit.conf` 中的核心输出块: ``` [OUTPUT] Name opensearch Match * Host opensearch Port 9200 Logstash_Format On Logstash_Prefix app-logs Retry_Limit False ``` ## 分布式追踪 - Jaeger + OpenTelemetry 只需埋点一次,即可获取所有操作的 traces —— HTTP、Express、数据库调用、gRPC。 **Node.js** ``` npm install @opentelemetry/sdk-node \ @opentelemetry/auto-instrumentations-node \ @opentelemetry/exporter-trace-otlp-http ``` **Python** ``` pip install opentelemetry-sdk opentelemetry-instrumentation ``` ### 带来最大改变的部分 将 trace ID 注入到每一行日志中。当你在 OpenSearch 中发现错误时,点击 `trace_id` 就会直接跳转到 Jaeger,查看跨所有服务的完整请求旅程。在此之前,跨服务故障意味着手动关联时间戳和猜测。有了它之后,通常只需 **不到 2 分钟**。 ``` class TraceIdFilter(logging.Filter): def filter(self, record): span = trace.get_current_span() ctx = span.get_span_context() record.trace_id = format(ctx.trace_id, '032x') if ctx.is_valid else 'no-trace' record.span_id = format(ctx.span_id, '016x') if ctx.is_valid else 'no-span' return True ``` ## 告警 - Alertmanager 我们旧告警系统的问题不在于工具本身——告警触发得太晚,而且会发送给所有人,所以它们实际上被忽略了。我们围绕三个原则重建了它: - **针对症状告警,而不是原因。** 高错误率很重要。高 CPU 可能并不重要。 - **路由给正确的人。** DB 告警 → DBA 渠道。基础设施 → 运维。不要发给所有人。 - **在告警中提供上下文。** 摘要、受影响的服务、runbook 链接——值班工程师不应该到处去翻找信息。 `alertmanager/alertmanager.yml` 中的路由配置: ``` route: routes: - match: severity: critical receiver: slack-critical # Immediate Slack + PagerDuty - match: service: database receiver: dba-team # DBA channel only - match_re: alertname: ^(NodeDown|DiskFull|HighCPU)$ receiver: ops-team ``` ### SLO 消耗率告警 不是在突破错误预算后才告警,而是当我们的消耗速度足以在 **5 天**内耗尽预算时,消耗率告警就会触发。这就是主动与被动的区别。 ``` - alert: SLOBudgetBurnRateHigh expr: | (1 - job:http_success_rate:ratio_rate1h) > (1 - 0.999) * 14.4 for: 2m labels: severity: critical ``` ## 自动修复 — AWS Lambda 两个 Lambda 函数会自动处理最常见的故障模式: - **`auto_remediate_ecs.py`** - 在触发 `ServiceDown` 告警时强制进行新的 ECS 部署。无论结果如何都会通知 Slack;如果修复本身失败,则升级交由人工处理。 - **`auto_scale_ec2.py`** - 在 CPU 过高告警时向 ASG 添加两个实例,并在问题解决时自动缩容。 这些涵盖了大约 **30% 的事件**。并非所有问题都能自动修复,但那些能够自动修复的问题不应该需要叫醒某个人。 ### 部署 ``` cd lambda zip auto_remediate_ecs.zip auto_remediate_ecs.py ``` ``` aws lambda create-function \ --function-name auto-remediate-ecs \ --runtime python3.11 \ --role arn:aws:iam::${ACCOUNT_ID}:role/lambda-remediation-role \ --handler auto_remediate_ecs.lambda_handler \ --zip-file fileb://auto_remediate_ecs.zip \ --timeout 60 ``` ``` aws sns subscribe \ --topic-arn arn:aws:sns:us-east-1:${ACCOUNT_ID}:ops-alerts \ --protocol lambda \ --notification-endpoint ${LAMBDA_ARN} ``` ## 实用命令 无需重启即可重载 Prometheus 配置: ``` curl -X POST http://localhost:9090/-/reload ``` 端到端测试完整的告警流水线: ``` curl -X POST http://localhost:9093/api/v1/alerts \ -H "Content-Type: application/json" \ -d '[{ "labels": { "alertname": "TestAlert", "severity": "warning" }, "annotations": { "summary": "Pipeline check — ignore this" } }]' ``` 检查所有抓取目标是否健康: ``` curl -s http://localhost:9090/api/v1/targets | python3 -m json.tool ``` 追踪任意服务的实时日志: ``` docker compose logs -f prometheus docker compose logs -f fluent-bit docker compose logs -f jaeger ``` ## 仓库结构 ``` observability-platform/ ├── docker-compose.yml ├── prometheus/ │ ├── prometheus.yml │ └── rules/ │ ├── alerts.yml # Infrastructure + app + SLO alerts │ └── slo.yml # Error budget recording rules ├── grafana/ │ └── provisioning/ │ ├── datasources/ # Prometheus, OpenSearch, Jaeger auto-wired │ └── dashboards/ ├── alertmanager/ │ └── alertmanager.yml # Routing + Slack + SNS config ├── fluent-bit/ │ ├── fluent-bit.conf │ └── parsers.conf ├── lambda/ │ ├── auto_remediate_ecs.py │ └── auto_scale_ec2.py ├── thanos/ │ └── objstore.yml # S3 long-term metrics storage └── runbooks/ └── high-error-rate.md ``` ## 正式上线前 - 更改 Grafana 管理员密码 (`GF_SECURITY_ADMIN_PASSWORD`) - 启用 OpenSearch TLS —— `plugins.security.disabled=true` 仅适用于本地开发 - 将你的 Slack webhook URL 添加到 `alertmanager/alertmanager.yml` - 在生产环境中将 Jaeger `badger` 存储替换为 OpenSearch (`SPAN_STORAGE_TYPE=elasticsearch`) - 将 Lambda IAM 角色收紧为最小权限 - 更新 `prometheus/rules/slo.yml` 中的 SLO 目标,以匹配实际的承诺 ## 技术栈版本 | 工具 | 版本 | |---|---| | Prometheus | `2.47.0` | | Grafana | `10.2.0` | | Alertmanager | `0.26.0` | | OpenSearch | `2.11.0` | | Fluent Bit | `2.2.0` | | Jaeger | `1.51` | | Node Exporter | `1.7.0` | ## 📄 许可证 MIT
标签:API集成, Grafana, 可观测性, 用户代理, 自定义请求头, 请求拦截, 运维监控, 链路追踪