Skip to content

Commit

Permalink
Merge pull request #11692 from spowelljr/addNoLimit
Browse files Browse the repository at this point in the history
Add ability to pass 'max' value to memory and cpus flags
  • Loading branch information
spowelljr authored Jun 28, 2021
2 parents 02abe78 + 5559a84 commit e8b3db9
Show file tree
Hide file tree
Showing 15 changed files with 116 additions and 64 deletions.
2 changes: 1 addition & 1 deletion cmd/minikube/cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ var settings = []Setting{
{
name: "cpus",
set: SetInt,
validations: []setFn{IsPositive},
validations: []setFn{IsValidCPUs},
callbacks: []setFn{RequiresRestartMsg},
},
{
Expand Down
12 changes: 12 additions & 0 deletions cmd/minikube/cmd/config/validations.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"strings"

units "github.com/docker/go-units"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/cruntime"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/out"
Expand Down Expand Up @@ -53,8 +54,19 @@ func IsValidDiskSize(name string, disksize string) error {
return nil
}

// IsValidCPUs checks if a string is a valid number of CPUs
func IsValidCPUs(name string, cpus string) error {
if cpus == constants.MaxResources {
return nil
}
return IsPositive(name, cpus)
}

// IsValidMemory checks if a string is a valid memory size
func IsValidMemory(name string, memsize string) error {
if memsize == constants.MaxResources {
return nil
}
_, err := units.FromHumanSize(memsize)
if err != nil {
return fmt.Errorf("invalid memory size: %v", err)
Expand Down
74 changes: 43 additions & 31 deletions cmd/minikube/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -1030,56 +1030,49 @@ func validateRequestedMemorySize(req int, drvName string) {

// validateCPUCount validates the cpu count matches the minimum recommended & not exceeding the available cpu count
func validateCPUCount(drvName string) {
var cpuCount int
if driver.BareMetal(drvName) {
var availableCPUs int

// Uses the gopsutil cpu package to count the number of logical cpu cores
ci, err := cpu.Counts(true)
cpuCount := getCPUCount(drvName)
isKIC := driver.IsKIC(drvName)

if isKIC {
si, err := oci.CachedDaemonInfo(drvName)
if err != nil {
klog.Warningf("Unable to get CPU info: %v", err)
} else {
cpuCount = ci
si, err = oci.DaemonInfo(drvName)
if err != nil {
exit.Message(reason.Usage, "Ensure your {{.driver_name}} is running and is healthy.", out.V{"driver_name": driver.FullName(drvName)})
}
}
availableCPUs = si.CPUs
} else {
cpuCount = viper.GetInt(cpus)
ci, err := cpu.Counts(true)
if err != nil {
exit.Message(reason.Usage, "Unable to get CPU info: {{.err}}", out.V{"err": err})
}
availableCPUs = ci
}

if cpuCount < minimumCPUS {
exitIfNotForced(reason.RsrcInsufficientCores, "Requested cpu count {{.requested_cpus}} is less than the minimum allowed of {{.minimum_cpus}}", out.V{"requested_cpus": cpuCount, "minimum_cpus": minimumCPUS})
}

if !driver.IsKIC((drvName)) {
return
}

si, err := oci.CachedDaemonInfo(drvName)
if err != nil {
out.Styled(style.Confused, "Failed to verify '{{.driver_name}} info' will try again ...", out.V{"driver_name": drvName})
si, err = oci.DaemonInfo(drvName)
if err != nil {
exit.Message(reason.Usage, "Ensure your {{.driver_name}} is running and is healthy.", out.V{"driver_name": driver.FullName(drvName)})
}

}

if si.CPUs < cpuCount {

if availableCPUs < cpuCount {
if driver.IsDockerDesktop(drvName) {
out.Styled(style.Empty, `- Ensure your {{.driver_name}} daemon has access to enough CPU/memory resources.`, out.V{"driver_name": drvName})
if runtime.GOOS == "darwin" {
out.Styled(style.Empty, `- Docs https://docs.docker.com/docker-for-mac/#resources`, out.V{"driver_name": drvName})
out.Styled(style.Empty, `- Docs https://docs.docker.com/docker-for-mac/#resources`)
}
if runtime.GOOS == "windows" {
out.String("\n\t")
out.Styled(style.Empty, `- Docs https://docs.docker.com/docker-for-windows/#resources`, out.V{"driver_name": drvName})
out.Styled(style.Empty, `- Docs https://docs.docker.com/docker-for-windows/#resources`)
}
}

exitIfNotForced(reason.RsrcInsufficientCores, "Requested cpu count {{.requested_cpus}} is greater than the available cpus of {{.avail_cpus}}", out.V{"requested_cpus": cpuCount, "avail_cpus": si.CPUs})
exitIfNotForced(reason.RsrcInsufficientCores, "Requested cpu count {{.requested_cpus}} is greater than the available cpus of {{.avail_cpus}}", out.V{"requested_cpus": cpuCount, "avail_cpus": availableCPUs})
}

// looks good
if si.CPUs >= 2 {
if availableCPUs >= 2 {
return
}

Expand Down Expand Up @@ -1236,13 +1229,32 @@ func validateChangedMemoryFlags(drvName string) {
if !driver.HasResourceLimits(drvName) {
out.WarningT("The '{{.name}}' driver does not respect the --memory flag", out.V{"name": drvName})
}
req, err := util.CalculateSizeInMB(viper.GetString(memory))
if err != nil {
exitIfNotForced(reason.Usage, "Unable to parse memory '{{.memory}}': {{.error}}", out.V{"memory": viper.GetString(memory), "error": err})
var req int
var err error
memString := viper.GetString(memory)
if memString == constants.MaxResources {
sysLimit, containerLimit, err := memoryLimits(drvName)
if err != nil {
klog.Warningf("Unable to query memory limits: %+v", err)
}
req = noLimitMemory(sysLimit, containerLimit)
} else {
req, err = util.CalculateSizeInMB(memString)
if err != nil {
exitIfNotForced(reason.Usage, "Unable to parse memory '{{.memory}}': {{.error}}", out.V{"memory": memString, "error": err})
}
}
validateRequestedMemorySize(req, drvName)
}

func noLimitMemory(sysLimit int, containerLimit int) int {
if containerLimit != 0 {
return containerLimit
}
// Recommend 1GB to handle OS/VM overhead
return sysLimit - 1024
}

// This function validates if the --registry-mirror
// args match the format of http://localhost
func validateRegistryMirror() {
Expand Down
43 changes: 37 additions & 6 deletions cmd/minikube/cmd/start_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ import (

"github.com/blang/semver"
"github.com/pkg/errors"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/klog/v2"
"k8s.io/minikube/pkg/drivers/kic"
"k8s.io/minikube/pkg/drivers/kic/oci"
"k8s.io/minikube/pkg/minikube/bootstrapper/bsutil"
"k8s.io/minikube/pkg/minikube/bootstrapper/bsutil/kverify"
"k8s.io/minikube/pkg/minikube/cni"
Expand Down Expand Up @@ -135,8 +137,8 @@ func initMinikubeFlags() {
startCmd.Flags().Bool(interactive, true, "Allow user prompts for more information")
startCmd.Flags().Bool(dryRun, false, "dry-run mode. Validates configuration, but does not mutate system state")

startCmd.Flags().Int(cpus, 2, "Number of CPUs allocated to Kubernetes.")
startCmd.Flags().String(memory, "", "Amount of RAM to allocate to Kubernetes (format: <number>[<unit>], where unit = b, k, m or g).")
startCmd.Flags().String(cpus, "2", fmt.Sprintf("Number of CPUs allocated to Kubernetes. Use %q to use the maximum number of CPUs.", constants.MaxResources))
startCmd.Flags().String(memory, "", fmt.Sprintf("Amount of RAM to allocate to Kubernetes (format: <number>[<unit>], where unit = b, k, m or g). Use %q to use the maximum amount of memory.", constants.MaxResources))
startCmd.Flags().String(humanReadableDiskSize, defaultDiskSize, "Disk size allocated to the minikube VM (format: <number>[<unit>], where unit = b, k, m or g).")
startCmd.Flags().Bool(downloadOnly, false, "If true, only download and cache files for later use - don't install or start anything.")
startCmd.Flags().Bool(cacheImages, true, "If true, cache docker images for the current bootstrapper and load them into the machine. Always false with --driver=none.")
Expand Down Expand Up @@ -290,6 +292,30 @@ func generateClusterConfig(cmd *cobra.Command, existing *config.ClusterConfig, k
return createNode(cc, kubeNodeName, existing)
}

func getCPUCount(drvName string) int {
if viper.GetString(cpus) != constants.MaxResources {
return viper.GetInt(cpus)
}

if !driver.IsKIC(drvName) {
ci, err := cpu.Counts(true)
if err != nil {
exit.Message(reason.Usage, "Unable to get CPU info: {{.err}}", out.V{"err": err})
}
return ci
}

si, err := oci.CachedDaemonInfo(drvName)
if err != nil {
si, err = oci.DaemonInfo(drvName)
if err != nil {
exit.Message(reason.Usage, "Ensure your {{.driver_name}} is running and is healthy.", out.V{"driver_name": driver.FullName(drvName)})
}
}

return si.CPUs
}

func getMemorySize(cmd *cobra.Command, drvName string) int {
sysLimit, containerLimit, err := memoryLimits(drvName)
if err != nil {
Expand All @@ -298,10 +324,15 @@ func getMemorySize(cmd *cobra.Command, drvName string) int {

mem := suggestMemoryAllocation(sysLimit, containerLimit, viper.GetInt(nodes))
if cmd.Flags().Changed(memory) || viper.IsSet(memory) {
memString := viper.GetString(memory)
var err error
mem, err = pkgutil.CalculateSizeInMB(viper.GetString(memory))
if err != nil {
exit.Message(reason.Usage, "Generate unable to parse memory '{{.memory}}': {{.error}}", out.V{"memory": viper.GetString(memory), "error": err})
if memString == constants.MaxResources {
mem = noLimitMemory(sysLimit, containerLimit)
} else {
mem, err = pkgutil.CalculateSizeInMB(memString)
if err != nil {
exit.Message(reason.Usage, "Generate unable to parse memory '{{.memory}}': {{.error}}", out.V{"memory": memString, "error": err})
}
}
if driver.IsKIC(drvName) && mem > containerLimit {
exit.Message(reason.Usage, "{{.driver_name}} has only {{.container_limit}}MB memory but you specified {{.specified_memory}}MB", out.V{"container_limit": containerLimit, "specified_memory": mem, "driver_name": driver.FullName(drvName)})
Expand Down Expand Up @@ -384,7 +415,7 @@ func generateNewConfigFromFlags(cmd *cobra.Command, k8sVersion string, drvName s
KicBaseImage: viper.GetString(kicBaseImage),
Network: viper.GetString(network),
Memory: getMemorySize(cmd, drvName),
CPUs: viper.GetInt(cpus),
CPUs: getCPUCount(drvName),
DiskSize: getDiskSize(),
Driver: drvName,
ListenAddress: viper.GetString(listenAddress),
Expand Down
2 changes: 2 additions & 0 deletions pkg/minikube/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ const (

// TimeFormat is the format that should be used when outputting time
TimeFormat = time.RFC1123
// MaxResources is the value that can be passed into the memory and cpus flags to specify to use maximum resources
MaxResources = "max"
)

var (
Expand Down
4 changes: 2 additions & 2 deletions site/content/en/docs/commands/start.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ minikube start [flags]
--cache-images If true, cache docker images for the current bootstrapper and load them into the machine. Always false with --driver=none. (default true)
--cni string CNI plug-in to use. Valid options: auto, bridge, calico, cilium, flannel, kindnet, or path to a CNI manifest (default: auto)
--container-runtime string The container runtime to be used (docker, cri-o, containerd). (default "docker")
--cpus int Number of CPUs allocated to Kubernetes. (default 2)
--cpus string Number of CPUs allocated to Kubernetes. Use "max" to use the maximum number of CPUs. (default "2")
--cri-socket string The cri socket path to be used.
--delete-on-failure If set, delete the current cluster if start fails and try again. Defaults to false.
--disable-driver-mounts Disables the filesystem mounts provided by the hypervisors
Expand Down Expand Up @@ -73,7 +73,7 @@ minikube start [flags]
--kvm-numa-count int Simulate numa node count in minikube, supported numa node count range is 1-8 (kvm2 driver only) (default 1)
--kvm-qemu-uri string The KVM QEMU connection URI. (kvm2 driver only) (default "qemu:///system")
--listen-address string IP Address to use to expose ports (docker and podman driver only)
--memory string Amount of RAM to allocate to Kubernetes (format: <number>[<unit>], where unit = b, k, m or g).
--memory string Amount of RAM to allocate to Kubernetes (format: <number>[<unit>], where unit = b, k, m or g). Use "max" to use the maximum amount of memory.
--mount This will start the mount daemon and automatically mount files into minikube.
--mount-string string The argument to pass the minikube mount command on start.
--namespace string The named space to activate after start (default "default")
Expand Down
6 changes: 6 additions & 0 deletions site/content/en/docs/faq/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,9 @@ For the docker and podman driver, use `--listen-address` flag:
minikube start --listen-address=0.0.0.0
```

## How can I allocate maximum resources to minikube?

Setting the `memory` and `cpus` flags on the start command to `max` will use maximum available resources:
```
minikube start --memory=max --cpus=max
```
6 changes: 2 additions & 4 deletions translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
"Allow user prompts for more information": "",
"Alternative image repository to pull docker images from. This can be used when you have limited access to gcr.io. Set it to \\\"auto\\\" to let minikube decide one for you. For Chinese mainland users, you may use local gcr.io mirrors such as registry.cn-hangzhou.aliyuncs.com/google_containers": "Alternatives Bild-Repository zum Abrufen von Docker-Images. Dies ist hilfreich, wenn Sie nur eingeschränkten Zugriff auf gcr.io haben. Stellen Sie \\\"auto\\\" ein, dann wählt minikube eins für sie aus. Nutzer vom chinesischen Festland können einen lokalen gcr.io-Mirror wie registry.cn-hangzhou.aliyuncs.com/google_containers verwenden.",
"Amount of RAM allocated to the minikube VM (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g)": "Größe des der minikube-VM zugewiesenen Arbeitsspeichers (Format: \u003cNummer\u003e [\u003cEinheit\u003e], wobei Einheit = b, k, m oder g)",
"Amount of RAM to allocate to Kubernetes (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g).": "",
"Amount of time to wait for a service in seconds": "",
"Amount of time to wait for service in seconds": "",
"Another hypervisor, such as VirtualBox, is conflicting with KVM. Please stop the other hypervisor, or use --driver to switch to it.": "",
Expand Down Expand Up @@ -260,7 +259,6 @@
"Failed to stop node {{.name}}": "",
"Failed to update cluster": "",
"Failed to update config": "",
"Failed to verify '{{.driver_name}} info' will try again ...": "",
"Failed unmount: {{.error}}": "",
"File permissions used for the mount": "",
"Filter to use only VM Drivers": "",
Expand Down Expand Up @@ -395,7 +393,6 @@
"None of the known repositories is accessible. Consider specifying an alternative image repository with --image-repository flag": "Keines der bekannten Repositories ist zugänglich. Erwägen Sie, ein alternatives Image-Repository mit der Kennzeichnung --image-repository anzugeben",
"Noticed you have an activated docker-env on {{.driver_name}} driver in this terminal:": "",
"Noticed you have an activated podman-env on {{.driver_name}} driver in this terminal:": "",
"Number of CPUs allocated to Kubernetes.": "",
"Number of CPUs allocated to the minikube VM": "Anzahl der CPUs, die der minikube-VM zugeordnet sind",
"Number of lines back to go within the log": "",
"OS release is {{.pretty_name}}": "",
Expand Down Expand Up @@ -700,6 +697,7 @@
"Unable to find control plane": "",
"Unable to generate docs": "",
"Unable to generate the documentation. Please ensure that the path specified is a directory, exists \u0026 you have permission to write to it.": "",
"Unable to get CPU info: {{.err}}": "",
"Unable to get bootstrapper: {{.error}}": "Bootstrapper kann nicht abgerufen werden: {{.error}}",
"Unable to get command runner": "",
"Unable to get control plane status: {{.error}}": "",
Expand Down Expand Up @@ -943,4 +941,4 @@
"{{.profile}} profile is not valid: {{.err}}": "",
"{{.type}} is not yet a supported filesystem. We will try anyways!": "",
"{{.url}} is not accessible: {{.error}}": ""
}
}
6 changes: 2 additions & 4 deletions translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
"Allow user prompts for more information": "Permitir que el usuario solicite más información",
"Alternative image repository to pull docker images from. This can be used when you have limited access to gcr.io. Set it to \\\"auto\\\" to let minikube decide one for you. For Chinese mainland users, you may use local gcr.io mirrors such as registry.cn-hangzhou.aliyuncs.com/google_containers": "Repositorio de imágenes alternativo del que extraer imágenes de Docker. Puedes usarlo cuando tengas acceso limitado a gcr.io. Si quieres que minikube elija uno por ti, solo tienes que definir el valor como \"auto\". Los usuarios de China continental pueden utilizar réplicas locales de gcr.io, como registry.cn-hangzhou.aliyuncs.com/google_containers",
"Amount of RAM allocated to the minikube VM (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g)": "Cantidad de RAM asignada a la VM de minikube (formato: \u003cnúmero\u003e[\u003cunidad\u003e], donde unidad = b, k, m o g)",
"Amount of RAM to allocate to Kubernetes (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g).": "",
"Amount of time to wait for a service in seconds": "Cantidad de tiempo para esperar por un servicio en segundos",
"Amount of time to wait for service in seconds": "Cantidad de tiempo para esperar un servicio en segundos",
"Another hypervisor, such as VirtualBox, is conflicting with KVM. Please stop the other hypervisor, or use --driver to switch to it.": "Otro hipervisor, por ejemplo VirtualBox, está en conflicto con KVM. Por favor detén el otro hipervisor, o usa --driver para cambiarlo.",
Expand Down Expand Up @@ -265,7 +264,6 @@
"Failed to stop node {{.name}}": "",
"Failed to update cluster": "",
"Failed to update config": "",
"Failed to verify '{{.driver_name}} info' will try again ...": "",
"Failed unmount: {{.error}}": "",
"File permissions used for the mount": "",
"Filter to use only VM Drivers": "",
Expand Down Expand Up @@ -400,7 +398,6 @@
"None of the known repositories is accessible. Consider specifying an alternative image repository with --image-repository flag": "No se puede acceder a ninguno de los repositorios conocidos. Plantéate indicar un repositorio de imágenes alternativo con la marca --image-repository.",
"Noticed you have an activated docker-env on {{.driver_name}} driver in this terminal:": "",
"Noticed you have an activated podman-env on {{.driver_name}} driver in this terminal:": "",
"Number of CPUs allocated to Kubernetes.": "",
"Number of CPUs allocated to the minikube VM": "Número de CPU asignadas a la VM de minikube",
"Number of lines back to go within the log": "",
"OS release is {{.pretty_name}}": "",
Expand Down Expand Up @@ -705,6 +702,7 @@
"Unable to find control plane": "",
"Unable to generate docs": "",
"Unable to generate the documentation. Please ensure that the path specified is a directory, exists \u0026 you have permission to write to it.": "",
"Unable to get CPU info: {{.err}}": "",
"Unable to get bootstrapper: {{.error}}": "No se ha podido obtener el programa previo: {{.error}}",
"Unable to get command runner": "",
"Unable to get control plane status: {{.error}}": "",
Expand Down Expand Up @@ -947,4 +945,4 @@
"{{.profile}} profile is not valid: {{.err}}": "",
"{{.type}} is not yet a supported filesystem. We will try anyways!": "",
"{{.url}} is not accessible: {{.error}}": ""
}
}
Loading

0 comments on commit e8b3db9

Please sign in to comment.