Skip to content

节点 Agent 部署

node-agent 在真实节点上跑宿主原生 venv 加 systemd,不走容器。

这样安排有三个理由:apply 模式下渲染产物直接落宿主;宿主 dockerd 给路由容器做 bind 挂载时路径一致;agent 直接访问宿主的 docker.sock

接入流程(注册、审批、provision)见 节点接入;配置项见 Node Agent 配置


systemd 单元

deploy/tools/systemd/ 提供模板单元,文件头注释里有完整安装步骤。

单元说明
dn42-node-agent@.serviceagent 模板单元:%inode_id,同机可跑多实例;Restart=always 常驻
dn42-control-server.service控制面也可走 systemd(uvicorn 加外部 postgres 与 redis),但生产推荐 docker 整栈
agent-self-update/dn42-node-agent-update.service自更新器单元,由 install-updater.sh 一次性安装

生产 fleet 的实际布局与模板单元略有差异:每节点单实例、用非模板单元 dn42-node-agent.service,venv 在 /opt/dn42-agent(与 agent_pip_rollout.sh 与自更新器一致)。模板单元适合实验环境同机多实例。


安装

bash
sudo cp deploy/tools/systemd/*.service /etc/systemd/system/
sudo mkdir -p /opt/dn42-control && sudo rsync -a ./ /opt/dn42-control/
sudo python3 -m venv /opt/dn42-control/.venv
# 安装依赖与一方包(见单元文件的 PYTHONPATH / ExecStart)
sudo systemctl daemon-reload
sudo systemctl enable --now dn42-node-agent@edge1
journalctl -u dn42-node-agent@edge1.service -f

节点专属变量放 /etc/dn42-control/<node_id>.env

dotenv
DN42_AGENT_CONTROLLER_URL=https://api.natlan.io
DN42_AGENT_ENROLLMENT_TOKEN=change-me
# STATE_DIR 与 REQUESTED_NODE_ID 已由 unit 注入

DN42_AGENT_CONTROLLER_URL 不带尾斜杠。改动后 systemctl restart 才生效。


安装自更新器

首次装机后每节点装一次:

bash
sudo bash deploy/tools/agent-self-update/install-updater.sh

此后 agent 升级由控制面驱动——上传 wheel → 设目标版本 → 心跳推送 → 更新器安装 → 健康门校验,失败自动回滚,不再逐机 pip。见 Agent 滚动升级

更新器是独立的 systemd oneshot 单元,由 agent 用 systemctl start --no-block 触发。进程隔离是必须的:升级会重启 agent,跟着 agent 一起被杀的更新器没法完成安装与回滚。


加固

模板单元已开:

  • Restart=on-failure / Restart=always
  • ProtectSystem=strict
  • NoNewPrivileges=true
  • 受限的 ReadWritePaths

agent 需要访问宿主 docker.sock,这是它能操作路由容器的唯一通道。控制面不提供远程 shell 或任意命令执行接口,agent 拿到的只是声明式期望状态——见 安全模型


验证

bash
# 单次诊断,不动机器
python -m agent.main --plan-only --state-dir /var/lib/dn42-control

# 自检(配置 / 状态目录 / 身份 / 控制面 / Docker / 指标)
python -m agent.main --doctor --state-dir /var/lib/dn42-control

常驻后从控制面看:GET /control/v1/admin/nodes/{node_id}/health 应在一轮 reconcile 后返回 ok。排障见 故障排查