mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2024-12-14 11:57:51 +00:00
Replayed commit history.
This commit is contained in:
commit
570d1ae5be
18 changed files with 1303 additions and 2 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
node-feature-discovery
|
||||
node-feature-discovery-job.json
|
||||
vendor/
|
||||
intel-cmt-cat/
|
||||
rdt-discovery/l2-alloc-discovery
|
||||
rdt-discovery/l3-alloc-discovery
|
||||
rdt-discovery/mon-discovery
|
7
.travis.yml
Normal file
7
.travis.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
sudo: required
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
script:
|
||||
- docker build -t intelsdi/dbi-iafeature-discovery .
|
16
Dockerfile
Normal file
16
Dockerfile
Normal file
|
@ -0,0 +1,16 @@
|
|||
FROM golang:1.6
|
||||
|
||||
ADD . /go/src/github.com/kubernetes-incubator/node-feature-discovery
|
||||
|
||||
WORKDIR /go/src/github.com/kubernetes-incubator/node-feature-discovery
|
||||
|
||||
RUN git clone --depth 1 https://github.com/01org/intel-cmt-cat.git
|
||||
RUN cd intel-cmt-cat/lib; make install
|
||||
RUN cd rdt-discovery; make
|
||||
RUN go get github.com/Masterminds/glide
|
||||
RUN glide install
|
||||
RUN go install \
|
||||
-ldflags "-s -w -X main.version=`git describe --tags --dirty --always`" \
|
||||
github.com/kubernetes-incubator/node-feature-discovery
|
||||
|
||||
ENTRYPOINT ["/go/bin/node-feature-discovery"]
|
13
Makefile
Normal file
13
Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
.PHONY: all
|
||||
|
||||
DOCKER_REGISTRY_USER := kubernetesincubator
|
||||
DOCKER_IMAGE_NAME := node-feature-discovery
|
||||
|
||||
VERSION := $(shell git describe --tags --dirty --always)
|
||||
|
||||
all: docker
|
||||
|
||||
# To override DOCKER_REGISTRY_USER use the -e option as follows:
|
||||
# DOCKER_REGISTRY_USER=<my-username> make docker -e
|
||||
docker:
|
||||
docker build -t $(DOCKER_REGISTRY_USER)/$(DOCKER_IMAGE_NAME):$(VERSION) ./
|
147
README.md
147
README.md
|
@ -1,6 +1,16 @@
|
|||
# Node feature discovery for [Kubernetes](https://kubernetes.io)
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Command line interface](#command-line-interface)
|
||||
- [Feature discovery](#feature-discovery)
|
||||
- [Feature sources](#feature-sources)
|
||||
- [Feature labels](#feature-labels)
|
||||
- [Getting started](#getting-started)
|
||||
- [System requirements](#system-requirements)
|
||||
- [Usage](#usage)
|
||||
- [Building from source](#building-from-source)
|
||||
- [Targeting nodes with specific features](#targeting-nodes-with-specific-features)
|
||||
- [References](#references)
|
||||
- [License](#license)
|
||||
|
||||
## Overview
|
||||
|
@ -9,8 +19,29 @@ This software enables node feature discovery for Kubernetes. It detects
|
|||
hardware features available on each node in a Kubernetes cluster, and advertises
|
||||
those features using node labels.
|
||||
|
||||
## Command line interface
|
||||
|
||||
```
|
||||
node-feature-discovery.
|
||||
|
||||
Usage:
|
||||
node-feature-discovery [--no-publish --sources=<sources>]
|
||||
node-feature-discovery -h | --help
|
||||
node-feature-discovery --version
|
||||
|
||||
Options:
|
||||
-h --help Show this screen.
|
||||
--version Output version and exit.
|
||||
--sources=<sources> Comma separated list of feature sources. [Default: cpuid,rdt,pstate]
|
||||
--no-publish Do not publish discovered features to the cluster-local Kubernetes API server.
|
||||
```
|
||||
|
||||
## Feature discovery
|
||||
|
||||
### Feature sources
|
||||
|
||||
The current set of feature sources are the following:
|
||||
|
||||
- [CPUID][cpuid] for x86 CPU details
|
||||
- [Intel Resource Director Technology][intel-rdt]
|
||||
- [Intel P-State driver][intel-pstate]
|
||||
|
@ -31,14 +62,120 @@ the only label value published for features is the string `"true"`._
|
|||
|
||||
```json
|
||||
{
|
||||
"node.alpha.intel.com/dbi-iafeature-discovery.version": "v0.1.0",
|
||||
"node.alpha.intel.com/node-feature-discovery.version": "v0.1.0",
|
||||
"node.alpha.intel.com/v0.1.0-cpuid-<feature-name>": "true",
|
||||
"node.alpha.intel.com/v0.1.0-rdt-<feature-name>": "true",
|
||||
"node.alpha.intel.com/v0.1.0-pstate-<feature-name>": "true"
|
||||
}
|
||||
```
|
||||
|
||||
### References
|
||||
The `--sources` flag controls which sources to use for discovery.
|
||||
|
||||
### Intel Resource Director Technology (RDT) Features
|
||||
|
||||
| Feature name | Description |
|
||||
| :------------: | :---------------------------------------------------------------------------------: |
|
||||
| RDTMON | Intel Cache Monitoring Technology (CMT) and Intel Memory Bandwidth Monitoring (MBM)
|
||||
| RDTL3CA | Intel L3 Cache Allocation Technology
|
||||
| RDTL2CA | Intel L2 Cache Allocation Technology
|
||||
|
||||
### CPUID Features (Partial List)
|
||||
|
||||
| Feature name | Description |
|
||||
| :------------: | :----------------------------------------------------------: |
|
||||
| ADX | Multi-Precision Add-Carry Instruction Extensions (ADX)
|
||||
| AESNI | Advanced Encryption Standard (AES) New Instructions (AES-NI)
|
||||
| AVX | Advanced Vector Extensions (AVX)
|
||||
| AVX2 | Advanced Vector Extensions 2 (AVX2)
|
||||
| BMI1 | Bit Manipulation Instruction Set 1 (BMI)
|
||||
| BMI2 | Bit Manipulation Instruction Set 2 (BMI2)
|
||||
| SSE4.1 | Streaming SIMD Extensions 4.1 (SSE4.1)
|
||||
| SSE4.2 | Streaming SIMD Extensions 4.2 (SSE4.2)
|
||||
| SGX | Software Guard Extensions (SGX)
|
||||
|
||||
### System Requirements
|
||||
|
||||
1. Linux (x86_64)
|
||||
1. [kubectl] [kubectl-setup] (properly set up and configured to work with your
|
||||
Kubernetes cluster)
|
||||
1. [Docker] [docker-down] (only required to build and push docker images)
|
||||
|
||||
### Usage
|
||||
|
||||
Feature discovery is done as a one-shot job. There is an example script in this
|
||||
repo that demonstrates how to deploy the job to unlabeled nodes.
|
||||
|
||||
```
|
||||
./label-nodes.sh
|
||||
```
|
||||
|
||||
The discovery script will launch a job on each each unlabeled node in the
|
||||
cluster. When the job runs, it contacts the Kubernetes API server to add labels
|
||||
to the node to advertise hardware features (initially, from `cpuid` and RDT).
|
||||
|
||||
## Building from source
|
||||
|
||||
Download the source code.
|
||||
|
||||
```
|
||||
git clone https://github.com/kubernetes-incubator/node-feature-discovery
|
||||
```
|
||||
|
||||
**Build the Docker image:**
|
||||
|
||||
```
|
||||
cd <project-root>
|
||||
make
|
||||
```
|
||||
|
||||
**NOTE: To override the `DOCKER_REGISTRY_USER` use the `-e` option as follows:
|
||||
`DOCKER_REGISTRY_USER=<my-username> make docker -e`**
|
||||
|
||||
Push the Docker Image (optional)
|
||||
|
||||
```
|
||||
docker push <registry-user>/<image-name>:<version>
|
||||
```
|
||||
|
||||
**Change the job spec to use your custom image (optional):**
|
||||
|
||||
To use your published image from the step above instead of the
|
||||
`kubernetesincubator/node-feature-discovery` image, edit line 40 in the file
|
||||
[node-feature-discovery-job.json.template](node-feature-discovery-job.json.template)
|
||||
to the new location (`<registry-user>/<image-name>[:<version>]`).
|
||||
|
||||
## Targeting Nodes with Specific Features
|
||||
|
||||
Nodes with specific features can be targeted using the `nodeSelector` field. The
|
||||
following example shows how to target nodes with Intel TurboBoost enabled.
|
||||
|
||||
```json
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"env": "test"
|
||||
},
|
||||
"name": "golang-test"
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"image": "golang",
|
||||
"name": "go1",
|
||||
}
|
||||
],
|
||||
"nodeSelector": {
|
||||
"node.alpha.intel.com/v0.1.0-pstate-turbo": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For more details on targeting nodes, see [node selection][node-sel].
|
||||
|
||||
## References
|
||||
|
||||
Github issues
|
||||
|
||||
|
@ -48,6 +185,7 @@ Github issues
|
|||
|
||||
[Design proposal](https://docs.google.com/document/d/1uulT2AjqXjc_pLtDu0Kw9WyvvXm-WAZZaSiUziKsr68/edit)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
This is open source software released under the [Apache 2.0 License](LICENSE).
|
||||
|
@ -56,3 +194,8 @@ This is open source software released under the [Apache 2.0 License](LICENSE).
|
|||
[cpuid]: http://man7.org/linux/man-pages/man4/cpuid.4.html
|
||||
[intel-rdt]: http://www.intel.com/content/www/us/en/architecture-and-technology/resource-director-technology.html
|
||||
[intel-pstate]: https://www.kernel.org/doc/Documentation/cpu-freq/intel-pstate.txt
|
||||
[docker-down]: https://docs.docker.com/engine/installation
|
||||
[golang-down]: https://golang.org/dl
|
||||
[gcc-down]: https://gcc.gnu.org
|
||||
[kubectl-setup]: https://coreos.com/kubernetes/docs/latest/configure-kubectl.html
|
||||
[node-sel]: http://kubernetes.io/docs/user-guide/node-selection
|
||||
|
|
366
glide.lock
generated
Normal file
366
glide.lock
generated
Normal file
|
@ -0,0 +1,366 @@
|
|||
hash: 9943a35009296355c6a66485228855db99eefab65890c8fa89a4776cba9c9b71
|
||||
updated: 2016-07-28T17:22:20.295749043-07:00
|
||||
imports:
|
||||
- name: github.com/beorn7/perks
|
||||
version: 3ac7bf7a47d159a033b107610db8a1b6575507a4
|
||||
subpackages:
|
||||
- quantile
|
||||
- name: github.com/blang/semver
|
||||
version: 31b736133b98f26d5e078ec9eb591666edfd091f
|
||||
- name: github.com/coreos/go-oidc
|
||||
version: 5cf2aa52da8c574d3aa4458f471ad6ae2240fe6b
|
||||
subpackages:
|
||||
- http
|
||||
- jose
|
||||
- key
|
||||
- oauth2
|
||||
- oidc
|
||||
- name: github.com/coreos/go-systemd
|
||||
version: 4484981625c1a6a2ecb40a390fcb6a9bcfee76e3
|
||||
subpackages:
|
||||
- activation
|
||||
- daemon
|
||||
- dbus
|
||||
- journal
|
||||
- unit
|
||||
- util
|
||||
- name: github.com/coreos/pkg
|
||||
version: 7f080b6c11ac2d2347c3cd7521e810207ea1a041
|
||||
subpackages:
|
||||
- capnslog
|
||||
- dlopen
|
||||
- health
|
||||
- httputil
|
||||
- timeutil
|
||||
- name: github.com/davecgh/go-spew
|
||||
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
|
||||
subpackages:
|
||||
- spew
|
||||
- name: github.com/docker/distribution
|
||||
version: cd27f179f2c10c5d300e6d09025b538c475b0d51
|
||||
subpackages:
|
||||
- digest
|
||||
- reference
|
||||
- name: github.com/docker/docker
|
||||
version: 0f5c9d301b9b1cca66b3ea0f9dec3b5317d3686d
|
||||
subpackages:
|
||||
- pkg/jsonmessage
|
||||
- pkg/mount
|
||||
- pkg/stdcopy
|
||||
- pkg/symlink
|
||||
- pkg/term
|
||||
- pkg/term/winconsole
|
||||
- pkg/timeutils
|
||||
- pkg/units
|
||||
- name: github.com/docker/go-units
|
||||
version: 0bbddae09c5a5419a8c6dcdd7ff90da3d450393b
|
||||
- name: github.com/docopt/docopt-go
|
||||
version: 784ddc588536785e7299f7272f39101f7faccc3f
|
||||
- name: github.com/docopt/docopt.go
|
||||
version: 784ddc588536785e7299f7272f39101f7faccc3f
|
||||
- name: github.com/emicklei/go-restful
|
||||
version: 7c47e2558a0bbbaba9ecab06bc6681e73028a28a
|
||||
subpackages:
|
||||
- log
|
||||
- swagger
|
||||
- name: github.com/ghodss/yaml
|
||||
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
|
||||
- name: github.com/gogo/protobuf
|
||||
version: 82d16f734d6d871204a3feb1a73cb220cc92574c
|
||||
subpackages:
|
||||
- gogoproto
|
||||
- plugin/defaultcheck
|
||||
- plugin/description
|
||||
- plugin/embedcheck
|
||||
- plugin/enumstringer
|
||||
- plugin/equal
|
||||
- plugin/face
|
||||
- plugin/gostring
|
||||
- plugin/grpc
|
||||
- plugin/marshalto
|
||||
- plugin/oneofcheck
|
||||
- plugin/populate
|
||||
- plugin/size
|
||||
- plugin/stringer
|
||||
- plugin/testgen
|
||||
- plugin/union
|
||||
- plugin/unmarshal
|
||||
- proto
|
||||
- protoc-gen-gogo/descriptor
|
||||
- protoc-gen-gogo/generator
|
||||
- protoc-gen-gogo/plugin
|
||||
- sortkeys
|
||||
- vanity
|
||||
- vanity/command
|
||||
- name: github.com/golang/glog
|
||||
version: 44145f04b68cf362d9c4df2182967c2275eaefed
|
||||
- name: github.com/golang/protobuf
|
||||
version: b982704f8bb716bb608144408cff30e15fbde841
|
||||
subpackages:
|
||||
- proto
|
||||
- name: github.com/google/cadvisor
|
||||
version: 4dbefc9b671b81257973a33211fb12370c1a526e
|
||||
subpackages:
|
||||
- api
|
||||
- cache/memory
|
||||
- collector
|
||||
- container
|
||||
- container/common
|
||||
- container/docker
|
||||
- container/libcontainer
|
||||
- container/raw
|
||||
- container/rkt
|
||||
- container/systemd
|
||||
- devicemapper
|
||||
- events
|
||||
- fs
|
||||
- healthz
|
||||
- http
|
||||
- http/mux
|
||||
- info/v1
|
||||
- info/v1/test
|
||||
- info/v2
|
||||
- machine
|
||||
- manager
|
||||
- manager/watcher
|
||||
- manager/watcher/raw
|
||||
- manager/watcher/rkt
|
||||
- metrics
|
||||
- pages
|
||||
- pages/static
|
||||
- storage
|
||||
- summary
|
||||
- utils
|
||||
- utils/cloudinfo
|
||||
- utils/cpuload
|
||||
- utils/cpuload/netlink
|
||||
- utils/docker
|
||||
- utils/oomparser
|
||||
- utils/sysfs
|
||||
- utils/sysinfo
|
||||
- utils/tail
|
||||
- validate
|
||||
- version
|
||||
- name: github.com/google/gofuzz
|
||||
version: bbcb9da2d746f8bdbd6a936686a0a6067ada0ec5
|
||||
- name: github.com/jonboulle/clockwork
|
||||
version: 3f831b65b61282ba6bece21b91beea2edc4c887a
|
||||
- name: github.com/juju/ratelimit
|
||||
version: 77ed1c8a01217656d2080ad51981f6e99adaa177
|
||||
- name: github.com/klauspost/cpuid
|
||||
version: 09cded8978dc9e80714c4d85b0322337b0a1e5e0
|
||||
- name: github.com/matttproud/golang_protobuf_extensions
|
||||
version: fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a
|
||||
subpackages:
|
||||
- pbutil
|
||||
- name: github.com/opencontainers/runc
|
||||
version: 7ca2aa4873aea7cb4265b1726acb24b90d8726c6
|
||||
subpackages:
|
||||
- libcontainer
|
||||
- libcontainer/apparmor
|
||||
- libcontainer/cgroups
|
||||
- libcontainer/cgroups/fs
|
||||
- libcontainer/cgroups/systemd
|
||||
- libcontainer/configs
|
||||
- libcontainer/configs/validate
|
||||
- libcontainer/criurpc
|
||||
- libcontainer/label
|
||||
- libcontainer/seccomp
|
||||
- libcontainer/selinux
|
||||
- libcontainer/stacktrace
|
||||
- libcontainer/system
|
||||
- libcontainer/user
|
||||
- libcontainer/utils
|
||||
- name: github.com/pborman/uuid
|
||||
version: ca53cad383cad2479bbba7f7a1a05797ec1386e4
|
||||
- name: github.com/pmezard/go-difflib
|
||||
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
||||
subpackages:
|
||||
- difflib
|
||||
- name: github.com/prometheus/client_golang
|
||||
version: 3b78d7a77f51ccbc364d4bc170920153022cfd08
|
||||
subpackages:
|
||||
- prometheus
|
||||
- name: github.com/prometheus/client_model
|
||||
version: fa8ad6fec33561be4280a8f0514318c79d7f6cb6
|
||||
subpackages:
|
||||
- go
|
||||
- name: github.com/prometheus/common
|
||||
version: a6ab08426bb262e2d190097751f5cfd1cfdfd17d
|
||||
subpackages:
|
||||
- expfmt
|
||||
- internal/bitbucket.org/ww/goautoneg
|
||||
- model
|
||||
- name: github.com/prometheus/procfs
|
||||
version: 490cc6eb5fa45bf8a8b7b73c8bc82a8160e8531d
|
||||
- name: github.com/smartystreets/goconvey
|
||||
version: d4c757aa9afd1e2fc1832aaab209b5794eb336e1
|
||||
subpackages:
|
||||
- convey
|
||||
- convey/reporting
|
||||
- convey/gotest
|
||||
- name: github.com/spf13/pflag
|
||||
version: 08b1a584251b5b62f458943640fc8ebd4d50aaa5
|
||||
- name: github.com/stretchr/objx
|
||||
version: 1a9d0bb9f541897e62256577b352fdbc1fb4fd94
|
||||
- name: github.com/stretchr/testify
|
||||
version: f390dcf405f7b83c997eac1b06768bb9f44dec18
|
||||
subpackages:
|
||||
- mock
|
||||
- assert
|
||||
- name: github.com/ugorji/go
|
||||
version: f4485b318aadd133842532f841dc205a8e339d74
|
||||
subpackages:
|
||||
- codec
|
||||
- codec/codecgen
|
||||
- name: github.com/vektra/errors
|
||||
version: c64d83aba85aa4392895aadeefabbd24e89f3580
|
||||
- name: golang.org/x/net
|
||||
version: 62685c2d7ca23c807425dca88b11a3e2323dab41
|
||||
subpackages:
|
||||
- context
|
||||
- context/ctxhttp
|
||||
- html
|
||||
- html/atom
|
||||
- http2
|
||||
- http2/hpack
|
||||
- internal/timeseries
|
||||
- proxy
|
||||
- trace
|
||||
- websocket
|
||||
- name: golang.org/x/oauth2
|
||||
version: b5adcc2dcdf009d0391547edc6ecbaff889f5bb9
|
||||
subpackages:
|
||||
- google
|
||||
- internal
|
||||
- jws
|
||||
- jwt
|
||||
- name: google.golang.org/appengine
|
||||
version: 12d5545dc1cfa6047a286d5e853841b6471f4c19
|
||||
subpackages:
|
||||
- urlfetch
|
||||
- internal
|
||||
- internal/urlfetch
|
||||
- internal/app_identity
|
||||
- internal/modules
|
||||
- internal/base
|
||||
- internal/datastore
|
||||
- internal/log
|
||||
- internal/remote_api
|
||||
- name: google.golang.org/cloud
|
||||
version: eb47ba841d53d93506cfbfbc03927daf9cc48f88
|
||||
subpackages:
|
||||
- compute/metadata
|
||||
- internal
|
||||
- name: gopkg.in/inf.v0
|
||||
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
|
||||
- name: gopkg.in/yaml.v2
|
||||
version: a83829b6f1293c91addabc89d0571c246397bbf4
|
||||
- name: k8s.io/kubernetes
|
||||
version: 283137936a498aed572ee22af6774b6fb6e9fd94
|
||||
subpackages:
|
||||
- pkg/api
|
||||
- pkg/client/unversioned
|
||||
- pkg/api/meta
|
||||
- pkg/api/meta/metatypes
|
||||
- pkg/api/resource
|
||||
- pkg/api/unversioned
|
||||
- pkg/auth/user
|
||||
- pkg/conversion
|
||||
- pkg/fields
|
||||
- pkg/labels
|
||||
- pkg/runtime
|
||||
- pkg/runtime/serializer
|
||||
- pkg/types
|
||||
- pkg/util
|
||||
- pkg/util/intstr
|
||||
- pkg/util/rand
|
||||
- pkg/util/sets
|
||||
- pkg/api/errors
|
||||
- pkg/api/install
|
||||
- pkg/apimachinery/registered
|
||||
- pkg/apis/apps
|
||||
- pkg/apis/apps/install
|
||||
- pkg/apis/authentication.k8s.io/install
|
||||
- pkg/apis/authorization/install
|
||||
- pkg/apis/autoscaling
|
||||
- pkg/apis/autoscaling/install
|
||||
- pkg/apis/batch
|
||||
- pkg/apis/batch/install
|
||||
- pkg/apis/batch/v2alpha1
|
||||
- pkg/apis/componentconfig/install
|
||||
- pkg/apis/extensions
|
||||
- pkg/apis/extensions/install
|
||||
- pkg/apis/policy
|
||||
- pkg/apis/policy/install
|
||||
- pkg/apis/rbac
|
||||
- pkg/apis/rbac/install
|
||||
- pkg/client/restclient
|
||||
- pkg/client/typed/discovery
|
||||
- pkg/util/net
|
||||
- pkg/util/wait
|
||||
- pkg/version
|
||||
- pkg/watch
|
||||
- plugin/pkg/client/auth
|
||||
- pkg/util/errors
|
||||
- third_party/forked/reflect
|
||||
- pkg/util/validation
|
||||
- pkg/conversion/queryparams
|
||||
- pkg/util/json
|
||||
- pkg/runtime/serializer/json
|
||||
- pkg/runtime/serializer/protobuf
|
||||
- pkg/runtime/serializer/recognizer
|
||||
- pkg/runtime/serializer/versioning
|
||||
- pkg/util/validation/field
|
||||
- pkg/api/v1
|
||||
- pkg/apimachinery
|
||||
- pkg/watch/versioned
|
||||
- pkg/apis/apps/v1alpha1
|
||||
- pkg/apis/authentication.k8s.io
|
||||
- pkg/apis/authentication.k8s.io/v1beta1
|
||||
- pkg/apis/authorization
|
||||
- pkg/apis/authorization/v1beta1
|
||||
- pkg/apis/autoscaling/v1
|
||||
- pkg/apis/batch/v1
|
||||
- pkg/apis/componentconfig
|
||||
- pkg/apis/componentconfig/v1alpha1
|
||||
- pkg/apis/extensions/v1beta1
|
||||
- pkg/apis/policy/v1alpha1
|
||||
- pkg/apis/rbac/v1alpha1
|
||||
- pkg/api/validation
|
||||
- pkg/client/metrics
|
||||
- pkg/client/transport
|
||||
- pkg/client/unversioned/clientcmd/api
|
||||
- pkg/runtime/serializer/streaming
|
||||
- pkg/util/crypto
|
||||
- pkg/util/flowcontrol
|
||||
- pkg/util/runtime
|
||||
- plugin/pkg/client/auth/gcp
|
||||
- plugin/pkg/client/auth/oidc
|
||||
- pkg/util/framer
|
||||
- pkg/util/yaml
|
||||
- pkg/util/parsers
|
||||
- pkg/kubelet/qos
|
||||
- pkg/master/ports
|
||||
- pkg/api/endpoints
|
||||
- pkg/api/pod
|
||||
- pkg/api/service
|
||||
- pkg/api/unversioned/validation
|
||||
- pkg/api/util
|
||||
- pkg/capabilities
|
||||
- pkg/util/integer
|
||||
- pkg/kubelet/qos/util
|
||||
- pkg/util/hash
|
||||
- pkg/util/net/sets
|
||||
testImports:
|
||||
- name: github.com/gopherjs/gopherjs
|
||||
version: 72e303cb5f235b23471872477b57e573dc1c71d0
|
||||
subpackages:
|
||||
- js
|
||||
- name: github.com/jtolds/gls
|
||||
version: 8ddce2a84170772b95dd5d576c48d517b22cac63
|
||||
- name: github.com/smartystreets/assertions
|
||||
version: 2063fd1cc7c975db70502811a34b06ad034ccdf2
|
||||
subpackages:
|
||||
- internal/go-render/render
|
||||
- internal/oglematchers
|
20
glide.yaml
Normal file
20
glide.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
package: github.com/kubernetes-incubator/node-feature-discovery
|
||||
import:
|
||||
- package: github.com/klauspost/cpuid
|
||||
version: v1.0
|
||||
- package: github.com/docopt/docopt.go
|
||||
version: ^0.6.2
|
||||
- package: k8s.io/kubernetes
|
||||
version: v1.3.0
|
||||
subpackages:
|
||||
- pkg/api
|
||||
- pkg/client/unversioned
|
||||
- package: github.com/smartystreets/goconvey
|
||||
version: 1.6.2
|
||||
subpackages:
|
||||
- convey
|
||||
- package: github.com/stretchr/testify
|
||||
version: v1.1.3
|
||||
subpackages:
|
||||
- mock
|
||||
- package: github.com/vektra/errors
|
12
label-nodes.sh
Executable file
12
label-nodes.sh
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env bash
|
||||
# Get the node count in the Kubernetes cluster
|
||||
NumNodes=$(kubectl get nodes | grep -i ready | wc -l)
|
||||
|
||||
# We set the .spec.completions and .spec.parallelism to the node count
|
||||
# We request a specific hostPort in the job spec to limit the number of pods
|
||||
# that run on a node to one. As a result, one pod runs on each node in parallel
|
||||
# We set the POD_NAME and POD_NAMESPACE environemnt variables to the pod name
|
||||
# and pod namespace. These enivornment variables are used by the feature
|
||||
# discovery software to get the Kubernetes pod and node object.
|
||||
sed -e "s/COMPLETION_COUNT/$NumNodes/" -e "s/PARALLELISM_COUNT/$NumNodes/" node-feature-discovery-job.json.template > node-feature-discovery-job.json
|
||||
kubectl create -f node-feature-discovery-job.json
|
233
main.go
Normal file
233
main.go
Normal file
|
@ -0,0 +1,233 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docopt/docopt-go"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
)
|
||||
|
||||
const (
|
||||
// ProgramName is the canonical name of this discovery program.
|
||||
ProgramName = "node-feature-discovery"
|
||||
|
||||
// Namespace is the prefix for all published labels.
|
||||
Namespace = "node.alpha.intel.com"
|
||||
|
||||
// PodNameEnv is the environment variable that contains this pod's name.
|
||||
PodNameEnv = "POD_NAME"
|
||||
|
||||
// PodNamespaceEnv is the environment variable that contains this pod's
|
||||
// namespace.
|
||||
PodNamespaceEnv = "POD_NAMESPACE"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "" // Must not be const, set using ldflags at build time
|
||||
prefix = fmt.Sprintf("%s/%s", Namespace, version)
|
||||
)
|
||||
|
||||
// Labels are a Kubernetes representation of discovered features.
|
||||
type Labels map[string]string
|
||||
|
||||
// APIHelpers represents a set of API helpers for Kubernetes
|
||||
type APIHelpers interface {
|
||||
// GetClient returns a client
|
||||
GetClient() (*client.Client, error)
|
||||
|
||||
// GetNode returns the Kubernetes node on which this container is running.
|
||||
GetNode(*client.Client) (*api.Node, error)
|
||||
|
||||
// addLabels modifies the supplied node's labels collection.
|
||||
// In order to publish the labels, the node must be subsequently updated via the
|
||||
// API server using the client library.
|
||||
AddLabels(*api.Node, Labels)
|
||||
|
||||
// UpdateNode updates the node via the API server using a client.
|
||||
UpdateNode(*client.Client, *api.Node) error
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Assert that the version is known
|
||||
if version == "" {
|
||||
log.Fatalf("main.version not set! Set -ldflags \"-X main.version `git describe --tags --dirty --always`\" during build or run.")
|
||||
}
|
||||
|
||||
usage := fmt.Sprintf(`%s.
|
||||
|
||||
Usage:
|
||||
%s [--no-publish --sources=<sources>]
|
||||
%s -h | --help
|
||||
%s --version
|
||||
|
||||
Options:
|
||||
-h --help Show this screen.
|
||||
--version Output version and exit.
|
||||
--sources=<sources> Comma separated list of feature sources.
|
||||
[Default: cpuid,rdt,pstate]
|
||||
--no-publish Do not publish discovered features to the cluster-local
|
||||
Kubernetes API server.`,
|
||||
ProgramName,
|
||||
ProgramName,
|
||||
ProgramName,
|
||||
ProgramName,
|
||||
)
|
||||
|
||||
arguments, _ := docopt.Parse(usage, nil, true,
|
||||
fmt.Sprintf("%s %s", ProgramName, version), false)
|
||||
|
||||
// Parse argument values as usable types.
|
||||
noPublish := arguments["--no-publish"].(bool)
|
||||
sourcesArg := strings.Split(arguments["--sources"].(string), ",")
|
||||
|
||||
enabledSources := map[string]struct{}{}
|
||||
for _, s := range sourcesArg {
|
||||
enabledSources[strings.TrimSpace(s)] = struct{}{}
|
||||
}
|
||||
|
||||
// Configure feature sources.
|
||||
allSources := []FeatureSource{
|
||||
cpuidSource{},
|
||||
rdtSource{},
|
||||
pstateSource{},
|
||||
}
|
||||
|
||||
sources := []FeatureSource{}
|
||||
for _, s := range allSources {
|
||||
if _, enabled := enabledSources[s.Name()]; enabled {
|
||||
sources = append(sources, s)
|
||||
}
|
||||
}
|
||||
|
||||
labels := Labels{}
|
||||
|
||||
// Add the version of this discovery code as a node label
|
||||
versionLabel := fmt.Sprintf("%s/%s.version", Namespace, ProgramName)
|
||||
labels[versionLabel] = version
|
||||
// Log version label.
|
||||
log.Printf("%s = %s", versionLabel, version)
|
||||
|
||||
// Do feature discovery from all configured sources.
|
||||
for _, source := range sources {
|
||||
labelsFromSource, err := getFeatureLabels(source)
|
||||
if err != nil {
|
||||
log.Fatalf("discovery failed for source [%s]: %s", source.Name(), err.Error())
|
||||
}
|
||||
|
||||
for name, value := range labelsFromSource {
|
||||
labels[name] = value
|
||||
// Log discovered feature.
|
||||
log.Printf("%s = %s", name, value)
|
||||
}
|
||||
}
|
||||
|
||||
// Update the node with the node labels, unless disabled via flags.
|
||||
if !noPublish {
|
||||
helper := APIHelpers(k8sHelpers{})
|
||||
err := advertiseFeatureLabels(helper, labels)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to advertise labels: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// getFeatureLabels returns node labels for features discovered by the
|
||||
// supplied source.
|
||||
func getFeatureLabels(source FeatureSource) (Labels, error) {
|
||||
labels := Labels{}
|
||||
features, err := source.Discover()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, f := range features {
|
||||
labels[fmt.Sprintf("%s-%s-%s", prefix, source.Name(), f)] = "true"
|
||||
}
|
||||
return labels, nil
|
||||
}
|
||||
|
||||
// advertiseFeatureLabels advertises the feature labels to a Kubernetes node
|
||||
// via the API server.
|
||||
func advertiseFeatureLabels(helper APIHelpers, labels Labels) error {
|
||||
// Set up K8S client.
|
||||
cli, err := helper.GetClient()
|
||||
if err != nil {
|
||||
log.Printf("can't get kubernetes client: %s", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the current node.
|
||||
node, err := helper.GetNode(cli)
|
||||
if err != nil {
|
||||
log.Printf("failed to get node: %s", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// Add labels to the node object.
|
||||
helper.AddLabels(node, labels)
|
||||
|
||||
// Send the updated node to the apiserver.
|
||||
err = helper.UpdateNode(cli, node)
|
||||
if err != nil {
|
||||
log.Printf("can't update node: %s", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implements main.APIHelpers
|
||||
type k8sHelpers struct{}
|
||||
|
||||
func (h k8sHelpers) GetClient() (*client.Client, error) {
|
||||
// Set up K8S client.
|
||||
cli, err := client.NewInCluster()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func (h k8sHelpers) GetNode(cli *client.Client) (*api.Node, error) {
|
||||
// Get the pod name and pod namespace from the env variables
|
||||
podName := os.Getenv(PodNameEnv)
|
||||
podns := os.Getenv(PodNamespaceEnv)
|
||||
log.Printf("%s: %s", PodNameEnv, podName)
|
||||
log.Printf("%s: %s", PodNamespaceEnv, podns)
|
||||
|
||||
// Get the pod object using the pod name and pod namespace
|
||||
pod, err := cli.Pods(podns).Get(podName)
|
||||
if err != nil {
|
||||
log.Printf("can't get pods: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the node object using the pod name and pod namespace
|
||||
node, err := cli.Nodes().Get(pod.Spec.NodeName)
|
||||
if err != nil {
|
||||
log.Printf("can't get node: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (h k8sHelpers) AddLabels(n *api.Node, labels Labels) {
|
||||
for k, v := range labels {
|
||||
n.Labels[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
func (h k8sHelpers) UpdateNode(c *client.Client, n *api.Node) error {
|
||||
// Send the updated node to the apiserver.
|
||||
_, err := c.Nodes().Update(n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
102
main_test.go
Normal file
102
main_test.go
Normal file
|
@ -0,0 +1,102 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"github.com/vektra/errors"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
)
|
||||
|
||||
func TestDiscoveryWithMockSources(t *testing.T) {
|
||||
Convey("When I discover features from fake source and update the node using fake client", t, func() {
|
||||
mockFeatureSource := new(MockFeatureSource)
|
||||
fakeFeatureSourceName := string("testSource")
|
||||
fakeFeatures := []string{"testfeature1", "testfeature2", "testfeature3"}
|
||||
fakeFeatureLabels := Labels{}
|
||||
for _, f := range fakeFeatures {
|
||||
fakeFeatureLabels[fmt.Sprintf("%s-testSource-%s", prefix, f)] = "true"
|
||||
}
|
||||
fakeFeatureSource := FeatureSource(mockFeatureSource)
|
||||
|
||||
Convey("When I successfully get the labels from the mock source", func() {
|
||||
mockFeatureSource.On("Name").Return(fakeFeatureSourceName)
|
||||
mockFeatureSource.On("Discover").Return(fakeFeatures, nil)
|
||||
|
||||
returnedLabels, err := getFeatureLabels(fakeFeatureSource)
|
||||
Convey("Proper label is returned", func() {
|
||||
So(returnedLabels, ShouldResemble, fakeFeatureLabels)
|
||||
})
|
||||
Convey("Error is nil", func() {
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When I fail to get the labels from the mock source", func() {
|
||||
expectedError := errors.New("fake error")
|
||||
mockFeatureSource.On("Discover").Return(nil, expectedError)
|
||||
|
||||
returnedLabels, err := getFeatureLabels(fakeFeatureSource)
|
||||
Convey("No label is returned", func() {
|
||||
So(returnedLabels, ShouldBeNil)
|
||||
})
|
||||
Convey("Error is produced", func() {
|
||||
So(err, ShouldEqual, expectedError)
|
||||
})
|
||||
})
|
||||
|
||||
mockAPIHelper := new(MockAPIHelpers)
|
||||
testHelper := APIHelpers(mockAPIHelper)
|
||||
var mockClient *client.Client
|
||||
var mockNode *api.Node
|
||||
|
||||
Convey("When I successfully advertise feature labels to a node", func() {
|
||||
mockAPIHelper.On("GetClient").Return(mockClient, nil)
|
||||
mockAPIHelper.On("GetNode", mockClient).Return(mockNode, nil).Once()
|
||||
mockAPIHelper.On("AddLabels", mockNode, fakeFeatureLabels).Return().Once()
|
||||
mockAPIHelper.On("UpdateNode", mockClient, mockNode).Return(nil).Once()
|
||||
err := advertiseFeatureLabels(testHelper, fakeFeatureLabels)
|
||||
|
||||
Convey("Error is nil", func() {
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When I fail to get a mock client while advertising feature labels", func() {
|
||||
expectedError := errors.New("fake error")
|
||||
mockAPIHelper.On("GetClient").Return(nil, expectedError)
|
||||
err := advertiseFeatureLabels(testHelper, fakeFeatureLabels)
|
||||
|
||||
Convey("Error is produced", func() {
|
||||
So(err, ShouldEqual, expectedError)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When I fail to get a mock node while advertising feature labels", func() {
|
||||
expectedError := errors.New("fake error")
|
||||
mockAPIHelper.On("GetClient").Return(mockClient, nil)
|
||||
mockAPIHelper.On("GetNode", mockClient).Return(nil, expectedError).Once()
|
||||
err := advertiseFeatureLabels(testHelper, fakeFeatureLabels)
|
||||
|
||||
Convey("Error is produced", func() {
|
||||
So(err, ShouldEqual, expectedError)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When I fail to update a mock node while advertising feature labels", func() {
|
||||
expectedError := errors.New("fake error")
|
||||
mockAPIHelper.On("GetClient").Return(mockClient, nil)
|
||||
mockAPIHelper.On("GetNode", mockClient).Return(mockNode, nil).Once()
|
||||
mockAPIHelper.On("AddLabels", mockNode, fakeFeatureLabels).Return().Once()
|
||||
mockAPIHelper.On("UpdateNode", mockClient, mockNode).Return(expectedError).Once()
|
||||
err := advertiseFeatureLabels(testHelper, fakeFeatureLabels)
|
||||
|
||||
Convey("Error is produced", func() {
|
||||
So(err, ShouldEqual, expectedError)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
}
|
80
mockapihelpers.go
Normal file
80
mockapihelpers.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/mock"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
)
|
||||
|
||||
type MockAPIHelpers struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// GetClient provides a mock function with no input arguments and
|
||||
// *client.Client and error as return value
|
||||
func (_m *MockAPIHelpers) GetClient() (*client.Client, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 *client.Client
|
||||
if rf, ok := ret.Get(0).(func() *client.Client); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*client.Client)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetNode provides a mock function with *client.Client as input argument and
|
||||
// *api.Node and error as return values
|
||||
func (_m *MockAPIHelpers) GetNode(_a0 *client.Client) (*api.Node, error) {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
var r0 *api.Node
|
||||
if rf, ok := ret.Get(0).(func(*client.Client) *api.Node); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*api.Node)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*client.Client) error); ok {
|
||||
r1 = rf(_a0)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AddLabels provides a mock function with *api.Node and main.Labels as the input arguments and
|
||||
// no return value
|
||||
func (_m *MockAPIHelpers) AddLabels(_a0 *api.Node, _a1 Labels) {
|
||||
_m.Called(_a0, _a1)
|
||||
}
|
||||
|
||||
// UpdateNode provides a mock function with *client.Client and *api.Node as the input arguments and
|
||||
// error as the return value
|
||||
func (_m *MockAPIHelpers) UpdateNode(_a0 *client.Client, _a1 *api.Node) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*client.Client, *api.Node) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
46
mockfeaturesource.go
Normal file
46
mockfeaturesource.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
package main
|
||||
|
||||
import "github.com/stretchr/testify/mock"
|
||||
|
||||
type MockFeatureSource struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Name provides a mock function with no input arguments
|
||||
// and string as return value
|
||||
func (_m *MockFeatureSource) Name() string {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Discover provides a mock function with no input arguments
|
||||
// and []string and error as the return values
|
||||
func (_m *MockFeatureSource) Discover() ([]string, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []string
|
||||
if rf, ok := ret.Get(0).(func() []string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]string)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
54
node-feature-discovery-job.json.template
Normal file
54
node-feature-discovery-job.json.template
Normal file
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"apiVersion": "extensions/v1beta1",
|
||||
"kind": "Job",
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"app": "node-feature-discovery"
|
||||
},
|
||||
"name": "node-feature-discovery"
|
||||
},
|
||||
"spec": {
|
||||
"completions": COMPLETION_COUNT,
|
||||
"parallelism": PARALLELISM_COUNT,
|
||||
"template": {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"app": "node-feature-discovery"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"env": [
|
||||
{
|
||||
"name": "POD_NAME",
|
||||
"valueFrom": {
|
||||
"fieldRef": {
|
||||
"fieldPath": "metadata.name"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "POD_NAMESPACE",
|
||||
"valueFrom": {
|
||||
"fieldRef": {
|
||||
"fieldPath": "metadata.namespace"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"image": "kubernetesincubator/node-feature-discovery",
|
||||
"name": "node-feature-discovery",
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 2233,
|
||||
"hostPort": 7156
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Never"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
14
rdt-discovery/Makefile
Normal file
14
rdt-discovery/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
CC=gcc
|
||||
LIBDIR=/usr/local/lib
|
||||
INCDIR=/go/src/github.com/kubernetes-incubator/node-feature-discovery/intel-cmt-cat/lib/
|
||||
|
||||
LDFLAGS=-L$(LIBDIR)
|
||||
LDLIBS=-lpqos
|
||||
CFLAGS=-I$(INCDIR)
|
||||
|
||||
default:
|
||||
$(MAKE) all
|
||||
all:
|
||||
$(CC) $(CFLAGS) -o mon-discovery monitoring-discovery.c $(LDFLAGS) $(LDLIBS)
|
||||
$(CC) $(CFLAGS) -o l3-alloc-discovery l3-allocation-discovery.c $(LDFLAGS) $(LDLIBS)
|
||||
$(CC) $(CFLAGS) -o l2-alloc-discovery l2-allocation-discovery.c $(LDFLAGS) $(LDLIBS)
|
27
rdt-discovery/l2-allocation-discovery.c
Normal file
27
rdt-discovery/l2-allocation-discovery.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "machine.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int ret, det=1;
|
||||
struct cpuid_out res;
|
||||
|
||||
// Logic below from https://github.com/01org/intel-cmt-cat/blob/master/lib/host_cap.c
|
||||
lcpuid(0x7, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 15))) {
|
||||
det = 0;
|
||||
printf("NOT DETECTED");
|
||||
}
|
||||
else {
|
||||
lcpuid(0x10, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 2))) {
|
||||
det = 0;
|
||||
printf("NOT DETECTED");
|
||||
}
|
||||
}
|
||||
|
||||
if (det)
|
||||
printf("DETECTED");
|
||||
|
||||
return 0;
|
||||
}
|
30
rdt-discovery/l3-allocation-discovery.c
Normal file
30
rdt-discovery/l3-allocation-discovery.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "machine.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int ret, det=1;
|
||||
struct cpuid_out res;
|
||||
|
||||
// Logic below from https://github.com/01org/intel-cmt-cat/blob/master/lib/host_cap.c
|
||||
// TODO(balajismaniam): Implement L3 CAT detection using brand string and MSR probing if
|
||||
// not detected using cpuid
|
||||
|
||||
lcpuid(0x7, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 15))) {
|
||||
det = 0;
|
||||
printf("NOT DETECTED");
|
||||
}
|
||||
else {
|
||||
lcpuid(0x10, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 1))) {
|
||||
det = 0;
|
||||
printf("NOT DETECTED");
|
||||
}
|
||||
}
|
||||
|
||||
if (det)
|
||||
printf("DETECTED");
|
||||
|
||||
return 0;
|
||||
}
|
27
rdt-discovery/monitoring-discovery.c
Normal file
27
rdt-discovery/monitoring-discovery.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "machine.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int ret, det=1;
|
||||
struct cpuid_out res;
|
||||
|
||||
// Logic below from https://github.com/01org/intel-cmt-cat/blob/master/lib/host_cap.c
|
||||
lcpuid(0x7, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 12))) {
|
||||
det = 0;
|
||||
printf("NOT DETECTED");
|
||||
}
|
||||
else {
|
||||
lcpuid(0xf, 0x0, &res);
|
||||
if (!(res.edx & (1 << 1))) {
|
||||
det=0;
|
||||
printf("NOT DETECTED");
|
||||
}
|
||||
}
|
||||
|
||||
if (det)
|
||||
printf("DETECTED");
|
||||
|
||||
return 0;
|
||||
}
|
104
sources.go
Normal file
104
sources.go
Normal file
|
@ -0,0 +1,104 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"path"
|
||||
|
||||
"github.com/klauspost/cpuid"
|
||||
)
|
||||
|
||||
// FeatureSource represents a source of discovered node features.
|
||||
type FeatureSource interface {
|
||||
// Returns a friendly name for this source of node features.
|
||||
Name() string
|
||||
|
||||
// Returns discovered features for this node.
|
||||
Discover() ([]string, error)
|
||||
}
|
||||
|
||||
const (
|
||||
// DETECTED is compared with stdout for RDT detection helper programs.
|
||||
DETECTED = "DETECTED"
|
||||
|
||||
// RDTBin is the path to RDT detection helpers.
|
||||
RDTBin = "/go/src/github.com/kubernetes-incubator/node-feature-discovery/rdt-discovery"
|
||||
)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// CPUID Source
|
||||
|
||||
// Implements main.FeatureSource.
|
||||
type cpuidSource struct{}
|
||||
|
||||
func (s cpuidSource) Name() string { return "cpuid" }
|
||||
func (s cpuidSource) Discover() ([]string, error) {
|
||||
// Get the cpu features as strings
|
||||
return cpuid.CPU.Features.Strings(), nil
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// RDT (Intel Resource Director Technology) Source
|
||||
|
||||
// Implements main.FeatureSource.
|
||||
type rdtSource struct{}
|
||||
|
||||
func (s rdtSource) Name() string { return "rdt" }
|
||||
|
||||
// Returns feature names for CMT, MBM and CAT if suppported.
|
||||
func (s rdtSource) Discover() ([]string, error) {
|
||||
features := []string{}
|
||||
|
||||
out, err := exec.Command("bash", "-c", path.Join(RDTBin, "mon-discovery")).Output()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't detect support for RDT monitoring: %s", err.Error())
|
||||
}
|
||||
if string(out[:]) == DETECTED {
|
||||
// RDT monitoring detected.
|
||||
features = append(features, "RDTMON")
|
||||
}
|
||||
|
||||
out, err = exec.Command("bash", "-c", path.Join(RDTBin, "l3-alloc-discovery")).Output()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't detect support for RDT L3 allocation: %s", err.Error())
|
||||
}
|
||||
if string(out[:]) == DETECTED {
|
||||
// RDT L3 cache allocation detected.
|
||||
features = append(features, "RDTL3CA")
|
||||
}
|
||||
|
||||
out, err = exec.Command("bash", "-c", path.Join(RDTBin, "l2-alloc-discovery")).Output()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't detect support for RDT L2 allocation: %s", err.Error())
|
||||
}
|
||||
if string(out[:]) == DETECTED {
|
||||
// RDT L2 cache allocation detected.
|
||||
features = append(features, "RDTL2CA")
|
||||
}
|
||||
|
||||
return features, nil
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PState Source
|
||||
|
||||
// Implements main.FeatureSource.
|
||||
type pstateSource struct{}
|
||||
|
||||
func (s pstateSource) Name() string { return "pstate" }
|
||||
func (s pstateSource) Discover() ([]string, error) {
|
||||
features := []string{}
|
||||
|
||||
// Only looking for turbo boost for now...
|
||||
bytes, err := ioutil.ReadFile("/sys/devices/system/cpu/intel_pstate/no_turbo")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't detect whether turbo boost is enabled: %s", err.Error())
|
||||
}
|
||||
if bytes[0] == byte('0') {
|
||||
// Turbo boost is enabled.
|
||||
features = append(features, "turbo")
|
||||
}
|
||||
|
||||
return features, nil
|
||||
}
|
Loading…
Reference in a new issue