WeKnora企业级部署:基于Docker Swarm的高可用架构
WeKnora企业级部署:基于Docker Swarm的高可用架构
1. 为什么企业需要WeKnora的高可用部署
在企业实际使用中,知识库系统从来不是简单的“能用就行”。当它成为客服团队的应答中枢、研发人员的技术手册、法务部门的合规依据时,任何一次服务中断都可能带来真实业务损失。我们见过太多这样的场景:某制造企业的技术文档知识库在下午三点突然不可用,导致二十多名工程师无法查询最新工艺参数;某金融机构的合规知识库在审计关键期响应缓慢,影响了整个合规报告的提交进度。
WeKnora本身设计精良,但默认的Docker Compose部署方式更适合开发测试环境。它把所有服务运行在单台机器上,没有故障转移能力,也没有负载均衡机制。当PostgreSQL容器意外退出,或者Ollama模型服务内存溢出时,整个知识库就陷入瘫痪——这显然无法满足企业对系统稳定性的基本要求。
Docker Swarm提供了一种轻量级但足够强大的解决方案。它不需要像Kubernetes那样复杂的学习曲线和运维成本,却能实现服务的多副本部署、自动故障恢复、跨节点负载均衡等核心高可用能力。更重要的是,Swarm与Docker原生集成,WeKnora项目原有的Dockerfile和docker-compose.yml几乎无需修改就能迁移到Swarm环境中。
企业选择Swarm而非其他编排方案,往往基于几个务实考量:运维团队已经熟悉Docker命令体系,不需要额外学习新工具;现有服务器资源有限,Swarm的资源开销比K8s小得多;对服务发现、滚动更新等企业级功能有明确需求,但又不想引入过度复杂的架构。
2. Docker Swarm集群搭建与初始化
2.1 环境准备与节点规划
在开始之前,我们需要明确一个基本事实:Swarm集群至少需要三个管理节点才能实现真正的高可用。单个管理节点虽然可以运行,但一旦该节点宕机,整个集群将失去控制能力。因此,我们的最小生产环境配置是三台服务器,每台既是管理节点也是工作节点。
假设我们有三台服务器,IP地址分别为192.168.1.10、192.168.1.11和192.168.1.12。在每台服务器上执行以下操作:
# 更新系统并安装Docker(以Ubuntu为例) sudo apt update && sudo apt upgrade -y curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USER重启后验证Docker安装:
docker --version docker info | grep "Server Version"2.2 初始化Swarm集群
选择第一台服务器(192.168.1.10)作为初始管理节点:
# 初始化Swarm,指定监听地址为内网IP docker swarm init --advertise-addr 192.168.1.10 # 输出类似以下内容,其中token是加入集群的关键 # docker swarm join --token SWMTKN-1-xxxxxx 192.168.1.10:2377在第二台和第三台服务器上执行上一步输出的join命令:
# 在192.168.1.11上执行 docker swarm join --token SWMTKN-1-xxxxxx 192.168.1.10:2377 # 在192.168.1.12上执行 docker swarm join --token SWMTKN-1-xxxxxx 192.168.1.10:2377回到第一台服务器,验证集群状态:
# 查看所有节点 docker node ls # 应该看到三台节点,状态均为Ready,其中一台标记为Leader ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION xk5j...qz4c node1 Ready Active Leader 24.0.7 yv8f...p9m2 node2 Ready Active Reachable 24.0.7 zr3d...t7n8 node3 Ready Active Reachable 24.0.72.3 配置Swarm网络与存储
WeKnora涉及多个服务间的通信,我们需要创建一个覆盖网络(overlay network)确保跨主机容器能够相互通信:
# 创建名为weknora-net的覆盖网络 docker network create --driver overlay --attachable weknora-net # 验证网络创建成功 docker network ls | grep weknora-net对于持久化存储,WeKnora的PostgreSQL和MinIO服务需要可靠的存储后端。在生产环境中,我们不推荐使用本地卷(local volume),因为容器迁移时数据无法跟随。更稳妥的方式是使用NFS或云存储,但为简化演示,我们先配置一个基础的本地存储方案:
# 在每台节点上创建共享目录 sudo mkdir -p /data/weknora/postgres sudo mkdir -p /data/weknora/minio # 设置适当权限 sudo chown -R 991:991 /data/weknora/postgres sudo chown -R 991:991 /data/weknora/minio3. WeKnora服务的Swarm适配改造
3.1 docker-compose.yml的Swarm适配
WeKnora官方提供的docker-compose.yml文件是为单机环境设计的。要迁移到Swarm,我们需要进行几处关键修改。首先,创建一个新的docker-stack.yml文件:
version: '3.8' services: # 前端服务 - 使用多副本提高可用性 frontend: image: tencent/weknora-frontend:latest deploy: replicas: 3 restart_policy: condition: on-failure delay: 5s max_attempts: 3 placement: constraints: - node.role == worker networks: - weknora-net ports: - "80:80" depends_on: - app # 后端API服务 - 核心业务逻辑 app: image: tencent/weknora-app:latest deploy: replicas: 3 restart_policy: condition: on-failure delay: 5s max_attempts: 3 update_config: parallelism: 1 delay: 10s order: start-first resources: limits: memory: 2G cpus: '1.0' reservations: memory: 1G cpus: '0.5' placement: constraints: - node.role == worker networks: - weknora-net environment: - DB_HOST=postgres - DB_PORT=5432 - REDIS_HOST=redis - MINIO_ENDPOINT=minio:9000 - OLLAMA_HOST=ollama:11434 volumes: - /data/weknora/app-logs:/var/log/weknora depends_on: - postgres - redis - minio - ollama # PostgreSQL数据库 - 使用外部卷确保数据持久化 postgres: image: tencent/weknora-postgres:latest deploy: mode: replicated replicas: 1 restart_policy: condition: on-failure delay: 10s max_attempts: 3 placement: constraints: - node.role == manager networks: - weknora-net environment: - POSTGRES_DB=weknora - POSTGRES_USER=weknora - POSTGRES_PASSWORD=your_strong_password volumes: - /data/weknora/postgres:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U weknora -d weknora"] interval: 30s timeout: 10s retries: 3 # Redis缓存与消息队列 redis: image: redis:7-alpine deploy: mode: replicated replicas: 1 restart_policy: condition: on-failure delay: 5s max_attempts: 3 placement: constraints: - node.role == manager networks: - weknora-net environment: - REDIS_PASSWORD=your_redis_password volumes: - /data/weknora/redis:/data # MinIO对象存储 minio: image: minio/minio:latest deploy: mode: replicated replicas: 1 restart_policy: condition: on-failure delay: 5s max_attempts: 3 placement: constraints: - node.role == manager networks: - weknora-net command: server /data --console-address ":9001" environment: - MINIO_ROOT_USER=minioadmin - MINIO_ROOT_PASSWORD=minioadmin volumes: - /data/weknora/minio:/data ports: - "9000:9000" - "9001:9001" # Ollama大模型服务 - 可根据硬件资源调整副本数 ollama: image: ollama/ollama:latest deploy: mode: replicated replicas: 1 restart_policy: condition: on-failure delay: 10s max_attempts: 3 placement: constraints: - node.role == manager networks: - weknora-net volumes: - /data/weknora/ollama:/root/.ollama ports: - "11434:11434" # Jaeger链路追踪 - 用于生产环境监控 jaeger: image: jaegertracing/all-in-one:1.48 deploy: mode: replicated replicas: 1 restart_policy: condition: on-failure delay: 5s max_attempts: 3 placement: constraints: - node.role == manager networks: - weknora-net environment: - COLLECTOR_ZIPKIN_HOST_PORT=:9411 ports: - "16686:16686" - "9411:9411"这个配置文件与原始docker-compose.yml的主要区别在于:
- 添加了
deploy部分,定义了服务的副本数、重启策略、资源限制等 - 使用
placement.constraints将数据库、缓存等有状态服务固定在管理节点上,而无状态的前端和后端服务分布在工作节点 - 为PostgreSQL添加了健康检查,Swarm会自动检测并重启不健康的实例
- 所有服务都连接到我们之前创建的
weknora-net覆盖网络
3.2 关键服务的高可用增强
PostgreSQL的高可用考虑
虽然我们在Swarm中只部署了一个PostgreSQL实例,但这并不意味着单点故障。实际上,Swarm的健康检查和自动重启机制已经提供了基本的故障恢复能力。当PostgreSQL容器异常退出时,Swarm会在同一节点上自动启动一个新的容器实例。
但对于真正关键的企业应用,我们建议进一步增强数据库的可靠性:
# 在管理节点上创建PostgreSQL的备份脚本 cat > /usr/local/bin/pg-backup.sh << 'EOF' #!/bin/bash DATE=$(date +%Y%m%d_%H%M%S) docker exec weknora_postgres pg_dump -U weknora weknora > /data/weknora/backups/weknora_$DATE.sql find /data/weknora/backups -name "weknora_*.sql" -mtime +7 -delete EOF chmod +x /usr/local/bin/pg-backup.sh # 设置每日凌晨2点自动备份 echo "0 2 * * * root /usr/local/bin/pg-backup.sh" | sudo tee -a /etc/crontab负载均衡器的引入
Swarm内置的服务发现机制可以将流量分发到多个副本,但前端访问仍需一个入口点。我们可以在集群边缘添加一个Traefik反向代理,它不仅能提供负载均衡,还能自动处理HTTPS证书:
# 在docker-stack.yml中添加traefik服务 traefik: image: traefik:v2.10 command: - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--certificatesresolvers.myresolver.acme.tlschallenge=true" - "--certificatesresolvers.myresolver.acme.email=your-email@example.com" - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" deploy: mode: global placement: constraints: - node.role == manager ports: - "80:80" - "443:443" - "8080:8080" # Traefik仪表板 volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" - "/data/weknora/traefik:/letsencrypt" networks: - weknora-net然后为frontend服务添加Traefik标签:
frontend: # ... 其他配置保持不变 labels: - "traefik.enable=true" - "traefik.http.routers.frontend.rule=Host(\`your-domain.com\`)" - "traefik.http.routers.frontend.entrypoints=web,websecure" - "traefik.http.routers.frontend.tls.certresolver=myresolver"4. 高可用部署的实战验证
4.1 服务部署与状态监控
现在我们可以将WeKnora部署到Swarm集群中:
# 在管理节点上执行部署 docker stack deploy -c docker-stack.yml weknora # 查看服务部署状态 docker stack services weknora # 查看各服务的任务状态 docker stack ps weknora # 实时监控服务日志 docker service logs -f weknora_app部署完成后,通过浏览器访问http://<任意节点IP>应该能看到WeKnora的登录界面。此时,Swarm已经将前端服务的三个副本分布在不同的工作节点上,用户请求会被自动负载均衡到任一可用的前端实例。
4.2 故障注入与恢复测试
真正的高可用不是纸上谈兵,而是经过实际故障验证的。我们可以主动模拟几种常见故障场景:
场景一:前端服务实例故障
# 查找一个前端任务的容器ID docker service ps weknora_frontend # 强制停止其中一个容器 docker container kill <container_id> # 观察Swarm如何自动恢复 docker service ps weknora_frontend # 几秒钟后,应该看到新的任务状态为Running场景二:数据库节点故障
# 在运行PostgreSQL的管理节点上,模拟节点宕机 sudo systemctl stop docker # 观察其他管理节点上的服务状态 docker node ls # 故障节点状态变为Down,但服务仍在其他节点正常运行 # 恢复节点 sudo systemctl start docker docker node update --availability active <node_id>场景三:网络分区模拟
# 在某个工作节点上,临时阻断与管理节点的通信 sudo iptables -A OUTPUT -d 192.168.1.10 -j DROP # 观察该节点上的服务任务是否被重新调度到其他节点 docker service ps weknora_frontend这些测试不仅验证了Swarm的自动恢复能力,也让我们对系统的实际行为有了直观理解。在真实企业环境中,我们建议将这些测试步骤编写成自动化脚本,定期执行以确保高可用机制始终有效。
4.3 性能与稳定性指标
部署完成后,我们需要建立一套基本的监控指标来评估高可用效果:
| 指标类别 | 监控项 | 健康阈值 | 监控方法 |
|---|---|---|---|
| 可用性 | 服务整体可用率 | ≥99.9% | 记录HTTP 200响应率 |
| 响应时间 | API平均响应时间 | ≤1.5秒 | 使用curl或专用监控工具 |
| 错误率 | 5xx错误率 | <0.1% | 分析Nginx或Traefik日志 |
| 资源使用 | 内存使用率 | <80% | docker stats或Prometheus |
| 恢复时间 | 故障恢复时间 | <30秒 | 记录从故障发生到服务恢复的时间 |
一个简单但有效的监控脚本示例:
#!/bin/bash # monitor-weknora.sh URL="http://localhost/api/v1/health" while true; do START=$(date +%s.%N) HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$URL") END=$(date +%s.%N) RESPONSE_TIME=$(echo "$END - $START" | bc) if [ "$HTTP_CODE" = "200" ]; then echo "$(date): OK - ${RESPONSE_TIME}s" else echo "$(date): ERROR $HTTP_CODE - ${RESPONSE_TIME}s" fi sleep 5 done5. 运维实践与持续优化
5.1 日常维护操作
高可用架构的价值不仅体现在故障时的自动恢复,更体现在日常运维的便捷性上。Swarm提供了许多实用的运维命令:
# 查看服务详细信息 docker service inspect weknora_app # 查看服务的滚动更新历史 docker service history weknora_app # 手动触发滚动更新(例如更新环境变量) docker service update \ --env-add "OLLAMA_HOST=new-ollama-host:11434" \ weknora_app # 临时扩展服务副本数以应对流量高峰 docker service scale weknora_frontend=5 # 查看服务的资源使用情况 docker service ps --format "table {{.Name}}\t{{.CurrentState}}\t{{.Node}}\t{{.DesiredState}}" weknora_app5.2 安全加固建议
企业级部署必须考虑安全因素。除了WeKnora自身提供的认证机制外,Swarm层面的安全加固同样重要:
# 1. 为Swarm集群启用TLS加密 docker swarm ca --rotate # 2. 创建安全的Overlay网络(加密) docker network create \ --driver overlay \ --opt encrypted \ --attachable secure-weknora-net # 3. 限制管理节点的远程访问 # 编辑/etc/docker/daemon.json { "tls": true, "tlscacert": "/etc/docker/ca.pem", "tlscert": "/etc/docker/server.pem", "tlskey": "/etc/docker/server-key.pem", "hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"] }5.3 持续优化方向
随着WeKnora在企业中的深入使用,我们会发现更多优化空间:
智能扩缩容:当前的副本数是静态配置的。可以结合Prometheus监控指标,使用自定义脚本实现基于CPU使用率或请求延迟的自动扩缩容。
灰度发布:对于关键业务,我们不希望所有用户同时接收新版本。可以通过Traefik的权重路由实现灰度发布:
# 在Traefik配置中添加 - "traefik.http.routers.weknora.rule=Host(\`weknora.example.com\`)" - "traefik.http.services.weknora.loadbalancer.sticky=true" - "traefik.http.services.weknora.weighted.roundRobin=1" - "traefik.http.services.weknora.weighted.services=0.9" - "traefik.http.services.weknora.weighted.services=0.1"多区域部署:对于跨地域的企业,可以考虑在不同地理区域部署独立的Swarm集群,并通过全局负载均衡器(如Cloudflare Load Balancing)进行流量分发,实现真正的异地多活。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
