mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-28 18:57:10 +00:00
Refactored feature sources.
- Added interface FeatureSource, moved cpuid, rdt and pstate discovery logic into implementations. - Updated logging output to make it more machine-readable (one feature, in label-format, per line). - Normalized label names (derived from the underlying feature source). - Added makefile. - Added command-line argument parsing and proper CLI documentation. - Added ability to filter the enabled feature sources: cpuid,rdt,pstate. - Added ability to print the software version and exit. - Added ability to print the CLI help. - Updated README. - Updated dep versions. - Added -s -w to ldflags. - Output version label along with discovered feature labels. - Added sources section to README. - Normalized README link for pstate
This commit is contained in:
parent
7788f2ebea
commit
e79ffd2c2a
8 changed files with 664 additions and 117 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,2 +1,7 @@
|
|||
dbi-iafeature-discovery
|
||||
dbi-iafeature-discovery-job.json
|
||||
vendor/
|
||||
intel-cmt-cat/
|
||||
rdt-discovery/l2-alloc-discovery
|
||||
rdt-discovery/l3-alloc-discovery
|
||||
rdt-discovery/mon-discovery
|
||||
|
|
|
@ -22,7 +22,7 @@ RUN cd rdt-discovery; make
|
|||
RUN go get github.com/Masterminds/glide
|
||||
RUN glide install
|
||||
RUN go install \
|
||||
-ldflags "-X main.version=`git describe --tags --dirty --always`" \
|
||||
-ldflags "-s -w -X main.version=`git describe --tags --dirty --always`" \
|
||||
github.com/intelsdi-x/dbi-iafeature-discovery
|
||||
|
||||
ENTRYPOINT /go/bin/dbi-iafeature-discovery
|
||||
ENTRYPOINT ["/go/bin/dbi-iafeature-discovery"]
|
||||
|
|
13
Makefile
Normal file
13
Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
.PHONY: all
|
||||
|
||||
DOCKER_REGISTRY_USER := intelsdi
|
||||
DOCKER_IMAGE_NAME := nodelabels
|
||||
|
||||
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) ./
|
88
README.md
88
README.md
|
@ -12,10 +12,36 @@
|
|||
|
||||
## Overview
|
||||
|
||||
This software enables Intel Architecture (IA) feature discovery for Kubernetes.
|
||||
It detects CPU features available on each node in a Kubernetes cluster, such as
|
||||
Intel [Resource Director Technology][intel-rdt] and advertises those
|
||||
features using node labels.
|
||||
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.
|
||||
|
||||
### Feature sources
|
||||
|
||||
The current set of feature sources are the following:
|
||||
|
||||
- [CPUID](http://man7.org/linux/man-pages/man4/cpuid.4.html) for x86 CPU details
|
||||
- [Intel Resource Director Technology][intel-rdt]
|
||||
- [Intel P-State driver][intel-pstate]
|
||||
|
||||
The `--sources` flag controls which sources to use for discovery.
|
||||
|
||||
### Command line interface
|
||||
|
||||
```
|
||||
dbi-iafeature-discovery.
|
||||
|
||||
Usage:
|
||||
dbi-iafeature-discovery [--no-publish --sources=<sources>]
|
||||
dbi-iafeature-discovery -h | --help
|
||||
dbi-iafeature-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.
|
||||
```
|
||||
|
||||
### Intel Resource Director Technology (RDT) Features
|
||||
|
||||
|
@ -41,23 +67,26 @@ features using node labels.
|
|||
|
||||
The published node labels encode a few pieces of information:
|
||||
|
||||
- A "namespace" to denote vendor-specific information
|
||||
(`node.alpha.intel.com`).
|
||||
- A "namespace" to denote vendor-specific information (`node.alpha.intel.com`).
|
||||
- The version of this discovery code that wrote the label, for example
|
||||
`"node.alpha.intel.com/dbi-iafeature-discovery.version": "v0.1.0"`.
|
||||
The value of this label corresponds to the output from
|
||||
`git describe --tags --dirty --always`.
|
||||
- The relevant hardware component each label describes (e.g. `cpu`).
|
||||
- The relevant information source for each label (e.g. `cpuid`).
|
||||
- The name of the discovered feature as it appears in the underlying
|
||||
source, mostly `cpuid` (e.g. `AESNI`).
|
||||
|
||||
_Note: only features that are available on a given node are labeled, so the
|
||||
only label value published is the string `"true"`. This feature discovery code
|
||||
will not add a label with the value `"false"` for features that are not
|
||||
present._
|
||||
_Note: only features that are available on a given node are labeled, so
|
||||
the only label value published for features is the string `"true"`. This
|
||||
feature discovery code will not add a label with the value `"false"` for
|
||||
features that are not present._
|
||||
|
||||
```
|
||||
"node.alpha.intel.com/v0.1.0-cpu-<feature-name>": "true"
|
||||
```json
|
||||
{
|
||||
"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"
|
||||
}
|
||||
```
|
||||
|
||||
### System Requirements
|
||||
|
@ -65,7 +94,8 @@ present._
|
|||
At a minimum, you will need:
|
||||
|
||||
1. Linux (x86_64)
|
||||
1. [kubectl] [kubectl-setup] (properly set up and configured to work with your Kubernetes cluster)
|
||||
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
|
||||
|
@ -78,9 +108,8 @@ repo that demonstrates how to deploy the job to unlabeled nodes.
|
|||
```
|
||||
|
||||
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).
|
||||
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
|
||||
|
||||
|
@ -94,13 +123,16 @@ git clone https://github.com/intelsdi-x/dbi-iafeature-discovery
|
|||
|
||||
```
|
||||
cd <project-root>
|
||||
docker build -t <user-name>/<image-name> .
|
||||
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
|
||||
docker push <registry-user>/<image-name>:<version>
|
||||
```
|
||||
|
||||
**Change the job spec to use your custom image (optional):**
|
||||
|
@ -108,13 +140,12 @@ docker push
|
|||
To use your published image from the step above instead of the
|
||||
`intelsdi/nodelabels` image, edit line 40 in the file
|
||||
[dbi-iafeature-discovery-job.json.template](dbi-iafeature-discovery-job.json.template)
|
||||
to the new location (`<user>/<image-name>`).
|
||||
to the new location (`<registry-user>/<image-name>`).
|
||||
|
||||
## Targeting Nodes with Specific Features
|
||||
|
||||
Nodes with specific features can be targeted using the `nodeSelector` field.
|
||||
The following example shows how to target the Intel RDT L3 cache allocation
|
||||
(RDTL3CA) feature.
|
||||
Nodes with specific features can be targeted using the `nodeSelector` field. The
|
||||
following example shows how to target nodes with Intel TurboBoost enabled.
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -134,7 +165,7 @@ The following example shows how to target the Intel RDT L3 cache allocation
|
|||
}
|
||||
],
|
||||
"nodeSelector": {
|
||||
"node.alpha.intel.com/v0.1.0-cpu-RDTL3CA": "true"
|
||||
"node.alpha.intel.com/v0.1.0-pstate-turbo": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -149,9 +180,10 @@ This is open source software released under the [Apache 2.0 License](LICENSE).
|
|||
|
||||
<!-- Links -->
|
||||
[intel-rdt]: http://www.intel.com/content/www/us/en/architecture-and-technology/resource-director-technology.html
|
||||
[docker-down]: https://docs.docker.com/engine/installation/
|
||||
[golang-down]: https://golang.org/dl/
|
||||
[gcc-down]: https://gcc.gnu.org/
|
||||
[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
|
||||
[balaji-github]: https://github.com/balajismaniam
|
||||
[node-sel]: http://kubernetes.io/docs/user-guide/node-selection/
|
||||
[node-sel]: http://kubernetes.io/docs/user-guide/node-selection
|
||||
|
|
336
glide.lock
generated
Normal file
336
glide.lock
generated
Normal file
|
@ -0,0 +1,336 @@
|
|||
hash: b3a6656f552e85def420fa859d14f27dc2897209ce315ed25ce9cadeff6fae21
|
||||
updated: 2016-07-20T00:33:41.257155246-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/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/spf13/pflag
|
||||
version: 08b1a584251b5b62f458943640fc8ebd4d50aaa5
|
||||
- name: github.com/ugorji/go
|
||||
version: f4485b318aadd133842532f841dc205a8e339d74
|
||||
subpackages:
|
||||
- codec
|
||||
- codec/codecgen
|
||||
- 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: []
|
|
@ -2,7 +2,10 @@ package: github.com/intelsdi-x/dbi-iafeature-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
|
||||
|
|
229
main.go
229
main.go
|
@ -17,113 +17,168 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/klauspost/cpuid"
|
||||
"github.com/docopt/docopt-go"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
)
|
||||
|
||||
const namespace = "node.alpha.intel.com"
|
||||
const (
|
||||
// ProgramName is the canonical name of this discovery program.
|
||||
ProgramName = "dbi-ia-feature-discovery"
|
||||
|
||||
var version = "" // Must not be const, set using ldflags at build time
|
||||
var prefix = fmt.Sprintf("%s/%s", namespace, version)
|
||||
// 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
|
||||
|
||||
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.")
|
||||
}
|
||||
log.Printf("Version: [%s]", version)
|
||||
log.Printf("Label prefix: [%s]", prefix)
|
||||
|
||||
// Setting-up K8S client
|
||||
cli, err := client.NewInCluster()
|
||||
if err != nil {
|
||||
log.Fatalf("Can't Get K8s Client: %v", err)
|
||||
log.Fatalf("main.version not set! Set -ldflags \"-X main.version `git describe --tags --dirty --always`\" during build or run.")
|
||||
}
|
||||
|
||||
// Get the pod name and namespace from the env variables
|
||||
podName := os.Getenv("POD_NAME")
|
||||
podns := os.Getenv("POD_NAMESPACE")
|
||||
log.Printf("Pod Name ENV Variable: %s\n", podName)
|
||||
log.Printf("Pod Namespace ENV Variable: %s\n", podns)
|
||||
usage := fmt.Sprintf(`%s.
|
||||
|
||||
// Get the pod object using the pod name and namespace
|
||||
pod, err := cli.Pods(podns).Get(podName)
|
||||
if err != nil {
|
||||
log.Fatalf("Can't Get Pod: %v", err)
|
||||
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{}{}
|
||||
}
|
||||
|
||||
// Get the node object using the pod name and namespace
|
||||
node, err := cli.Nodes().Get(pod.Spec.NodeName)
|
||||
if err != nil {
|
||||
log.Fatalf("Can't Get Node: %v", err)
|
||||
// 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
|
||||
node.Labels[fmt.Sprintf("%s/dbi-ia-feature-discovery.version", prefix)] = version
|
||||
versionLabel := fmt.Sprintf("%s/%s.version", Namespace, ProgramName)
|
||||
labels[versionLabel] = version
|
||||
// Log version label.
|
||||
log.Printf("%s = %s", versionLabel, version)
|
||||
|
||||
// Get the cpu features as strings
|
||||
features := cpuid.CPU.Features.Strings()
|
||||
log.Printf("CPU Features Detected from cpuid: %s\n", features)
|
||||
// Add each of the cpu feature as the node label
|
||||
for _, feature := range features {
|
||||
node.Labels[fmt.Sprintf("%s-cpu-%s", prefix, feature)] = "true"
|
||||
// Do feature discovery from all configured sources.
|
||||
for _, source := range sources {
|
||||
for name, value := range featureLabels(source) {
|
||||
labels[name] = value
|
||||
// Log discovered feature.
|
||||
log.Printf("%s = %s", name, value)
|
||||
}
|
||||
}
|
||||
|
||||
// If supported, add CMT, MBM and CAT features as a node label
|
||||
cmd := "/go/src/github.com/intelsdi-x/dbi-iafeature-discovery/rdt-discovery/mon-discovery"
|
||||
out, err := exec.Command("bash", "-c", cmd).Output()
|
||||
if err != nil {
|
||||
log.Fatalf("Can't Dectect Support for RDT Monitoring: %v", err)
|
||||
}
|
||||
// Update the node with the node labels, unless disabled via flags.
|
||||
if !noPublish {
|
||||
// Set up K8S client.
|
||||
cli, err := client.NewInCluster()
|
||||
if err != nil {
|
||||
log.Fatalf("can't get kubernetes client: %s", err.Error())
|
||||
}
|
||||
|
||||
outString := string(out[:])
|
||||
if outString == "DETECTED" {
|
||||
node.Labels[fmt.Sprintf("%s-cpu-RDTMON", prefix)] = "true"
|
||||
log.Printf("RDT Monitoring Detected\n")
|
||||
}
|
||||
|
||||
cmd = "/go/src/github.com/intelsdi-x/dbi-iafeature-discovery/rdt-discovery/l3-alloc-discovery"
|
||||
out, err = exec.Command("bash", "-c", cmd).Output()
|
||||
if err != nil {
|
||||
log.Fatalf("Can't Dectect Support for RDT L3 Allocation: %v", err)
|
||||
}
|
||||
|
||||
outString = string(out[:])
|
||||
if outString == "DETECTED" {
|
||||
node.Labels[fmt.Sprintf("%s-cpu-RDTL3CA", prefix)] = "true"
|
||||
log.Printf("RDT L3 Cache Allocation Detected\n")
|
||||
}
|
||||
|
||||
cmd = "/go/src/github.com/intelsdi-x/dbi-iafeature-discovery/rdt-discovery/l2-alloc-discovery"
|
||||
out, err = exec.Command("bash", "-c", cmd).Output()
|
||||
if err != nil {
|
||||
log.Fatalf("Can't Dectect Support for RDT L2 Allocation: %v", err)
|
||||
}
|
||||
|
||||
outString = string(out[:])
|
||||
if outString == "DETECTED" {
|
||||
node.Labels[fmt.Sprintf("%s-cpu-RDTL2CA", prefix)] = "true"
|
||||
log.Printf("RDT L2 Cache Allocation Detected\n")
|
||||
}
|
||||
|
||||
// If turbo boost is enabled, add it as a node label
|
||||
cmd = "cat /sys/devices/system/cpu/intel_pstate/no_turbo"
|
||||
out, err = exec.Command("bash", "-c", cmd).Output()
|
||||
if err != nil {
|
||||
log.Fatalf("Can't Dectect if Turbo Boost is Enabled: %v", err)
|
||||
}
|
||||
|
||||
outString = string(out[:])
|
||||
if outString == "0\n" {
|
||||
node.Labels[fmt.Sprintf("%s-cpu-turbo", prefix)] = "true"
|
||||
log.Printf("Turbo Boost is Enabled\n")
|
||||
}
|
||||
|
||||
// Update the node with the node labels
|
||||
_, err = cli.Nodes().Update(node)
|
||||
if err != nil {
|
||||
log.Fatalf("Can't Update Node: %v", err)
|
||||
// Get the current node.
|
||||
node := getNode(cli)
|
||||
// Add labels to the node object.
|
||||
addLabels(node, labels)
|
||||
// Send the updated node to the apiserver.
|
||||
_, err = cli.Nodes().Update(node)
|
||||
if err != nil {
|
||||
log.Fatalf("can't update node: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// featureLabels returns node labels for features discovered by the
|
||||
// supplied source.
|
||||
func featureLabels(source FeatureSource) Labels {
|
||||
labels := Labels{}
|
||||
features, err := source.Discover()
|
||||
if err != nil {
|
||||
log.Fatalf("discovery failed for source [%s]: %s", source.Name(), err.Error())
|
||||
}
|
||||
for _, f := range features {
|
||||
labels[fmt.Sprintf("%s-%s-%s", prefix, source.Name(), f)] = "true"
|
||||
}
|
||||
return labels
|
||||
}
|
||||
|
||||
// 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.
|
||||
func addLabels(n *api.Node, labels Labels) {
|
||||
for k, v := range labels {
|
||||
n.Labels[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// getNode returns the Kubernetes node on which this container is running.
|
||||
func getNode(cli *client.Client) *api.Node {
|
||||
// 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.Fatalf("can't get pod: %s", err.Error())
|
||||
}
|
||||
|
||||
// Get the node object using the pod name and pod namespace
|
||||
node, err := cli.Nodes().Get(pod.Spec.NodeName)
|
||||
if err != nil {
|
||||
log.Fatalf("can't get node: %s", err.Error())
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
|
103
sources.go
Normal file
103
sources.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
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/intelsdi-x/dbi-iafeature-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
|
||||
|
||||
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: %v", err)
|
||||
}
|
||||
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: %v", err)
|
||||
}
|
||||
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: %v", err)
|
||||
}
|
||||
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…
Add table
Reference in a new issue