不要用WSL,否则会变得不幸

本文最后更新于 2026年3月20日 晚上

有位前辈用一句话形容 Linux:“Linux 本身不要钱,但你(折腾)的时间更费钱。”

而寄宿在 Windows 上的 WSL,更是把这句话发挥到极致。

当时我从头搭建 Kubernetes 工具链。由于家境贫寒,本想用手头 4 台老旧 PC 搭个能用就行的集群;结果在 Windows 里装 WSL、再在 WSL 里折腾 Kubernetes 的过程中,遇到太多看不到尽头的问题,最后只好放弃。

目前我的方案是:把其中 2 台 PC 直接装 Ubuntu,至少先把一个最小可用的主从集群跑起来。

这篇文章就当作一次“失败复盘”:记录我在 WSL 上踩过的坑,等以后学有余力了再回头补课。

没想到吧,3年后是 AI (GPT-5.3-Codex) 来帮忙补课!

既然都 update 了那就多写两句,那个时候刚刚从云原生的 start-up 被开,怀着现在已经想不起的心情,想着要潜心打好云原生相关的基础,大展拳脚,所以想从头夯实基础,且那个时候手头拮据,不像现在家里好几台电脑,又加戏想通过不用虚拟机来体现逼格顺便学更多东西,真的是学习的门都没有摸到。

后来进了声网又做和富途一样的客户端相关的事情了,完全和云原生没关系。

再后来去了百度云,也不需要自己装了,光速跑路之后终于到了 NXP 而且巧合的也是客户端,这下是彻底告别云原生了,不过总结来看,其实我也就只有这一段经历而已,其他基本上都是客户端。

现在又是 AI 时代,除非我有缘做到 AI Infra,否则再也不会和云原生有关了。

文字的神奇之处就在于可以穿越时空对话,不知道我下次 update 的时候又是什么境地。

--- 2026年3月,写于上海黄浦区

1. WSL 的适用范围(我的结论)

写写 Python、跑跑普通的前后端应用,WSL 非常合适,甚至能省掉在 Windows 上装一堆软件的麻烦。

但一旦涉及更底层的东西,比如虚拟化、容器化、集群化,尤其是会碰到“网卡/路由/桥接/iptables”这类东西时,WSL 这种基于 Hyper-V 的“精简版虚拟机”就容易变得缺胳膊少腿。

那种感觉很像早年用“番茄花园”精简版 Windows 打游戏:能用,但关键组件缺一块,问题还特别难查。


AI 辅助解法(2026 视角补充)

  • 如果你的目标是 Kubernetes/容器/网络实验:优先顺序基本是
    1. 物理机 Linux
    2. 正经虚拟机(VMware/VirtualBox/Hyper-V VM)
    3. WSL(适合开发,不适合当“底层实验场”)
  • 如果你只是想在 Windows 上跑容器:可以直接用 Docker Desktop(WSL2 后端),不要手搓一堆 systemd/iptables/网络。

2. 最好的方案是物理机,其次是真正的虚拟机

那几天我一直在坑里匍匐:很多问题要么没有通用解法,要么网上的“解法”试下来根本不管用。

最后我的学习阶段建议很朴素:真要折腾底层,就用物理机;退而求其次,用 VMware / VirtualBox 这种成熟到不能再成熟的虚拟机。


AI 辅助解法(2026 视角补充)

  • 如果你坚持 Windows 作为主力:可以把“底层实验环境”彻底隔离成一台 VM,省心很多。
  • 如果你要做局域网里多节点互联:VM 的桥接、Host-only、NAT 这些网络模式更可控,也更符合大多数教程的默认前提。

AI 没活硬整, prompt 里说了补充下就真没什么说的废话也要补充一下,像极了我写周报的样子。

3. 时用 WSL 上遇到的问题

3.1 systemd 与 systemctl:很多服务根本起不来

systemd 是 Linux 常见的初始化系统和服务管理器;

systemctl 是 systemd 的命令行工具,用来启动、停止、重启、查看服务状态、设置开机自启等。

WSL2 本身是由 Windows 负责运行的,因此你用 treeps 去看进程时,会发现根进程(PID 1)不是 systemd。这会导致很多依赖 systemd 的服务守护进程(daemon)无法按预期启动。

当我执行 systemctl 时,会提示 init system (PID 1) 并非 systemd,而是微软提供的 init。

即使在 /etc/wsl.conf 里加 systemd=true 之类的配置,当时也还是会遇到各种问题。

3.1.1 用 service 代替 systemctl 也不稳

