From 29002bceef3e0ef71a64093737a4fd934bb9c749 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Sat, 25 Aug 2018 18:08:12 -0300 Subject: [PATCH] Check if cgroup cpu limits are defined to get the number of CPUs --- internal/ingress/controller/config/config.go | 2 +- .../ingress/controller/template/configmap.go | 12 ++++ internal/runtime/cpu.go | 64 +++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 internal/runtime/cpu.go diff --git a/internal/ingress/controller/config/config.go b/internal/ingress/controller/config/config.go index 5cd700f35..be74cb044 100644 --- a/internal/ingress/controller/config/config.go +++ b/internal/ingress/controller/config/config.go @@ -18,7 +18,6 @@ package config import ( "fmt" - "runtime" "strconv" "time" @@ -28,6 +27,7 @@ import ( "k8s.io/ingress-nginx/internal/ingress" "k8s.io/ingress-nginx/internal/ingress/defaults" + "k8s.io/ingress-nginx/internal/runtime" ) const ( diff --git a/internal/ingress/controller/template/configmap.go b/internal/ingress/controller/template/configmap.go index ab6edd883..604d20813 100644 --- a/internal/ingress/controller/template/configmap.go +++ b/internal/ingress/controller/template/configmap.go @@ -31,6 +31,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/ingress-nginx/internal/ingress/controller/config" ing_net "k8s.io/ingress-nginx/internal/net" + "k8s.io/ingress-nginx/internal/runtime" ) const ( @@ -45,6 +46,7 @@ const ( nginxStatusIpv4Whitelist = "nginx-status-ipv4-whitelist" nginxStatusIpv6Whitelist = "nginx-status-ipv6-whitelist" proxyHeaderTimeout = "proxy-protocol-header-timeout" + workerProcesses = "worker-processes" ) var ( @@ -166,6 +168,16 @@ func ReadConfig(src map[string]string) config.Configuration { delete(conf, nginxStatusIpv6Whitelist) } + if val, ok := conf[workerProcesses]; ok { + to.WorkerProcesses = val + + if val == "auto" { + to.WorkerProcesses = strconv.Itoa(runtime.NumCPU()) + } + + delete(conf, workerProcesses) + } + to.CustomHTTPErrors = filterErrors(errors) to.SkipAccessLogURLs = skipUrls to.WhitelistSourceRange = whiteList diff --git a/internal/runtime/cpu.go b/internal/runtime/cpu.go new file mode 100644 index 000000000..bd1865e74 --- /dev/null +++ b/internal/runtime/cpu.go @@ -0,0 +1,64 @@ +/* +Copyright 2018 The Kubernetes Authors. + +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 runtime + +import ( + "io/ioutil" + "math" + "path/filepath" + "runtime" + "strconv" + "strings" + + libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups" +) + +// NumCPU returns the number of logical CPUs usable by the current process. +// If CPU cgroups limits are configured, use cfs_quota_us / cfs_period_us +// as formula +// https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt +func NumCPU() int { + cpus := runtime.NumCPU() + + cgroupPath, err := libcontainercgroups.FindCgroupMountpoint("cpu") + if err != nil { + return cpus + } + + cpuQuota := readCgroupFileToInt64(cgroupPath, "cpu.cfs_quota_us") + cpuPeriod := readCgroupFileToInt64(cgroupPath, "cpu.cfs_period_us") + + if cpuQuota == -1 || cpuPeriod == -1 { + return cpus + } + + return int(math.Ceil(float64(cpuQuota) / float64(cpuPeriod))) +} + +func readCgroupFileToInt64(cgroupPath, cgroupFile string) int64 { + contents, err := ioutil.ReadFile(filepath.Join(cgroupPath, cgroupFile)) + if err != nil { + return -1 + } + + strValue := strings.TrimSpace(string(contents)) + if value, err := strconv.ParseInt(strValue, 10, 64); err == nil { + return value + } + + return -1 +}