From 3ddf9d65f6e3c102f82130d65d1790a63351f420 Mon Sep 17 00:00:00 2001 From: Fabian Deutsch Date: Fri, 16 Feb 2018 07:05:54 +0100 Subject: [PATCH] kvm: Passthrough host CPU in order to allow nesting Before this patch the virtual CPU was the stock qemu CPU, in the sense that the virtual CPU features were set according to the default qemu CPU. With this change the CPU features of the host will be copied at start to the domain definition. This includes features like svm and vmx, which in turn allow to run nested virtualization if the host is configured accordingly i.e. `kvm_intel nested=y` in `/etc/modprobe.d/kvm.conf`. To turn on nesting, a user has to specify `--kvm-cpu-model host-model` when creating the VM. Resolves #2553 Signed-off-by: Fabian Deutsch --- cmd/minikube/cmd/start.go | 3 +++ docs/drivers.md | 10 ++++++++++ pkg/drivers/kvm/domain.go | 1 + pkg/drivers/kvm/kvm.go | 4 ++++ pkg/minikube/cluster/cluster_linux.go | 2 ++ pkg/minikube/cluster/types.go | 1 + pkg/minikube/constants/constants.go | 1 + 7 files changed, 22 insertions(+) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index e6b9bf8459..61dce13b2f 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -61,6 +61,7 @@ const ( networkPlugin = "network-plugin" hypervVirtualSwitch = "hyperv-virtual-switch" kvmNetwork = "kvm-network" + kvmCPUModel = "kvm-cpu-model" keepContext = "keep-context" createMount = "mount" featureGates = "feature-gates" @@ -145,6 +146,7 @@ func runStart(cmd *cobra.Command, args []string) { HostOnlyCIDR: viper.GetString(hostOnlyCIDR), HypervVirtualSwitch: viper.GetString(hypervVirtualSwitch), KvmNetwork: viper.GetString(kvmNetwork), + KvmCPUModel: viper.GetString(kvmCPUModel), Downloader: pkgutil.DefaultDownloader{}, DisableDriverMounts: viper.GetBool(disableDriverMounts), UUID: viper.GetString(uuid), @@ -379,6 +381,7 @@ func init() { startCmd.Flags().String(hostOnlyCIDR, "192.168.99.1/24", "The CIDR to be used for the minikube VM (only supported with Virtualbox driver)") startCmd.Flags().String(hypervVirtualSwitch, "", "The hyperv virtual switch name. Defaults to first found. (only supported with HyperV driver)") startCmd.Flags().String(kvmNetwork, "default", "The KVM network name. (only supported with KVM driver)") + startCmd.Flags().String(kvmCPUModel, "custom", "The KVM CPU model name. (only supported with KVM driver)") startCmd.Flags().String(xhyveDiskDriver, "ahci-hd", "The disk driver to use [ahci-hd|virtio-blk] (only supported with xhyve driver)") startCmd.Flags().StringSlice(NFSShare, []string{}, "Local folders to share with Guest via NFS mounts (Only supported on with hyperkit now)") startCmd.Flags().String(NFSSharesRoot, "/nfsshares", "Where to root the NFS Shares (defaults to /nfsshares, only supported with hyperkit now)") diff --git a/docs/drivers.md b/docs/drivers.md index d059af8c4f..1a4ef6a93f 100644 --- a/docs/drivers.md +++ b/docs/drivers.md @@ -54,6 +54,16 @@ To use the driver you would do: minikube start --vm-driver kvm2 ``` +##### Nesting + +The KVM2 driver allows to run [nested VMs](https://en.wikipedia.org/wiki/Virtualization#Nested_virtualization) +if the right CPU model is specyfied when launching minikube: + +```shell +minikube --start --vm-driver kvm2 --kvm-cpu-model host-model +``` + + #### KVM driver Minikube is currently tested against [`docker-machine-driver-kvm` v0.10.0](https://github.com/dhiltgen/docker-machine-kvm/releases). diff --git a/pkg/drivers/kvm/domain.go b/pkg/drivers/kvm/domain.go index 1942583a5b..c85c07d908 100644 --- a/pkg/drivers/kvm/domain.go +++ b/pkg/drivers/kvm/domain.go @@ -37,6 +37,7 @@ const domainTmpl = ` + hvm diff --git a/pkg/drivers/kvm/kvm.go b/pkg/drivers/kvm/kvm.go index 5bdc647574..564ea2097c 100644 --- a/pkg/drivers/kvm/kvm.go +++ b/pkg/drivers/kvm/kvm.go @@ -44,6 +44,9 @@ type Driver struct { // How many cpus to allocate to the VM CPU int + // What CPU model to expose + CPUModel string + // The name of the default network Network string @@ -83,6 +86,7 @@ func NewDriver(hostName, storePath string) *Driver { CommonDriver: &pkgdrivers.CommonDriver{}, Boot2DockerURL: constants.DefaultIsoUrl, CPU: constants.DefaultCPUS, + CPUModel: constants.DefaultCPUModel, DiskSize: util.CalculateDiskSizeInMB(constants.DefaultDiskSize), Memory: constants.DefaultMemory, PrivateNetwork: defaultPrivateNetworkName, diff --git a/pkg/minikube/cluster/cluster_linux.go b/pkg/minikube/cluster/cluster_linux.go index fb21521cef..cc93cf9f1e 100644 --- a/pkg/minikube/cluster/cluster_linux.go +++ b/pkg/minikube/cluster/cluster_linux.go @@ -33,6 +33,7 @@ type kvmDriver struct { Memory int DiskSize int CPU int + CPUModel string Network string PrivateNetwork string ISO string @@ -71,6 +72,7 @@ func createKVM2Host(config MachineConfig) *kvmDriver { }, Memory: config.Memory, CPU: config.CPUs, + CPUModel: config.KvmCPUModel, Network: config.KvmNetwork, PrivateNetwork: "minikube-net", Boot2DockerURL: config.Downloader.GetISOFileURI(config.MinikubeISO), diff --git a/pkg/minikube/cluster/types.go b/pkg/minikube/cluster/types.go index e535d05f96..efbd43e906 100644 --- a/pkg/minikube/cluster/types.go +++ b/pkg/minikube/cluster/types.go @@ -35,6 +35,7 @@ type MachineConfig struct { HostOnlyCIDR string // Only used by the virtualbox driver HypervVirtualSwitch string KvmNetwork string // Only used by the KVM driver + KvmCPUModel string // Only used by the KVM driver Downloader util.ISODownloader `json:"-"` DockerOpt []string // Each entry is formatted as KEY=VALUE. DisableDriverMounts bool // Only used by virtualbox and xhyve diff --git a/pkg/minikube/constants/constants.go b/pkg/minikube/constants/constants.go index e4f237fb31..13502ce7f3 100644 --- a/pkg/minikube/constants/constants.go +++ b/pkg/minikube/constants/constants.go @@ -89,6 +89,7 @@ const ( ShaSuffix = ".sha256" DefaultMemory = 2048 DefaultCPUS = 2 + DefaultCPUModel = "custom" DefaultDiskSize = "20g" MinimumDiskSizeMB = 2000 DefaultVMDriver = "virtualbox"