有些时候能用 service 顶一下 systemctl,但也经常出现:

Failed to connect to bus: No such file or directory

比如我跑一个“自动安装 Docker / 自动开启 SSH”的脚本,脚本默认用 systemctl,还是绕不开这个问题。

而我如果去批量替换别人的脚本,又会引入新的问题。


AI 辅助解法(2026 视角补充)

  • 先确认 WSL 版本是否足够新:
    • wsl --version
    • 旧版 WSL 对 systemd 支持不完整,很多“教程能跑”的前提是 新 WSL + 新发行版
  • 如果要启用 systemd(适用于支持 systemd 的新版 WSL):
    1. 编辑 /etc/wsl.conf
      1
      2
      [boot]
      systemd=true
    2. 在 Windows 侧执行:
      1
      wsl --shutdown
    3. 重新进入 WSL 验证:ps -p 1 -o comm= 应该看到 systemd
  • 如果你只是“为了跑 Docker”:
    • 直接用 Docker Desktop,或者在 VM/物理机里装 Docker,会省掉 80% 的时间。

真不愧是 AI ,我当时肯定是试过的,这个 systemd 在装当时的 k8s 某些组件的时候会疯狂报错,只能说让 AI 处理互相矛盾的资料还是太难为它了。

3.2 WSL2 无法联网:DNS / 网络栈异常

3.2.1 resolv.conf 被自动生成,而且 nameserver 不对

参考:

打开:

sudo vim /etc/resolv.conf

你会看到类似:

1
2
3
4
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf
# [network]
# generateResolvConf = false
nameserver xxx.xx.xx

把 nameserver 改成 8.8.8.8 保存后,就可能恢复网络。

3.2.2 winsock 相关的重置

参考:

管理员模式打开 CMD,执行:

1
2
3
4
netsh winsock reset
netsh int ip reset all
netsh winhttp reset proxy
ipconfig /flushdns

完成之后一定要重启 WSL,否则修改不生效。


AI 辅助解法(2026 视角补充)

  • 修改 DNS 时,建议“从根上禁止自动覆盖”,否则你下次重启又变回去:
    1. 编辑 /etc/wsl.conf
      1
      2
      [network]
      generateResolvConf=false
    2. 删除并重建 resolv.conf:
      1
      2
      sudo rm -f /etc/resolv.conf
      echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
    3. Windows 侧执行 wsl --shutdown 再重进。

3.3 SSH / 局域网访问:连得上 localhost,连不上局域网

WSL2 可以直接用 Windows 命令行进入,也可以通过 VSCode 的 WSL 插件直接连。

但我想要的其实是:从局域网另一台机器 ssh 进来(因为我要做集群)。

3.3.1 无法设置 Bridge Network(桥接)

在正经虚拟机里,设置桥接网络通常就是点两下。

但在 WSL 上我没搞定。各种教程都说去 Windows 的 Hyper-V 管理器里设置一下就行,可如果真这么简单,也不会有这篇文章了。

3.3.2 kex_exchange_identification: Connection closed by remote host

在 WSL2 里开启 sshd 之后,连本机 WSL2 用 ssh localhost 通常没问题。

但当我从局域网另一台 PC 去连 WSL2 时,就会出现标题这个报错,甚至更离谱的 timeout。我尝试了很多次都没成功(多半还是因为上面的桥接没搞定)。


AI 辅助解法(2026 视角补充)

  • 先认清一个现实:WSL2 的网络更像“在 NAT 后面的一台虚拟机”,它并不是设计来当“局域网可直连服务器”的。
  • 如果你只是需要“从 Windows 以外访问 WSL 的 ssh”:
    • 一个常见思路是 Windows 做端口转发(portproxy)把 Windows 的 22 转到 WSL 的 22(或别的端口)。
    • 但这条路会牵扯到防火墙、WSL IP 变化、重启失效等一堆维护成本。
  • 如果你的目标是“局域网多节点互联 + 固定 IP + 跑集群”:
    • 直接用 VM(桥接)或物理机 Linux,会更接近真实环境,也更省时间。

AI 还是太怕得罪人了,是我我就直说建议放弃。

3.4 Transport endpoint is not connected:建议放弃

这个问题的原因太多了。

我当时的临时做法是不断重启 LxssManager 服务,有时能暂时恢复一下。但最后我就是被这个问题搞到彻底放弃。

LxssManager 是 Windows 10 中的一个服务,它支持运行本机 ELF 二进制文件。该服务提供在 Windows 上运行 ELF 二进制文件所需的基础结构。WSL 是 Windows Subsystem for Linux 的缩写,它是一个允许在 Windows 10 上运行 Linux 二进制文件的兼容层。LxssManager 是 WSL 的一部分,它负责管理 WSL 的 Linux 发行版。


