Skip to content

Commit

Permalink
kvm2 driver support simulate numa node
Browse files Browse the repository at this point in the history
  • Loading branch information
phantooom committed Feb 13, 2021
1 parent a99c6c2 commit ad961ad
Show file tree
Hide file tree
Showing 20 changed files with 198 additions and 69 deletions.
7 changes: 7 additions & 0 deletions cmd/minikube/cmd/start_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const (
kvmQemuURI = "kvm-qemu-uri"
kvmGPU = "kvm-gpu"
kvmHidden = "kvm-hidden"
kvmNUMACount = "kvm-numa-count"
minikubeEnvPrefix = "MINIKUBE"
installAddons = "install-addons"
defaultDiskSize = "20000mb"
Expand Down Expand Up @@ -193,6 +194,7 @@ func initDriverFlags() {
startCmd.Flags().String(kvmQemuURI, "qemu:///system", "The KVM QEMU connection URI. (kvm2 driver only)")
startCmd.Flags().Bool(kvmGPU, false, "Enable experimental NVIDIA GPU support in minikube")
startCmd.Flags().Bool(kvmHidden, false, "Hide the hypervisor signature from the guest in minikube (kvm2 driver only)")
startCmd.Flags().Int(kvmNUMACount, 1, "Simulate numa node count in minikube. (kvm2 driver only)")

// virtualbox
startCmd.Flags().String(hostOnlyCIDR, "192.168.99.1/24", "The CIDR to be used for the minikube VM (virtualbox driver only)")
Expand Down Expand Up @@ -338,6 +340,7 @@ func generateClusterConfig(cmd *cobra.Command, existing *config.ClusterConfig, k
KVMQemuURI: viper.GetString(kvmQemuURI),
KVMGPU: viper.GetBool(kvmGPU),
KVMHidden: viper.GetBool(kvmHidden),
KVMNUMACount: viper.GetInt(kvmNUMACount),
DisableDriverMounts: viper.GetBool(disableDriverMounts),
UUID: viper.GetString(uuid),
NoVTXCheck: viper.GetBool(noVTXCheck),
Expand Down Expand Up @@ -545,6 +548,10 @@ func updateExistingConfigFromFlags(cmd *cobra.Command, existing *config.ClusterC
cc.KVMHidden = viper.GetBool(kvmHidden)
}

if cmd.Flags().Changed(kvmNUMACount){
cc.KVMNUMACount = viper.GetInt(kvmNUMACount)
}

if cmd.Flags().Changed(disableDriverMounts) {
cc.DisableDriverMounts = viper.GetBool(disableDriverMounts)
}
Expand Down
8 changes: 5 additions & 3 deletions pkg/drivers/kvm/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ const domainTmpl = `
</kvm>
{{end}}
</features>
<cpu mode='host-passthrough'/>
<cpu mode='host-passthrough'>
{{if gt .NUMANodeCount 1}}
{{.NUMANodeXML}}
{{end}}
</cpu>
<os>
<type>hvm</type>
<boot dev='cdrom'/>
Expand Down Expand Up @@ -158,14 +162,12 @@ func (d *Driver) createDomain() (*libvirt.Domain, error) {
}
d.PrivateMAC = mac.String()
}

// create the XML for the domain using our domainTmpl template
tmpl := template.Must(template.New("domain").Parse(domainTmpl))
var domainXML bytes.Buffer
if err := tmpl.Execute(&domainXML, d); err != nil {
return nil, errors.Wrap(err, "executing domain xml")
}

conn, err := getConnection(d.ConnectionURI)
if err != nil {
return nil, errors.Wrap(err, "error getting libvirt connection")
Expand Down
15 changes: 14 additions & 1 deletion pkg/drivers/kvm/kvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ type Driver struct {

// QEMU Connection URI
ConnectionURI string

// NUMA node count default value is 1
NUMANodeCount int

// NUMA XML
NUMANodeXML string
}

const (
Expand Down Expand Up @@ -301,7 +307,6 @@ func (d *Driver) Start() (err error) {
func (d *Driver) Create() (err error) {
log.Info("Creating KVM machine...")
defer log.Infof("KVM machine creation complete!")

err = d.createNetwork()
if err != nil {
return errors.Wrap(err, "creating network")
Expand All @@ -314,6 +319,14 @@ func (d *Driver) Create() (err error) {
}
}

if d.NUMANodeCount > 1{
NUMAXML,err :=GetNUMAXml(d.CPU,d.Memory,d.NUMANodeCount)
if err != nil{
return errors.Wrap(err, "creating NUMA XML")
}
d.NUMANodeXML = NUMAXML
}

store := d.ResolveStorePath(".")
log.Infof("Setting up store path in %s ...", store)
// 0755 because it must be accessible by libvirt/qemu across a variety of configs
Expand Down
74 changes: 74 additions & 0 deletions pkg/drivers/kvm/numa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package kvm

import (
"bytes"
"fmt"
"strconv"
"strings"
"text/template"
)

// NUMATmpl NUMA XML Template
const NUMATmpl = `
<numa>
{{- range $idx,$val :=. }}
<cell id='{{$idx}}' cpus='{{$val.CPUTopology}}' memory='{{$val.Memory}}' unit='MiB'/>
{{- end }}
</numa>
`

// NUMA this struct use for NUMATmpl
type NUMA struct {
CPUCount int
Memory int
CPUTopology string
}

// GetNUMAXml generate numa xml
// evenly distributed cpu core & memory to each numa node
func GetNUMAXml(cpu, memory, numaCount int) (string, error) {
if numaCount < 1 {
return "", fmt.Errorf("numa node count must >= 1")
}
if cpu < numaCount {
return "", fmt.Errorf("cpu count must >= numa node count")
}
numaNodes := make([]*NUMA, numaCount)
CPUSeq := 0
cpuBaseCount := cpu / numaCount
cpuExtraCount := cpu % numaCount

for i := range numaNodes {
numaNodes[i] = &NUMA{CPUCount: cpuBaseCount}
}

for i := 0; i < cpuExtraCount; i++ {
numaNodes[i].CPUCount++
}
for i := range numaNodes {
CPUTopologySlice := make([]string, 0)
for seq := CPUSeq; seq < CPUSeq+numaNodes[i].CPUCount; seq++ {
CPUTopologySlice = append(CPUTopologySlice, strconv.Itoa(seq))
}
numaNodes[i].CPUTopology = strings.Join(CPUTopologySlice, ",")
CPUSeq += numaNodes[i].CPUCount
}

memoryBaseCount := memory / numaCount
memoryExtraCount := memory % numaCount

for i := range numaNodes {
numaNodes[i].Memory = memoryBaseCount
}

for i := 0; i < memoryExtraCount; i++ {
numaNodes[i].Memory++
}

tmpl := template.Must(template.New("numa").Parse(NUMATmpl))
var NUMAXML bytes.Buffer
if err := tmpl.Execute(&NUMAXML, numaNodes); err != nil {
return "", fmt.Errorf("couldn't generate numa XML: %v", err)
}
return NUMAXML.String(), nil
}
29 changes: 29 additions & 0 deletions pkg/drivers/kvm/numa_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package kvm

import (
"strings"
"testing"
)

func TestGetNUMAXml(t *testing.T) {
_, err := GetNUMAXml(1, 1024, 0)
if err == nil {
t.Errorf("check invalid numa count failed: %s", err)
}

xml, err := GetNUMAXml(10, 10240, 8)
expXML := `<numa>
<cell id='0' cpus='0,1' memory='1280' unit='MiB'/>
<cell id='1' cpus='2,3' memory='1280' unit='MiB'/>
<cell id='2' cpus='4' memory='1280' unit='MiB'/>
<cell id='3' cpus='5' memory='1280' unit='MiB'/>
<cell id='4' cpus='6' memory='1280' unit='MiB'/>
<cell id='5' cpus='7' memory='1280' unit='MiB'/>
<cell id='6' cpus='8' memory='1280' unit='MiB'/>
<cell id='7' cpus='9' memory='1280' unit='MiB'/>
</numa>`
if strings.TrimSpace(xml) != expXML {
t.Errorf("gen xml: %s not match expect xml: %s", xml, expXML)
}

}
1 change: 1 addition & 0 deletions pkg/minikube/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type ClusterConfig struct {
KVMQemuURI string // Only used by kvm2
KVMGPU bool // Only used by kvm2
KVMHidden bool // Only used by kvm2
KVMNUMACount int // Only used by kvm2
DockerOpt []string // Each entry is formatted as KEY=VALUE.
DisableDriverMounts bool // Only used by virtualbox
NFSShare []string
Expand Down
2 changes: 2 additions & 0 deletions pkg/minikube/registry/drvs/kvm2/kvm2.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type kvmDriver struct {
GPU bool
Hidden bool
ConnectionURI string
NUMANodeCount int
}

func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) {
Expand All @@ -88,6 +89,7 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) {
GPU: cc.KVMGPU,
Hidden: cc.KVMHidden,
ConnectionURI: cc.KVMQemuURI,
NUMANodeCount: cc.KVMNUMACount,
}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion site/content/en/docs/commands/addons.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Enable or disable a minikube addon

### Synopsis

addons modifies minikube addons files using subcommands like "minikube addons enable dashboard"
插件使用诸如 "minikube addons enable dashboard" 的子命令修改 minikube 的插件文件

```shell
minikube addons SUBCOMMAND [flags]
Expand Down
2 changes: 1 addition & 1 deletion site/content/en/docs/commands/dashboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ minikube dashboard [flags]
### Options

```
--url Display dashboard URL instead of opening a browser
--url 显示 dashboard URL,而不是打开浏览器
```

### Options inherited from parent commands
Expand Down
4 changes: 2 additions & 2 deletions site/content/en/docs/commands/delete.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ minikube delete [flags]
### Options

```
--all Set flag to delete all profiles
--purge Set this flag to delete the '.minikube' folder from your user directory.
--all 设置标志以删除所有配置文件
--purge 设置这个标志来删除您用户目录下的 '.minikube' 文件夹。
```

### Options inherited from parent commands
Expand Down
10 changes: 5 additions & 5 deletions site/content/en/docs/commands/docker-env.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
---
title: "docker-env"
description: >
Configure environment to use minikube's Docker daemon
配置环境以使用 minikube's Docker daemon
---


## minikube docker-env

Configure environment to use minikube's Docker daemon
配置环境以使用 minikube's Docker daemon

### Synopsis

Sets up docker env variables; similar to '$(docker-machine env)'.
设置 docker env 变量;类似于 '$(docker-machine env)'

```shell
minikube docker-env [flags]
Expand All @@ -20,8 +20,8 @@ minikube docker-env [flags]
### Options

```
--no-proxy Add machine IP to NO_PROXY environment variable
--shell string Force environment to be configured for a specified shell: [fish, cmd, powershell, tcsh, bash, zsh], default is auto-detect
--no-proxy 将机器IP添加到环境变量 NO_PROXY
--shell string 强制为指定的 shell 配置环境:[fish, cmd, powershell, tcsh, bash, zsh],默认为 auto-detect
--ssh-add Add SSH identity key to SSH authentication agent
--ssh-host Use SSH connection instead of HTTPS (port 2376)
-u, --unset Unset variables instead of setting them
Expand Down
2 changes: 1 addition & 1 deletion site/content/en/docs/commands/logs.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Returns logs to debug a local Kubernetes cluster

### Synopsis

Gets the logs of the running instance, used for debugging minikube, not user code.
获取正在运行的实例日志,用于调试 minikube,不是用户代码

```shell
minikube logs [flags]
Expand Down
14 changes: 7 additions & 7 deletions site/content/en/docs/commands/mount.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
---
title: "mount"
description: >
Mounts the specified directory into minikube
将指定的目录挂载到 minikube
---


## minikube mount

Mounts the specified directory into minikube
将指定的目录挂载到 minikube

### Synopsis

Mounts the specified directory into minikube.
将指定的目录挂载到 minikube

```shell
minikube mount [flags] <source directory>:<target directory>
Expand All @@ -21,14 +21,14 @@ minikube mount [flags] <source directory>:<target directory>

```
--9p-version string Specify the 9p version that the mount should use (default "9p2000.L")
--gid string Default group id used for the mount (default "docker")
--gid string 用于挂载默认的 group id (default "docker")
--ip string Specify the ip that the mount should be setup on
--kill Kill the mount process spawned by minikube start
--mode uint File permissions used for the mount (default 493)
--mode uint 用于 mount 的文件权限 (default 493)
--msize int The number of bytes to use for 9p packet payload (default 262144)
--options strings Additional mount options, such as cache=fscache
--options strings 其他挂载选项,例如:cache=fscache
--type string Specify the mount filesystem type (supported types: 9p) (default "9p")
--uid string Default user id used for the mount (default "docker")
--uid string 用于挂载默认的 user id (default "docker")
```

### Options inherited from parent commands
Expand Down
8 changes: 4 additions & 4 deletions site/content/en/docs/commands/podman-env.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
---
title: "podman-env"
description: >
Configure environment to use minikube's Podman service
配置环境以使用 minikube's Podman service
---


## minikube podman-env

Configure environment to use minikube's Podman service
配置环境以使用 minikube's Podman service

### Synopsis

Sets up podman env variables; similar to '$(podman-machine env)'.
设置 podman env 变量;类似于 '$(podman-machine env)'

```shell
minikube podman-env [flags]
Expand All @@ -20,7 +20,7 @@ minikube podman-env [flags]
### Options

```
--shell string Force environment to be configured for a specified shell: [fish, cmd, powershell, tcsh, bash, zsh], default is auto-detect
--shell string 强制为指定的 shell 配置环境:[fish, cmd, powershell, tcsh, bash, zsh],默认为 auto-detect
-u, --unset Unset variables instead of setting them
```

Expand Down
2 changes: 1 addition & 1 deletion site/content/en/docs/commands/service.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ minikube service [flags] SERVICE
--interval int The initial time interval for each check that wait performs in seconds (default 1)
-n, --namespace string The service namespace (default "default")
--url Display the Kubernetes service URL in the CLI instead of opening it in the default browser
--wait int Amount of time to wait for a service in seconds (default 2)
--wait int 等待服务的时间(单位秒) (default 2)
```

### Options inherited from parent commands
Expand Down
Loading

0 comments on commit ad961ad

Please sign in to comment.