kvm: Build kvm driver only for linux/amd64

The build fails on linux/arm64 because libvirt.org/go/libvirt is using
CGO, and cross compiling CGO requires a C cross compiler. Setting
GOARCH=arm64 is not enough. The issue is tracked in
https://github.com/kubernetes/minikube/issues/19959.

Previously we built the kvm driver also on arm64 as part of the
docker-machine-driver-kvm2 executable, but the build was skipped on
arm64.

Now that we build the driver as part of minikube, we cannot skip the
entire build. Change the build tag so the libvirt bits are built only on
amd64.

To make this possible, the generic linux bits needed by the registry
moved to pkg/drivers/kvm/driver.go, and a kvm_stub.go is used for
unsupported architectures.

In the registry Driver.Status(), move the arm64 check to front since
there is no point in checking that libvirt is installed correctly if the
driver is not supported yet.
pull/21625/head
Nir Soffer 2025-09-24 03:44:49 +03:00 committed by Nir Soffer
parent 7bc97d7ce1
commit 4089e1ca2a
6 changed files with 178 additions and 97 deletions

View File

@ -1,4 +1,4 @@
//go:build linux
//go:build linux && amd64
/*
Copyright 2016 The Kubernetes Authors All rights reserved.

107
pkg/drivers/kvm/driver.go Normal file
View File

@ -0,0 +1,107 @@
//go:build linux
/*
Copyright 2025 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kvm
import (
"github.com/docker/machine/libmachine/drivers"
"k8s.io/minikube/pkg/drivers/common"
)
const (
qemusystem = "qemu:///system"
defaultPrivateNetworkName = "minikube-net"
defaultNetworkName = "default"
)
// Driver is the machine driver for KVM
type Driver struct {
*drivers.BaseDriver
*common.CommonDriver
// How much memory, in MB, to allocate to the VM
Memory int
// How many cpus to allocate to the VM
CPU int
// The name of the default network
Network string
// The name of the private network
PrivateNetwork string
// The size of the disk to be created for the VM, in MB
DiskSize int
// The path of the disk .img
DiskPath string
// A file or network URI to fetch the minikube ISO
Boot2DockerURL string
// The location of the iso to boot from
ISO string
// The randomly generated MAC Address
// If empty, a random MAC will be generated.
MAC string
// The randomly generated MAC Address for the NIC attached to the private network
// If empty, a random MAC will be generated.
PrivateMAC string
// Whether to passthrough GPU devices from the host to the VM.
GPU bool
// Whether to hide the KVM hypervisor signature from the guest
Hidden bool
// XML that needs to be added to passthrough GPU devices.
DevicesXML string
// QEMU Connection URI
ConnectionURI string
// NUMA node count default value is 1
NUMANodeCount int
// NUMA XML
NUMANodeXML string
// Extra Disks
ExtraDisks int
// Extra Disks XML
ExtraDisksXML []string
}
// NewDriver creates a new driver for a host
func NewDriver(hostName, storePath string) *Driver {
return &Driver{
BaseDriver: &drivers.BaseDriver{
MachineName: hostName,
StorePath: storePath,
SSHUser: "docker",
},
CommonDriver: &common.CommonDriver{},
PrivateNetwork: defaultPrivateNetworkName,
Network: defaultNetworkName,
ConnectionURI: qemusystem,
}
}

View File

@ -1,4 +1,4 @@
//go:build linux
//go:build linux && amd64
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
@ -34,89 +34,6 @@ import (
"libvirt.org/go/libvirt"
)
// Driver is the machine driver for KVM
type Driver struct {
*drivers.BaseDriver
*common.CommonDriver
// How much memory, in MB, to allocate to the VM
Memory int
// How many cpus to allocate to the VM
CPU int
// The name of the default network
Network string
// The name of the private network
PrivateNetwork string
// The size of the disk to be created for the VM, in MB
DiskSize int
// The path of the disk .img
DiskPath string
// A file or network URI to fetch the minikube ISO
Boot2DockerURL string
// The location of the iso to boot from
ISO string
// The randomly generated MAC Address
// If empty, a random MAC will be generated.
MAC string
// The randomly generated MAC Address for the NIC attached to the private network
// If empty, a random MAC will be generated.
PrivateMAC string
// Whether to passthrough GPU devices from the host to the VM.
GPU bool
// Whether to hide the KVM hypervisor signature from the guest
Hidden bool
// XML that needs to be added to passthrough GPU devices.
DevicesXML string
// QEMU Connection URI
ConnectionURI string
// NUMA node count default value is 1
NUMANodeCount int
// NUMA XML
NUMANodeXML string
// Extra Disks
ExtraDisks int
// Extra Disks XML
ExtraDisksXML []string
}
const (
qemusystem = "qemu:///system"
defaultPrivateNetworkName = "minikube-net"
defaultNetworkName = "default"
)
// NewDriver creates a new driver for a host
func NewDriver(hostName, storePath string) *Driver {
return &Driver{
BaseDriver: &drivers.BaseDriver{
MachineName: hostName,
StorePath: storePath,
SSHUser: "docker",
},
CommonDriver: &common.CommonDriver{},
PrivateNetwork: defaultPrivateNetworkName,
Network: defaultNetworkName,
ConnectionURI: qemusystem,
}
}
// GetURL returns a Docker URL inside this host
// e.g. tcp://1.2.3.4:2376
// more info https://github.com/docker/machine/blob/b170508bf44c3405e079e26d5fdffe35a64c6972/libmachine/provision/utils.go#L159_L175

View File

@ -0,0 +1,51 @@
//go:build linux && !amd64
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kvm
import (
"fmt"
"runtime"
"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/mcnflag"
"github.com/docker/machine/libmachine/state"
)
// This is a stub driver for unsupported architectures. All function fail with
// notSupported error or return an zero value.
var notSupported = fmt.Errorf("the kvm driver is not supported on %q", runtime.GOARCH)
func (d *Driver) Create() error { return notSupported }
func (d *Driver) GetCreateFlags() []mcnflag.Flag { return nil }
func (d *Driver) GetIP() (string, error) { return "", notSupported }
func (d *Driver) GetMachineName() string { return "" }
func (d *Driver) GetSSHHostname() (string, error) { return "", notSupported }
func (d *Driver) GetSSHKeyPath() string { return "" }
func (d *Driver) GetSSHPort() (int, error) { return 0, notSupported }
func (d *Driver) GetSSHUsername() string { return "" }
func (d *Driver) GetURL() (string, error) { return "", notSupported }
func (d *Driver) GetState() (state.State, error) { return state.None, notSupported }
func (d *Driver) Kill() error { return notSupported }
func (d *Driver) PreCreateCheck() error { return notSupported }
func (d *Driver) Remove() error { return notSupported }
func (d *Driver) Restart() error { return notSupported }
func (d *Driver) SetConfigFromFlags(opts drivers.DriverOptions) error { return notSupported }
func (d *Driver) Start() error { return notSupported }
func (d *Driver) Stop() error { return notSupported }

View File

@ -1,4 +1,4 @@
//go:build linux
//go:build linux && amd64
/*
Copyright 2016 The Kubernetes Authors All rights reserved.

View File

@ -26,6 +26,7 @@ import (
"os/user"
"path/filepath"
"runtime"
"slices"
"strings"
"time"
@ -43,6 +44,10 @@ const (
docURL = "https://minikube.sigs.k8s.io/docs/reference/drivers/kvm2/"
)
// The driver is implemented for amd64 and arm64, but we cannot build the arm64
// version yet: https://github.com/kubernetes/minikube/issues/19959.
var supportedArchictures = []string{"amd64"}
func init() {
if err := registry.Register(registry.DriverDef{
Name: driver.KVM2,
@ -99,6 +104,18 @@ func defaultURI() string {
}
func status() registry.State {
if !slices.Contains(supportedArchictures, runtime.GOARCH) {
rs := registry.State{
Error: fmt.Errorf("KVM is not supported on %q, contributions are welcome", runtime.GOARCH),
Fix: fmt.Sprintf("you can use the KVM driver on %s", strings.Join(supportedArchictures, ",")),
}
// The driver is implemented but we cannot build it yet.
if runtime.GOARCH == "arm64" {
rs.Doc = "https://github.com/kubernetes/minikube/issues/19959"
}
return rs
}
// Allow no more than 6 seconds for querying state
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second)
defer cancel()
@ -150,17 +167,6 @@ func status() registry.State {
}
}
if runtime.GOARCH == "arm64" {
return registry.State{
Installed: true,
Running: true,
Error: fmt.Errorf("KVM is not supported on arm64 due to a gcc build error, contributions are welcome"),
Fix: "follow the github issue for possible fix",
Doc: "https://github.com/kubernetes/minikube/issues/19959",
}
}
if err != nil {
return registry.State{
Installed: true,