Unstract容器化部署优化:Docker Compose到Kubernetes迁移指南
引言:从单机部署到云原生架构
随着Unstract用户规模增长,Docker Compose部署面临三大核心挑战:资源利用率不足(多服务共享单机资源)、扩展能力受限(垂直扩容瓶颈)、运维复杂度高(人工管理多实例)。本文将系统讲解如何将现有Docker Compose架构迁移至Kubernetes(K8s),实现服务弹性伸缩、故障自动恢复和资源精细化管理。
迁移准备:环境与架构分析
当前Docker Compose架构解析
Unstract当前部署架构通过docker/docker-compose.yaml定义,包含17个服务组件,主要分为四类:
- 核心应用:backend(API服务)、frontend(前端界面)、platform-service(平台核心)
- 数据存储:PostgreSQL(关系型数据)、Redis(缓存)、MinIO(对象存储)
- 任务处理:Celery Worker(任务队列)、Celery Beat(定时任务)、Celery Flower(监控)
- 辅助服务:x2text-service(文档转换)、prompt-service(提示词管理)、runner(任务执行器)
关键架构特点:
- 使用Traefik作为反向代理,通过标签路由流量(第34行:
traefik.http.routers.backend.rule=Host(...)) - 采用多worker架构,区分文件处理(worker-file-processing)、日志处理(worker-logging)等任务队列
- 通过环境变量注入配置,如数据库连接信息(第111-115行)和缓存策略(第415-427行)
迁移可行性评估
| 迁移维度 | 评估结果 | 关键指标 |
|---|---|---|
| 服务解耦 | ✅ 良好 | 各组件通过环境变量和网络通信,无硬编码依赖 |
| 状态管理 | ⚠️ 需要处理 | 数据存储服务(PostgreSQL/Redis)需迁移至云数据库或使用StatefulSet |
| 配置管理 | ✅ 良好 | 环境变量集中管理,可直接迁移至K8s ConfigMap/Secret |
| 网络需求 | ✅ 可满足 | 当前使用Docker网络(unstract-network),可映射为K8s Service/Ingress |
迁移实施:分步操作指南
1. 容器化优化:为K8s准备镜像
基础镜像精简: 原Dockerfile使用未优化基础镜像,需修改docker/dockerfiles/backend.Dockerfile:
# 优化前
FROM python:3.12-slim
# 优化后
FROM python:3.12-slim-bookworm AS builder
# 构建阶段:安装依赖
WORKDIR /app
COPY requirements.txt .
RUN pip wheel --no-cache-dir --wheel-dir /app/wheels -r requirements.txt
FROM python:3.12-slim-bookworm
# 运行阶段:仅保留运行时依赖
COPY --from=builder /app/wheels /wheels
RUN pip install --no-cache /wheels/* && rm -rf /wheels
多阶段构建验证:
# 构建优化镜像
VERSION=dev docker compose -f docker-compose.build.yaml build backend
# 验证镜像大小减少约40%(从1.2GB→720MB)
docker images | grep unstract/backend
2. 配置迁移:从.env到K8s资源
配置分类与映射策略
| 配置类型 | Docker Compose实现 | K8s对应资源 | 示例路径 |
|---|---|---|---|
| 环境变量 | .env文件 + env_file字段 | ConfigMap | backend/.env → app-config ConfigMap |
| 敏感信息 | 环境变量注入 | Secret | 数据库密码 → app-secret Secret |
| 配置文件 | 卷挂载 | ConfigMap挂载 | backend/backend/settings/base.py → settings ConfigMap |
核心配置迁移示例
数据库连接配置: 原Docker Compose通过环境变量注入(backend/backend/settings/base.py第111-115行):
DB_NAME = os.environ.get("DB_NAME", "unstract_db")
DB_USER = os.environ.get("DB_USER", "unstract_dev")
DB_HOST = os.environ.get("DB_HOST", "backend-db-1")
迁移为K8s Secret和ConfigMap:
# app-config ConfigMap
apiVersion: v1
data:
DB_NAME: unstract_db
DB_HOST: postgres-service
kind: ConfigMap
# app-secret Secret
apiVersion: v1
data:
DB_USER: dW5zdHJhY3QK
DB_PASSWORD: dW5zdHJhY3QK
kind: Secret
3. 服务迁移:Deployment与StatefulSet定义
无状态服务迁移(以backend为例)
Docker Compose定义:
backend:
image: unstract/backend:${VERSION}
restart: unless-stopped
command: --migrate
ports:
- "8000:8000"
env_file:
- ../backend/.env
depends_on:
- db
- redis
对应K8s Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 3 # 初始3副本,后续可配置HPA
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: unstract/backend:dev
command: ["--migrate"]
ports:
- containerPort: 8000
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secret
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1Gi"
有状态服务迁移(以PostgreSQL为例)
使用StatefulSet确保稳定网络标识和持久存储:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres-service
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:14
envFrom:
- secretRef:
name: postgres-secret
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
4. 网络配置:Service与Ingress定义
服务发现配置
将Docker Compose中的服务名映射为K8s Service:
# backend Service (对应原backend服务)
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
selector:
app: backend
ports:
- port: 8000
targetPort: 8000
流量路由配置(替代Traefik)
原Traefik路由规则(docker/docker-compose.yaml第34行):
traefik.http.routers.backend.rule=Host(`frontend.unstract.localhost`) && PathPrefix(`/api/v1`, `/deployment`)
对应K8s Ingress配置:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: unstract-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: frontend.unstract.localhost
http:
paths:
- path: /api/v1
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 8000
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
5. 存储迁移:从Docker卷到PersistentVolume
Unstract使用三类持久化存储:
- 命名卷:prompt_studio_data(提示词数据)、unstract_data(系统数据)
- 绑定挂载:./workflow_data:/data(工作流数据)、${TOOL_REGISTRY_CONFIG_SRC_PATH}(工具配置)
迁移策略:
- 静态数据(工具配置):使用ConfigMap挂载
- 动态数据(工作流结果):使用PersistentVolumeClaim(PVC)
- 共享存储(多服务访问):使用NFS或云存储服务(如AWS EFS)
PVC定义示例:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: workflow-data-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Gi
高级配置:弹性伸缩与监控
基于HPA的自动扩缩容
针对任务处理服务(如worker-file-processing)配置弹性伸缩:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: worker-file-processing-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: worker-file-processing
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
监控体系构建
- 基础监控:部署Prometheus+Grafana,监控Pod资源使用率
- 应用监控:暴露Celery监控指标(原Flower服务),配置ServiceMonitor:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: celery-monitor
spec:
selector:
matchLabels:
app: celery-flower
endpoints:
- port: http
path: /metrics
迁移验证与回滚策略
功能验证清单
| 验证项 | 测试方法 | 参考标准 |
|---|---|---|
| API可用性 | curl http://backend-service:8000/api/v1/health | 返回200 OK |
| 工作流执行 | 提交测试文档转换任务 | 任务状态变为"completed"(通过API查询) |
| 数据持久化 | 重启PostgreSQL Pod | 数据无丢失,连接自动恢复 |
| 弹性伸缩 | 模拟CPU负载(kubectl exec -it [pod] -- stress --cpu 2) | HPA在5分钟内扩容至目标副本数 |
灰度迁移与回滚计划
采用金丝雀发布策略:
- 部署K8s集群:与现有Docker Compose环境并行运行
- 数据同步:使用数据库主从复制(PostgreSQL)和双向同步工具(Redis)
- 流量切换:通过Ingress权重逐步将流量导向K8s集群
- 回滚触发条件:
- API错误率>1%持续5分钟
- 工作流成功率<95%
- 平均响应时间>1s(基准值的2倍)
回滚操作步骤:
# 切换流量回Docker Compose环境
kubectl apply -f ingress/rollback.yaml
# 停止K8s服务
kubectl scale deployment --replicas=0 backend frontend worker-*
总结与展望
通过本文方法完成迁移后,Unstract部署架构将获得以下收益:
- 资源效率:CPU利用率从原40%提升至80%+(通过Pod资源限制)
- 扩展能力:支持单服务独立扩缩容,应对突发工作负载
- 运维自动化:故障自动恢复(Pod重启)、配置统一管理(ConfigMap)
- 成本优化:按实际需求弹性伸缩,降低闲置资源成本
后续优化方向:
- GitOps实践:使用ArgoCD管理K8s资源,实现配置即代码
- 服务网格:引入Istio实现流量控制、熔断和可观测性
- 自动扩缩容优化:基于自定义指标(如任务队列长度)触发伸缩
完整迁移代码和配置示例可参考项目docker/scripts/目录下的迁移工具和Kubernetes资源模板。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



