headscale系列:headsale压力测试
headscale 压力测试
总结摘要
- 测试脚本: Github下载
用法速记:
- 解压后
cp .env.example .env,填好HEADSCALE_URL与TS_AUTHKEY bash scripts/00_check_env.shbash scripts/01_bootstrap_up.sh(默认 200 节点)bash scripts/02_list_nodes.sh→ 生成nodes.tsv- 终端 A:
bash scripts/03_churn.sh(每 30s 随机 up/down/restart) - 终端 B:
watch -n 20 'bash scripts/04_traffic_round.sh'持续抽样流量 - 结束:
bash scripts/99_cleanup.sh
200个客户端同时连接

headscale服务器资源消耗

tailscale客户端服务器资源消耗-200个客户端

一、推荐机器规格(200 设备规模)
将被测 headscale与**发压端(loadgen)**分离,更易定位瓶颈。若你只买一台也能做,但推荐两台。
A. 发压端(运行 200 个 Tailscale 客户端容器)
vCPU:16 核
内存:32 GB
磁盘:100 GB NVMe(Docker 层与容器日志)
网卡:≥ 1 Gbps(最好 5–10 Gbps)
OS:Ubuntu 22.04 LTS / Debian 12
内核参数(建议):
fs.file-max=200000net.core.rmem_max=16777216net.core.wmem_max=16777216net.ipv4.ip_local_port_range=10000 65000
Docker 守护进程日志轮转(避免日志撑满磁盘):
log-driver: "local",log-opts: {"max-size":"10m","max-file":"3"}
B. 被测 headscale(控制面)
- vCPU:4 核
- 内存:8 GB
- 磁盘:100 GB
- 网卡:≥ 1 Gbps
- 数据库:SQLite(WAL 打开)或 PostgreSQL(随你已有环境)
- 反向代理:如必须放在反代后,请放宽超时/保持连接,保证长轮询不被切。
C.(可选)自建 DERP 中继
- vCPU:2–4 核
- 内存:2–4 GB
- 网卡:≥ 1 Gbps
- 开放 TCP(derp) 与 UDP 3478(STUN)
二、目录结构(建议)
你可以在任意目录新建如下文件(均在本文给出内容):
1 | headscale-loadtest/ |
三、使用说明
- 准备:在 headscale 上生成一个 pre-auth key(预授权密钥)。
- 编辑
.env(复制.env.example)填入HEADSCALE_URL和TS_AUTHKEY。 bash scripts/00_check_env.sh检查环境(tun、docker 等)。bash scripts/01_bootstrap_up.sh一键起 200 个 tailscale 客户端容器。bash scripts/02_list_nodes.sh导出容器名 ↔ Tailscale IP 列表。- 抖动:另开终端运行
bash scripts/03_churn.sh(每 30s 随机 up/down/restart 一批)。 - 流量:再开终端循环跑
bash scripts/04_traffic_round.sh(随机挑对做 TCP/UDP 10s 压力)。 - 结束后
bash scripts/99_cleanup.sh清理容器与临时 sidecar。
四、docker-compose 与 .env
说明:我们用
docker compose up --scale tsnode=200 -d来“一行扩容 200 台设备”。hostname 不必手配,容器会使用唯一的容器 ID 作为主机名,注册到 headscale 时也会保持唯一性。
iperf3 不安装进 tailscale 容器里,而是用短生命的 sidecar 容器通过--network=container:<tsnode>共享网络命名空间来发流/收流,避免镜像扩展与 apt 依赖。
docker-compose.yml
1 | services: |
.env.example(复制为 .env 并修改)
1 | # 你的 headscale 外部可达地址(含 https://,勿带结尾斜杠) |
五、脚本集合(保存到 scripts/)
注意:脚本使用
docker compose(v2),以及networkstatic/iperf3作为临时 sidecar 镜像。首次需要联网docker pull,之后就可离线复用。
1) 00_check_env.sh
1 |
|
2) 01_bootstrap_up.sh
1 |
|
3) 02_list_nodes.sh
1 |
|
4) 03_churn.sh(每 30s 随机 up/down/restart 一批)
1 |
|
5) 04_traffic_round.sh(随机起对做 TCP/UDP 流量)
设计为一轮 10s的抽样压测;你可以循环调用或配合
watch -n 20调度。
服务器与客户端都用 临时 sidecar 容器,--network=container:<tsnode>共享网络命名空间,无需在 tsnode 内安装 iperf3。
1 |
|
6) 99_cleanup.sh
1 |
|
六、测试步骤建议
单节点验证
- 修改
.env为REPLICAS=1,bash scripts/01_bootstrap_up.sh。 docker compose exec tsnode-1 tailscale status看是否已连上你的 headscale(可用tailscale netcheck验证直连/DERP)。bash scripts/02_list_nodes.sh确认导出了 IP。
- 修改
扩到 200 节点
.env改回REPLICAS=200,再次01_bootstrap_up.sh。02_list_nodes.sh导出nodes.tsv。
控制面抖动
- 终端 A:
bash scripts/03_churn.sh(默认每 30s 对 10% 做 up/down/restart) - 观察 headscale
/metrics、CPU、内存、日志中PollNetMap等请求量与耗时。
- 终端 A:
数据面吞吐
- 终端 B:
watch -n 20 'bash scripts/04_traffic_round.sh'连续抽样回合。 - 对比直连与 DERP(可在安全组/防火墙层面封掉 UDP,观察 DERP 回退下的吞吐变化)。
- 终端 B:
扩大/缩小与对比
- 把
REPLICAS改为 300/500 试试 headscale 的上限趋势(若机器足够)。 - 分别在无抖动与强抖动两种状态下记录 headscale 的指标差异。
- 把
七、常见问题(FAQ)
为什么用 sidecar 跑 iperf3?
这样无需在 tailscale 镜像里安装任何包;--network=container:<tsnode>会共享该 tsnode 的网络命名空间,等价于“在该设备上跑 iperf3”。Compose 扩容 200 个需要唯一主机名吗?
不需要手工设置。默认容器主机名是容器 ID,Tailscale 设备名会唯一。也可自行加--hostname脚本模式(不建议和--scale混用)。抖动脚本中的
tailscale down/up与docker restart区别?down/up更接近“客户端主动注销/重登录”;restart模拟“设备重启或网络闪断”,三者混合能覆盖更多状态机分支。



















