Friday, May 10, 2019

Running Minikube in Win10 Hyper-V without admin privileges

I wanted to try out minikube, and have access to a Windows 10 computer. Windows 10 has the MS hypervisor Hyper-V built in. There are several blog entries on getting minikube running in such an environment, but all of them that I found assume or explicitly state that you must run as an administrator on the Win10 host. Desktop security is part of my job, so I wanted to try and run minikube as a normal user. Here is how I got it working.

My Environment

  • Windows 10 1809
  • physical machine (not a VM, since we want to run a hypervisor)
  • minikube version 1.0.1
  • I log in and run things as an account that is only in .\Users, but I do have access to another account that is in .\Administrators (this is needed only for a couple of the setup steps)

Grant yourself permissions to manage Hyper-V

Win10 has a local group named "Hyper-V Administrators". All you need to do is ensure your normal, non-admin account is a member of this group.

NAT and DHCP on Win10

Hyper-V on Win10 only has three networking options for the VMs, at least that is all you see in the GUI. None of the options are NAT, which is what I want to use. There are powershell commands to create a NAT environment, but it still does not have a built-in DHCP service, like other hypervisors do. Here is how I got all of that running.

Create a NAT'd vSwitch

This command will create a new vSwitch (named "NAT") in HyperV


C:\Users\daves> New-VMSwitch -SwitchName "NAT" -SwitchType Internal

Name SwitchType NetAdapterInterfaceDescription
---- ---------- ------------------------------
NAT  Internal

You will need the ifIndex of the new switch's interface in a later step, so here is how to get it.


C:\Users\daves> get-netadapter | ft -Property Name,ifIndex

Name                         ifIndex
----                         -------
vEthernet (MinikubeLAN)           21
vEthernet (NAT)                   60
Wi-Fi                             15
Bluetooth Network Connection      14
Ethernet 2                         9
vEthernet (MinikubeWIFI)           8
vEthernet (Default Switch)        53
Ethernet                           5
Network Bridge                     3
In my case, the ifIndex of the interface is 60.

Configure the NAT gateway

Use the ifIndex from the adapter assigned to the new vSwitch (60 in my case). I am using private network 192.168.7.0/24 (GW will use 192.168.7.1).
This has to be run in an elevated powershell instance.

PS C:\WINDOWS\system32> New-NetIPAddress -IPAddress 192.168.7.1 -PrefixLength 24 -InterfaceIndex 60 


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

IPAddress         : 192.168.7.1
InterfaceIndex    : 60
InterfaceAlias    : vEthernet (NAT)
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Invalid
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : PersistentStore


Create the NAT configuration. You will need to know the CIDR formatted network you selected from above (192.168.7.0/24 for me).
This also has to be run in an elevated powershell instance.

PS C:\WINDOWS\system32> New-NetNat -Name MyNATnetwork -InternalIPInterfaceAddressPrefix 192.168.7.0/24


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


Create and configure a DHCP service for you VMs


Installation is easy, and the download comes with a good readme. Here is a high-level summary of how I configured it.


  • Extract the files to C:\Program Files\DHCP\
  • From that folder, run dhcpwiz.exe
    • Select the NAT ethernet adapter created abovce for the NIC on which to run DHCP
      • Mine was labeled "vEthernet (NAT)"
    • Save the settings in an INI file
    • Enabling the HTTP web server will help you troubleshoot - go to http://127.0.0.1/dhcpstatus.xml to check the services status
    • Set your DNS server
      • I used OpenDNS
    • enter your network range
    • Under [Advanced] you can specify DNS and other services to be sent to DHCP clients
    • Use [Write INI file] to save your settings to C:\Program Files\DHCP\dhcpsrv.ini
    • Use the [Admin] button to install a Windows Service to run DHCP
      • The service will be named "dhcpServer" (Display name is "DHCP Server")
  • User powershell or the services control panel to start and stop the service. The service must be running when you start your minikube VM, or it won't get an IP address
Here is what my copy of dhcpsrv.ini looks like:


