Table of Content

The main difference between WSL1 and WSL2 that later is hyper-v based Microsoft Linux version, it sounds like excited news at least it is running full Linux kernel but there are too many issues if use as devops box.

Here are some examples:

  • WSL2 ip dynamic assigned after reboot, so it is not static ip, will give trouble for app like k8s api server
  • WSL2 uses own boot system so systemd not run as default even it exists

install WSL2 Ubuntu

https://docs.microsoft.com/en-us/windows/wsl/install

PS C:\Users\oldhorse> wsl -l -o
The following is a list of valid distributions that can be installed.
Install using 'wsl --install -d '.

NAME            FRIENDLY NAME
Ubuntu          Ubuntu
Debian          Debian GNU/Linux
kali-linux      Kali Linux Rolling
openSUSE-42     openSUSE Leap 42
SLES-12         SUSE Linux Enterprise Server v12
Ubuntu-16.04    Ubuntu 16.04 LTS
Ubuntu-18.04    Ubuntu 18.04 LTS
Ubuntu-20.04    Ubuntu 20.04 LTS
PS C:\Users\oldhorse> wsl --install -d Ubuntu-20.04
Downloading: Ubuntu 20.04 LTS
Installing: Ubuntu 20.04 LTS
Ubuntu 20.04 LTS has been installed.
Launching Ubuntu 20.04 LTS...

will launch new terminal,
Installing, this may take a few minutes...
Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: oldhorse
New password:
Retype new password:
passwd: password updated successfully
Installation successful!
To run a command as administrator (user "root"), use "sudo ".
See "man sudo_root" for details.

Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.10.16.3-microsoft-standard-WSL2 x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sat Oct 23 12:28:21 EDT 2021

  System load:  0.0                Processes:             8
  Usage of /:   0.4% of 250.98GB   Users logged in:       0
  Memory usage: 4%                 IPv4 address for eth0: 172.30.142.245
  Swap usage:   0%

0 updates can be installed immediately.
0 of these updates are security updates.

The list of available updates is more than a week old.
To check for new updates run: sudo apt update

This message is shown once once a day. To disable it please create the
/home/oldhorse/.hushlogin file.                        ]

remedy for "static" ip

WSL2 Set static ip? · Issue #4210 · microsoft/WSL · GitHub

Assume we want to keep static ip 192.168.80.2 for WSL2 Ubuntu, run below batch script as Administrator on windows host, you can type wsl2ip.bat from CMD, PS or place shortcut icon on desktop. It re-create eth0 with static ip, update routing, nameserver and re-create adapter vEthernet for WSL, also change to NAT.

C:\Users\oldhorse>type wsl2ip.bat

 

date /t
time /t

wsl -d Ubuntu-20.04 -u root ip addr del $(ip addr show eth0 ^| grep 'inet\b' ^| awk '{print $2}' ^| head -n 1) dev eth0
wsl -d Ubuntu-20.04 -u root ip addr add 192.168.80.2/24 broadcast 192.168.80.255 dev eth0
wsl -d Ubuntu-20.04 -u root ip route add 0.0.0.0/0 via 192.168.80.1 dev eth0
wsl -d Ubuntu-20.04 -u root echo nameserver 192.168.80.1 ^> /etc/resolv.conf

powershell -c "Get-NetAdapter 'vEthernet (WSL)' | Get-NetIPAddress | Remove-NetIPAddress -Confirm:$False; New-NetIPAddress -IPAddress 192.168.80.1 -PrefixLength 24 -InterfaceAlias 'vEthernet (WSL)'; Get-NetNat | ? Name -Eq WSLNat | Remove-NetNat -Confirm:$False; New-NetNat -Name WSLNat -InternalIPInterfaceAddressPrefix 192.168.80.0/24;"

date /t
time /t

more detail after run above script, you can access from host to WSL2,

 
PS C:\Users\oldhorse> Get-NetAdapter 'vEthernet (WSL)' | Get-NetIPAddress

