Skip to content

Repository files navigation

Keeploy

基于 KeePass 凭据托管的 Nginx 负载均衡无感滚动部署工具。

Dockerless(零容器):不依赖 Docker、K8s 或任何容器运行时。直接在宿主机上操作——jar 服务走进程启停、static 资源走目录覆盖、流量切换用 sed 注释 Nginx 的 server 行 + nginx -s reload。目标机上除了要发布的程序本身,无需安装任何额外中间件。

一句话:把「拉代码 → 打包 → 备份 → 逐台上传 → Nginx 摘流量 → 停服替换 → 健康检查 → Nginx 恢复流量」这套上线流程,做成一个可重复、可回滚、fail-fast、且完全不需要容器的命令行 / 桌面 GUI 工具。


核心特性

  • Dockerless(零容器,零中间件):目标机无需安装 Docker / 容器运行时 / 任何 Agent。发布即直接操作宿主机进程与文件,流量切换靠 sed 改 Nginx 配置。现有裸金属 / 虚拟机环境开箱即用,不侵入既有部署形态。
  • 凭据零落地:SSH 主机密码、Nginx 主机密码统一存进 KeePass 数据库(.kdbx),运行时不写明文到配置文件;支持 环境变量 → 配置文件 → keyfile → 交互输入 四级回退。
  • 无感滚动:逐台发布,任意时刻最多一台离线;发布前 Nginx 摘节点流量、发布后恢复,业务无感知。
  • 多种认证:主机与 Nginx 支持 keepass(KeePass 凭据引用)或 manual(配置文件内明文用户名/密码)两种 auth_mode
  • 两类产物jar(Java 服务,停服替换后重启)与 static(前端静态资源,上传解压覆盖站点目录,无需重启)。
  • 一键回滚:基于每次部署在远程 backup_dir 落地的带时间戳备份({time_dir}/bak/)原样回滚,回滚复用同一套滚动流程。
  • 本地打包:按应用维度的 compile_dir / fetch_cmd / package_cmd / target_dir 在本地完成拉取与构建。
  • 断点续发resume 仅对上一次失败、且已摘流量未恢复的节点继续发布。
  • 双形态入口:纯命令行 keeploy + 桌面 GUI(Tkinter 纯客户端,无 Web 服务,支持深/浅色主题)。
  • 可观测:本地 SQLite 记录每次部署/回滚历史,支持 status 查询与演练(--dry-run)。

工作原理

滚动发布(每台机器依次执行,保证任意时刻只有一台离线):

  1. 本地打包 + 上传新包(此阶段不影响线上)
  2. Nginx 注释该节点的 server 行 → nginx -tnginx -s reload
  3. 等待存量连接处理完(drain)
  4. 停服 → 替换包 → 启服
  5. 健康检查轮询(未配置 health_check 时降级为固定等待)
  6. Nginx 恢复该节点 → nginx -tnginx -s reload

回滚走完全相同的流程,区别只在第 4 步从 bak/ 而非 new/ 取包。

fail-fast 与安全中止:全程任一步失败立即终止,不再处理后续机器。若失败发生在「已摘流量」之后,会生成带恢复命令的告警,由人工确认服务状态后再恢复流量。


目录结构

Keeploy/
├── main.py                 # CLI 入口(python main.py <command> ...)
├── keeploy_gui.py          # 桌面 GUI 入口(python keeploy_gui.py [-c config])
├── requirements.txt        # CLI(无 GUI)依赖
├── requirements-gui.txt    # GUI 额外依赖(tk 相关)
├── config/
│   └── example.json        # 配置样例(部署配置)
├── keeploy/                # 核心库
│   ├── __init__.py         # 版本号 __version__
│   ├── cli.py              # Click 命令行解析
│   ├── config.py           # 配置加载 / 校验 / 主机·应用选择
│   ├── credentials.py      # KeePass / 密码解析(CredentialProvider)
│   ├── deploy.py           # 交互确认(input/prompt)
│   ├── local_builder.py    # 本地拉代码 + 打包
│   ├── remote.py           # SSH 封装(exec/scp/put/exists)
│   ├── nginx.py            # NginxManager(摘/恢复流量、配置校验)
│   ├── strategies.py       # 部署策略(jar / static)
│   ├── workflow.py         # 编排引擎(deploy/rollback/resume)
│   ├── health.py           # 健康检查轮询
│   ├── history.py          # SQLite 部署历史
│   └── errors.py           # 异常与中止提示
├── gui/                    # 桌面 GUI 包(Tkinter 纯客户端,无 Web 服务)
│   ├── app.py              # 整体布局 / 导航 / 主题切换 / 视图分发
│   ├── runner.py           # 后台部署运行器(进度解析 + 日志累积)
│   ├── theme.py            # 深 / 浅色主题令牌
│   ├── dialogs.py          # 密码框 / 确认框等模态对话框
│   ├── exporter.py         # 历史导出
│   ├── widgets.py          # 通用组件(面板 / 按钮 / 状态点等)
│   ├── views/              # 各页面(配置管理 / 部署执行 / 历史记录 / 新建配置)
│   └── *.py                # 其他 GUI 支撑模块
└── docs/
    └── canvas_alignment.md # GUI 画布像素对齐校验报告(设计稿 vs 实现)

