forked from xiaohei/taiji-AI-PAD
初版 consume_device_code 用裸 redis_client.delete() 且吞异常,在集群 Azure Redis 上删除未生效,导致一个 device_code 换发 token 后仍能在每次 >interval 的轮询继续换发新 token —— 违反 RFC 8628 一次性语义与验收「换一次后再用→拒绝」。 初测二次轮询都在 slow_down 窗口内(<5s)被限流响应遮住,未暴露;>5s 公网 真实轮询复测才暴露。 修复:consume 改用已验证可靠的 _set_keepttl 置 status=consumed(token 端点 签发前硬检查 consumed → expired_token),并 best-effort 删除 device_code + device_user_code 两个 key。即使集群删除失败,状态位硬拦截。 复测(公网 APIM 真实路径,间隔 >5s):首 poll 签发 → 二/三次 poll 均 expired_token,不再重复签发。 镜像 device-code-fix2-20260722-arm64 @sha256:716c2e2d 已部署生产 3/3 Running。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
309 lines
7.8 KiB
YAML
309 lines
7.8 KiB
YAML
# MCP Server Deployment for Azure AKS
|
||
# 生产环境配置 - PostgreSQL 使用 postgres 数据库,Redis 使用 Azure Cache for Redis
|
||
apiVersion: apps/v1
|
||
kind: Deployment
|
||
metadata:
|
||
name: mcp-server
|
||
namespace: taiji-ai
|
||
labels:
|
||
app: mcp-server
|
||
version: v1
|
||
environment: production
|
||
spec:
|
||
replicas: 2
|
||
selector:
|
||
matchLabels:
|
||
app: mcp-server
|
||
strategy:
|
||
type: RollingUpdate
|
||
rollingUpdate:
|
||
maxSurge: 1
|
||
maxUnavailable: 0
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: mcp-server
|
||
version: v1
|
||
annotations:
|
||
prometheus.io/scrape: "true"
|
||
prometheus.io/port: "8000"
|
||
prometheus.io/path: "/metrics"
|
||
spec:
|
||
containers:
|
||
- name: mcp-server
|
||
image: taiji.azurecr.io/mcp-server:device-code-fix2-20260722-arm64
|
||
imagePullPolicy: Always
|
||
ports:
|
||
- containerPort: 8000
|
||
name: http
|
||
protocol: TCP
|
||
env:
|
||
# 应用环境配置
|
||
- name: ENVIRONMENT
|
||
value: "production"
|
||
- name: APP_ENV
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: APP_ENV
|
||
- name: LOG_LEVEL
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: LOG_LEVEL
|
||
|
||
# 数据库配置 (Azure Database for PostgreSQL - 生产库 postgres)
|
||
- name: DATABASE_URL
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: database-url
|
||
- name: ASYNC_DATABASE_URL
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: async-database-url
|
||
|
||
# Redis配置 (Azure Cache for Redis with SSL)
|
||
- name: REDIS_URL
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: redis-url
|
||
|
||
# NATS配置 (K8s内部服务)
|
||
- name: NATS_URL
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: NATS_URL
|
||
|
||
# LiteLLM网关配置
|
||
- name: LITELLM_URL
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: LITELLM_URL
|
||
- name: LLM_BASE_URL
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: LITELLM_URL
|
||
- name: LITELLM_MASTER_KEY
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: litellm-master-key
|
||
- name: LITELLM_API_KEY
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: litellm-master-key
|
||
|
||
# Agent Manager 配置 (AKS内部服务)
|
||
- name: AGENT_MANAGER_URL
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: AGENT_MANAGER_URL
|
||
- name: AGENT_K8S_NAMESPACE
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: AGENT_K8S_NAMESPACE
|
||
# 服务令牌:调 agent-manager 鉴权(契约 §2.1,= agent-manager 的 AGNET_RUNTIME_SERVICE_TOKEN)
|
||
- name: AGENT_MANAGER_SERVICE_TOKEN
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: agent-manager-service-token
|
||
|
||
# JWT配置
|
||
- name: SECRET_KEY
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: jwt-secret
|
||
- name: JWT_SECRET_KEY
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: jwt-secret
|
||
- name: JWT_ALGORITHM
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: JWT_ALGORITHM
|
||
- name: JWT_EXPIRE_MINUTES
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: JWT_EXPIRE_MINUTES
|
||
|
||
# SMTP邮箱配置
|
||
- name: SMTP_SERVER
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: SMTP_SERVER
|
||
- name: SMTP_PORT
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: SMTP_PORT
|
||
- name: SMTP_EMAIL
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: SMTP_EMAIL
|
||
- name: SMTP_USE_SSL
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: SMTP_USE_SSL
|
||
- name: SMTP_PASSWORD
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: smtp-password
|
||
|
||
# Heicode magic-link 邮箱登录:本服务对外公网基址(§11 终态=APIM)
|
||
- name: MAGIC_LINK_PUBLIC_BASE_URL
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: MAGIC_LINK_PUBLIC_BASE_URL
|
||
# 发信总闸(默认 false=mock);D-5 签字后改 configmap 的 MAGIC_LINK_EMAIL_ENABLED=true
|
||
- name: MAGIC_LINK_EMAIL_ENABLED
|
||
valueFrom:
|
||
configMapKeyRef:
|
||
name: taiji-config
|
||
key: MAGIC_LINK_EMAIL_ENABLED
|
||
|
||
# PayPal 支付配置 (生产环境)
|
||
- name: PAYPAL_CLIENT_ID
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: paypal-client-id
|
||
- name: PAYPAL_CLIENT_SECRET
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: paypal-client-secret
|
||
- name: PAYPAL_ENVIRONMENT
|
||
value: "production"
|
||
- name: PAYPAL_WEBHOOK_ID
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: taiji-secrets
|
||
key: paypal-webhook-id
|
||
|
||
# 健康检查
|
||
livenessProbe:
|
||
httpGet:
|
||
path: /health
|
||
port: 8000
|
||
initialDelaySeconds: 60
|
||
periodSeconds: 30
|
||
timeoutSeconds: 10
|
||
failureThreshold: 5
|
||
|
||
readinessProbe:
|
||
httpGet:
|
||
path: /health
|
||
port: 8000
|
||
initialDelaySeconds: 30
|
||
periodSeconds: 10
|
||
timeoutSeconds: 10
|
||
failureThreshold: 5
|
||
|
||
# 资源限制
|
||
resources:
|
||
requests:
|
||
memory: "256Mi"
|
||
cpu: "200m"
|
||
limits:
|
||
memory: "1Gi"
|
||
cpu: "1000m"
|
||
|
||
# 挂载卷
|
||
volumeMounts:
|
||
- name: logs
|
||
mountPath: /app/logs
|
||
|
||
# 卷定义
|
||
volumes:
|
||
- name: logs
|
||
emptyDir: {}
|
||
|
||
# 重启策略
|
||
restartPolicy: Always
|
||
|
||
# ACR 镜像拉取凭据
|
||
imagePullSecrets:
|
||
- name: acr-secret
|
||
|
||
# 服务账户(如果需要访问K8s API)
|
||
# serviceAccountName: mcp-server-sa
|
||
|
||
---
|
||
# MCP Server Service
|
||
apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: mcp-server
|
||
namespace: taiji-ai
|
||
labels:
|
||
app: mcp-server
|
||
spec:
|
||
type: ClusterIP
|
||
selector:
|
||
app: mcp-server
|
||
ports:
|
||
- name: http
|
||
port: 8000
|
||
targetPort: 8000
|
||
protocol: TCP
|
||
|
||
---
|
||
# HorizontalPodAutoscaler - 自动扩缩容
|
||
apiVersion: autoscaling/v2
|
||
kind: HorizontalPodAutoscaler
|
||
metadata:
|
||
name: mcp-server-hpa
|
||
namespace: taiji-ai
|
||
spec:
|
||
scaleTargetRef:
|
||
apiVersion: apps/v1
|
||
kind: Deployment
|
||
name: mcp-server
|
||
minReplicas: 2
|
||
maxReplicas: 10
|
||
metrics:
|
||
- type: Resource
|
||
resource:
|
||
name: cpu
|
||
target:
|
||
type: Utilization
|
||
averageUtilization: 70
|
||
- type: Resource
|
||
resource:
|
||
name: memory
|
||
target:
|
||
type: Utilization
|
||
averageUtilization: 80
|
||
|
||
---
|
||
# PodDisruptionBudget - 确保高可用
|
||
apiVersion: policy/v1
|
||
kind: PodDisruptionBudget
|
||
metadata:
|
||
name: mcp-server-pdb
|
||
namespace: taiji-ai
|
||
spec:
|
||
minAvailable: 1
|
||
selector:
|
||
matchLabels:
|
||
app: mcp-server
|