IPAddress         : 192.168.80.1
InterfaceIndex    : 24
InterfaceAlias    : vEthernet (WSL)
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Preferred
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : ActiveStore

PS C:\Users\oldhorse> Get-NetNat 'WSLNat'

Name                             : WSLNat
ExternalIPInterfaceAddressPrefix :
InternalIPInterfaceAddressPrefix : 192.168.80.0/24
IcmpQueryTimeout                 : 30
TcpEstablishedConnectionTimeout  : 1800
TcpTransientConnectionTimeout    : 120
TcpFilteringBehavior             : AddressDependentFiltering
UdpFilteringBehavior             : AddressDependentFiltering
UdpIdleSessionTimeout            : 120
UdpInboundRefresh                : False
Store                            : Local
Active                           : True

PS C:\Users\oldhorse> ipconfig

Windows IP Configuration

Ethernet adapter Ethernet0:

   Connection-specific DNS Suffix  . : localdomain
   Link-local IPv6 Address . . . . . : fe80::11ea:5863:88e8:de93%10
   IPv4 Address. . . . . . . . . . . : 100.94.195.130
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 100.94.195.2

Ethernet adapter vEthernet (Default Switch):

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::f46d:852c:ce33:4823%13
   IPv4 Address. . . . . . . . . . . : 172.26.160.1
   Subnet Mask . . . . . . . . . . . : 255.255.240.0
   Default Gateway . . . . . . . . . :

Ethernet adapter vEthernet (WSL):

   Connection-specific DNS Suffix  . :
   IPv4 Address. . . . . . . . . . . : 192.168.80.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . :
PS C:\Users\oldhorse> ping 192.168.80.2

Pinging 192.168.80.2 with 32 bytes of data:
Reply from 192.168.80.2: bytes=32 time=1ms TTL=64
Reply from 192.168.80.2: bytes=32 time=1ms TTL=64

also you can access from WSL2 to host, Internet like google as well,

oldhorse@dreamcloud:~$ ping google.ca
PING google.ca (172.217.13.195) 56(84) bytes of data.
64 bytes from yul03s05-in-f3.1e100.net (172.217.13.195): icmp_seq=1 ttl=127 time=15.4 ms
64 bytes from yul03s05-in-f3.1e100.net (172.217.13.195): icmp_seq=2 ttl=127 time=14.0 ms

# access to host from WSL2
oldhorse@dreamcloud:~$ ping 100.94.195.130
PING 100.94.195.130 (100.94.195.130) 56(84) bytes of data.
64 bytes from 100.94.195.130: icmp_seq=1 ttl=127 time=1.28 ms
64 bytes from 100.94.195.130: icmp_seq=2 ttl=127 time=0.623 ms

enable systemd

Found this smart guy who created script to enable systemd on WSL2.

GitHub – DamionGans/ubuntu-wsl2-systemd-script: Script to enable systemd support on current Ubuntu WSL2 images [Unsupported, no longer updated]

sudo apt install git
git clone https://github.com/DamionGans/ubuntu-wsl2-systemd-script.git
cd ubuntu-wsl2-systemd-script/
bash ubuntu-wsl2-systemd-script.sh

log sample here,

