网络命名空间边界
路由、规则与解析配置各自独立
每个容器拥有独立的 network namespace,内核路由表、iptables 规则与解析配置按命名空间隔离。容器内写入的路由与规则对宿主机不可见,宿主机 main 命名空间保持只读,两个空间之间不存在状态共享。
隔离能力由三件事共同构成:网络命名空间提供边界,策略路由表提供出口选择,隧道设备提供实际的数据通路。三者都位于容器一侧。
路由、规则与解析配置各自独立
每个容器拥有独立的 network namespace,内核路由表、iptables 规则与解析配置按命名空间隔离。容器内写入的路由与规则对宿主机不可见,宿主机 main 命名空间保持只读,两个空间之间不存在状态共享。
额外路由表承载加速出口
容器内新建独立路由表(例如表 100),默认路由与加速出口写在这张表里。规则匹配只对本容器内发起的连接生效,不影响同宿主机上其它容器与宿主机自身进程的查表路径。
数据通路的终点在容器内
隧道设备在容器命名空间内创建,承接策略路由表选中的流量。隧道建立、MTU 协商与重连全部发生在容器内部,宿主机既不需要新增网卡,也不需要加载额外内核模块即可完成加速。
所有加速相关的路由、规则与 DNS 状态都写在业务容器自己的命名空间里,宿主机 main 命名空间保持只读。反过来说,宿主机上已有的出口程序无需停用、无需让出默认网关,可以与加速容器并行运行。分流维度与规则优先级见 智能分流引擎;镜像获取与协议选择见 官方镜像与多协议矩阵。
逐项列出两类方案在网络对象上的差异。判断标准只有一个:该对象最终被写在哪个命名空间里。
| 网络对象 | 所属命名空间 | 传统全局方案 | 快连VPN 容器方案 | 宿主机是否变更 |
|---|---|---|---|---|
| 默认路由 0.0.0.0/0 | main | 覆盖为隧道网卡 | 保持原网关 | 否 |
| 策略路由规则 ip rule | main | 新增 2–5 条规则 | main 表不写入任何规则 | 否 |
| 路由表 100 | 容器 netns | 不适用 | 容器内新建并指向隧道设备 | 否 |
| DNS 解析配置 | 按容器注入 | 改写主机 resolv.conf | 仅覆盖容器内 resolv.conf | 否 |
| iptables/nftables | main / 容器 | 新增 NAT 与 TPROXY 链 | 规则写在容器 netns 内 | 否 |
| 已有出口进程 | 宿主机 | 需停用或让出默认网关 | 并行运行互不抢占 | 否 |
| 回滚方式 | — | 需清理残留规则并重连 | 移除容器即完全回滚,秒级 | 否 |
「传统全局方案」一列描述的是需要改写宿主机 main 命名空间的同类工具的典型行为,用于对照,不代表对任何具体产品的评价。宿主机侧只读这一点也意味着:加速状态随容器生命周期存在,容器重建即重新建立,不会在宿主机上留下需要长期维护的残留规则。镜像体积与 tag 选择见 镜像版本与体积。
理解这套架构只需要五个术语。下面先逐个解释,再给出容器内可直接查看的命令与输出形态。
进入容器查看策略路由规则:规则自上而下匹配,带标记的连接查表 100,其余连接仍按容器原本的 main 表转发。下面是命令与输出形态的示例。
终端 · 容器内查看策略路由# 查看容器命名空间内的策略路由规则
$ docker exec kl-proxy ip rule show
0: from all lookup local
100: from all fwmark 0x1 lookup 100 # 带标记的连接查表 100
32766: from all lookup main # 其余连接按容器原 main 表转发
32767: from all lookup default
# 查看表 100:加速出口指向容器内的隧道设备
$ docker exec kl-proxy ip route show table 100
default dev kl-tun0 # 隧道设备承接表 100 的出向流量
表 100 与设备名 kl-tun0 均为示例口径,用于说明结构关系;实际编号与命名以官方镜像的实现为准。表编号只需要在单个命名空间内唯一,不同容器之间可以重复使用。分流规则如何决定哪些连接打上标记,见 智能分流引擎 的优先级表。
加速要生效,域名解析结果必须与实际出口一致。快连VPN 通过覆盖容器内的解析配置实现这一点,宿主机 resolv.conf 不参与。
容器启动时,解析配置以文件形式挂载进容器命名空间。只读根文件系统场景下,该文件由运行时以 bind 挂载方式提供,因此宿主机 /etc/resolv.conf 既不会被读取改写,也不会被备份还原。
终端 · 查看容器内实际生效的解析配置# 容器内实际生效的 resolv.conf
$ docker exec kl-proxy cat /etc/resolv.conf
nameserver 172.17.0.1
options ndots:1
# fake-ip 模式下的解析结果示例
$ docker exec kl-proxy getent hosts registry.npmjs.org
198.18.0.31 registry.npmjs.org
容器需要解析 *.internal、*.svc.cluster.local 等内网域名时,fake-ip 的保留地址段会让这类请求无法按预期命中内网解析路径,表现为解析成功但连接超时。此类环境应改用真实 IP 模式,并把内网域名指向直连;具体分流写法见 典型配置示例。
零改动是一个可以被证伪的断言。方法很简单:在业务流量跑起来前后各记录一次宿主机路由状态,对比两次输出是否完全一致。
先取基线。基线本身包含宿主机上其它组件留下的规则,后续对比以它为准。
sudo ip rule show | tee /tmp/rule-before.txt
sudo ip route show table main | tee /tmp/main-before.txt
必须由容器内的进程发起,宿主机侧发起的请求不经过容器命名空间,验证不到加速路径。
docker exec kl-proxy curl -sS -o /dev/null https://registry.npmjs.org/
请求完成后立即记录,确保加速链路的建立过程已经结束。
sudo ip rule show | tee /tmp/rule-after.txt
sudo ip route show table main | tee /tmp/main-after.txt
两次 diff 均无输出且退出码为 0,即表示宿主机路由在整个过程中未被改写。
diff /tmp/rule-before.txt /tmp/rule-after.txt ; echo "rule exit=$?"
diff /tmp/main-before.txt /tmp/main-after.txt ; echo "main exit=$?"
两条 diff 命令均不输出任何内容,退出码为 0;若宿主机 main 表出现新增规则、默认路由被替换为隧道网卡,说明存在其它组件在改写宿主机路由,需要先定位该组件,再判断加速链路是否真的可用。容器内加速状态是否生效,可用 kl-ctl status 查看决策元数据。
完整部署顺序、启动参数与验证步骤见 快连VPN 部署文档。若验证中发现加速链路不通但宿主机状态正常,优先检查分流规则的命中维度与出口配置;容器镜像的获取与来源核验见 来源核验与防钓鱼。
不会。加速相关的路由、策略规则与 DNS 状态全部写在业务容器自己的 network namespace 内,宿主机 main 命名空间不写入任何 ip rule,默认路由保持原有网关不变。这正是容器网络隔离方案与传统全局代理工具在行为上的根本差异。
不会。加速规则通过容器命名空间内的策略路由表 100 与 fwmark 只对本容器内发起的连接生效,宿主机上的既有出口进程继续使用 main 表。两套路由表并行存在,不存在抢占默认网关、也不需要停用或让出路由的情况。
删除加速容器即可。容器命名空间内的路由表、策略规则与解析配置随容器一并销毁,宿主机侧从未产生需要清理的残留状态,回滚在秒级完成,不需要重连、重装或手工清理任何 iptables 规则。