Skip to content

Commit

Permalink
Merge pull request #17491 from spowelljr/noLimit
Browse files Browse the repository at this point in the history
Kic: Add "no-limit" option to cpus & memory flags
  • Loading branch information
medyagh authored Oct 26, 2023
2 parents d437eed + b9c6c6e commit 68d187f
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 25 deletions.
40 changes: 26 additions & 14 deletions cmd/minikube/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -1149,6 +1149,11 @@ func validateRequestedMemorySize(req int, drvName string) {
exitIfNotForced(reason.RsrcInsufficientSysMemory, "System only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes", out.V{"size": sysLimit, "req": minUsableMem})
}

// if --memory=no-limit, ignore remaining checks
if req == 0 && driver.IsKIC(drvName) {
return
}

if req < minUsableMem {
exitIfNotForced(reason.RsrcInsufficientReqMemory, "Requested memory allocation {{.requested}}MiB is less than the usable minimum of {{.minimum_memory}}MB", out.V{"requested": req, "minimum_memory": minUsableMem})
}
Expand Down Expand Up @@ -1208,6 +1213,21 @@ func validateCPUCount(drvName string) {
availableCPUs = ci
}

if availableCPUs < 2 {
if drvName == oci.Docker && runtime.GOOS == "darwin" {
exitIfNotForced(reason.RsrcInsufficientDarwinDockerCores, "Docker Desktop has less than 2 CPUs configured, but Kubernetes requires at least 2 to be available")
} else if drvName == oci.Docker && runtime.GOOS == "windows" {
exitIfNotForced(reason.RsrcInsufficientWindowsDockerCores, "Docker Desktop has less than 2 CPUs configured, but Kubernetes requires at least 2 to be available")
} else {
exitIfNotForced(reason.RsrcInsufficientCores, "{{.driver_name}} has less than 2 CPUs available, but Kubernetes requires at least 2 to be available", out.V{"driver_name": driver.FullName(viper.GetString("driver"))})
}
}

// if --cpus=no-limit, ignore remaining checks
if cpuCount == 0 && driver.IsKIC(drvName) {
return
}

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})
}
Expand All @@ -1226,19 +1246,6 @@ func validateCPUCount(drvName string) {

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 availableCPUs >= 2 {
return
}

if drvName == oci.Docker && runtime.GOOS == "darwin" {
exitIfNotForced(reason.RsrcInsufficientDarwinDockerCores, "Docker Desktop has less than 2 CPUs configured, but Kubernetes requires at least 2 to be available")
} else if drvName == oci.Docker && runtime.GOOS == "windows" {
exitIfNotForced(reason.RsrcInsufficientWindowsDockerCores, "Docker Desktop has less than 2 CPUs configured, but Kubernetes requires at least 2 to be available")
} else {
exitIfNotForced(reason.RsrcInsufficientCores, "{{.driver_name}} has less than 2 CPUs available, but Kubernetes requires at least 2 to be available", out.V{"driver_name": driver.FullName(viper.GetString("driver"))})
}
}

