文章构建了一个部署规划Agent,将自然语言服务描述转化为Dockerfile、Kubernetes Manifest和GitHub Actions工作流,消除每次新服务上线时的模板复制粘贴。
我们会构建一个部署规划 Agent,它能将一段纯英文的服务描述转化为生产可用的制品:一个 Dockerfile、一份 Kubernetes 清单文件,以及一条 GitHub Actions 工作流。如果你厌倦了每次新微服务上线都要复制粘贴模板,那么这个工具可以自动生成初稿,并在配置错误进入集群之前就捕获它们。
开始之前,确保准备好以下内容:
安装好 OpenAI Python SDK:pip install openai
从 https://portal.oxlo.ai 获取一个 Oxlo.ai API Key
Oxlo.ai 是一个面向开发者的推理平台,采用按请求计费的定价方式。这一点很关键,因为我们会给 Agent 输入详细的技术栈描述,而对于按 token 计费的提供商,长输入会很快变得昂贵。在 Oxlo.ai 上,无论你的 prompt 是两行还是两百行,成本都是一样的。
由于 Oxlo.ai 完全兼容 OpenAI API,除了 base URL 之外与标准 OpenAI 设置没有任何区别。将 SDK 指向 Oxlo.ai,并从环境变量中加载你的 key。
from openai import OpenAI
import os
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=os.environ.get("OXLO_API_KEY")
)
system prompt 是一份契约,它让模型保持在 SRE 模式,并强制输出可预测的结构。我们稍后会解析这些部分,所以格式规则是严格的。
SYSTEM_PROMPT = """You are a senior site-reliability engineer. The user will describe a service stack. Your job is to generate three artifacts:
1. Dockerfile - optimized for production, non-root user, explicit base image tags, multi-stage if beneficial.
2. Kubernetes manifest - a Deployment and a Service. Include resource requests/limits, liveness probe, and readiness probe.
3. GitHub Actions workflow - build the image, run a security scan with Trivy, and deploy to the cluster.
Output your response in the following exact structure:
---DOCKERFILE---
```dockerfile
...
---K8S---
...
---CI---
...
---NOTES--- Brief notes on any security or performance decisions made. """
## 步骤 3:通过 Oxlo.ai 生成制品
这个函数将用户描述发送给模型并返回原始 markdown。我使用 kimi-k2.6,因为它的推理和编码能力能很好地处理多文件基础设施逻辑,而且 Oxlo.ai 的按请求计费意味着将来我扩展 prompt 添加额外上下文时,不需要担心 token 数量。
```python
def generate_deployment(description: str) -> str:
response = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": description},
],
temperature=0.2,
)
return response.choices[0].message.content
生成的代码仍然是初稿。我们会运行一个轻量级验证器,用正则表达式在输出中搜索常见错误:浮动的镜像 tag、缺失的健康检查、以 root 运行的容器。
import re
def validate_artifacts(raw_output: str) -> dict:
findings = []
if "latest" in raw_output.lower():
findings.append("Warning: 'latest' tag detected. Pin to a digest or explicit version.")
if not re.search(r"USER\s+\d+|USER\s+\w+", raw_output):
findings.append("Warning: Dockerfile may be missing a non-root USER directive.")
if "HEALTHCHECK" not in raw_output.upper():
findings.append("Warning: No HEALTHCHECK found in Dockerfile.")
if "readinessProbe" not in raw_output:
findings.append("Warning: Kubernetes manifest may be missing a readinessProbe.")
return {
"passed": len(findings) == 0,
"findings": findings,
"raw_output": raw_output,
}
这将各个部分串联起来。它接收一个描述,调用 Oxlo.ai,验证结果,并打印制品以及任何警告信息。
def main():
print("Complex Coding Deployment Agent")
print("Describe your service (e.g., 'FastAPI + Postgres + Redis on K3s'):")
try:
while True:
user_input = input("\n> ").strip()
if not user_input:
continue
if user_input.lower() in ("exit", "quit"):
break
print("\nGenerating artifacts via Oxlo.ai...")
raw = generate_deployment(user_input)
result = validate_artifacts(raw)
print("\n=== GENERATED ARTIFACTS ===")
print(result["raw_output"])
if result["findings"]:
print("\n=== VALIDATION FINDINGS ===")
for f in result["findings"]:
print(f)
else:
print("\nValidation passed with no major warnings.")
except KeyboardInterrupt:
print("\nShutting down.")
if __name__ == "__main__":
main()
将脚本保存为 deploy_agent.py,导出你的 key,然后运行它。下面是一个真实的交互示例,我描述了一个 Python worker 技术栈。为简洁起见输出有所截断,但结构与 Agent 返回的完全一致。
$ export OXLO_API_KEY="sk-oxlo.ai-..."
$ python deploy_agent.py
Complex Coding Deployment Agent
Describe your service (e.g., 'FastAPI + Postgres + Redis on K3s'):
> Python 3.11 FastAPI app with Celery worker, Redis broker, Postgres 15. Target is a single-node K3s cluster.
Generating artifacts via Oxlo.ai...
=== GENERATED ARTIFACTS ===
---DOCKERFILE---
```dockerfile
FROM python:3.11-slim-bookworm AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y gcc libpq-dev
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
FROM python:3.11-slim-bookworm
WORKDIR /app
RUN apt-get update && apt-get install -y libpq5 && rm -rf /var/lib/apt/lists/*
COPY --from=builder /root/.local /root/.local
COPY ./app ./app
ENV PATH=/root/.local/bin:$PATH
EXPOSE 8000
USER 1000
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
---K8S---
apiVersion: apps/v1
kind: Deployment
metadata:
name: fastapi-celery
spec:
replicas: 2
selector:
matchLabels:
app: fastapi-celery
template:
metadata:
labels:
app: fastapi-celery
spec:
containers:
- name: api
image: fastapi-celery:1.0.0
ports:
- containerPort: 8000
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 8000
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: fastapi-celery-service
spec:
selector:
app: fastapi-celery
ports:
- port: 80
targetPort: 8000
---CI---
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t fastapi-celery:${{ github.sha }} .
- name: Run Trivy scan
uses: aquasecurity/trivy-action@master
with:
image-ref: fastapi-celery:${{ github.sha }}
format: sarif
output: trivy-results.sarif
- name: Deploy to K3s
run: kubectl set image deployment/fastapi-celery api=fastapi-celery:${{ github.sha }}
---NOTES--- Used a multi-stage build to keep the final image small. Pinned to python:3.11-slim-bookworm instead of latest. Added non-root USER 1000. Included both liveness and readiness probes so K3s can roll out safely.
=== VALIDATION FINDINGS === Validation passed with no major warnings.
## 总结与后续步骤
这个 Agent 为每个新服务提供了一致的起点。由于 Oxlo.ai 采用按请求计费,你可以负担得起对 prompt 进行迭代、喂给它冗长的现有 compose 文件进行重构,或者在 CI 循环中运行它,而不必担心长上下文带来的 token 成本上涨。
两个具体的扩展方向:
将脚本接入 pre-commit hook,这样每个新仓库都会自动获得一个初始的 Dockerfile 和 K8s 清单文件。
在内部基础镜像目录上添加一层检索层,让 Agent 默认使用你加固过的、已批准的基础镜像,而不是公共 Docker Hub 的 tag。