[SETTINGS]
IPPOOL_1=192.168.7.1-254
IPBIND_1=192.168.7.1
AssociateBindsToPools=1
Trace=1
DeleteOnRelease=0
ExpiredLeaseTimeout=3600

[GENERAL]
LEASETIME=31104000
NODETYPE=8
SUBNETMASK=255.255.255.0
NEXTSERVER=192.168.7.1
DNS_0=208.67.222.222
ROUTER_0=192.168.7.1

[DNS-SETTINGS]
EnableDNS=1
FORWARD=208.67.222.222

[TFTP-SETTINGS]
EnableTFTP=0
ROOT=C:\Program Files\DHCP\wwwroot
WritePermission=0

[HTTP-SETTINGS]
EnableHTTP=1
ROOT=C:\Program Files\DHCP\wwwroot


As the service leases addresses, they will show up in this file as well.


Install minikube

Install kubectl through the powershell gallery

https://kubernetes.io/docs/tasks/tools/install-kubectl/

I want my minikube related executables in c:\bin\ (which is in the systems PATH env variable)

C:\Users\daves> Install-Script -Name install-kubectl -Scope CurrentUser -Force

C:\Users\daves> install-kubectl.ps1 -Downloadlocation "C:\bin\"
==>analyzing Downloadlink
==>starting 'C:\users\daves\AppData\bin\kubectl.exe version'
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.0", GitCommit:"641856db18352033a0d96dbc99153fa3b27298e5", GitTreeState:"clean", BuildDate:"2019-03-25T15:53:57Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"windows/amd64"}
Unable to connect to the server: dial tcp [::1]:8080: connectex: No connection could be made because the target machine actively refused it.

You can now start kubectl from C:\bin\kubectl.exe

copy your remote kubernetes cluster information to C:\Users\daves\.kube/config

Install minikube


To install Minikube manually on Windows, download minikube-windows-amd64, rename it to minikube.exe, and add it to your path. I installed it to C:\bin\

Configure user environment variables for minikube

In a powershell, as the non-admin user you want to run minikube as, add an env variable named "MINIKUBE_HOME". This is a single command, and you will need to reload your shell when done.

C:\Users\daves> [System.Environment]::SetEnvironmentVariable('MINIKUBE_HOME', 'C:\Users\daves\.minikube', [System.EnvironmentVariableTarget]::User)

Configure minikube to use Hyper-V and your NAT'd switch by default

While you can specify the hypervisor and switch in command arguments, I like to set defaults.

C:\Users\daves> minikube config set vm-driver hyperv
!   These changes will take effect upon a minikube delete and then a minikube start
C:\Users\daves> minikube config set hyperv-virtual-switch NAT

Start minikube

Be sure your dhcpServer service is running!

This takes a few minutes, so be patient. You can troubleshoot by making the output more verbose with the arguments "--v=7 --alsologtostderr". You can also watch some of the progress in the Hyper-V admin console.

C:\Users\daves> minikube start
o   minikube v1.0.1 on windows (amd64)
$   Downloading Kubernetes v1.14.1 images in the background ...
>   Creating hyperv VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...
-   "minikube" IP address is 192.168.7.5
-   Configuring Docker as the container runtime ...
-   Version of container runtime is 18.06.3-ce
:   Waiting for image downloads to complete ...
-   Preparing Kubernetes environment ...
-   Pulling images required by Kubernetes v1.14.1 ...
-   Launching Kubernetes v1.14.1 using kubeadm ...
:   Waiting for pods: apiserver proxy etcd scheduler controller dns
-   Configuring cluster permissions ...
-   Verifying component health .....
+   kubectl is now configured to use "minikube"
=   Done! Thank you for using minikube!

Now you can experiment with kubectl and minicube commands against your minikube instance.

Clean up

Stopping the minikube VM doesn't work with the default command for me. Here is a discussion on the topic

The command "minikube stop" should stop the VM, but doesn't in my current lab. This command works fine:

C:\Users\daves> minikube ssh "sudo shutdown -h now"

If you are done, you can delete the minikube VM.

C:\Users\daves> minikube delete
x   Deleting "minikube" from hyperv ...
-   The "minikube" cluster has been deleted.