oldhorse@dreamcloud:~$ sudo apt install git
[sudo] password for oldhorse:
Reading package lists... Done
Building dependency tree
Reading state information... Done
git is already the newest version (1:2.25.1-1ubuntu3).
git set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
oldhorse@dreamcloud:~$ git clone https://github.com/DamionGans/ubuntu-wsl2-systemd-script.git
-systemd-script/
bash ubuntu-wsl2-systemd-script.shCloning into 'ubuntu-wsl2-systemd-script'...
remote: Enumerating objects: 118, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 118 (delta 0), reused 2 (delta 0), pack-reused 115
Receiving objects: 100% (118/118), 34.22 KiB | 730.00 KiB/s, done.
Resolving deltas: 100% (57/57), done.
oldhorse@dreamcloud:~$ cd ubuntu-wsl2-systemd-script/
oldhorse@dreamcloud:~/ubuntu-wsl2-systemd-script$ bash ubuntu-wsl2-systemd-script.sh
Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:2 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]
Get:3 http://security.ubuntu.com/ubuntu focal-security/main amd64 Packages [945 kB]
Get:4 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:5 http://archive.ubuntu.com/ubuntu focal-backports InRelease [101 kB]
Get:6 http://security.ubuntu.com/ubuntu focal-security/main Translation-en [178 kB]
Get:7 http://security.ubuntu.com/ubuntu focal-security/main amd64 c-n-f Metadata [8840 B]
Get:8 http://security.ubuntu.com/ubuntu focal-security/restricted amd64 Packages [482 kB]
Get:9 http://archive.ubuntu.com/ubuntu focal/main amd64 Packages [970 kB]
Get:10 http://security.ubuntu.com/ubuntu focal-security/restricted Translation-en [69.2 kB]
Get:11 http://security.ubuntu.com/ubuntu focal-security/restricted amd64 c-n-f Metadata [508 B]
Get:12 http://security.ubuntu.com/ubuntu focal-security/universe amd64 Packages [647 kB]
Get:13 http://security.ubuntu.com/ubuntu focal-security/universe Translation-en [106 kB]
Get:14 http://security.ubuntu.com/ubuntu focal-security/universe amd64 c-n-f Metadata [12.6 kB]
Get:15 http://security.ubuntu.com/ubuntu focal-security/multiverse amd64 Packages [21.9 kB]
Get:16 http://security.ubuntu.com/ubuntu focal-security/multiverse Translation-en [4948 B]
Get:17 http://security.ubuntu.com/ubuntu focal-security/multiverse amd64 c-n-f Metadata [540 B]
Get:18 http://archive.ubuntu.com/ubuntu focal/main Translation-en [506 kB]
Get:19 http://archive.ubuntu.com/ubuntu focal/main amd64 c-n-f Metadata [29.5 kB]
Get:20 http://archive.ubuntu.com/ubuntu focal/universe amd64 Packages [8628 kB]
Get:21 http://archive.ubuntu.com/ubuntu focal/universe Translation-en [5124 kB]
Get:22 http://archive.ubuntu.com/ubuntu focal/universe amd64 c-n-f Metadata [265 kB]
Get:23 http://archive.ubuntu.com/ubuntu focal/multiverse amd64 Packages [144 kB]
Get:24 http://archive.ubuntu.com/ubuntu focal/multiverse Translation-en [104 kB]
Get:25 http://archive.ubuntu.com/ubuntu focal/multiverse amd64 c-n-f Metadata [9136 B]
Get:26 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages [1294 kB]
Get:27 http://archive.ubuntu.com/ubuntu focal-updates/main Translation-en [269 kB]
Get:28 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 c-n-f Metadata [14.4 kB]
Get:29 http://archive.ubuntu.com/ubuntu focal-updates/restricted amd64 Packages [522 kB]
Get:30 http://archive.ubuntu.com/ubuntu focal-updates/restricted Translation-en [74.8 kB]
Get:31 http://archive.ubuntu.com/ubuntu focal-updates/restricted amd64 c-n-f Metadata [504 B]
Get:32 http://archive.ubuntu.com/ubuntu focal-updates/universe amd64 Packages [866 kB]
Get:33 http://archive.ubuntu.com/ubuntu focal-updates/universe Translation-en [186 kB]
Get:34 http://archive.ubuntu.com/ubuntu focal-updates/universe amd64 c-n-f Metadata [19.3 kB]
Get:35 http://archive.ubuntu.com/ubuntu focal-updates/multiverse amd64 Packages [24.6 kB]
Get:36 http://archive.ubuntu.com/ubuntu focal-updates/multiverse Translation-en [6856 B]
Get:37 http://archive.ubuntu.com/ubuntu focal-updates/multiverse amd64 c-n-f Metadata [620 B]
Get:38 http://archive.ubuntu.com/ubuntu focal-backports/main amd64 Packages [2568 B]
Get:39 http://archive.ubuntu.com/ubuntu focal-backports/main Translation-en [1120 B]
Get:40 http://archive.ubuntu.com/ubuntu focal-backports/main amd64 c-n-f Metadata [400 B]
Get:41 http://archive.ubuntu.com/ubuntu focal-backports/restricted amd64 c-n-f Metadata [116 B]
Get:42 http://archive.ubuntu.com/ubuntu focal-backports/universe amd64 Packages [5800 B]
Get:43 http://archive.ubuntu.com/ubuntu focal-backports/universe Translation-en [2068 B]
Get:44 http://archive.ubuntu.com/ubuntu focal-backports/universe amd64 c-n-f Metadata [276 B]
Get:45 http://archive.ubuntu.com/ubuntu focal-backports/multiverse amd64 c-n-f Metadata [116 B]
Fetched 22.1 MB in 39s (562 kB/s)
Reading package lists... Done
(Reading database ... 31836 files and directories currently installed.)
Preparing to unpack .../0-dbus-user-session_1.12.16-2ubuntu2.1_amd64.deb ...
Unpacking dbus-user-session (1.12.16-2ubuntu2.1) over (1.12.16-2ubuntu2) ...
Preparing to unpack .../1-dbus-x11_1.12.16-2ubuntu2.1_amd64.deb ...
Unpacking dbus-x11 (1.12.16-2ubuntu2.1) over (1.12.16-2ubuntu2) ...
Preparing to unpack .../2-dbus_1.12.16-2ubuntu2.1_amd64.deb ...
Unpacking dbus (1.12.16-2ubuntu2.1) over (1.12.16-2ubuntu2) ...
Preparing to unpack .../3-libdbus-1-3_1.12.16-2ubuntu2.1_amd64.deb ...
Unpacking libdbus-1-3:amd64 (1.12.16-2ubuntu2.1) over (1.12.16-2ubuntu2) ...
Selecting previously unselected package daemonize.
Preparing to unpack .../4-daemonize_1.7.8-1_amd64.deb ...
Unpacking daemonize (1.7.8-1) ...
Selecting previously unselected package fontconfig.
Preparing to unpack .../5-fontconfig_2.13.1-2ubuntu3_amd64.deb ...
Unpacking fontconfig (2.13.1-2ubuntu3) ...
Setting up fontconfig (2.13.1-2ubuntu3) ...
Regenerating fonts cache... done.
Setting up libdbus-1-3:amd64 (1.12.16-2ubuntu2.1) ...
Setting up dbus (1.12.16-2ubuntu2.1) ...
Setting up daemonize (1.7.8-1) ...
Setting up dbus-x11 (1.12.16-2ubuntu2.1) ...
Setting up dbus-user-session (1.12.16-2ubuntu2.1) ...
Processing triggers for systemd (245.4-4ubuntu3) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for libc-bin (2.31-0ubuntu9) ...
'\\wsl.localhost\Ubuntu-20.04\home\oldhorse\ubuntu-wsl2-systemd-script'
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported.  Defaulting to Windows directory.