安装

需要 Python 3.8+。

# CLI(无 GUI)
pip install -r requirements.txt

# 如需桌面 GUI
pip install -r requirements-gui.txt

KeePass 凭据默认通过 pykeepass 读取;若未安装,运行涉及 KeePass 凭据的操作时会提示:

请执行 pip install -r requirements.txt,或移除配置中的 keepass 段

快速开始

  1. 复制 config/example.json 为你的环境配置(如 config/prod.json),按需填写主机、应用与 KeePass 信息。
  2. 校验配置:
    python main.py status -c config/prod.json
  3. 先做一次演练,确认流程正确(不实际改线上):
    python main.py deploy -c config/prod.json --dry-run
  4. 正式部署:
    python main.py deploy -c config/prod.json
  5. (可选)桌面 GUI:
    python keeploy_gui.py -c config/prod.json

命令行用法

python main.py <command> [options]

子命令

命令 说明
deploy 部署:本地打包 → 上传 → 逐台滚动发布
rollback 回滚:基于历史备份恢复到上一成功版本
resume 续发:仅对上次失败且已摘流量未恢复的节点继续发布
status 查询本地部署历史记录(默认最近 20 条)

通用参数

  • -c, --config PATH:JSON 配置文件路径(必需,指定目标环境)。
  • --ask-password:强制交互输入 KeePass 主密码(不依赖环境变量 / 配置文件)。
  • -y, --yes:跳过所有确认交互,用于无人值守。
  • --hosts:逗号分隔的主机名子集(仅对这些主机操作)。
  • --apps:逗号分隔的应用名子集(仅部署这些应用)。
  • --dry-run:演练模式,打印流程但不实际改线上(部署/回滚均支持)。

deploy 专属参数

  • --skip-package:跳过本地拉取与打包,直接复用上次产物(需 target_dir 已有包)。
  • --companion-restart APPS:伴随重启:仅指定的、且本机承载但未被选中的应用,随目标应用一起重启。
  • --dry-run:见上。

rollback 专属参数

  • --time TIME_DIR:指定回滚用的备份时间戳(远程 backup_dir 下的目录名)。省略则自动取该环境最近一次成功部署。
  • --companion-restart APPS:同 deploy。
  • --dry-run:见上。

resume 专属参数

  • --nodes HOSTS:逗号分隔的节点主机名,仅对这些节点续发(默认续发所有上次失败且已摘流量未恢复的节点)。

示例

# 部署全部主机与应用
python main.py deploy -c config/prod.json

# 只部署 payment / recon 两个应用,且跳过确认
python main.py deploy -c config/prod.json --apps demo-payment,demo-recon -y

# 只部署 192.168.10.21 一台
python main.py deploy -c config/prod.json --hosts 192.168.10.21

# 演练(不实际改线上)
python main.py deploy -c config/prod.json --dry-run

# 回滚到指定时间戳版本
python main.py rollback -c config/prod.json --time 20260814-153000

# 查看最近 50 条历史
python main.py status -c config/prod.json --limit 50

桌面 GUI 用法

启动器:keeploy_gui.py,纯 Tkinter 客户端(无 Web 服务)。

# 直接启动(自动发现 config/ 下的 JSON)
python keeploy_gui.py

# 指定默认加载的配置文件
python keeploy_gui.py -c config/prod.json

GUI 提供三大视图:

  • 配置管理:编辑 / 校验 config/ 下的 JSON 配置。
  • 部署执行:选择主机子集与应用子集,实时展示阶段进度(打包 / 上传 / 摘流量 / 替换 / 健康检查 / 恢复)、逐台日志与按应用分桶进度;支持中途中止。
  • 历史记录:浏览部署/回滚历史,可导出。

主题:左下角开关切换深 / 浅色(偏好保存在 ~/.keeploy_gui_theme)。

GUI 完全基于现有 keeploy 包实现,不改动任何 CLI 代码;后台部署通过重定向 stdout 捕获进度日志,并通过注入 stop_event 支持中止。


配置参考

配置文件为 JSON,包含两个一级区块 hosts(目标服务器)与 apps(待部署应用),以及 name / keepass / nginx 等全局设置。

⚠️ 注意:config/example.json 中仍使用旧版扁平字段(如 health_url),当前代码解析的是 health_check 子段。请以本参考的字段为准(或按本段更新你的配置)。