// validateFlags validates the supplied flags against known bad combinations
Expand Down Expand Up @@ -1505,13 +1512,18 @@ func validateChangedMemoryFlags(drvName string) {
var req int
var err error
memString := viper.GetString(memory)
if memString == constants.MaxResources {
if memString == constants.NoLimit && driver.IsKIC(drvName) {
req = 0
} else 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, drvName)
} else {
if memString == constants.NoLimit {
exit.Message(reason.Usage, "The '{{.name}}' driver does not support --memory=no-limit", out.V{"name": drvName})
}
req, err = util.CalculateSizeInMB(memString)
if err != nil {
exitIfNotForced(reason.Usage, "Unable to parse memory '{{.memory}}': {{.error}}", out.V{"memory": memString, "error": err})
Expand Down
14 changes: 11 additions & 3 deletions cmd/minikube/cmd/start_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,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().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(cpus, "2", fmt.Sprintf("Number of CPUs allocated to Kubernetes. Use %q to use the maximum number of CPUs. Use %q to not specify a limit (Docker/Podman only)", constants.MaxResources, constants.NoLimit))
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. Use %q to not specify a limit (Docker/Podman only)", constants.MaxResources, constants.NoLimit))
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 @@ -337,6 +337,12 @@ func generateClusterConfig(cmd *cobra.Command, existing *config.ClusterConfig, k
}

func getCPUCount(drvName string) int {
if viper.GetString(cpus) == constants.NoLimit {
if driver.IsKIC(drvName) {
return 0
}
exit.Message(reason.Usage, "The '{{.name}}' driver does not support --cpus=no-limit", out.V{"name": drvName})
}
if viper.GetString(cpus) != constants.MaxResources {
return viper.GetInt(cpus)
}
Expand Down Expand Up @@ -370,7 +376,9 @@ func getMemorySize(cmd *cobra.Command, drvName string) int {
if cmd.Flags().Changed(memory) || viper.IsSet(memory) {
memString := viper.GetString(memory)
var err error
if memString == constants.MaxResources {
if memString == constants.NoLimit && driver.IsKIC(drvName) {
mem = 0
} else if memString == constants.MaxResources {
mem = noLimitMemory(sysLimit, containerLimit, drvName)
} else {
mem, err = pkgutil.CalculateSizeInMB(memString)
Expand Down
5 changes: 4 additions & 1 deletion pkg/drivers/kic/kic.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,16 @@ func (d *Driver) Create() error {
ClusterLabel: oci.ProfileLabelKey + "=" + d.MachineName,
NodeLabel: oci.NodeLabelKey + "=" + d.NodeConfig.MachineName,
CPUs: strconv.Itoa(d.NodeConfig.CPU),
Memory: strconv.Itoa(d.NodeConfig.Memory) + "mb",
Memory: strconv.Itoa(d.NodeConfig.Memory),
Envs: d.NodeConfig.Envs,
ExtraArgs: append([]string{"--expose", fmt.Sprintf("%d", d.NodeConfig.APIServerPort)}, d.NodeConfig.ExtraArgs...),
OCIBinary: d.NodeConfig.OCIBinary,
APIServerPort: d.NodeConfig.APIServerPort,
GPUs: d.NodeConfig.GPUs,
}
if params.Memory != "0" {
params.Memory += "mb"
}

networkName := d.NodeConfig.Network
if networkName == "" {
Expand Down
12 changes: 6 additions & 6 deletions pkg/drivers/kic/oci/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func checkRunning(p CreateParams) func() error {
}

// CreateContainerNode creates a new container node
func CreateContainerNode(p CreateParams) error {
func CreateContainerNode(p CreateParams) error { //nolint to suppress cyclomatic complexity
// on windows os, if docker desktop is using Windows Containers. Exit early with error
if p.OCIBinary == Docker && runtime.GOOS == "windows" {
info, err := DaemonInfo(p.OCIBinary)
Expand Down Expand Up @@ -203,11 +203,11 @@ func CreateContainerNode(p CreateParams) error {
// podman mounts var/lib with no-exec by default https://github.com/containers/libpod/issues/5103
runArgs = append(runArgs, "--volume", fmt.Sprintf("%s:/var:exec", p.Name))

if memcgSwap {
if memcgSwap && p.Memory != NoLimit {
runArgs = append(runArgs, fmt.Sprintf("--memory-swap=%s", p.Memory))
}

if memcg {
if memcg && p.Memory != NoLimit {
runArgs = append(runArgs, fmt.Sprintf("--memory=%s", p.Memory))
}

Expand All @@ -218,10 +218,10 @@ func CreateContainerNode(p CreateParams) error {
// ignore apparmore github actions docker: https://github.com/kubernetes/minikube/issues/7624
runArgs = append(runArgs, "--security-opt", "apparmor=unconfined")

if memcg {
if memcg && p.Memory != NoLimit {
runArgs = append(runArgs, fmt.Sprintf("--memory=%s", p.Memory))
}
if memcgSwap {
if memcgSwap && p.Memory != NoLimit {
// Disable swap by setting the value to match
runArgs = append(runArgs, fmt.Sprintf("--memory-swap=%s", p.Memory))
}
Expand All @@ -244,7 +244,7 @@ func CreateContainerNode(p CreateParams) error {
}
}

if cpuCfsPeriod && cpuCfsQuota {
if cpuCfsPeriod && cpuCfsQuota && p.CPUs != NoLimit {
runArgs = append(runArgs, fmt.Sprintf("--cpus=%s", p.CPUs))
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/drivers/kic/oci/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const (
nodeRoleLabelKey = "role.minikube.sigs.k8s.io"
// CreatedByLabelKey is applied to any container/volume that is created by minikube created_by.minikube.sigs.k8s.io=true
CreatedByLabelKey = "created_by.minikube.sigs.k8s.io"
// NoLimit is the value that specifies that no resource limit should be set
NoLimit = "0"
)

// CreateParams are parameters needed to create a container
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 @@ -138,6 +138,8 @@ const (
TimeFormat = time.RFC822
// MaxResources is the value that can be passed into the memory and cpus flags to specify to use maximum resources
MaxResources = "max"
// NoLimit is the value that can be passed into the memory and cpus flags to specify to not set the resource limit on the container (Docker & Podman only)
NoLimit = "no-limit"

// DefaultCertExpiration is the amount of time in the future a certificate will expire in by default, which is 3 years
DefaultCertExpiration = time.Hour * 24 * 365 * 3
Expand Down
2 changes: 1 addition & 1 deletion pkg/minikube/machine/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ func showHostInfo(h *host.Host, cfg config.ClusterConfig) {
}
if driver.IsKIC(cfg.Driver) { // TODO:medyagh add free disk space on docker machine
register.Reg.SetStep(register.CreatingContainer)
out.Step(style.StartingVM, "Creating {{.driver_name}} {{.machine_type}} (CPUs={{.number_of_cpus}}, Memory={{.memory_size}}MB) ...", out.V{"driver_name": cfg.Driver, "number_of_cpus": cfg.CPUs, "memory_size": cfg.Memory, "machine_type": machineType})
out.Step(style.StartingVM, "Creating {{.driver_name}} {{.machine_type}} (CPUs={{if not .number_of_cpus}}no-limit{{else}}{{.number_of_cpus}}{{end}}, Memory={{if not .memory_size}}no-limit{{else}}{{.memory_size}}MB{{end}}) ...", out.V{"driver_name": cfg.Driver, "number_of_cpus": cfg.CPUs, "memory_size": cfg.Memory, "machine_type": machineType})
return
}
register.Reg.SetStep(register.CreatingVM)
Expand Down

0 comments on commit 68d187f

Please sign in to comment.