SUCCESS: Specified value was saved.
'\\wsl.localhost\Ubuntu-20.04\home\oldhorse\ubuntu-wsl2-systemd-script'
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported.  Defaulting to Windows directory.

SUCCESS: Specified value was saved.

shutdown WSL2 and apply static ip script before reboot,

wsl --shutdown 
.\wsl2ip.bat 

will see systemctl is working now.

Linux native Docker

The systemd is ready so just following the docker doc to install docker on Ubuntu,

https://docs.docker.com/engine/install/

install success using Ubuntu procedure, put in script docker-install.sh below,

sudo apt-get update -y
sudo apt-get install -y ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update -y
sudo apt-get install -y docker-ce docker-ce-cli containerd.io

sudo groupadd docker
sudo usermod -aG docker $USER

# turn off swap
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab

sudo mkdir /etc/docker
cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF
sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker

re-login to WSL2, docker working for non-root user,

 
docker info 
docker ps 

verify docker daemon,

oldhorse@dreamcloud:/mnt/c/Users/oldhorse$ systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2021-10-23 14:50:26 EDT; 12min ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 7346 (dockerd)
      Tasks: 8
     Memory: 40.4M
     CGroup: /system.slice/docker.service
             └─7346 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Oct 23 14:50:24 dreamcloud dockerd[7346]: time="2021-10-23T14:50:24.769716900-04:00" level=warning msg="Your kernel does not support cgroup blkio throttle.write_bps_dev>
