首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python 全栈运维:用最少的代码,打通采集到展示的闭环

Python 全栈运维:用最少的代码,打通采集到展示的闭环

原创
作者头像
资源shanxueit.com
发布于 2026-10-04 15:06:13
发布于 2026-10-04 15:06:13
440
举报

一、为什么运维需要"全栈"

传统运维脚本的宿命往往是:写完一个 check_disk.py,再写一个 check_mem.py,然后用 crontab 串起来,输出一堆 txt,最后靠人肉登录服务器去翻。问题不在于脚本写得不好,而在于链路是断的——采集、存储、调度、展示各在一处,没有形成闭环。

"全栈运维"不是要求运维去写前端框架,而是用同一门语言覆盖整条链路:

代码语言:javascript
复制
采集 → 存储 → 调度 → 展示
 ↑________________________↓
        反馈与告警

Python 恰好在这四段都有足够成熟的库,且不需要切换心智模型。下面用尽可能少的代码,走一遍完整流程。


二、采集:并发执行,别用 for 循环

巡检的本质是"对 N 台机器执行同一条命令"。新手会写 for host in hosts:,100 台机器串行 SSH,一轮下来十分钟。

用 asyncio 把 SSH 变成并发任务,代码量几乎没有增加:

代码语言:javascript
复制
import asyncio

async def run(host, cmd):
    p = await asyncio.create_subprocess_shell(
        f"ssh -o BatchMode=yes -o ConnectTimeout=5 {host} {cmd}",
        stdout=asyncio.subprocess.PIPE,
    )
    out, _ = await p.communicate()
    return host, out.decode().strip()

async def gather(hosts, cmd):
    return await asyncio.gather(*(run(h, cmd) for h in hosts))

print(asyncio.run(gather(["web01", "web02", "db01"], "uptime")))

十行代码,100 台机器和 3 台机器的耗时几乎一样——瓶颈从"机器数量"变成了"单次 SSH 延迟"。

这里刻意用系统 ssh 而非 paramiko:免密、跳板机、ProxyCommand 这些配置复用现成的 ~/.ssh/config,不用在代码里重新实现一遍。


三、存储:先别急着上时序数据库

很多人一上来就上 Prometheus + InfluxDB,结果发现 90% 的查询只是"最近 20 条巡检结果"。这种场景,SQLite 足够,而且零运维成本。

用 SQLModel(SQLAlchemy + Pydantic 的封装)定义一个表,代码短到不像 ORM:

代码语言:javascript
复制
from datetime import datetime
from sqlmodel import SQLModel, Field, Session, create_engine

class Metric(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    host: str
    load: float
    ts: datetime = Field(default_factory=datetime.now)

engine = create_engine("sqlite:///ops.db")
SQLModel.metadata.create_all(engine)

def save(host, load):
    with Session(engine) as s:
        s.add(Metric(host=host, load=load))
        s.commit()

表结构即代码,改字段就是改一行类型注解,不用手写 DDL。等数据量真的涨到 SQLite 扛不住,再把 create_engine 的 URL 换成 PostgreSQL 即可,上层逻辑一行不用动。


四、展示:FastAPI 让脚本长出界面

运维脚本最难用的地方是"只有写它的人会用"。把它包成 HTTP 接口,价值立刻不一样——浏览器能看,Grafana 能接,告警系统能调。

代码语言:javascript
复制
from fastapi import FastAPI
from sqlmodel import select

app = FastAPI()

@app.get("/metrics")
def metrics(limit: int = 20):
    with Session(engine) as s:
        return s.exec(select(Metric).order_by(Metric.ts.desc()).limit(limit)).all()

启动就一句:uvicorn main:app --host 0.0.0.0 --port 8000。

/docs 路径自动生成交互式文档,前端同事要对接时直接甩链接,不用再写接口说明。


五、调度:把 crontab 收进进程

crontab 的问题是分散——crontab -l 在每台机器上都不同,出了事没人知道任务到底跑没跑。把调度收进应用进程:

代码语言:javascript
复制
from apscheduler.schedulers.asyncio import AsyncIOScheduler

sched = AsyncIOScheduler()

@sched.scheduled_job("interval", minutes=1)
async def collect():
    for host, out in await gather(HOSTS, "cat /proc/loadavg"):
        save(host, float(out.split()[0]))

sched.start()

好处是:任务定义和业务代码在同一个仓库,能打日志、能加异常捕获、能被 /health 接口观测。crontab 里那行 >> /dev/null 2>&1 造成的失联,从此消失。


六、部署:一个 Dockerfile 收尾

代码语言:javascript
复制
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

requirements.txt 里也就四五个包:fastapi、uvicorn、sqlmodel、apscheduler。


七、这套方案的边界

必须说清楚它不适合什么:

  • 配置管理(批量改 Nginx 配置、下发证书)——交给 Ansible,它更专业;
  • 海量指标(每秒百万级数据点)——交给 Prometheus + VictoriaMetrics;
  • 复杂前端——交给专业前端,FastAPI 只提供 JSON。

Python 全栈运维的定位是中间层:比 shell 脚本更可维护,比 Ansible 更灵活,比完整监控平台更轻。它擅长的是那些"用现成工具太重、用 shell 又太脆"的活儿。


八、小结

整条链路的核心代码加起来不到 60 行,却完成了:并发采集、结构化存储、HTTP 展示、进程内调度、容器化部署。

全栈的意义不在"什么都会",而在于消除语言和工具之间的接缝。当采集、存储、调度、展示都在同一个进程、同一个仓库、同一套类型系统里时,运维系统才真正变成了"软件",而不是一堆散落的脚本。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、为什么运维需要"全栈"
  • 二、采集:并发执行,别用 for 循环
  • 三、存储:先别急着上时序数据库
  • 四、展示:FastAPI 让脚本长出界面
  • 五、调度:把 crontab 收进进程
  • 六、部署:一个 Dockerfile 收尾
  • 七、这套方案的边界
  • 八、小结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档