多服务器集群部署
本文档介绍如何在多台服务器上部署 Data Agent 集群,适用于需要高可用但不使用 Kubernetes 的场景。
前置条件
- 至少 3 台 Linux 服务器(以 CentOS 为例)
- 所有服务器需具备 sudo 权限
- 服务器之间网络互通
- 已阅读 环境变量 文档
机器推荐配置
每台服务器的配置要求:
架构概述
┌─────────────────┐
│ 负载均衡器 │
│ (Nginx/HAProxy) │
└────────┬────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 服务器 1 │ │ 服务器 2 │ │ 服务器 3 │
│ App + PG主 │ │ App + PG从 │ │ App + PG从 │
└───────────────┘ └───────────────┘ └───────────────┘
部署说明:
- 每台服务器运行一个 Data Agent 应用实例
- PostgreSQL 可选择外部数据库或本地集群部署(1 主 2 从)
- 应用层通过负载均衡器分发请求
- 所有应用实例连接同一个 PostgreSQL 主库
1. 安装 Docker
在 每台服务器 上安装 Docker,安装方式与单台服务器部署相同。
1.1 Linux 在线安装
参考 Docker 官方文档:Install Docker Engine on CentOS
1.2 Linux 离线安装
如服务器无法访问外网,可使用离线安装方式。
注意
仅支持 x86_64 架构的 Linux 服务器。
1. 下载离线安装文件
下载以下三个文件并放置在同一目录下:
docker-install.sh 脚本内容(点击展开)
#!/bin/bash
set -e # 遇到错误即退出
# 设置文件名
docker_file="docker-27.5.1.tgz"
docker_compose_file="docker-compose-linux-x86_64"
# 检查架构
ARCH=$(uname -m)
if [ "$ARCH" != "x86_64" ]; then
echo "当前服务器的架构是: $ARCH,仅支持x86_64架构"
exit 1
fi
echo "当前服务器的架构是 x86_64 (64-bit),继续进行"
install_docker(){
# 检查文件是否存在(内网环境,不进行下载,仅检查文件是否存在)
if [[ ! -f "$docker_file" || ! -f "$docker_compose_file" ]]; then
echo "错误:未在当前目录找到必要的安装文件!"
echo "请确保 $docker_file 和 $docker_compose_file 已放置在脚本同路径下"
exit 1
fi
# 执行离线安装 Docker
offline_install() {
local origin_path=$(pwd) # 记录当前目录
file_path=$(pwd) # 设置离线文件所在目录为当前目录
# 解压 Docker 文件并安装
cd $file_path
tar xzvf $docker_file
cp -rf docker/* /usr/bin/ # 复制 Docker 可执行文件到 /usr/bin/
rm -rf docker # 删除解压后的临时文件
cd ${origin_path} >/dev/null # 回到原来的目录
}
# 写入 Docker systemd 服务配置
write_service() {
mkdir -p /usr/lib/systemd/system/
# 定义 Docker 服务配置内容
docker_service_config="[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP \$MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target"
# 将服务配置内容写入 docker.service 文件
echo "$docker_service_config" > /usr/lib/systemd/system/docker.service
}
# 执行离线安装步骤
offline_install
write_service
systemctl daemon-reload
# 安装 Docker Compose
mv $docker_compose_file docker-compose
mv docker-compose /usr/local/bin/
chmod +x /usr/local/bin/docker-compose
# 判断是否存在 systemctl
if command -v systemctl &>/dev/null; then
# 启用并重启 Docker 服务
systemctl enable docker.service
systemctl restart docker
else
echo "未找到 systemctl,无法管理 Docker 服务。"
fi
echo "Docker 和 Docker Compose 安装完成!"
}
# 检查 docker 是否存在
if ! command -v docker &> /dev/null; then
echo "未安装 Docker,开始安装..."
install_docker && echo "Docker 安装完成"
else
echo "Docker 已安装,版本:$(docker --version)"
# 检查 docker compose(支持新版和旧版)
if command -v docker-compose &> /dev/null; then
echo "安装了旧版 docker-compose,版本:$(docker-compose --version)"
elif docker compose version &> /dev/null; then
echo "安装了新版 Docker Compose,版本:$(docker compose version --short)"
else
echo "未安装 Docker Compose,开始安装..."
install_docker && echo "Docker Compose 安装完成"
fi
fi
echo "所有任务执行完毕!"
2. 执行安装脚本
在每台服务器上执行:
# 赋予脚本执行权限
chmod +x docker-install.sh
# 执行安装脚本
sudo ./docker-install.sh
1.3 验证安装
在每台服务器上验证:
# 检查 Docker 是否正常运行
sudo docker ps
# 检查 Compose 插件是否安装
sudo docker-compose --version
# 设置开机自启(如未设置)
sudo systemctl enable docker
2. 网络规划
假设三台服务器 IP 如下(请根据实际情况替换):
2.1 防火墙配置
确保以下端口在服务器之间互通:
# CentOS/RHEL 防火墙配置示例
sudo firewall-cmd --permanent --add-port=5432/tcp
sudo firewall-cmd --permanent --add-port=3052/tcp
sudo firewall-cmd --reload
3. PostgreSQL 数据库配置
根据实际情况选择以下两种方案之一。
数据库部署方案
- 方案 A:使用外部 PostgreSQL 数据库(客户自备,单机或集群均可)
- 方案 B:在三台服务器上部署新的 PostgreSQL 主从集群
3.1 方案 A:使用外部 PostgreSQL 数据库
如果已有 PostgreSQL 数据库(单机或集群),可直接使用。
数据库要求
请让数据库管理员为 Data Agent 创建专用账号和专用库,并授予读写权限。
配置完成后,跳转到 4. 验证应用状态。
3.2 方案 B:部署 PostgreSQL 主从集群
在三台服务器上部署 PostgreSQL,采用流复制(Streaming Replication)实现 1 主 2 从架构。PostgreSQL 与应用服务共用同一个 docker-compose.yml 文件。
3.2.1 主库配置(服务器 1)
在服务器 1 上创建部署目录并配置 docker-compose.yml:
mkdir -p /opt/data-agent
cd /opt/data-agent
创建 docker-compose.yml(主库配置):
services:
app:
image: chatbi/yiask:latest
container_name: yiask
restart: always
environment:
- PROJECT=prod-agent
- LOGGER_LEVEL=error
- DB_HOST=postgres
- DB_DATABASE=mydatabase
- DB_USER=postgres
- DB_PASSWORD=your_strong_password
volumes:
- storage:/app/nocobase/storage
depends_on:
- postgres
ports:
- "3052:80"
init: true
extra_hosts:
- "host.docker.internal:host-gateway"
postgres:
container_name: postgres-primary
image: pgvector/pgvector:pg17-trixie
restart: always
command: >
postgres
-c wal_level=replica
-c max_wal_senders=10
-c max_replication_slots=10
-c hot_standby=on
-c listen_addresses='*'
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: your_strong_password
POSTGRES_DB: mydatabase
volumes:
- pg-data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
storage:
pg-data:
启动服务:
sudo docker-compose up -d
等待主库完全启动后,再配置从库。
3.2.2 从库配置(服务器 2 和 3)
在服务器 2 和服务器 3 上分别执行以下步骤。
创建部署目录:
mkdir -p /opt/data-agent
cd /opt/data-agent
创建 docker-compose.yml(从库配置):
services:
app:
image: chatbi/yiask:latest
container_name: yiask
restart: always
environment:
- PROJECT=prod-agent
- LOGGER_LEVEL=error
# 注意:从库的应用也连接主库
- DB_HOST=192.168.1.101
- DB_DATABASE=mydatabase
- DB_USER=postgres
- DB_PASSWORD=your_strong_password
volumes:
- storage:/app/nocobase/storage
ports:
- "3052:80"
init: true
extra_hosts:
- "host.docker.internal:host-gateway"
postgres:
container_name: postgres-replica
image: pgvector/pgvector:pg17-trixie
restart: always
command: >
postgres
-c hot_standby=on
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: your_strong_password
POSTGRES_DB: mydatabase
volumes:
- pg-data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
storage:
pg-data:
初始化从库数据(从主库同步):
# 使用 pg_basebackup 从主库同步数据
# 注意:将 192.168.1.101 替换为主库实际 IP
sudo docker run --rm \
-v data-agent_pg-data:/var/lib/postgresql/data \
pgvector/pgvector:pg17-trixie \
bash -c "
rm -rf /var/lib/postgresql/data/*
PGPASSWORD='replicator_password' pg_basebackup \
-h 192.168.1.101 \
-U replicator \
-D /var/lib/postgresql/data \
-Fp -Xs -P -R
"
# 启动服务
sudo docker-compose up -d
注意
- 将
192.168.1.101 替换为主库实际 IP
- 确保主库已完全启动后再执行从库同步
-R 参数会自动创建 standby.signal 文件和配置复制连接
- 从库上的应用服务
DB_HOST 应填写主库 IP,确保写操作指向主库
3.2.3 验证集群状态
在主库服务器上验证复制状态:
sudo docker exec -it postgres-primary psql -U postgres -c "SELECT client_addr, state, sync_state FROM pg_stat_replication;"
正常输出应显示两个从库连接:
client_addr | state | sync_state
----------------+-----------+------------
192.168.1.102 | streaming | async
192.168.1.103 | streaming | async
4. 验证应用状态
在每台服务器上验证:
# 查看容器状态
sudo docker ps
# 查看日志
sudo docker-compose logs -f
访问 http://<服务器IP>:3052 确认应用正常运行。
5. 负载均衡配置
使用 Nginx、HAProxy 或其他负载均衡器将请求分发到多个应用实例。
配置要点:
- 后端服务器地址:各服务器的
3052 端口
- 建议使用
least_conn(最少连接)负载均衡策略
- 需支持 WebSocket 连接(配置
Upgrade 和 Connection 头)
6. 运维管理
6.1 查看集群状态
# PostgreSQL 复制状态(在主库执行)
sudo docker exec -it postgres-primary psql -U postgres -c "SELECT * FROM pg_stat_replication;"
# 应用容器状态
sudo docker ps
6.2 日志查看
# PostgreSQL 日志
sudo docker logs -f postgres-primary
# 应用日志
sudo docker logs -f yiask
6.3 故障切换
PostgreSQL 原生流复制不支持自动故障切换,当主库故障时需要手动将从库提升为主库。如需自动故障切换,可考虑使用 Patroni、repmgr 等高可用方案。
手动切换步骤:
# 在从库服务器上执行
sudo docker exec -it postgres-replica psql -U postgres -c "SELECT pg_promote();"
提升后,更新所有应用实例的 docker-compose.yml 中的 DB_HOST,将其指向新主库,然后重启应用:
sudo docker-compose down && sudo docker-compose up -d
7. 常见问题
7.1 从库无法连接主库
检查以下几点:
- 主库
pg_hba.conf 是否允许从库 IP 连接
- 防火墙是否开放 5432 端口
- 复制用户密码是否正确
7.2 应用无法连接数据库
# 在应用服务器上测试
docker run --rm pgvector/pgvector:pg17-trixie psql -h <数据库IP> -U postgres -d mydatabase
7.3 存储不同步
各应用实例的上传文件默认不会同步。如需共享存储,可使用 NFS 或对象存储方案。
完成以上配置后,Data Agent 集群即可对外提供高可用服务。