Oct 23 14:50:24 dreamcloud dockerd[7346]: time="2021-10-23T14:50:24.769812100-04:00" level=warning msg="Your kernel does not support cgroup blkio throttle.read_iops_dev>
Oct 23 14:50:24 dreamcloud dockerd[7346]: time="2021-10-23T14:50:24.770885100-04:00" level=warning msg="Your kernel does not support cgroup blkio throttle.write_iops_de>
Oct 23 14:50:24 dreamcloud dockerd[7346]: time="2021-10-23T14:50:24.771694200-04:00" level=info msg="Loading containers: start."
Oct 23 14:50:25 dreamcloud dockerd[7346]: time="2021-10-23T14:50:25.422879100-04:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/>
Oct 23 14:50:26 dreamcloud dockerd[7346]: time="2021-10-23T14:50:26.078144600-04:00" level=info msg="Loading containers: done."
Oct 23 14:50:26 dreamcloud dockerd[7346]: time="2021-10-23T14:50:26.170241500-04:00" level=info msg="Docker daemon" commit=79ea9d3 graphdriver(s)=overlay2 version=20.10>
Oct 23 14:50:26 dreamcloud dockerd[7346]: time="2021-10-23T14:50:26.170987700-04:00" level=info msg="Daemon has completed initialization"
Oct 23 14:50:26 dreamcloud systemd[1]: Started Docker Application Container Engine.
Oct 23 14:50:26 dreamcloud dockerd[7346]: time="2021-10-23T14:50:26.218677300-04:00" level=info msg="API listen on /run/docker.sock"

oldhorse@dreamcloud:/mnt/c/Users/oldhorse$ ps -ef|grep docker
root        7346       1  0 14:50 ?        00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

docker bridge docker0 ready,

7: docker0:  mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:0c:a2:59:19 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

oldhorse@dreamcloud:~$ ip route
default via 192.168.80.1 dev eth0
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
192.168.80.0/24 dev eth0 proto kernel scope link src 192.168.80.2

k8s cluster

1) install k8s packages using below script k8s-install.sh,

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

sudo apt-get update -y
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update -y
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

# cli completion
sudo apt-get install bash-completion -y
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
echo 'alias k=kubectl' >>~/.bashrc
echo 'complete -F __start_kubectl k' >>~/.bashrc
echo "export do='--dry-run=client -o yaml'" >>~/.bashrc

run k8s-init.sh for first time setup k8s cluster on WSL2,

date

sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --ignore-preflight-errors=NumCPU --ignore-preflight-errors=Mem | tee /tmp/kubeadm.log
# allow normal user to run kubectl
if [ -d $HOME/.kube ]; then
  rm -r $HOME/.kube
fi
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# install calico network addon
kubectl create -f https://docs.projectcalico.org/manifests/tigera-operator.yaml
kubectl create -f https://docs.projectcalico.org/manifests/custom-resources.yaml

# allow run on master
kubectl taint nodes --all node-role.kubernetes.io/master-

date

run k8s-reset.sh to quickly rebuild k8s cluster on WSL2 if anything mess up,

date
sudo kubeadm reset -f
date
sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --ignore-preflight-errors=NumCPU --ignore-preflight-errors=Mem | tee /tmp/kubeadm.log
# allow normal user to run kubectl
if [ -d $HOME/.kube ]; then
  rm -r $HOME/.kube
fi
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# install calico network addon
kubectl create -f https://docs.projectcalico.org/manifests/tigera-operator.yaml
kubectl create -f https://docs.projectcalico.org/manifests/custom-resources.yaml

