mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2024-12-14 11:57:51 +00:00
Implement cpu feature source
Currently, it only detects one feature, i.e. hardware multithreading (such as Intel hyper-threading technology). The corresponding feature label is: feature.node.kubernetes.io/cpu-hardware_multithreading=true However, this (architecture/platform dependent) feature is not detected directly, and, the heuristics can be mislead. Detection works by checking the thread siblings of each logical (and online) cpu in the system. If any cpu has any thread siblings the feature label is set to true. Thus, hardware multithreading could be effectively disabled e.g. by putting all sibling cpus offline (even if the technology would be enabled in hardware).
This commit is contained in:
parent
649d8a3ae1
commit
da2cb07c64
4 changed files with 87 additions and 4 deletions
15
README.md
15
README.md
|
@ -52,7 +52,7 @@ node-feature-discovery.
|
|||
will override settings read from the config file.
|
||||
[Default: ]
|
||||
--sources=<sources> Comma separated list of feature sources.
|
||||
[Default: cpuid,iommu,kernel,local,memory,network,pci,pstate,rdt,selinux,storage,system]
|
||||
[Default: cpu,cpuid,iommu,kernel,local,memory,network,pci,pstate,rdt,selinux,storage,system]
|
||||
--no-publish Do not publish discovered features to the
|
||||
cluster-local Kubernetes API server.
|
||||
--label-whitelist=<pattern> Regular expression to filter label names to
|
||||
|
@ -75,6 +75,7 @@ for up-to-date information about the required volume mounts.
|
|||
|
||||
The current set of feature sources are the following:
|
||||
|
||||
- CPU
|
||||
- [CPUID][cpuid] for x86/Arm64 CPU details
|
||||
- IOMMU
|
||||
- Kernel
|
||||
|
@ -110,6 +111,7 @@ the only label value published for features is the string `"true"`._
|
|||
|
||||
```json
|
||||
{
|
||||
"feature.node.kubernetes.io/cpu-<feature-name>": "true",
|
||||
"feature.node.kubernetes.io/cpuid-<feature-name>": "true",
|
||||
"feature.node.kubernetes.io/iommu-<feature-name>": "true",
|
||||
"feature.node.kubernetes.io/kernel-config.<option-name>": "true",
|
||||
|
@ -133,6 +135,17 @@ given node. If features are not discovered on a consecutive run, the correspondi
|
|||
label will be removed. This includes any restrictions placed on the consecutive run,
|
||||
such as restricting discovered features with the --label-whitelist option._
|
||||
|
||||
### CPU Features
|
||||
|
||||
The CPU feature source differs from the CPUID feature source in that it
|
||||
discovers CPU related features that are actually enabled, whereas CPUID only
|
||||
reports *supported* CPU capabilities (i.e. a capability might be supported but
|
||||
not enabled) as reported by the `cpuid` instruction.
|
||||
|
||||
| Feature name | Description |
|
||||
| ----------------------- | -------------------------------------------------- |
|
||||
| hardware_multithreading | Hardware multithreading, such as Intel HTT, enabled (number of locical CPUs is greater than physical CPUs)
|
||||
|
||||
### X86 CPUID Features (Partial List)
|
||||
|
||||
| Feature name | Description |
|
||||
|
|
4
main.go
4
main.go
|
@ -17,6 +17,7 @@ import (
|
|||
k8sclient "k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/node-feature-discovery/source"
|
||||
"sigs.k8s.io/node-feature-discovery/source/cpu"
|
||||
"sigs.k8s.io/node-feature-discovery/source/cpuid"
|
||||
"sigs.k8s.io/node-feature-discovery/source/fake"
|
||||
"sigs.k8s.io/node-feature-discovery/source/iommu"
|
||||
|
@ -183,7 +184,7 @@ func argsParse(argv []string) (args Args) {
|
|||
will override settings read from the config file.
|
||||
[Default: ]
|
||||
--sources=<sources> Comma separated list of feature sources.
|
||||
[Default: cpuid,iommu,kernel,local,memory,network,pci,pstate,rdt,selinux,storage,system]
|
||||
[Default: cpu,cpuid,iommu,kernel,local,memory,network,pci,pstate,rdt,selinux,storage,system]
|
||||
--no-publish Do not publish discovered features to the
|
||||
cluster-local Kubernetes API server.
|
||||
--label-whitelist=<pattern> Regular expression to filter label names to
|
||||
|
@ -259,6 +260,7 @@ func configureParameters(sourcesWhiteList []string, labelWhiteListStr string) (e
|
|||
|
||||
// Configure feature sources.
|
||||
allSources := []source.FeatureSource{
|
||||
cpu.Source{},
|
||||
cpuid.Source{},
|
||||
fake.Source{},
|
||||
iommu.Source{},
|
||||
|
|
|
@ -152,7 +152,7 @@ func TestArgsParse(t *testing.T) {
|
|||
So(args.sleepInterval, ShouldEqual, 60*time.Second)
|
||||
So(args.noPublish, ShouldBeTrue)
|
||||
So(args.oneshot, ShouldBeTrue)
|
||||
So(args.sources, ShouldResemble, []string{"cpuid", "iommu", "kernel", "local", "memory", "network", "pci", "pstate", "rdt", "selinux", "storage", "system"})
|
||||
So(args.sources, ShouldResemble, []string{"cpu", "cpuid", "iommu", "kernel", "local", "memory", "network", "pci", "pstate", "rdt", "selinux", "storage", "system"})
|
||||
So(len(args.labelWhiteList), ShouldEqual, 0)
|
||||
})
|
||||
})
|
||||
|
@ -174,7 +174,7 @@ func TestArgsParse(t *testing.T) {
|
|||
|
||||
Convey("args.labelWhiteList is set to appropriate value and args.sources is set to default value", func() {
|
||||
So(args.noPublish, ShouldBeFalse)
|
||||
So(args.sources, ShouldResemble, []string{"cpuid", "iommu", "kernel", "local", "memory", "network", "pci", "pstate", "rdt", "selinux", "storage", "system"})
|
||||
So(args.sources, ShouldResemble, []string{"cpu", "cpuid", "iommu", "kernel", "local", "memory", "network", "pci", "pstate", "rdt", "selinux", "storage", "system"})
|
||||
So(args.labelWhiteList, ShouldResemble, ".*rdt.*")
|
||||
})
|
||||
})
|
||||
|
|
68
source/cpu/cpu.go
Normal file
68
source/cpu/cpu.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
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 cpu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
|
||||
"sigs.k8s.io/node-feature-discovery/source"
|
||||
)
|
||||
|
||||
// Implement FeatureSource interface
|
||||
type Source struct{}
|
||||
|
||||
func (s Source) Name() string { return "cpu" }
|
||||
|
||||
func (s Source) Discover() (source.Features, error) {
|
||||
features := source.Features{}
|
||||
|
||||
// Check if hyper-threading seems to be enabled
|
||||
found, err := haveThreadSiblings()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to detect hyper-threading: %v", err)
|
||||
} else if found {
|
||||
features["hardware_multithreading"] = true
|
||||
}
|
||||
return features, nil
|
||||
}
|
||||
|
||||
// Check if any (online) CPUs have thread siblings
|
||||
func haveThreadSiblings() (bool, error) {
|
||||
const baseDir = "/sys/bus/cpu/devices"
|
||||
files, err := ioutil.ReadDir(baseDir)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
// Try to read siblings from topology
|
||||
siblings, err := ioutil.ReadFile(path.Join(baseDir, file.Name(), "topology/thread_siblings_list"))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, char := range siblings {
|
||||
// If list separator found, we determine that there are multiple siblings
|
||||
if char == ',' || char == '-' {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
// No siblings were found
|
||||
return false, nil
|
||||
}
|
Loading…
Reference in a new issue