AI 辅助解法(2026 视角补充)

  • 先做“最小破坏”的恢复动作(比重启机器轻):
    • Windows 侧:wsl --shutdown(这一步很关键)
    • 或者:wsl --terminate <发行版名>
  • 如果你频繁遇到这个错误,通常要从“文件系统挂载/虚拟化通道/磁盘状态”去排:
    • 尽量把重 IO 的东西放在 WSL 自己的 Linux 文件系统里(而不是 /mnt/c/...
    • 检查 Windows 磁盘、杀毒软件、同步软件是否在干扰
  • 但说实话:如果你的主要目标是 Kubernetes 集群,这个坑不值得长时间死磕。

嘿,这里学会说放弃了。

3.5 swap:在 WSL 上关不掉(当时)

部署 Kubernetes 的机器通常要求关闭 swap,因为写入虚拟内存会影响性能,也可能造成系统卡顿。

在实体机上只要 sudo swapoff -a 就能搞定;

但我当时在 WSL 上死活不起作用。推测 WSL 的 swap 是由 Windows 上某个专门负责虚拟化的东西统一配置的,所以这个问题既偏门又难查。


AI 辅助解法(2026 视角补充)

  • WSL 的 swap/内存上限通常由 Windows 侧配置控制:
    • 检查用户目录下的 ~/.wslconfig(Windows 路径:C:\Users\<你>\.wslconfig
    • 常见写法类似:
      1
      2
      [wsl2]
      swap=0
    • 改完后执行:wsl --shutdown
  • Kubernetes 角度还有一个“绕开法”(不推荐长期用):让 kubelet 不因为 swap 直接 fail(具体参数随版本变化)。
    • 但这会掩盖真实环境问题,不适合作为学习路线的默认方案。

4. 后来我怎么做的:Ubuntu 物理机/虚拟机桥接 + 固定 IP

最后我还是回到了“正统解法”:用 Ubuntu 直接桥接进局域网,给节点固定 IP。

4.1 入网方式(虚拟机常见三种)

一般虚拟机软件都提供多种网络模式,主要有:

  • NAT 模式:虚拟机不直接接入局域网,和集群里的 Node 宿主机互相 ping 不通,不选
  • Bridged Adapter 模式:即桥接模式,为虚拟机模拟出一个独立网卡,用独立 IP 接入局域网,

4.2 固定 IP(netplan)

当虚拟机使用桥接模式接入局域网之后,就和物理机 Ubuntu 的设置一样了。

Ubuntu 18.04 LTS 之后的版本使用 /etc/netplan/ 下的文件来配置网络。我当时用的文件名是 01-network-manager-all.yaml

先用 ifconfig 查看网络情况,找到桥接网卡名称(我这里是 enp0s3);

然后:sudo vim /etc/netplan/01-network-manager-all.yaml,添加类似内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Let NetworkManager manage all devices on this system
network:
ethernets:
enp0s3: # 配置的网卡名称
addresses: [192.168.31.50/24] # 静态 IP 和掩码
dhcp4: no # 关闭 DHCP,如果需要打开则写 yes
optional: true
routes:
- to: 0.0.0.0/0
via: 192.168.31.1 # 网关地址
nameservers:
addresses: [192.168.31.1] # DNS 地址,多个用英文逗号分隔
version: 2
renderer: networkd # 指定后端采用 systemd-networkd 或 NetworkManager

networkd 和 NetworkManager 都是用于管理网络接口的后端。networkd 是 systemd 的一部分,是一个轻量级网络管理器;NetworkManager 更“高级”,一般桌面版用得多。


AI 辅助解法(2026 视角补充)

  • netplan 改完别忘了:
    1
    sudo netplan apply
  • 如果你在服务器上只想要稳定:
    • renderer 选 networkd 往往更省心;桌面环境/需要 GUI 再考虑 NetworkManager。
  • 集群环境下,固定 IP 只是第一步:
    • 还要同步考虑网关、DNS、节点名解析(hosts / 内网 DNS)、以及后续的 CNI 网络规划。

按行数算钱是吧,这都不是 WSL 遇到的问题了,而且写的也是废话,料想我领导看我写的估计也是这个感觉。


不要用WSL,否则会变得不幸
https://gou7ma7.github.io/2023/04/30/devops/@2023_no_wsl/
作者
Roy Lee
发布于
2023年4月30日
许可协议