全局字段

字段 说明
name 环境名(如 prod-demoapp),用于历史记录归类
manage_nginx 是否启用 Nginx 摘/恢复流量(true/false)
confirm_steps 是否对关键步骤逐条交互确认(true/false)
keepass.kdbx_path KeePass 数据库路径(.kdbx
keepass.keyfile keyfile 路径(可空)
keepass.password KeePass 主密码(可空;建议留空,由环境变量/交互输入提供)
keepass.env_var 读取主密码的环境变量名(如 KEEPLOY_KDBX_PASSWORD

hosts[].(目标主机)

字段 说明
hostname 主机名 / IP(SSH 连接地址)
port SSH 端口(字符串,如 "22"
inet 内网地址,用于同机房机器间直传(省一次公网上传)
auth_mode keepassmanual;缺省时按是否配置了 credential 自动推断
credential KeePass 中的凭据条目路径(如 演示/节点-01),auth_mode=keepass 时必填
username / password auth_mode=manual 时的明文账号密码
backup_dir 远程备份根目录(带时间戳的 new/bak/ 在其下)
app_names 该主机承载的应用名列表(与 apps[].app_name 对应)

apps[].(应用定义)

字段 说明
app_name 应用名(全局唯一,被 hosts[].app_names 引用)
type jarstatic
package_name 产物名(jarxxx.jarstatic 为站点目录名,上传时打包为 xxx.zip
work_dir 远程工作目录(产物部署位置)
compile_dir 本地代码目录(用于 fetch_cmd 拉取)
fetch_cmd 拉取代码的命令(如 svn up / git pull
package_cmd 本地打包命令(如 mvn clean package / npm run build
pre_build_cmd 打包前置命令(可空)
target_dir 本地打包产物目录(jar 必填;static 可空,由 dist_dir 决定)
stop_cmd / start_cmd jar 的停服 / 启动命令(static 无需,留空)
jvm_opts jar 未配 start_cmd 时的 JVM 参数(可空)
log_file jar 未配 start_cmd 时的日志路径(可空,默认 work_dir/nohup.out
ng_port 接入 Nginx 负载均衡的端口(有值才在发布流程中摘/恢复该应用流量)
dist_dir static 打包后的产物子目录(如 dist
health_check 健康检查配置(子段),结构与说明见下

health_check 子段

字段 说明
url 健康检查地址(如 http://{inet}:9216/actuator/health{inet} 会替换为该主机的 inet
expect_status 期望 HTTP 状态码(默认 200
timeout 总超时秒数(默认 30
interval 轮询间隔秒数(默认 3
drain_seconds Nginx 摘流量后等待存量连接 draining 的秒数(亦可在 nginx 一级用 drain_seconds 全局指定)

未配置 health_check 时,健康检查降级为固定等待(由 drain_seconds / 默认值决定),视为启动完成。

nginx(负载均衡器,可选)

仅当 manage_nginx=true 且应用配置了 ng_port 时生效。

字段 说明
hostname Nginx 主机地址
port SSH 端口
conf_path nginx.conf 路径
cmd_path nginx 可执行路径
auth_mode keepassmanual
credential KeePass 凭据条目路径
username / password auth_mode=manual 时的明文账号密码
drain_seconds 摘流量后等待 draining 的全局默认秒数(可被 health_check.drain_seconds 覆盖)

凭据解析优先级(CredentialProvider)

KeePass 主密码按以下顺序解析,命中即止:

  1. 环境变量(如 KEEPLOY_KDBX_PASSWORD
  2. 配置文件 keepass.password
  3. keyfile(keepass.keyfile
  4. 交互输入(--ask-password 或运行时提示)

主机 / Nginx 的 SSH 凭据:从 KeePass 对应 credential 条目读取用户名与密码;auth_mode=manual 时直接使用配置文件内明文。


安全说明

  • 配置文件不写 KeePass 主密码明文;主密码优先来自环境变量或运行期交互输入。
  • 远程备份按时间戳落地于 backup_dir,回滚依赖这些备份,请勿清理正在用的时间戳目录。
  • fail-fast:任一步失败即终止后续机器;若失败在摘流量之后,会提示人工恢复流量的命令,避免节点长期离线。

开发 / 扩展

  • 新增产物类型(如 docker):在 strategies.py 实现 DeployStrategy 子类并注册到 _STRATEGIES,无需改动 workflow.py
  • 部署历史存储于本地 SQLite(history.py),可按需扩展查询 / 导出(GUI 已提供导出)。
  • GUI 与 CLI 共享同一 keeploy 包语义,GUI 不修改任何 CLI 代码。

About

基于 **KeePass** 凭据托管的 **Nginx 负载均衡无感滚动部署**工具。

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages