1
0
Fork 0
mirror of https://github.com/kubernetes-sigs/node-feature-discovery.git synced 2025-03-28 02:37:11 +00:00

Implement OS release detection

Implement new 'system' feature source. It now detects OS release
information from the os-release file, assumed to be available at
/host-etc/os-release. It currently creates two labels (assuming that the
corresponding fields are found in the os-release file), with example
values:
  feature.node.kubernetes.io/system-os_release.ID=opensuse
  feature.node.kubernetes.io/system-os_release.VERSION_ID=42.3

Also, update the template spec to mount /etc/os-release file from the
host inside the container.
This commit is contained in:
Markus Lehtonen 2018-07-10 12:00:02 +03:00
parent 1ccd69e6e3
commit 649d8a3ae1
6 changed files with 107 additions and 8 deletions

View file

@ -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]
[Default: 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
@ -85,6 +85,7 @@ The current set of feature sources are the following:
- RDT ([Intel Resource Director Technology][intel-rdt])
- Selinux
- Storage
- System
### Feature labels
@ -120,6 +121,7 @@ the only label value published for features is the string `"true"`._
"feature.node.kubernetes.io/rdt-<feature-name>": "true",
"feature.node.kubernetes.io/selinux-<feature-name>": "true",
"feature.node.kubernetes.io/storage-<feature-name>": "true",
"feature.node.kubernetes.io/system-<feature name>": "<feature value>",
"feature.node.kubernetes.io/<hook name>-<feature name>": "<feature value>"
}
```
@ -290,6 +292,13 @@ for more information on NFD config.
| :--------------: | :---------------------------------------------------------------------------------: |
| nonrotationaldisk | Non-rotational disk, like SSD, is present in the node
### System Features
| Feature | Attribute | Description |
| ----------- | ---------- | --------------------------------------------------|
| os_release | ID | Operating system identifier
| <br> | VERSION_ID | Operating system version identifier
## Getting started
### System requirements

12
main.go
View file

@ -12,6 +12,10 @@ import (
"github.com/docopt/docopt-go"
"github.com/ghodss/yaml"
api "k8s.io/api/core/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
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/cpuid"
"sigs.k8s.io/node-feature-discovery/source/fake"
@ -26,10 +30,7 @@ import (
"sigs.k8s.io/node-feature-discovery/source/rdt"
"sigs.k8s.io/node-feature-discovery/source/selinux"
"sigs.k8s.io/node-feature-discovery/source/storage"
api "k8s.io/api/core/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sclient "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest"
"sigs.k8s.io/node-feature-discovery/source/system"
)
const (
@ -182,7 +183,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]
[Default: 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
@ -270,6 +271,7 @@ func configureParameters(sourcesWhiteList []string, labelWhiteListStr string) (e
rdt.Source{},
selinux.Source{},
storage.Source{},
system.Source{},
// local needs to be the last source so that it is able to override
// labels from other sources
local.Source{},

View file

@ -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"})
So(args.sources, ShouldResemble, []string{"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"})
So(args.sources, ShouldResemble, []string{"cpuid", "iommu", "kernel", "local", "memory", "network", "pci", "pstate", "rdt", "selinux", "storage", "system"})
So(args.labelWhiteList, ShouldResemble, ".*rdt.*")
})
})

View file

@ -29,12 +29,18 @@ spec:
- name: host-boot
mountPath: "/host-boot"
readOnly: true
- name: host-os-release
mountPath: "/host-etc/os-release"
readOnly: true
- name: host-sys
mountPath: "/host-sys"
volumes:
- name: host-boot
hostPath:
path: "/boot"
- name: host-os-release
hostPath:
path: "/etc/os-release"
- name: host-sys
hostPath:
path: "/sys"

View file

@ -31,6 +31,9 @@ spec:
- name: host-boot
mountPath: "/host-boot"
readOnly: true
- name: host-os-release
mountPath: "/host-etc/os-release"
readOnly: true
- name: host-sys
mountPath: "/host-sys"
restartPolicy: Never
@ -38,6 +41,9 @@ spec:
- name: host-boot
hostPath:
path: "/boot"
- name: host-os-release
hostPath:
path: "/etc/os-release"
- name: host-sys
hostPath:
path: "/sys"

76
source/system/system.go Normal file
View file

@ -0,0 +1,76 @@
/*
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 system
import (
"bufio"
"log"
"os"
"regexp"
"strings"
"sigs.k8s.io/node-feature-discovery/source"
)
var osReleaseFields = [...]string{
"ID",
"VERSION_ID",
}
// Implement FeatureSource interface
type Source struct{}
func (s Source) Name() string { return "system" }
func (s Source) Discover() (source.Features, error) {
features := source.Features{}
release, err := parseOSRelease()
if err != nil {
log.Printf("ERROR: failed to get os-release: %s", err)
} else {
for _, key := range osReleaseFields {
if value, exists := release[key]; exists {
features["os_release."+key] = value
}
}
}
return features, nil
}
// Read and parse os-release file
func parseOSRelease() (map[string]string, error) {
release := map[string]string{}
f, err := os.Open("/host-etc/os-release")
if err != nil {
return nil, err
}
re := regexp.MustCompile(`^(?P<key>\w+)=(?P<value>.+)`)
// Read line-by-line
s := bufio.NewScanner(f)
for s.Scan() {
line := s.Text()
if m := re.FindStringSubmatch(line); m != nil {
release[m[1]] = strings.Trim(m[2], `"`)
}
}
return release, nil
}