# allow run on master
kubectl taint nodes --all node-role.kubernetes.io/master-
date

test on k8s cluster,

 
oldhorse@dreamcloud:~$ k get no
NAME         STATUS   ROLES                  AGE     VERSION
dreamcloud   Ready    control-plane,master   7m18s   v1.22.2
oldhorse@dreamcloud:~$ k run test --image=nginx $do
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: test
  name: test
spec:
  containers:
  - image: nginx
    name: test
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

oldhorse@dreamcloud:~$ k run test --image=nginx
pod/test created
oldhorse@dreamcloud:~$ k get po
NAME   READY   STATUS              RESTARTS   AGE
test   0/1     ContainerCreating   0          3s
oldhorse@dreamcloud:~$ k get po -o wide
NAME   READY   STATUS    RESTARTS   AGE    IP              NODE         NOMINATED NODE   READINESS GATES
test   1/1     Running   0          101s   192.168.246.6   dreamcloud              

k8s client on Host

I uninstall Docker for Desktop on WSL2 however I keep docker.exe, kubectl.exe windows client in someplace, as test to run them with WSL2 native k8s cluster, it is working fine as portable tools.

 
PS C:\oldhorse\portabledevops\tools> dir
    Directory: C:\oldhorse\portabledevops\tools
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         10/3/2021   5:14 AM       51728256 com.docker.cli.exe
-a----         10/3/2021   5:14 AM        6611328 docker-compose.exe
-a----         10/3/2021   5:14 AM       62670200 docker.exe
-a----         10/3/2021   5:14 AM       48089344 kubectl.exe

add folder to host win11 %PATH%, 
C:\Users\oldhorse>echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\HashiCorp\Vagrant\bin;C:\Users\oldhorse\AppData\Local\Microsoft\WindowsApps;C:\Users\oldhorse\AppData\Local\Programs\Microsoft VS Code\bin;C:\oldhorse\portabledevops\tools

C:\Users\oldhorse>kubectl version --client
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.5", GitCommit:"aea7bbadd2fc0cd689de94a54e5b7b758869d691", GitTreeState:"clean", BuildDate:"2021-09-15T21:10:45Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"windows/amd64"}

Before we use kubectl.exe client to communicate with WSL2 k8s server, need to copy config from WSL2 to Host,

oldhorse@dreamcloud:~/.kube$ mkdir /mnt/c/Users/oldhorse/.kube
oldhorse@dreamcloud:~/.kube$ cp ~/.kube/config /mnt/c/Users/oldhorse/.kube/

C:\Users\oldhorse>kubectl cluster-info
Kubernetes control plane is running at https://192.168.80.2:6443
CoreDNS is running at https://192.168.80.2:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

Python3 pip3

python3 is ready,

oldhorse@dreamcloud:~$ python3 --version
Python 3.8.2

install pip3,

oldhorse@dreamcloud:~$ sudo apt install python3-pip
oldhorse@dreamcloud:~$ pip3 --version
pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)

Ansible

oldhorse@dreamcloud:~$ pip install ansible
Successfully built ansible ansible-core
Installing collected packages: pyparsing, packaging, resolvelib, ansible-core, ansible
Successfully installed ansible-4.7.0 ansible-core-2.11.6 packaging-21.0 pyparsing-3.0.0 resolvelib-0.5.4

add binary to $PATH in ~/.bashrc
export PATH=~/.local/bin:$PATH

