第 9 课:进阶扩展
回顾:我们已经学了什么
第 1-2 课:基础认知 + 环境搭建
第 3 课:query() 一键自动化
第 4 课:自定义工具 MCP
第 5 课:Hook 安全管控
第 6 课:交互式会话 Client
第 7 课:多 Agent 协作
第 8 课:完整项目实战
这一课,我们来看看怎么把 DevOps 助手用到更多真实场景中。
扩展一:Docker 管理工具
from claude_agent_sdk import tool
@tool(
"docker_ps",
"列出运行中的 Docker 容器",
{"all": {"type": "boolean", "description": "是否显示所有容器(包括已停止的)"}}
)
async def docker_ps(all: bool = False) -> str:
import subprocess
cmd = ["docker", "ps", "--format", "table {{.Names}}\t{{.Status}}\t{{.Ports}}"]
if all:
cmd.insert(2, "-a")
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
return result.stdout.strip() or "没有运行中的容器"
except FileNotFoundError:
return "错误: docker 未安装"
except Exception as e:
return f"错误: {e}"
@tool(
"docker_logs",
"获取容器的最近日志",
{
"container": {"type": "string", "description": "容器名称或 ID"},
"lines": {"type": "number", "description": "获取最近几行日志,默认 50"},
}
)
async def docker_logs(container: str, lines: int = 50) -> str:
import subprocess
try:
result = subprocess.run(
["docker", "logs", "--tail", str(lines), container],
capture_output=True, text=True, timeout=15,
)
output = result.stdout + result.stderr
return output.strip() or "没有日志输出"
except Exception as e:
return f"错误: {e}"
@tool(
"docker_stats_snapshot",
"获取容器资源使用快照(CPU/内存)",
{}
)
async def docker_stats_snapshot() -> str:
import subprocess
try:
result = subprocess.run(
["docker", "stats", "--no-stream",
"--format", "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"],
capture_output=True, text=True, timeout=15,
)
return result.stdout.strip() or "没有运行中的容器"
except Exception as e:
return f"错误: {e}"
使用场景:
你: 看看哪些容器在跑
🤖 调用 docker_ps → 列出容器
你: web-app 容器最近有什么错误?
🤖 调用 docker_logs(container="web-app") → 读日志
🤖 分析日志中的 ERROR → 给出诊断
你: 哪个容器吃资源最多?
🤖 调用 docker_stats_snapshot → 资源对比
🤖 分析 CPU/内存使用 → 给出优化建议
扩展二:CI/CD 集成工具
@tool(
"run_lint",
"运行代码格式检查(ruff)",
{"path": {"type": "string", "description": "要检查的路径,默认 src/"}}
)
async def run_lint(path: str = "src/") -> str:
import subprocess
try:
# 先检查
check = subprocess.run(
["python", "-m", "ruff", "check", path],
capture_output=True, text=True, timeout=30,
)
if check.returncode == 0:
return f"✅ {path} 代码格式检查通过,没有问题!"
# 有问题,统计数量
lines = check.stdout.strip().split('\n')
issue_count = len([l for l in lines if l.strip()])
return f"⚠️ 发现 {issue_count} 个问题:\n{check.stdout[:1000]}"
except Exception as e:
return f"错误: {e}"
@tool(
"run_typecheck",
"运行类型检查(mypy)",
{"path": {"type": "string", "description": "要检查的路径,默认 src/"}}
)
async def run_typecheck(path: str = "src/") -> str:
import subprocess
try:
result = subprocess.run(
["python", "-m", "mypy", path],
capture_output=True, text=True, timeout=60,
)
if result.returncode == 0:
return f"✅ {path} 类型检查通过!"
return f"⚠️ 类型检查发现问题:\n{result.stdout[:1000]}"
except Exception as e:
return f"错误: {e}"
@tool(
"run_tests_with_coverage",
"运行测试并生成覆盖率报告",
{"test_path": {"type": "string", "description": "测试路径,默认 tests/"}}
)
async def run_tests_with_coverage(test_path: str = "tests/") -> str:
import subprocess
try:
result = subprocess.run(
["python", "-m", "pytest", test_path,
"--tb=short", "-q", "--co", "--no-header"],
capture_output=True, text=True, timeout=120,
)
# 简单统计
output = result.stdout
if "passed" in output:
return f"✅ 测试结果:\n{output[-500:]}"
elif "failed" in output or "error" in output.lower():
return f"❌ 测试失败:\n{output[-500:]}"
else:
return f"测试输出:\n{output[-500:]}"
except Exception as e:
return f"错误: {e}"
把这些工具组合成一个"CI 流水线":
async def ci_pipeline():
"""一键 CI:lint → typecheck → test"""
options = ClaudeAgentOptions(
system_prompt="你是 CI 流水线管理员。按顺序运行 lint、typecheck、test,任何一步失败就停止。用中文回复。",
mcp_servers={"ci": create_sdk_mcp_server(
name="ci",
version="1.0.0",
tools=[run_lint, run_typecheck, run_tests_with_coverage],
)},
allowed_tools=[
"mcp__ci__run_lint",
"mcp__ci__run_typecheck",
"mcp__ci__run_tests_with_coverage",
],
)
async for msg in query(
prompt="依次运行 lint、类型检查和测试,给出综合报告",
options=options,
):
# 处理输出...
pass
扩展三:环境配置检查器
@tool(
"env_check",
"检查开发环境配置是否齐全",
{}
)
async def env_check() -> str:
import subprocess
import shutil
checks = []
# 检查常用工具
tools = {
"python3": "Python",
"node": "Node.js",
"git": "Git",
"docker": "Docker",
"npm": "npm",
"pip": "pip",
}
for cmd, name in tools.items():
path = shutil.which(cmd)
if path:
try:
ver = subprocess.run(
[cmd, "--version"],
capture_output=True, text=True, timeout=5,
)
version = ver.stdout.strip().split('\n')[0]
checks.append(f"✅ {name}: {version}")
except Exception:
checks.append(f"✅ {name}: 已安装 ({path})")
else:
checks.append(f"❌ {name}: 未安装")
# 检查环境变量
import os
env_vars = ["ANTHROPIC_API_KEY", "HOME", "PATH"]
for var in env_vars:
value = os.environ.get(var)
if value:
# 隐藏敏感值
display = value[:8] + "..." if "KEY" in var or "SECRET" in var else "已设置"
checks.append(f"✅ ${var}: {display}")
else:
checks.append(f"❌ ${var}: 未设置")
return "\n".join(checks)
扩展四:告警 Hook
生产环境最怕的就是操作出错但没人知道。来做一个告警 Hook:
import json
import datetime
# 告警记录
alerts: list[dict] = []
async def alert_on_failure(
input_data: HookInput,
tool_use_id: str | None,
context: HookContext
) -> HookJSONOutput:
"""当工具执行失败时触发告警"""
tool_name = input_data.get("tool_name", "unknown")
tool_response = str(input_data.get("tool_response", ""))
# 检测错误关键词
error_keywords = ["error", "failed", "exception", "timeout", "denied", "not found"]
is_error = any(kw in tool_response.lower() for kw in error_keywords)
if is_error:
alert = {
"time": datetime.datetime.now().isoformat(),
"tool": tool_name,
"severity": "HIGH" if "denied" in tool_response.lower() else "MEDIUM",
"message": tool_response[:200],
}
alerts.append(alert)
# 打印告警
print(f"\n🚨 告警 [{alert['severity']}]: {tool_name} 执行出错")
print(f" {tool_response[:100]}")
# 给 AI 更多上下文
return {
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext":
f"⚠️ {tool_name} 执行出现错误,请谨慎处理。"
f"错误次数: {len(alerts)}",
}
}
return {}
扩展五:会话恢复与状态管理
长时间运行的 DevOps 任务可能需要保存和恢复状态:
import json
from pathlib import Path
STATE_FILE = Path("devops_state.json")
def save_state(state: dict) -> None:
"""保存会话状态"""
STATE_FILE.write_text(json.dumps(state, indent=2, ensure_ascii=False))
def load_state() -> dict:
"""加载上次的会话状态"""
if STATE_FILE.exists():
return json.loads(STATE_FILE.read_text())
return {"tasks_completed": [], "last_check": None}
async def stateful_devops():
"""带状态管理的 DevOps 助手"""
state = load_state()
options = ClaudeAgentOptions(
system_prompt=f"""你是 DevOps AI 助手。
上次会话信息:
- 已完成任务: {state.get('tasks_completed', [])}
- 上次检查时间: {state.get('last_check', '无')}
请根据历史信息继续工作。用中文回复。""",
# ... 其他配置
)
async with ClaudeSDKClient(options=options) as client:
# 使用 client 进行交互...
pass
# 退出时保存状态
state["last_check"] = datetime.datetime.now().isoformat()
save_state(state)
扩展六:Kubernetes 工具(进阶)
如果你的环境有 K8s,可以加这些工具:
@tool(
"k8s_pods",
"列出 Kubernetes Pod 状态",
{"namespace": {"type": "string", "description": "命名空间,默认 default"}}
)
async def k8s_pods(namespace: str = "default") -> str:
import subprocess
try:
result = subprocess.run(
["kubectl", "get", "pods", "-n", namespace,
"-o", "wide", "--no-headers"],
capture_output=True, text=True, timeout=15,
)
if result.returncode != 0:
return f"错误: {result.stderr}"
return result.stdout.strip() or "该命名空间没有 Pod"
except FileNotFoundError:
return "错误: kubectl 未安装"
@tool(
"k8s_events",
"获取 Kubernetes 集群最近的事件(用于排错)",
{"namespace": {"type": "string", "description": "命名空间,默认 default"}}
)
async def k8s_events(namespace: str = "default") -> str:
import subprocess
try:
result = subprocess.run(
["kubectl", "get", "events", "-n", namespace,
"--sort-by=.lastTimestamp",
"--field-selector", "type!=Normal"],
capture_output=True, text=True, timeout=15,
)
output = result.stdout.strip()
if not output or "No resources found" in output:
return "✅ 没有异常事件"
return output[:2000]
except FileNotFoundError:
return "错误: kubectl 未安装"
安全最佳实践总结
做 DevOps 工具,安全永远是第一位的:
1. 最小权限原则
├── 每个 Agent 只给必要的工具
├── 审查员不能写代码
└── 测试员不能部署
2. 命令管控
├── 危险命令黑名单(rm -rf /、shutdown 等)
├── 安全命令白名单(ls、git status 等)
└── 未知命令需要人工确认
3. 审计追踪
├── 每次工具调用都记录日志
├── 错误操作触发告警
└── 会话结束输出摘要
4. 环境隔离
├── 开发环境和生产环境分开
├── API Key 用环境变量,不硬编码
└── 敏感操作需要二次确认
5. 渐进式信任
├── 新工具先在测试环境验证
├── 逐步放开权限
└── 定期审查权限配置
完整能力清单
学完这套教程,你可以构建的 DevOps 自动化能力:
| 场景 | 用到的技术 | 课程 |
|---|---|---|
| 一键跑测试 | query() + Bash | 第 3 课 |
| Git 状态检查 | MCP 自定义工具 | 第 4 课 |
| 拦截危险命令 | PreToolUse Hook | 第 5 课 |
| 操作审计日志 | PostToolUse Hook | 第 5 课 |
| 交互式运维 | ClaudeSDKClient | 第 6 课 |
| 代码审查+测试 | 多 Agent 协作 | 第 7 课 |
| 完整 CI/CD | 全部组合 | 第 8 课 |
| Docker/K8s 管理 | MCP 工具扩展 | 本课 |
| 告警监控 | Hook + 状态管理 | 本课 |
接下来可以探索的方向
- Terraform/Ansible 集成:用 MCP 工具封装基础设施管理命令
- Prometheus/Grafana 集成:通过 API 查询监控数据,让 AI 分析趋势
- Slack/飞书通知:把告警信息推送到团队沟通工具
- 定时任务:结合 cron 或 APScheduler,定期自动巡检
- Web 仪表盘:用 Flask/FastAPI 做一个可视化界面,展示审计日志和告警
结束语
恭喜你学完了整套 DevOps AI 助手教程!
这套教程的核心思想其实就一句话:用 AI 做重复的事,用人做判断的事。
AI 擅长的是:快速读代码、跑测试、查日志、做格式化输出。人擅长的是:判断这个 bug 重不重要、这次该不该部署、这个告警需不需要处理。
把两者结合起来,就是最高效的 DevOps 团队。
祝你用得开心!