Install kubernetes on windows + WSL
While Windows Subsystem for Linux (WSL) does a decent job providing a unix system, it cannot run natively anything that requires access to virtualisation — for now.
If you already have docker installed, there’s a workaround: install minikube on windows, and then connect to that from within WSL.
To do that, start by opening powershell as an administrator:
In the powershell window, paste the following commands to install minikube and kubectl:
cd $env:userprofile\AppData\Local\Microsoft\WindowsApps
# replace 1.9.0 with the most recent version
wget https://storage.googleapis.com/kubernetes-release/release/v1
.9.0/bin/windows/amd64/kubectl.exe -OutFile kubectl.exe
# replace 0.24.1 with the most recent version
wget https://storage.googleapis.com/minikube/releases/v0.24.1/minikube-windows-amd64.exe -OutFile minikube.exe
Now we need to create a virtual machine using hyper-v.
There’s currently a bug that keeps minikube
hanging on start — as a workaround, create a new external virtual switch.
Name it “Primary Virtual Switch” (“The neighbours stole my dog” works just as well tbh) and use it to start the kubernetes cluster:
minikube.exe start --vm-driver=hyperv --hyperv-virtual-switch="Primary Virtual Switch"# at this point you can already use kubectl inside powershell, but we're going to set it up inside WSL instead:
kubectl.exe config view > $env:TEMP/kubectl-config
minikube.exe docker-env --shell=bash > $env:TEMP/minikube-config# convert line endings to unix format
Get-ChildItem -File -Filter *-config | % { $x = get-content -raw -path $_.fullname
; $x -replace "`r`n","`n" | set-content -path $_.fullname }
That’s everything we need to do in powershell, now open the WSL bash:
# install kubectl
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && \
chmod +x kubectl && \
sudo mv kubectl /usr/local/bin/# cd into windows' TEMP folder.
# Since paths are different from unix, we need to normalise them first
cd /mnt/$(cmd.exe /c echo\|set /p=%TEMP% | sed --expression='s|\\|/|g' | sed --expression='s|^\([A-Za-z]\):|\L\1|')
mkdir ~/.{kube,minikube}mv kubectl-config ~/.kube/config
mv minikube-config ~/.minikube/docker-env# convert windows paths to unix format
sed -i 's|\\|/|g' ~/.{kube,minikube}/{config,docker-env}
sed -i 's|\([ "]\)\([A-Za-z]\):|\1/mnt/\L\2|' ~/.{kube,minikube}/{config,docker-env}kubectl config use-context minikube# optional, if you want to use a local docker image
# e.g. docker build -t <your-image-name> .
eval $(cat ~/.minikube/docker-env)# we can now launch a sample app
kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.4 --port=8080# alternatively you can deploy your local docker image with
# kubectl run hello-minikube --image=<your-image-name> --port=<someport> --image-pull-policy=Never
That’s almost everything needed to see your service running — at this stage, it will only be accessible to kubernetes’ internal network.
Let’s make sure the deployment is working first:
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-minikube 1 1 1 1 21s
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-minikube-7844bdb9c6-wkqtb 1/1 Running 0 34s
Now we can expose the service to the outside world:
$ kubectl expose deployment hello-minikube --type=NodePort
service "hello-minikube" exposed
$ kubectl get service hello-minikube
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-minikube NodePort 10.110.6.111 <none> 8080:30668/TCP 19s
# ☝ ️30668 externally reachable port
We need to go back to powershell to see the service in action:
## should open a browser tab showing the service just deployed
minikube.exe service hello-minikube
That’s it! Now might be a good time to enable autocompletion for kubectl.
Go deploy all the things!