oldhorse@dreamcloud:~$ ansible --version
ansible [core 2.11.6]
  config file = None
  configured module search path = ['/home/oldhorse/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/oldhorse/.local/lib/python3.8/site-packages/ansible
  ansible collection location = /home/oldhorse/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/oldhorse/.local/bin/ansible
  python version = 3.8.10 (default, Sep 28 2021, 16:10:42) [GCC 9.3.0]
  jinja version = 2.10.1
  libyaml = True

Vagrant

Installed vagrant on WSL2 is not problem but didn’t see any point to run native vagrant from WSL2 since real work still needs vagrant on win11 Host to communicate with hypervisor Virtualbox or Hyper-V.

We can run vagrant.exe from both cmd/PS and WSL2 smoothly.

pre setup, allow access vagrant and hyper-v on windows from WSL2,

export VAGRANT_WSL_ENABLE_WINDOWS_ACCESS="1"
export PATH="$PATH:/mnt/c/Program Files/Hyper-V"
ln -s /mnt/c/Users/oldhorse/vagrant  ~/vagrant

verify windows vagrant ready,

 
Windows vagrant

C:\Users\oldhorse>where vagrant
C:\HashiCorp\Vagrant\bin\vagrant.exe

C:\Users\oldhorse>vagrant -v
Vagrant 2.2.18

build a ubuntu vm in hyper-v using vagrant,

C:\Users\oldhorse\vagrant\master\Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.box = "generic/ubuntu1804"
  config.vm.define "master" do |master|
      master.vm.hostname = "master"
      master.vm.provider "hyperv" do |v|
          v.memory=1024
          v.cpus=1
      end
  end
end

C:\Users\oldhorse\vagrant\master> vagrant.exe up
or
oldhorse@dreamcloud:~/vagrant/master$ vagrant.exe up
Bringing machine 'master' up with 'hyperv' provider...
==> master: Verifying Hyper-V is enabled...
==> master: Verifying Hyper-V is accessible...
==> master: Importing a Hyper-V instance
    master: Creating and registering the VM...
    master: Successfully imported VM
    master: Please choose a switch to attach to your Hyper-V instance.
    master: If none of these are appropriate, please open the Hyper-V manager
    master: to create a new virtual switch.
    master:
    master: 1) Default Switch
    master: 2) WSL
    master:
    master: What switch would you like to use? 1
    master: Configuring the VM...
    master: Setting VM Enhanced session transport type to disabled/default (VMBus)
==> master: Starting the machine...
==> master: Waiting for the machine to report its IP address...
    master: Timeout: 120 seconds
    master: IP: 172.26.160.242
==> master: Waiting for machine to boot. This may take a few minutes...
    master: SSH address: 172.26.160.242:22
    master: SSH username: vagrant
    master: SSH auth method: private key
    master: Warning: Remote connection disconnect. Retrying...
    master: Warning: Connection aborted. Retrying...
    master: Warning: Remote connection disconnect. Retrying...
    master:
    master: Vagrant insecure key detected. Vagrant will automatically replace
    master: this with a newly generated keypair for better security.
    master:
    master: Inserting generated public key within guest...
    master: Removing insecure key from the guest if it's present...
    master: Key inserted! Disconnecting and reconnecting using new SSH key...
==> master: Machine booted and ready!
==> master: Setting hostname...

oldhorse@dreamcloud:~/vagrant/master$ vagrant.exe ssh
vagrant@master:~$ ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:c3:82:0b brd ff:ff:ff:ff:ff:ff
    inet 172.26.160.242/20 brd 172.26.175.255 scope global dynamic eth0
       valid_lft 85700sec preferred_lft 85700sec
    inet6 fe80::215:5dff:fec3:820b/64 scope link
       valid_lft forever preferred_lft forever
vagrant@master:~$ cat /etc/resolv.conf
nameserver 127.0.0.53
options edns0
search mshome.net
vagrant@master:~$ ip route
default via 172.26.160.1 dev eth0 proto dhcp src 172.26.160.242 metric 100
172.26.160.0/20 dev eth0 proto kernel scope link src 172.26.160.242
172.26.160.1 dev eth0 proto dhcp scope link src 172.26.160.242 metric 100
vagrant@master:~$ ping google.ca
PING google.ca (142.250.81.195) 56(84) bytes of data.
64 bytes from 142.250.81.195: icmp_seq=1 ttl=127 time=50.2 ms
64 bytes from 142.250.81.195: icmp_seq=2 ttl=127 time=34.5 ms
64 bytes from 142.250.81.195: icmp_seq=3 ttl=127 time=31.7 ms