AIops-容器自动重启项目(一)

发布时间:2026/7/12 19:10:59
AIops-容器自动重启项目(一) 目录1.项目路径1.1.容器化监控1.2异常检测自动化1.3智能预测与根因分析1.4UI与完整闭环2.项目概述3.环境部署3.1前置环境3.2docker compose搭建prometheus3.3docker compose搭建Grafana3.4docker compose搭建cAdvisor4.配置告警4.1判断Prometheus是否正常4.2重启策略4.2.1重启脚本3.2.2容器化部署4.3.3grafana截图4.3修复报错-网络隔离5.主动检测脚本进阶1.容器存活检测与自动重启2.性能监控与告警3.自动化日志清理4. 每日监控报告5. 调度器管理6. 直接与 Prometheus 交互7. vs Grafana8.镜像构建8.镜像构建6.总结最后-结语1.项目路径1.1.容器化监控这一步是为了完成容器化监控和急促告警出发。路径为下三用 Docker Compose 启动 Prometheus Grafana cAdvisor。配置一个简单的阈值告警如CPU 80%触发Grafana Alert。告警通过 Webhook 发送到你的Python服务Python服务调用 Docker SDK 重启对应容器。1.2异常检测自动化在Python服务中增加异常检测模块用Prometheus查询过去1小时数据。实现“连续高CPU → 自动重启容器”策略先写日志再逐步增加自动执行。增加日志聚合查询Loki Grafana Explore。1.3智能预测与根因分析接入Prophet或LSTM模型预测未来30分钟负载提前发出“可能需要扩容”提示。简单根因分析当QPS下降时自动关联查询最近变更的容器镜像版本或配置变更。1.4UI与完整闭环构建独立控制台展示预测曲线、自动运维记录、策略配置界面。2.项目概述一个容器化的智能运维AIOps平台能自动监控业务和容器指标通过异常检测与时间序列预测模型自动执行运维动作如重启容器、扩容、告警形成“采集-分析-决策-执行”闭环。核心组成Prometheus监控 Loki日志 PythonAI分析 决策引擎 Docker SDK自动化执行 Grafana可视化全部跑在容器中。目标用AI替代人工盯盘缩短故障恢复时间MTTR提前预测资源瓶颈。3.环境部署3.1前置环境主要采用docker部署可用如下命令判断是否部署docker。docker compose version ##输出 Docker Compose version v2.32.4 查看docker_compose 版本3.2docker compose搭建prometheusversion: 3.8 services: prometheus: image: prom/prometheus:latest container_name: prometheus restart: unless-stopped ports: - 9090:9090 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus command: - --config.file/etc/prometheus/prometheus.yml - --storage.tsdb.path/prometheus - --web.enable-lifecycle #- storage.tsdb.retention.size50GB 防止磁盘爆 volumes: prometheus_data:global: scrape_interval: 15s scrape_configs: - job_name: prometheus static_configs: - targets: [localhost:9090]俩个文件放在同一目录下prometheus。docker compose up -d执行docker compose up -d 。成功抽取镜像并运行。查看镜像。保证存在docker images3.3docker compose搭建Grafana账号--- 密码---对数据的持久化有要求所以需要挂在外机上。必要时刻做备份。Prometheus 和 Grafana 在“数据重要性”和“默认行为”上不太一样。Prometheus 的主要数据是时序指标量大、周期短、通常可再采集。很多场景里 指标数据几天就够用 节点 / 服务一直在重启后可以重新抓取所以很多人部署 Prometheus 时不持久化接受“重启即丢历史数据”。换句话说Prometheus 的数据是“可再生成的”。Grafana 的数据更偏向“配置与资产”。Grafana 容器内/var/lib/grafana里主要存的是仪表盘Dashboards数据源配置用户 / 权限插件grafana.dbSQLite 数据库这些内容是手工建好的有业务价值不可自动恢复如果你不挂载持久化容器重启 / 重建 →仪表盘全丢。插件消失。账号配置清零换句话说Grafana 的数据是“不可再生成的”。Prometheus数据可再抓 → 可选持久化。Grafana配置是人做的 → 强烈建议持久化所以在教程里Prometheus 经常“裸跑”。Grafana 通常会把/var/lib/grafana挂出来。version: 3.8 services: grafana: image: grafana/grafana-oss:latest container_name: grafana restart: unless-stopped ports: - 3000:3000 volumes: - grafana-data:/var/lib/grafana environment: - GF_SECURITY_ADMIN_USERadmin - GF_SECURITY_ADMIN_PASSWORDadmin volumes: grafana-data:执行docker compose up -d 。成功抽取镜像并运行。运行镜像。端口放开3000。账号密码默认---。若在 docker-compose 或 docker run 中设置了GF_SECURITY_ADMIN_USER和GF_SECURITY_ADMIN_PASSWORD则以你设置的值为准。docker ps -a #16e9dbeae285 grafana/grafana-oss:latest /run.sh ----3.4docker compose搭建cAdvisor拉取镜像docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/gcr.io/cadvisor/cadvisor:v0.49.1运行镜像docker run -d \ --namecadvisor \ --privileged \ --device/dev/kmsg \ -p 8080:8080 \ -v /:/rootfs:ro \ -v /var/run:/var/run:ro \ -v /sys:/sys:ro \ -v /var/lib/docker/:/var/lib/docker:ro \ -v /dev/disk/:/dev/disk:ro \ swr.cn-north-4.myhuaweicloud.com/ddn-k8s/gcr.io/cadvisor/cadvisor:v0.49.1运行镜像至此三个应用全部搭建。4.配置告警4.1判断Prometheus是否正常配置一个简单的阈值告警如CPU 80%触发Grafana Alert在 Prometheus UIhttp://prometheus-ip:9090执行up{jobcadvisor} #为1则正常4.2重启策略4.2.1重启脚本负责收到请求后重启容器。需要在Grafana配置test.py:from fastapi import FastAPI, Request import docker import logging app FastAPI() docker_client docker.DockerClient(base_urlunix:///var/run/docker.sock) logging.basicConfig(levellogging.INFO) app.post(/webhook) async def handle_alert(request: Request): alert_data await request.json() logging.info(f收到告警: {alert_data}) # [MODIFIED] 兼容两种格式简单测试 {labels: {container: ...}} 和 Grafana 真实格式 {alerts: [{labels: {container: ...}}]} container_name None # 方式1顶层 labels如 curl 测试 if labels in alert_data and container in alert_data.get(labels, {}): container_name alert_data[labels][container] # 方式2Grafana/Alertmanager 标准格式取第一个告警中的 container 标签 elif alerts in alert_data and alert_data[alerts]: container_name alert_data[alerts][0].get(labels, {}).get(container) if not container_name: logging.warning(告警中没有 container 标签跳过) return {status: ignored, reason: no container label} try: container docker_client.containers.get(container_name) container.restart() logging.info(f✅ 已重启容器: {container_name}) return {status: restarted, container: container_name} except Exception as e: logging.error(f重启失败: {e}) return {status: error, message: str(e)} if __name__ __main__: import uvicorn uvicorn.run(app, host0.0.0.0, port8000)作用这段代码实现了一个 基于告警触发的 Docker 容器自动重启服务。当接收到来自 Grafana或其他兼容 Webhook 的监控系统的 POST 请求时解析告警中的容器名称标签然后调用 Docker API 重启对应的容器从而实现业务层面的“自愈”。3.2.2容器化部署根据脚本创建镜像也就是dockerfile中的test.py。创建dockerfile:# 使用官方 Python 3.12 slim 镜像体积小 FROM python:3.12-slim # 设置工作目录 WORKDIR /app # 安装系统依赖如果需要目前无需额外系统包 # 但为了确保虚拟环境工具可用python3-venv 已经存在 # 创建虚拟环境在 /app/venv RUN python -m venv /app/venv # 激活虚拟环境并安装 Python 依赖 # 使用虚拟环境的 pip ENV PATH/app/venv/bin:$PATH # 复制 requirements.txt先复制依赖文件利用 Docker 缓存 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制脚本 COPY test.py . # 暴露端口FastAPI 默认 8000 EXPOSE 8000 # 运行服务使用虚拟环境中的 python CMD [python, test.py]创建镜像#创建镜像当前目录下 docker build -t webhook-restarter .运行镜像创建容器#运行容器 docker run -d \ --name webhook-restarter \ -p 8000:8000 \ -v /var/run/docker.sock:/var/run/docker.sock \ webhook-restarter4.3.3grafana截图模糊处为ip及其脚本开启的端口。由于是开放端口所以后续在使用时在保持容器服务wbhook的情况下将端口隐藏。4.3修复报错-网络隔离rootVM-16-5-ubuntu:~/prometheus# docker inspect prometheus | grep -A5 Networks Networks: { prometheus_default: { IPAMConfig: null, Links: null, Aliases: [ prometheus, rootVM-16-5-ubuntu:~/prometheus# docker inspect cadvisor | grep -A5 Networks Networks: { bridge: { IPAMConfig: null, Links: null, Aliases: null, MacAddress: 02:42:ac:11:00:02,网络隔离问题。用docker run起的 cadvisor。用docker compose起的 prometheus。不在同一个 Docker 网络修复方法docker network connect prometheus_default cadvisor5.主动检测脚本进阶这是test脚本的进阶使用涉及删除使用时须审慎使用。test2.py#!/root/myenv/bin/python import asyncio import logging import subprocess from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.triggers.interval import IntervalTrigger from apscheduler.triggers.cron import CronTrigger import aiohttp import requests PROMETHEUS_URL http://124.220.56.48:9090 NGINX_CONTAINER_NAME nginx-web ALERT_WEBHOOK LOG_FILE auto_monitor.log logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, handlers[logging.FileHandler(LOG_FILE), logging.StreamHandler()] ) logger logging.getLogger(__name__) async def query_prometheus(metric: str): url f{PROMETHEUS_URL}/api/v1/query params {query: metric} async with aiohttp.ClientSession() as session: async with session.get(url, paramsparams) as resp: if resp.status ! 200: logger.error(f查询失败: {await resp.text()}) return None data await resp.json() if data[status] ! success: return None result {} for item in data[data][result]: labels item[metric] value float(item[value][1]) result[frozenset(labels.items())] value return result async def send_alert(msg: str, levelwarning): logger.warning(f告警[{level}]: {msg}) if ALERT_WEBHOOK: try: requests.post(ALERT_WEBHOOK, json{text: msg}, timeout3) except: pass def docker_restart(container_name): try: subprocess.run([docker, restart, container_name], checkTrue, capture_outputTrue) logger.info(f✅ 已自动重启容器: {container_name}) return True except subprocess.CalledProcessError as e: logger.error(f❌ 重启失败: {e.stderr.decode()}) return False def clean_old_logs(days7): try: subprocess.run( [docker, exec, NGINX_CONTAINER_NAME, find, /var/log/nginx, -name, *.log, -mtime, f{days}, -delete], checkTrue ) logger.info(f️ 已清理超过 {days} 天的日志) except Exception as e: logger.debug(f日志清理未执行: {e}) async def has_container_metrics(container_name): 通过查询cadvisor指标判断容器是否存在 queries [ fcontainer_cpu_usage_seconds_total{{name{container_name}}}, fcontainer_memory_working_set_bytes{{name{container_name}}} ] for q in queries: res await query_prometheus(q) if res: logger.debug(f找到容器指标: {q}) return True return False async def task_health_check(): logger.debug(执行健康检查...) exists await has_container_metrics(NGINX_CONTAINER_NAME) if not exists: logger.warning(f容器 {NGINX_CONTAINER_NAME} 无监控指标可能已停止尝试重启) await send_alert(f⚠️ nginx容器 {NGINX_CONTAINER_NAME} 未运行立即自动重启, levelcritical) docker_restart(NGINX_CONTAINER_NAME) else: logger.debug(nginx容器运行正常) async def task_performance_monitor(): cpu_val 0.0 res await query_prometheus(frate(container_cpu_usage_seconds_total{{name{NGINX_CONTAINER_NAME}}}[30s])) if res: cpu_val list(res.values())[0] mem_mb 0 res await query_prometheus(fcontainer_memory_working_set_bytes{{name{NGINX_CONTAINER_NAME}}}) if res: mem_mb list(res.values())[0] / (1024 * 1024) logger.info(f CPU: {cpu_val*100:.1f}% | 内存: {mem_mb:.0f} MB) if cpu_val 0.8: await send_alert(f CPU 使用率过高: {cpu_val*100:.1f}%, levelwarning) if mem_mb 500: await send_alert(f 内存使用过高: {mem_mb:.0f} MB, levelwarning) async def task_log_cleanup(): logger.info(开始清理旧日志...) clean_old_logs(7) async def task_daily_report(): logger.info( 生成每日监控报告...) await send_alert(【日报】nginx-web 今日监控无重大故障, levelinfo) def setup_scheduler(): scheduler AsyncIOScheduler() scheduler.add_job(task_health_check, triggerIntervalTrigger(seconds10), idhealth_check) scheduler.add_job(task_performance_monitor, triggerIntervalTrigger(seconds30), idperf_monitor) scheduler.add_job(task_log_cleanup, triggerCronTrigger(hour3, minute0), idlog_cleanup) scheduler.add_job(task_daily_report, triggerCronTrigger(hour18, minute0), iddaily_report) return scheduler async def main(): logger.info( nginx-web 智能监控脚本启动 (基于 name 标签)) scheduler setup_scheduler() scheduler.start() try: await asyncio.Event().wait() except KeyboardInterrupt: logger.info( 关闭调度器...) scheduler.shutdown() logger.info(脚本已退出) if __name__ __main__: asyncio.run(main()) EOF这串脚本的功能用1.容器存活检测与自动重启每隔10 秒查询 Prometheus 中container_cpu_usage_seconds_total{namenginx-web}指标。如果指标不存在说明容器已停止或被删除自动执行docker restart nginx-web并发送告警消息。2.性能监控与告警每隔30 秒采集一次 CPU 使用率rate函数和内存使用量container_memory_working_set_bytes。当 CPU 80% 或内存 500MB 时触发告警可发到钉钉/企微目前仅打日志。帮助提前发现资源瓶颈。3.自动化日志清理每天凌晨3:00执行docker exec nginx-web find /var/log/nginx -name *.log -mtime 7 -delete删除超过 7 天的 nginx 日志。避免磁盘被日志填满。4.每日监控报告每天下午18:00发送一条通知内容为“nginx-web 今日监控无重大故障”可替换为真实统计。让你每天定时了解服务状态无需手动查。在终端输出内容。5.调度器管理所有任务都由AsyncIOScheduler管理支持动态添加/删除/修改任务。即使脚本运行几个月也不会中断除非进程退出。6.直接与 Prometheus 交互绕过aiopromql因为腾讯云源没有该包用aiohttp直接调用 Prometheus HTTP API。查询语句已针对你的环境调整使用name标签。7. vs Grafana8.镜像构建场景Grafana这个脚本看图表✅ 很棒❌ 不提供自动重启容器❌ 做不到✅ 自动做发送钉钉告警✅ Alertmanager 可做✅ 内置发告警自动清理日志❌ 做不到✅ 定时清理定时生成报告✅ 通过报表插件配置复杂✅ 几行代码搞定修改阈值/频率需改规则文件改 Python 变量即可8.镜像构建FROM python:3.9-slim ENV TZAsia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ /etc/timezone # 更换 apt 源为腾讯云也可用阿里云 mirrors.aliyun.com RUN sed -i s/deb.debian.org/mirrors.tencentyun.com/g /etc/apt/sources.list.d/debian.sources RUN apt-get update apt-get install -y --no-install-recommends \ docker.io \ rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt . # 使用国内 pip 源加速 RUN pip install --no-cache-dir -r requirements.txt -i https://mirrors.tencentyun.com/pypi/simple COPY test2.py . RUN mkdir -p /app/logs CMD [python, -u, test2.py]镜像dockerfile文件构建:docker build -t nginx-monitor .运行镜像docker run -d \ --name nginx-monitor \ --restart unless-stopped \ -v /var/run/docker.sock:/var/run/docker.sock \ -v $(pwd)/logs:/app/logs \ --network host \ -e TZAsia/Shanghai \ nginx-monitor:latest查看日志docker logs -f nginx-monitor关键词 ---successfully---容器内测试是否联通#进入容器 docker exec -it nginx-monitor /bin/bash #执行脚本 python -c import asyncio import aiohttp async def test(): async with aiohttp.ClientSession() as sess: q container_cpu_usage_seconds_total{name\nginx-web\} async with sess.get(http://124.220.56.48:9090/api/v1/query, params{query: q}) as resp: data await resp.json() print(data) asyncio.run(test()) 6.总结预期目的一个容器化的智能运维AIOps平台能自动监控业务和容器指标通过异常检测与时间序列预测模型自动执行运维动作如重启容器、扩容、告警形成“采集-分析-决策-执行”闭环。· 达成目的1.已经完成了部署2.容器报警3.重启策略后续计划将报错日志写入Loki 实现日志聚合与异常关联。并完成轻量级异常检测模型的构建。最后-结语感谢观看欢迎指教。如写的不好请嘴下留情。最后美女镇楼鹿八岁baby