JumpServer多节点高可用实战:把PAM堡垒机从单点故障中彻底救出来

📅 2026/8/17 23:57:55
JumpServer多节点高可用实战:把PAM堡垒机从单点故障中彻底救出来
JumpServer多节点高可用实战把PAM堡垒机从单点故障中彻底救出来【免费下载链接】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/jumpserverJumpServer作为开源特权访问管理PAM平台承担着SSH、RDP、Kubernetes、数据库等资产的统一登录审计入口。当运维团队把全部服务器密钥都托付给一套单机部署的JumpServer时一个很现实的焦虑是它宕机的那一天等于整个堡垒机系统失守——不仅运维人员登不上任何资产审计记录也瞬间断档。你是否有过深夜被JumpServer挂了的电话叫醒的经历本文不按步骤1234的套路讲而是从三个真实故障场景出发倒推出高可用集群的每一项架构决策最终给出可照抄的落地配置。三个真实故障逼出高可用集群的三条铁律第一个场景数据库成为隐形单点。单机部署时PostgreSQL与JumpServer跑在同一台机器一次磁盘打满或内存耗尽Web界面、连接会话、任务调度全部瘫痪连排查的入口都没有。第二个场景升级变成赌博。为了打一个安全补丁需要重启整个服务运维窗口内业务完全停摆改密、批量授权这些自动化任务全部积压。第三个场景会话状态不共享。如果只靠多开几台机器用户在一号机登录后负载均衡把下一次请求转发到二号机登录态失效连接直接中断——多节点反而制造了新故障。这三个痛点分别指向三条铁律存储层必须与计算层解耦数据库、缓存独立成集群、任意单点都必须有冗余与自动转移、会话与任务状态必须能被所有节点共享。下面每一节都在回答其中一条。先看结果高可用架构全景图与每个组件的职责最终目标是负载均衡 多个无状态应用节点 主从数据库 集群缓存 共享存储。这里的无状态是关键应用节点本身不保存任何业务数据所有数据落在下层因此任何一台应用节点宕机其余节点都能无缝接管。图注请求层只与应用节点打交道应用节点不落任何本地数据全部依赖下层的数据库、Redis 与共享存储这是故障自动切换能成立的根本前提。部署前先按下面的表格把家底盘清楚小规模团队可从最小可用集起步业务增长后再横向扩应用节点节点类型数量参考配置承载职责负载均衡22C4G流量分发、健康检查、VIP漂移应用节点24C8G运行JumpServer核心服务与任务调度PostgreSQL1主1从4C16G资产、用户、授权等核心业务数据Redis3主3从2C4G会话缓存、Celery消息队列NFS共享存储1100G录像文件、备份、部分配置文件项目根目录的 config_example.yml 是所有配置的权威入口数据库、Redis、LDAP、MFA 等参数都能在其中找到对应项后文所有改动最终都落回这个文件。存储层解耦为什么数据库和缓存必须搬出去单机模式下JumpServer 的数据库和 Redis 与应用进程同吃一份资源这是故障场景一的病根。集群化第一步就是把它们拆成独立服务。数据库选型上PostgreSQL 主从流复制配合项目的 Django 数据层是最稳妥的组合。config_example.yml 中与数据库相关的核心配置如下# 所有应用节点填写同一个主库地址 DB_ENGINE: postgresql DB_HOST: 192.168.1.6 DB_PORT: 5432 DB_USER: jumpserver DB_PASSWORD: your_secure_password DB_NAME: jumpserver # Redis 作为 Celery broker 与缓存集群填法见下节 REDIS_HOST: 192.168.1.7 REDIS_PORT: 7000 REDIS_PASSWORD: your_redis_password主库上执行pg_basebackup或流复制工具拉起从库后用pg_stat_replication确认复制延迟在毫秒级。从库平时不承担读写它的价值在于主库硬件故障时手动提升为新的主库或用于备份、报表等只读场景。Redis 直接上 3 主 3 从集群理由是它同时承担两类职责一是 WebSocket 与 Celery 的 broker二是 Django 的会话与缓存后端。这两条链路中任意一条断掉应用节点都会假活——页面能打开但登录即失败。构建集群的命令如下假设三个节点分别为 10、11、12每节点跑两个端口# 三个物理节点上各启动两个 Redis 实例端口 7000/7001 for port in 7000 7001; do docker run -d --name redis-${port} \ -v /data/redis/${port}:/data \ -p ${port}:${port} \ redis:6 redis-server --port ${port} \ --cluster-enabled yes --appendonly yes done # 在任一节点上执行集群创建--cluster-replicas 1 表示每个主节点配一个从节点 redis-cli --cluster create \ 192.168.1.10:7000 192.168.1.10:7001 \ 192.168.1.11:7000 192.168.1.11:7001 \ 192.168.1.12:7000 192.168.1.12:7001 \ --cluster-replicas 1对应的 JumpServer 配置只需把REDIS_HOST指向集群中的任一节点端口指向其对应的REDIS_PORT密码保持一致即可。这里强调一个常被忽略的坑Redis 密码必须与配置文件严格一致否则应用节点能连通却认证失败健康检查会一直报 redis 异常。应用层无状态化多节点之间如何保持会话与任务一致应用节点要无状态靠的不是玄学而是三样东西的统一会话状态在 Redis、定时任务在 Celery 分布式锁、文件在共享存储。先看配置。每个应用节点从同一份 config_example.yml 复制配置修改SECRET_KEY与BOOTSTRAP_TOKEN为一致的随机串并保证DB_HOST、REDIS_HOST指向同一套底层服务。镜像构建直接用项目自带的脚本避免手写 Dockerfile 出错# 在源码根目录执行version 替换为你需要的版本号 bash utils/build_docker.sh v3.10.0构建完成后启动容器把配置目录、录像存储目录都挂到 NFS 共享路径上确保两个节点看到的是同一份文件docker run -d --name jumpserver \ -v /data/jumpserver/config:/opt/jumpserver/config \ -v /data/jumpserver/share:/opt/jumpserver/share \ -e DB_HOST192.168.1.6 -e DB_PORT5432 \ -e REDIS_HOST192.168.1.7 -e REDIS_PORT7000 \ -p 8080:8080 \ jumpserver/jumpserver:v3.10.0Celery 是 JumpServer 自动化能力的引擎改密、批量授权、资产巡检都跑在它上面。多节点下最怕的是同一个定时任务被多个节点重复执行。项目在 apps/ops/celery/utils.py 中实现了基于 Redis 的beat-distribute-start-lock分布式锁确保全局只有一个 beat 实例在派发任务worker 则分散在各节点并行消费。你可以直接用同文件里的get_celery_status()逻辑做一次自检它逐个 ping 所有 worker只有全部存活才返回 True这在扩容后值得作为验收脚本跑一遍。负载层接管流量健康检查端点这样配置负载均衡层选择 Nginx KeepalivedNginx 负责把请求分发到多个应用节点Keepalived 提供 VIP两台负载机之间互相探活主负载机宕机后 VIP 自动漂移负载层自身不再是单点。健康检查是这套架构的灵魂而 JumpServer 恰好内置了现成的端点。查看 apps/jumpserver/api/health.py 可知/api/health/接口会真实地做两件事向数据库发起一次查询、向 Redis 写入并回读一个测试键两者都成功才返回status: true。这是真健康检查而不是TCP 通就行——数据库或 Redis 挂了接口立即返回异常负载均衡就能及时摘除这台假活的节点。Nginx 配置要点如下注意健康检查要打在/api/health/上而不是网站首页upstream jumpserver_backend { server 192.168.1.10:8080 max_fails3 fail_timeout30s; server 192.168.1.11:8080 max_fails3 fail_timeout30s; } server { listen 80; server_name jumpserver.example.com; # WebSocket 升级支持JumpServer 的 Web 终端强依赖 location / { proxy_pass http://jumpserver_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # 主动健康检查请求打到内置接口而非只探 TCP 端口 location /api/health/ { proxy_pass http://jumpserver_backend/api/health/; proxy_next_upstream error timeout http_500 http_502 http_503 http_504; } }Nginx 层只能感知HTTP 层面是否正常感知不到 Celery 是否健康。项目在 utils/check_celery.sh 里给出了一个轻量方案celery worker 会持续刷新心跳文件脚本检查心跳文件是否存在且最后修改时间不超过 20 秒若超时则判定该节点的任务执行能力已丧失。建议把这段检查接到监控系统中作为应用节点摘除的辅助依据弥补 HTTP 健康检查的盲区。故障注入实验关掉一个节点验证流量真的自动切换了光说不练等于没搭。做一次可控的故障注入实验来证明这套架构成立整个流程建议在业务低峰期进行# 1. 先确认两个节点都在负载均衡的后端池中 curl -s http://127.0.0.1/api/health/ | jq .status # 期望 true # 2. 模拟故障停掉应用节点1 docker stop jumpserver # 3. 持续观察访问日志与健康检查确认节点1被摘除、节点2接管全部流量 tail -f /var/log/nginx/access.log随后做数据一致性验证在主库插入一条资产记录再从另一个会话查询确认从库已同步用浏览器在节点2上重新发起一次 Web 终端连接确认会话能正常建立——这一步验证的是跨节点会话共享是否真的打通。压测方面用ab对健康检查接口做轻量压测即可ab -n 1000 -c 100 http://jumpserver.example.com/api/health/验证负载均衡在并发下没有出现连接堆积。注意压测对象不要选 Web 终端这类长连接接口避免误判。监控与告警盯住这几个指标把事故消灭在发生前高可用不是配完就完监控是它持续有效的保证。JumpServer 的资源告警模型在 apps/ops/notifications.py 中有现成参考内置了组件离线、磁盘、内存、CPU 负载四类检查可据此规划告警阈值监控对象关键指标建议告警阈值应用节点CPU 平均负载超过 5 告警应用节点内存使用率超过 85% 告警应用节点磁盘使用率超过 80% 告警数据库连接数、复制延迟复制延迟 5s 告警Redis内存使用、集群节点存活单节点内存 80% 告警Celeryworker 心跳心跳中断 20s 告警另外把/api/health/的返回值纳入外部监控探针例如 Prometheus 的 blackbox exporter一旦返回status: false立即触发 PagerDuty 或企业微信通知。项目还内置了 Prometheus 指标导出端点配合PROMETHEUS_METRICS_TOKEN可接入完整的指标采集体系。生产环境避坑清单备份、升级与灾备演练的实战建议最后用一张清单收尾这些都是我在生产环境踩过的坑备份要独立于集群本身。utils/backup_db.sh 展示了备份脚本的写法生产环境建议把备份文件放在 NFS 之外的另一台机器或对象存储避免集群一起挂、备份一起没。升级走滚动发布。先停一台应用节点做升级验证通过后再升级另一台全程业务不中断数据库升级务必先提升从库验证再切换主从。SECRET_KEY与BOOTSTRAP_TOKEN必须全节点一致。这两者不一致会导致节点间认证错乱表现为登录偶尔失败、组件注册异常排查时极容易误判为网络问题。共享存储的读写延迟要纳入验收。录像文件是持续写入的NFS 网络抖动会导致录像录制中断建议用dd实测挂载点的写吞吐后再正式上线。定期做灾备演练。每季度挑一个低峰时段重复上文第三节的故障注入实验把切换时间记录在案确保故障恢复流程不是纸面流程。回到开篇的三个场景数据库独立成主从后单机磁盘打满不再拖垮整个平台节点冗余让升级从停服赌博变成滚动替换Redis 共享会话让多节点真正成为一个系统而不是多套孤儿。这套架构的每一块砖都是从真实故障里敲定的。如果你正打算从单机迁到集群建议按存储解耦 → 应用无状态 → 负载接管 → 故障演练的节奏推进先在测试环境完整跑一遍故障注入实验再上生产——高可用不是配置出来的是验证出来的。【免费下载链接】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),仅供参考