Cloudflare Tunnel 多节点实战手册 - 跨地域调度与 SSH 安全接入(脱敏版)
本文记录一次真实的多节点落地过程:将同地域内网节点与跨地域节点接入同一调度平面,并用 Cloudflare Tunnel 解决跨网段 Redis 访问与 SSH 运维可达性问题。全文已做脱敏处理,所有域名、IP、隧道 ID、用户名、机器名均为示例占位符,可直接按模板替换。
更新日志
- 2026-03-31: 首发。新增多节点拓扑、Redis 代理路径、R9 SSH 隧道化方案、故障排查清单与可复用脚本模板。
摘要
在多节点调度场景中,最常见的问题不是“算法不可用”,而是“网络不可达”。本次实践中,核心调度后端位于内网控制节点,部分节点可直连,部分跨地域节点无法访问内网地址。我们采用两条 Tunnel 路径:
- 跨地域 Worker 到 Redis 的 TCP 代理通道(cloudflared access tcp)。
- 受限节点 SSH 运维通道(cloudflared access ssh + tunnel ingress ssh://localhost:22)。
最终实现:
- 控制面保持单点(Redis 在控制节点)。
- 跨地域节点通过本地回环端口接入调度后端。
- SSH 管理从“偶发不可达”切换为“稳定可登录”。
导读
如果你的团队正在做跨机器训练、批处理任务或多地协作,几乎一定会遇到这类问题:
- 内网节点性能很好,但跨地域节点接不进来。
- 调度系统逻辑没问题,网络路径却经常“抽风”。
- SSH 一会儿能连、一会儿连不上,故障恢复全靠运气。
这篇文章给出一套实战可复用方案:
- 用 Cloudflare Tunnel 把跨地域 Worker 稳定接入控制面 Redis。
- 用 Access SSH 把“受限节点”变成可持续运维节点。
- 通过统一队列入口,保持调度策略不变、网络能力升级。
你将得到的不是“单条命令”,而是一套可长期运行的工程化模板:架构图、配置片段、SOP、巡检清单、脱敏发布规范全部齐全。
一图看懂
一、问题背景与目标
1.1 原始挑战
- 节点分散在不同网络地点,存在 NAT、ACL、防火墙差异。
- 调度后端仅在内网地址暴露,跨地域节点无法直接连通。
- 某些节点 SSH 连接偶发失败,影响运维与故障恢复。
1.2 目标定义
- 让所有 Worker 统一接入同一队列后端。
- 跨地域节点无需开放入站端口。
- SSH 通过域名稳定访问,便于日常巡检与自动化。
二、总体架构(脱敏)
graph TB
subgraph "用户侧"
OPS[运维终端]
DEV[开发终端]
end
subgraph "Cloudflare"
EDGE[Edge Network]
DNS[DNS]
end
subgraph "地域A(控制面)"
CP[control-node]
REDIS[(Redis Backend)]
W1[worker-a]
W2[worker-b]
end
subgraph "地域B(跨地域)"
WB[worker-remote]
PXY[cloudflared access tcp\n127.0.0.1:16379]
R9[ops-node]
SSHD[sshd:22]
end
OPS --> EDGE
DEV --> EDGE
DNS --> EDGE
CP --> REDIS
W1 --> REDIS
W2 --> REDIS
WB --> PXY
PXY -. encrypted tunnel .-> EDGE
EDGE -.-> REDIS
OPS -. access ssh .-> EDGE
EDGE -.-> SSHD
R9 --> SSHD
三、关键通道设计
3.1 通道 A:跨地域 Worker -> Redis
目标:将远端节点本地 127.0.0.1:16379 映射到控制面 Redis。
1
2
3
4
# 远端节点上启动本地 TCP 代理(示例)
cloudflared access tcp \
--hostname redis-control.example.com \
--url 127.0.0.1:16379
Worker 进程改为连接本地代理端口:
1
2
3
4
5
python worker_agent.py \
--name worker-remote \
--redis-host 127.0.0.1 \
--redis-port 16379 \
--workers 4
3.2 通道 B:受限节点 SSH 运维
目标:不依赖内网直连 SSH,统一走 Cloudflare Access。
R9(示例节点)上的 tunnel ingress:
1
2
3
4
5
6
tunnel: <tunnel-id-redacted>
credentials-file: /home/<user>/.cloudflared/<tunnel-id-redacted>.json
ingress:
- hostname: ssh-node.example.com
service: ssh://localhost:22
- service: http_status:404
客户端 SSH:
1
2
3
ssh \
-o ProxyCommand='cloudflared access ssh --hostname ssh-node.example.com' \
<user>@ssh-node.example.com
四、落地步骤(可复用)
4.1 准备与认证
1
2
3
4
5
# 控制节点/目标节点均安装 cloudflared
cloudflared --version
# 首次登录授权(浏览器)
cloudflared tunnel login
4.2 创建或复用 Tunnel
1
2
3
4
5
# 创建(若已有可跳过)
cloudflared tunnel create <tunnel-name>
# 查看所有隧道
cloudflared tunnel list
4.3 绑定 DNS
1
2
cloudflared tunnel route dns <tunnel-name> redis-control.example.com
cloudflared tunnel route dns <tunnel-name> ssh-node.example.com
4.4 启动守护进程
1
2
3
4
5
6
7
8
# Redis 通道(远端节点)
nohup cloudflared access tcp \
--hostname redis-control.example.com \
--url 127.0.0.1:16379 > /tmp/cloudflared_redis.log 2>&1 &
# SSH 通道(运维节点)
nohup cloudflared tunnel --config ~/.cloudflared/config-ssh.yml run <tunnel-name> \
> /tmp/cloudflared_ssh.log 2>&1 &
五、提交任务的生产 SOP
5.1 提交入口原则
- 统一提交到控制面(推荐)。
- Worker 自动从全局队列消费,不直接向每台机器单独投递。
5.2 任务 JSON 模板(脱敏示例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"type": "cpu",
"owner": "team-a",
"priority": 60,
"timeout": 3600,
"max_retries": 2,
"command": "cd /home/<user>/project && python3 run.py --mode batch",
"resources": {
"cpu_cores": 4,
"memory_gb": 16,
"gpu_count": 0
},
"labels": ["project:demo", "env:prod"]
}
5.3 提交命令(推荐)
1
bash scheduler_ops/scripts/submit_job_r203.sh scheduler_ops/jobs/example_gpu_job.json
5.4 查询任务状态(按 job_id)
1
2
3
4
from distributed_scheduler import JobPortal
portal = JobPortal(redis_host="<control-redis-ip>", redis_port=6379)
print(portal.get_job_status("job_xxx"))
六、故障处理与经验总结
6.1 常见症状与定位
| 症状 | 可能原因 | 快速检查 |
|---|---|---|
| Worker 在线但不消费 | 连接到错误 Redis 地址 | 检查 --redis-host 与 --redis-port |
| SSH 偶发失败 | 网络 ACL / NAT 路径抖动 | 切换 Cloudflare Access SSH |
| Tunnel 进程在但业务不通 | ingress hostname/service 不匹配 | 检查 config.yml 与 DNS route |
| 多进程互相干扰 | 重启脚本重复启动未清理 | pkill 后单实例拉起 |
6.2 建议的巡检命令
1
2
3
4
5
6
7
8
9
# 检查 worker
ps -ef | grep worker_agent.py | grep -v grep
# 检查 cloudflared
ps -ef | grep cloudflared | grep -v grep
# 检查日志
tail -n 50 /tmp/cloudflared_redis.log
tail -n 50 /tmp/cloudflared_ssh.log
七、图示
- 多节点拓扑总览:
- Tunnel 列表:
- 远端节点本地 TCP 代理日志:
- SSH over Cloudflare 登录:
- 调度任务状态面板:
八、附录:脱敏发布自检清单
为避免泄露环境信息,建议在发布前逐项核对:
- 所有真实域名已替换为示例域名(如
*.example.com)。 - 所有真实 IP 已替换为占位符(如
<control-redis-ip>)。 - 隧道 UUID、connector ID、证书路径不出现在正文或截图中。
- 用户名、主机名、目录名中的组织/个人标识已打码。
- 终端截图中的公网出口信息、地区标记、账号信息已隐藏。
九、结语
这套方案的核心价值不在“把某一台机器连通”,而在“把异构网络环境统一成可运维、可调度、可恢复的运行面”。Cloudflare Tunnel 解决的是连通性基础设施问题,调度系统解决的是资源利用问题;两者结合后,跨地域多节点的交付成本会显著下降。
如果你也在做分布式训练、批处理任务、跨地协作,建议先把网络路径标准化,再做策略优化。先连通,后优化,效率最高。
This post is licensed under CC BY 4.0 by the author.