JumpServer 集群部署指南:如何构建 99.9% 高可用架构
【免费下载链接】jumpserverJumpServer is an open-source Privileged Access Management (PAM) platform that provides DevOps and IT teams with on-demand and secure access to SSH, RDP, Kubernetes, Database and RemoteApp endpoints through a web browser.项目地址: https://gitcode.com/GitHub_Trending/ju/jumpserver
当唯一节点宕机、值班人员无法再远程接入任何生产资产时,你才意识到:运维入口本身就是单点故障。本文以 JumpServer 为例,拆解生产级 JumpServer 集群部署高可用的完整方案:2 个应用节点 + PostgreSQL 主从 + 3 节点 Redis 集群即可实现无人工干预的自动故障切换,可用性目标 99.9%,并教你用故障演练独立验证切换真的生效。
高可用集群架构设计 🎯
整个架构围绕三条目标展开:
- 无单点故障:任一层(负载、应用、数据、缓存、存储)至少 2 份冗余,单组件宕机服务不中断;
- 自动故障切换:故障由负载均衡器被动健康检查发现并摘除,全程无需人工介入;
- 数据一致同步:会话与任务队列存 Redis 实现跨节点共享,业务数据靠 PostgreSQL 流复制(主库实时同步到从库的复制机制)保持主从一致。
各组件职责与最小数量如下:
| 组件 | 职责 | 最小数量 |
|---|---|---|
| Nginx 负载均衡 | 分发 HTTP/WebSocket 请求,被动健康检查摘除故障节点 | 2(或配 Keepalived 做 VIP 漂移) |
| JumpServer 应用节点 | 提供 Web 界面与 API,无状态,会话外置 | 2 |
| PostgreSQL | 存储用户、资产、权限等核心业务数据,主从流复制 | 2(1 主 1 从) |
| Redis 集群 | 存储 Celery 任务队列、缓存与用户会话,节点故障不丢数据 | 3 |
| NFS 共享存储 | 录像文件、配置文件多节点共享读写 | 1 |
流量方向与依赖关系:
一句话说明每个组件:Nginx 负责请求分发与故障摘除;应用节点无状态可随时水平扩容;PostgreSQL 主从保证数据不丢并可从库接管;Redis 集群承载任务与会话,是跨节点切换的基础;NFS 保证录像与配置在所有节点视图一致。
架构就位后,接下来按层落地。
分层落地:负载均衡、应用、数据与存储
负载均衡层:Nginx 被动健康检查
为什么这么选:Nginx 的被动健康检查不需要额外组件,max_fails与fail_timeout两个参数即可实现"3 次失败、30 秒内摘除",对新手最友好。
关键配置项:
upstream jumpserver { server 192.168.1.10:8080 max_fails=3 fail_timeout=30s; server 192.168.1.11:8080 max_fails=3 fail_timeout=30s; } server { location / { proxy_pass http://jumpserver; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /api/health/ { proxy_pass http://jumpserver/api/health/; proxy_next_upstream error timeout http_502 http_503; } }| 参数 | 建议值 | 作用 |
|---|---|---|
max_fails | 3 | 连续 3 次失败标记节点不可用 |
fail_timeout | 30s | 失败观察窗口,到期后自动重试该节点 |
proxy_next_upstream | error timeout http_502 | 出错立即转下一节点,用户无感 |
JumpServer 内置健康检查接口/api/health/(见 apps/jumpserver/urls.py),可作为主动探活端点。
验证该层就绪:curl -s -o /dev/null -w "%{http_code}" http://负载均衡IP/api/health/,返回200即链路贯通。
应用层:JumpServer 多节点部署要点
为什么这么选:JumpServer 应用层无状态,会话、任务队列全部外置到 Redis,因此多节点只需指向同一套数据层。节点扩容即横向扩展,是 99.9% 可用性的主要弹性来源。
关键配置项(完整示例见 config_example.yml,每个节点配置需完全一致,仅HTTP_LISTEN_PORT可各自绑定):
DB_ENGINE: postgresql DB_HOST: 192.168.1.6 # 所有节点指向同一数据库 DB_PORT: 5432 DB_USER: jumpserver DB_PASSWORD: ****** DB_NAME: jumpserver REDIS_HOST: 192.168.1.7 # Redis 集群入口 REDIS_PORT: 6379 SESSION_COOKIE_AGE: 3600 # 会话有效期 1 小时,会话数据存 Redis部署上建议用 utils/build_docker.sh 构建镜像,各节点容器把共享目录(录像、配置)挂载到同一 NFS 路径;如需源码构建,先执行git clone https://gitcode.com/GitHub_Trending/ju/jumpserver再构建。登录入口效果如下:
验证该层就绪:bash utils/check_celery.sh,脚本检查/tmp/worker_heartbeat_*心跳文件(由 apps/ops/celery/heatbeat.py 每 20 秒刷新)是否在 20 秒内更新,退出码 0 表示 Celery 工作节点存活。
数据层:PostgreSQL 主从与 Redis 集群
为什么这么选:业务数据是集群中唯一不可重建的部分,PostgreSQL 流复制让从库可在主库故障后接管;Redis 3 节点集群模式保证任务队列与缓存单点故障不中断。特别注意定时任务:JumpServer 的 Beat 调度器通过 Redis 分布式锁(beat-distribute-start-lock,见 apps/ops/celery/utils.py)保证多节点环境下同一时刻只有一个调度器持有锁,避免任务重复执行。
关键配置项:
| 配置 | 建议值 | 说明 |
|---|---|---|
DB_ENGINE/DB_HOST | postgresql / 主库地址 | 主从复制在数据库侧配置,应用侧始终指向主库 |
| Redis | 3 节点cluster-enabled yes | 会话共享 + 任务队列,nodes.conf与 AOF 落盘 |
PERIOD_TASK_ENABLED | true | 定时任务依赖 Celery Beat,多节点由锁去重 |
验证该层就绪:
# 主库写入测试数据 psql -h 192.168.1.6 -U jumpserver -c "INSERT INTO users_user(username) VALUES('ha-test')" # 从库查询,非空即复制生效 psql -h 192.168.1.7 -U jumpserver -c "SELECT id FROM users_user WHERE username='ha-test'"存储层:NFS 共享存储挂载
为什么这么选:会话录像、导出文件、配置文件必须多节点一致读写,NFS 提供标准的 POSIX 共享挂载,比对象存储更贴合 JumpServer 的目录式文件访问模式。
关键配置项:
| 项目 | 示例 | 说明 |
|---|---|---|
服务端/etc/exports | /data/share 192.168.1.0/24(rw,sync,no_root_squash) | sync保证落盘一致性 |
| 客户端挂载点 | /opt/jumpserver/share | 录像与配置统一挂载,节点重启后重新 mount |
验证该层就绪:df -h /opt/jumpserver/share,输出中显示 NFS 挂载且剩余空间充足即就绪。
确认无误后,最后用故障演练检验整个集群。
故障演练:一键验证自动切换与数据一致性 🔥
怎么判断切换真的生效了——看三个现象:摘除时长符合预期、接口持续 200、从库数据可查到。
故障注入:停掉一个节点验证流量切换
docker stop jumpserver-node1 # 模拟应用节点故障 tail -f /var/log/nginx/access.log # 观察流量去向 curl -s -o /dev/null -w "%{http_code}\n" http://负载均衡IP/api/health/预期现象:Nginx 最多在 3 个失败请求(max_fails=3)后将该节点标记不可用,30 秒观察窗口内全部流量落到存活节点,健康检查接口持续返回 200,客户端无 5xx。
数据同步核验:确认主从复制
psql -h 192.168.1.7 -U jumpserver -c "SELECT id FROM users_user WHERE username='ha-test'"预期现象:上一节主库插入的测试数据在从库可立即查到,说明流复制延迟在秒级以内;若查不到,需检查复制槽位与网络。
并发压测:验证高负载下会话连续性
ab -n 1000 -c 100 http://jumpserver.example.com/api/v1/assets/assets/
预期现象:1000 请求 100 并发下无 5xx 尖峰(个别 502 属正常重试);且同一用户会话在两个节点间往返请求不被踢出——因为会话存 Redis,这正是跨节点故障切换不丢登录态的关键证据。
生产化上线清单 ✅
- 备份:每天用 数据库备份脚本 定时导出数据库,保留 30 天,每月至少 1 次真实恢复演练;
- 告警阈值:启用内置资源告警,CPU/内存/磁盘阈值建议 90%,磁盘超阈值自动推送通知(文案见国际化文件中的
Disk used more than {max_threshold}%); - 心跳巡检:将
utils/check_celery.sh接入监控系统,心跳文件超过 20 秒未更新即告警; - 蓝绿发布:升级时先在一个节点切新版本,观察 15 分钟无异常再切流量,避免全量升级风险;
- 灾备演练:每季度完整演练一次"停应用节点 + 主库切换",演练通过才算高可用达标;
- Beat 锁巡检:确认 Redis 中
beat-distribute-start-lock同一时刻仅被一个节点持有,防止定时任务重复执行。
至此集群达到 99.9% 可用性目标;JumpServer 应用层无状态的设计意味着后续只需在 Nginx upstream 中追加server行即可继续横向扩展,应用节点数可按业务增长线性增加。
【免费下载链接】jumpserverJumpServer is an open-source Privileged Access Management (PAM) platform that provides DevOps and IT teams with on-demand and secure access to SSH, RDP, Kubernetes, Database and RemoteApp endpoints through a web browser.项目地址: https://gitcode.com/GitHub_Trending/ju/jumpserver
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考