不要用WSL,否则会变得不幸
有位前辈用“Linux本身不要钱,但是你(折腾)的时间更费钱”来形容Linux上可能遇到的适配问题,从而表达自己对该系统又爱又恨的感情。
而寄宿在Windows上的WSL,更是将这个说法发挥到极致。
在我自己从头搭建Kubernetes工具链的时候,由于家境贫寒,本想就着手上4台老旧PC搭建个基本能用的集群就行,结果在Windows里面装WSL,以及WSL里面装Kubernetes的时候,遇到太多看不到尽头的问题,遂放弃。
目前我的解决方案是安装Ubuntu系统到其中2台PC,至少先跑起来一个最小的主从集群。
而本次我本身就是为了学习才搭建环境,因此记录下遇到的WSL相关的问题,以便学有余力的时候更加透彻的掌握操作系统相关的知识。
``WSL的适用范围
写写Python代码,搭建普通的前后端应用,WSL是非常合适的,甚至避免了在Windows上安装软件的麻烦事。
但是在涉及到底层的东西,比如说虚拟化、容器化、集群化等这种需要用到“网卡”之类硬件的配置的时候,WSL这类基于Hyper-v的“精简版”虚拟机就会变得缺胳膊少腿,有早年用过“番茄花园”这种精简版Windows打游戏然后缺少组件经历的朋友就能体会到我的感受。
最好的是物理机,其次是真正的虚拟机
这几天我一直在满是坑的泥泞中匍匐,很多问题要么是没有通用解法,要么是试下来根本不管用。
最后学习阶段只推荐VMware、VirtualBox这种成熟得不能再成熟的真正的虚拟机,如果不信欢迎自行尝试。
systemd与systemctl
systemd是一个Linux系统的初始化系统和服务管理器;
而systemctl是systemd的一个命令行工具,用于控制systemd系统和服务管理器。
systemctl可以启动、停止、重启、重载、状态检查、启用或禁用系统服务。
WSL2本身是由Windows负责运行的,因此使用tree或ps命令时会看到根进程不是systemd,这将导致无法启动Linux系统服务的守护进程(deamon)。当我们执行systemctl命令的时候,会显示出我们的init system (PID 1)并非systemd,而是微软提供的init system。
即使在/etc/wsl.conf添加systemd=true配置等操作也会有各种问题。
service代替systemctl
虽然有些时候能够通过service代替systemctl,但是有些时候会出现Failed to connect to bus: No such file or directory
的错误。
比如我跑一个自动安装docker / 自动开启ssh的脚本的时候,由于源头默认提供的脚本是使用systemctl的,还是绕不开这个问题。
如果我去批量替换别人的脚本,又会带来新的问题。
WSL2无法连接网络
Windows automatically generates resolv.conf file with wrong nameserver
https://stackoverflow.com/questions/62314789/no-internet-connection-on-wsl-ubuntu-windows-subsystem-for-linux
Locate the file by running the following command:
sudo vim /etc/resolv.conf
You will see the following in the file:
This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/resolv.conf
1 |
|
Change the nameserver value to 8.8.8.8 and save the file. You should now be able to connect to the internet.
winsock
https://github.com/microsoft/WSL/issues/3438#issuecomment-41051857
Open Command Prompt as an Administrator and type these commands:
1 |
|
完成之后一定重启WSL,否则修改不生效。
SSH
WSL2可以直接用Windows的命令行直接进入,也可以通过VSCode的WSL插件直接本地连接WSL;
无法Set Bridge Network
在正统的虚拟机配置设置Bridge Network都是点一键就能拿完成的工作,我无法在WSL上完成,虽然各种教程都说在Windows上的Hyper-v管理器上设置一下就好了,但是如果真的是这样的话,就不会有这篇文章了。
kex_exchange_identification: Connection closed by remote host
在WSL2中开启sshd服务之后,连接自己机器上的WSL2只需要通过ssh localhost
就可以;
连接局域网中另一个PC物理机上的WSL2就会出现标题标错,还有更离谱的timeout,我尝试过很多,就没成功过(多半是因为上面Set Bridge Network没成功导致的)。
Transport endpoint is not connected
导致这个问题的原因太多了,不断重启LxssManager服务可能会暂时可用一下,我就是被这个问题搞得彻底放弃的。
LxssManager是Windows 10中的一个服务,它支持运行本机ELF二进制文件。该服务提供在Windows上运行ELF二进制文件所需的基础结构。WSL是Windows Subsystem for Linux的缩写,它是一个允许在Windows 10上运行Linux二进制文件的兼容层。LxssManager是WSL的一部分,它负责管理WSL的Linux发行版。
swap
首先部署Kubernetes的机器不能开启swap,因为在写入虚拟内存的时候会影响性能和造成系统卡顿;
于是在实体机上只需要sudo swapoff -a
简单一步的操作,在WSL上死活不起作用,推测是WSL的swap是由Windows上的某个专门负责虚拟化的服务进行配置的,然后由于问题太过偏门,尝试了之后没有找到轻松有效的方法。
Ubuntu 桥接接入局域网固定IP
入网方式
一般虚拟机软件都提供多种网络模式,主要有:
NAT模式: 虚拟机没有直接接入局域网,和集群里面的Node宿主机互相ping不通,不选
Bridged Adapter模式:即桥接模式,为虚拟机模拟出一个独立的网卡,有独立的IP地址接入局域网,选
固定IP
当虚拟机使用桥接模式接入局域网之后,就和物理机Ubuntu的设置一样了。
Ubuntu 18.04 LTS之后的版本使用/etc/netplan/下得文件来配置网络,我这里叫01-network-manager-all.yaml。
首先使用ifconfig
查看当前机器的网络情况,找到桥接的网卡名称,我这里是enp0s3
;
然后使用sudo vim /etc/netplan/01-network-manager-all.yaml
打开配置文件,添加如下内容:
1 |
|
networkd和NetworkManager都是用于管理网络接口的后端。networkd是systemd的一部分,它是一个轻量级的网络管理器,可以在Ubuntu 18.04及更高版本中使用。它使用Netplan配置文件来配置网络接口。NetworkManager是一个更高级的网络管理器,可以在Ubuntu 16.04及更高版本中使用。它提供了一个GUI界面,可以方便地配置网络接口。