<!DOCTYPE html><htmllang="en"dir="auto"><head><metacharset="utf-8"><metaname="viewport"content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=no"><metaname="description"content="Developer guide Table of contents Building from source Download the source code Docker build Deployment Building locally Customizing the build Test..."><metaname="revised"content=""><metaname="author"content="Kubernetes SIGs"><metaname="generator"content="rundocs/jekyll-rtd-theme v2.0.10"><metaname="theme-color"content="#2980b9"><title>Developer guide · Node Feature Discovery</title><metaname="twitter:title"content="Developer guide · Node Feature Discovery"><metaname="twitter:description"content="Developer guide Table of contents Building from source Download the source code Docker build Deployment Building locally Customizing the build Test..."><metaname="twitter:card"content="summary"><metaname="twitter:site"content="@Kubernetes SIGs"><metaname="twitter:url"content="https://kubernetes-sigs.github.com/node-feature-discovery/v0.10/advanced/developer-guide.html"><metaname="twitter:creator"content="@rundocs/jekyll-rtd-theme v2.0.10"><metaproperty="og:title"content="Developer guide · Node Feature Discovery"><metaproperty="og:description"content="Developer guide Table of contents Building from source Download the source code Docker build Deployment Building locally Customizing the build Test..."><metaproperty="og:locale"content="en"><metaproperty="og:url"content="https://kubernetes-sigs.github.com/node-feature-discovery/v0.10/advanced/developer-guide.html"><metaproperty="og:type"content="article"><metaproperty="article:author"content="Kubernetes SIGs"><metaproperty="article:published_time"content="2016-07-23T00:07:52-05:00"><metaproperty="article:modified_time"content="2022-01-11T13:08:54-06:00"><scripttype="application/ld+json">{"@context":"https://schema.org","@type":"Article","mainEntityOfPage":{"@type":"WebPage","@id":"https://kubernetes-sigs.github.com/node-feature-discovery/v0.10/advanced/developer-guide.html"},"headline":"Developer guide · Node Feature Discovery","image":[],"author":{"@type":"Person","name":"Kubernetes SIGs"},"datePublished":"2016-07-23T00:07:52-05:00","dateModified":"2022-01-11T13:08:54-06:00","publisher":{"@type":"Organization","name":"Kubernetes SIGs","logo":{"@type":"ImageObject","url":"https://avatars.githubusercontent.com/u/36015203?v=4"}},"description":"Developer guide Table of contents Building from source Download the source code Docker build Deployment Building locally Customizing the build Test..."}</script><linkrel="dns-prefetch"href="https://cdn.jsdelivr.net"><linkrel="next"href="https://kubernetes-sigs.github.com/node-feature-discovery/v0.10/advanced/master-commandline-reference.html"><linkrel="canonical"href="https://kubernetes-sigs.github.com/node-feature-discovery/v0.10/advanced/developer-guide.html"><linkrel="icon"type="image/svg+xml"href="/node-feature-discovery/v0.10/assets/images/favicon.svg"><linkrel="icon"type="image/png"href="/node-feature-discovery/v0.10/assets/images/favicon-16x16.png"sizes="16x16"><linkrel="icon"type="image/png"href="/node-feature-discovery/v0.10/assets/images/favicon-32x32.png"sizes="32x32"><linkrel="icon"type="image/png"href="/node-feature-discovery/v0.10/assets/images/favicon-96x96.png"sizes="96x96"><linkrel="mask-icon"href="/node-feature-discovery/v0.10/assets/images/favicon.svg"color="#2980b9"><linkrel="apple-touch-icon"href="/node-feature-discovery/v0.10/assets/images/apple-touch-icon-300x300.jpg"><linkrel="stylesheet"href="https://cdn.jsdelivr.net/gh/rundocs/jekyll-rtd-theme@2.0.10/assets/css/theme.min.css"><style>@media(min-width:1280px){.content-wrap{max-width:1200px}}</style><script>window.ui={title:"NodeFeatureDiscovery",baseurl:"/node-feature-discovery/v0.10",i18n:{search_results:"SearchResults",search_results_found:"Searchfinished,found#page(s)matchingthesearchquery.",search_r
</code></pre></div></div><h3id="docker-build">Docker build</h3><h4id="build-the-container-image">Build the container image</h4><p>See <ahref="#customizing-the-build">customizing the build</a> below for altering the container image registry, for example.</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code>make
</code></pre></div></div><h4id="push-the-container-image">Push the container image</h4><p>Optional, this example with Docker.</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code>docker push <IMAGE_TAG>
</code></pre></div></div><h4id="change-the-job-spec-to-use-your-custom-image-optional">Change the job spec to use your custom image (optional)</h4><p>To use your published image from the step above instead of the <codeclass="language-plaintext highlighter-rouge notranslate">k8s.gcr.io/nfd/node-feature-discovery</code> image, edit <codeclass="language-plaintext highlighter-rouge notranslate">image</code> attribute in the spec template(s) to the new location (<codeclass="language-plaintext highlighter-rouge notranslate"><registry-name>/<image-name>[:<version>]</code>).</p><h3id="deployment">Deployment</h3><p>The <codeclass="language-plaintext highlighter-rouge notranslate">yamls</code> makefile generates a <codeclass="language-plaintext highlighter-rouge notranslate">kustomization.yaml</code> matching your locally built image and using the <codeclass="language-plaintext highlighter-rouge notranslate">deploy/overlays/default</code> deployment. See <ahref="#customizing-the-build">build customization</a> below for configurability, e.g. changing the deployment namespace.</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code><spanclass="nv">K8S_NAMESPACE</span><spanclass="o">=</span>my-ns make yamls
</code></pre></div></div><p>You can use alternative deployment methods by modifying the auto-generated kustomization file. For example, deploying worker and master in the same pod by pointing to <codeclass="language-plaintext highlighter-rouge notranslate">deployment/overlays/default-combined</code>.</p><h3id="building-locally">Building locally</h3><p>You can also build the binaries locally</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code>make build
</code></pre></div></div><p>This will compile binaries under <codeclass="language-plaintext highlighter-rouge notranslate">bin/</code></p><h3id="customizing-the-build">Customizing the build</h3><p>There are several Makefile variables that control the build process and the name of the resulting container image. The following are targeted targeted for build customization and they can be specified via environment variables or makefile overrides.</p><table><thead><tr><th>Variable</th><th>Description</th><th>Default value</th></tr></thead><tbody><tr><td>HOSTMOUNT_PREFIX</td><td>Prefix of system directories for feature discovery (local builds)</td><td>/ (<em>local builds</em>) /host- (<em>container builds</em>)</td></tr><tr><td>IMAGE_BUILD_CMD</td><td>Command to build the image</td><td>docker build</td></tr><tr><td>IMAGE_BUILD_EXTRA_OPTS</td><td>Extra options to pass to build command</td><td><em>empty</em></td></tr><tr><td>IMAGE_PUSH_CMD</td><td>Command to push the image to remote registry</td><td>docker push</td></tr><tr><td>IMAGE_REGISTRY</td><td>Container image registry to use</td><td>k8s.gcr.io/nfd</td></tr><tr><td>IMAGE_TAG_NAME</td><td>Container image tag name</td><td><nfd version></td></tr><tr><td>IMAGE_EXTRA_TAG_NAMES</td><td>Additional container image tag(s) to create when building image</td><td><em>empty</em></td></tr><tr><td>K8S_NAMESPACE</td><td>nfd-master and nfd-worker namespace</td><td>kube-system</td></tr><tr><td>KUBECONFIG</td><td>Kubeconfig for running e2e-tests</td><td><em>empty</em></td></tr><tr><td>E2E_TEST_CONFIG</td><td>Parameterization file of e2e-tests (see <ahref="https://github.com/kubernetes-sigs/node-feature-discovery/blob/v0.10.0/test/e2e/e2e-test-config.exapmle.yaml">example</a>)</td><td><em>empty</em></td></tr><tr><td>OPENSHIFT</td><td>Non-empty value enables OpenShift specific support (currently only effective in e2e tests)</td><td><em>empty</em></td></tr><tr><td>BASE_IMAGE_FULL</td><td>Container base image for target image full (–target full)</td><td>debian:buster-slim</td></tr><tr><td>BASE_IMAGE_MINIMAL</td><td>Container base image for target image minimal (–target minimal)</td><td>gcr.io/distroless/base</td></tr></tbody></table><p>For example, to use a custom registry:</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code>make <spanclass="nv">IMAGE_REGISTRY</span><spanclass="o">=</span><my custom registry uri>
</code></pre></div></div><p>Or to specify a build tool different from Docker, It can be done in 2 ways:</p><ol><li><p>via environment</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code><spanclass="nv">IMAGE_BUILD_CMD</span><spanclass="o">=</span><spanclass="s2">"buildah bud"</span> make
</code></pre></div></div></li><li><p>by overriding the variable value</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code> make <spanclass="nv">IMAGE_BUILD_CMD</span><spanclass="o">=</span><spanclass="s2">"buildah bud"</span>
</code></pre></div></div></li></ol><h3id="testing">Testing</h3><p>Unit tests are automatically run as part of the container image build. You can also run them manually in the source code tree by simply running:</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code>make <spanclass="nb">test</span>
</code></pre></div></div><p>End-to-end tests are built on top of the e2e test framework of Kubernetes, and, they required a cluster to run them on. For running the tests on your test cluster you need to specify the kubeconfig to be used:</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code>make e2e-test <spanclass="nv">KUBECONFIG</span><spanclass="o">=</span><spanclass="nv">$HOME</span>/.kube/config
</code></pre></div></div><h2id="running-locally">Running locally</h2><p>You can run NFD locally, either directly on your host OS or in containers for testing and development purposes. This may be useful e.g. for checking features-detection.</p><h3id="nfd-master">NFD-Master</h3><p>When running as a standalone container labeling is expected to fail because Kubernetes API is not available. Thus, it is recommended to use <codeclass="language-plaintext highlighter-rouge notranslate">-no-publish</code> command line flag. E.g.</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code><spanclass="nv">$ </span><spanclass="nb">export </span><spanclass="nv">NFD_CONTAINER_IMAGE</span><spanclass="o">=</span>k8s.gcr.io/nfd/node-feature-discovery:v0.10.0
<spanclass="nv">$ </span>docker run <spanclass="nt">--rm</span><spanclass="nt">--name</span><spanclass="o">=</span>nfd-test <spanclass="k">${</span><spanclass="nv">NFD_CONTAINER_IMAGE</span><spanclass="k">}</span> nfd-master <spanclass="nt">-no-publish</span>
2019/02/01 14:48:21 gRPC server serving on port: 8080
</code></pre></div></div><h3id="nfd-worker">NFD-Worker</h3><p>In order to run nfd-worker as a "stand-alone" container against your standalone nfd-master you need to run them in the same network namespace:</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code><spanclass="nv">$ </span>docker run <spanclass="nt">--rm</span><spanclass="nt">--network</span><spanclass="o">=</span>container:nfd-test <spanclass="k">${</span><spanclass="nv">NFD_CONTAINER_IMAGE</span><spanclass="k">}</span> nfd-worker
</code></pre></div></div><p>If you just want to try out feature discovery without connecting to nfd-master, pass the <codeclass="language-plaintext highlighter-rouge notranslate">-no-publish</code> flag to nfd-worker.</p><p><strong>NOTE</strong> Some feature sources need certain directories and/or files from the host mounted inside the NFD container. Thus, you need to provide Docker with the correct <codeclass="language-plaintext highlighter-rouge notranslate">--volume</code> options in order for them to work correctly when run stand-alone directly with <codeclass="language-plaintext highlighter-rouge notranslate">docker run</code>. See the <ahref="https://github.com/kubernetes-sigs/node-feature-discovery/blob/v0.10.0/deployment/components/common/worker-mounts.yaml">default deployment</a> for up-to-date information about the required volume mounts.</p><h3id="nfd-topology-updater">NFD-Topology-Updater</h3><p>In order to run nfd-topology-updater as a "stand-alone" container against your standalone nfd-master you need to run them in the same network namespace:</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code><spanclass="nv">$ </span>docker run <spanclass="nt">--rm</span><spanclass="nt">--network</span><spanclass="o">=</span>container:nfd-test <spanclass="k">${</span><spanclass="nv">NFD_CONTAINER_IMAGE</span><spanclass="k">}</span> nfd-topology-updater
</code></pre></div></div><p>If you just want to try out feature discovery without connecting to nfd-master, pass the <codeclass="language-plaintext highlighter-rouge notranslate">-no-publish</code> flag to nfd-topology-updater.</p><p>Command line flags of nfd-topology-updater:</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code><spanclass="nv">$ </span>docker run <spanclass="nt">--rm</span><spanclass="k">${</span><spanclass="nv">NFD_CONTAINER_IMAGE</span><spanclass="k">}</span> nfd-topology-updater <spanclass="nt">-help</span>
docker run <spanclass="nt">--rm</span> quay.io/swsehgal/node-feature-discovery:v0.10.0-devel-64-g93a0a9f-dirty nfd-topology-updater <spanclass="nt">-help</span>
Usage of nfd-topology-updater:
<spanclass="nt">-add_dir_header</span>
If <spanclass="nb">true</span>, adds the file directory to the header of the log messages
If non-empty, write log files <spanclass="k">in </span>this directory
<spanclass="nt">-log_file</span> string
If non-empty, use this log file
<spanclass="nt">-log_file_max_size</span> uint
Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. <spanclass="o">(</span>default 1800<spanclass="o">)</span>
<spanclass="nt">-logtostderr</span>
log to standard error instead of files <spanclass="o">(</span>default <spanclass="nb">true</span><spanclass="o">)</span>
<spanclass="nt">-no-publish</span>
Do not publish discovered features to the cluster-local Kubernetes API server.
<spanclass="nt">-one_output</span>
If <spanclass="nb">true</span>, only write logs to their native severity level <spanclass="o">(</span>vs also writing to each lower severity level<spanclass="o">)</span>
Pod Resource Socket path to use. <spanclass="o">(</span>default <spanclass="s2">"/host-var/lib/kubelet/pod-resources/kubelet.sock"</span><spanclass="o">)</span>
<spanclass="nt">-server</span> string
NFD server address to connecto to. <spanclass="o">(</span>default <spanclass="s2">"localhost:8080"</span><spanclass="o">)</span>
Hostname expected from server certificate, useful <spanclass="k">in </span>testing
<spanclass="nt">-skip_headers</span>
If <spanclass="nb">true</span>, avoid header prefixes <spanclass="k">in </span>the log messages
<spanclass="nt">-skip_log_headers</span>
If <spanclass="nb">true</span>, avoid headers when opening log files
<spanclass="nt">-sleep-interval</span> duration
Time to <spanclass="nb">sleep </span>between CR updates. Non-positive value implies no CR updatation <spanclass="o">(</span>i.e. infinite <spanclass="nb">sleep</span><spanclass="o">)</span><spanclass="nb">.</span><spanclass="o">[</span>Default: 60s] <spanclass="o">(</span>default 1m0s<spanclass="o">)</span>
<spanclass="nt">-stderrthreshold</span> value
logs at or above this threshold go to stderr <spanclass="o">(</span>default 2<spanclass="o">)</span>
<spanclass="nt">-v</span> value
number <spanclass="k">for </span>the log level verbosity
<spanclass="nt">-version</span>
Print version and exit.
<spanclass="nt">-vmodule</span> value
comma-separated list of <spanclass="nv">pattern</span><spanclass="o">=</span>N settings <spanclass="k">for </span>file-filtered logging
<spanclass="nt">-watch-namespace</span> string
Namespace to watch pods <spanclass="o">(</span><spanclass="k">for </span>testing/debugging purpose<spanclass="o">)</span><spanclass="nb">.</span> Use <spanclass="k">*</span><spanclass="k">for </span>all namespaces. <spanclass="o">(</span>default <spanclass="s2">"*"</span><spanclass="o">)</span>
</code></pre></div></div><p>NOTE:</p><p>NFD topology updater needs certain directories and/or files from the host mounted inside the NFD container. Thus, you need to provide Docker with the correct <codeclass="language-plaintext highlighter-rouge notranslate">--volume</code> options in order for them to work correctly when run stand-alone directly with <codeclass="language-plaintext highlighter-rouge notranslate">docker run</code>. See the <ahref="https://github.com/kubernetes-sigs/node-feature-discovery/blob/v0.10.0/deployment/components/topology-updater/topologyupdater-mounts.yaml">template spec</a> for up-to-date information about the required volume mounts.</p><p><ahref="https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/#monitoring-device-plugin-resources">PodResource API</a> is a prerequisite for nfd-topology-updater. Preceding Kubernetes v1.23, the <codeclass="language-plaintext highlighter-rouge notranslate">kubelet</code> must be started with the following flag: <codeclass="language-plaintext highlighter-rouge notranslate">--feature-gates=KubeletPodResourcesGetAllocatable=true</code>. Starting Kubernetes v1.23, the <codeclass="language-plaintext highlighter-rouge notranslate">GetAllocatableResources</code> is enabled by default through <codeclass="language-plaintext highlighter-rouge notranslate">KubeletPodResourcesGetAllocatable</code><ahref="https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates">feature gate</a>.</p><h2id="documentation">Documentation</h2><p>All documentation resides under the <ahref="https://github.com/kubernetes-sigs/node-feature-discovery/tree/v0.10.0/docs">docs</a> directory in the source tree. It is designed to be served as a html site by <ahref="https://pages.github.com/">GitHub Pages</a>.</p><p>Building the documentation is containerized in order to fix the build environment. The recommended way for developing documentation is to run:</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code>make site-serve
</code></pre></div></div><p>This will build the documentation in a container and serve it under <ahref="http://localhost:4000/">localhost:4000/</a> making it easy to verify the results. Any changes made to the <codeclass="language-plaintext highlighter-rouge notranslate">docs/</code> will automatically re-trigger a rebuild and are reflected in the served content and can be inspected with a simple browser refresh.</p><p>In order to just build the html documentation run:</p><divclass="language-bash highlighter-rouge notranslate"><divclass="highlight"><preclass="highlight"><code>make site-build
</code></pre></div></div><p>This will generate html documentation under <codeclass="language-plaintext highlighter-rouge notranslate">docs/_site/</code>.</p><!-- Links --></div></div><divclass="navigation-bottom d-flex flex-justify-between py-3"role="navigation"aria-label="footer navigation"><divclass="prev"></div><divclass="next"><ahref="/node-feature-discovery/v0.10/advanced/master-commandline-reference.html"class="btn"title="Master cmdline reference"accesskey="n"rel="next"> Next <iclass="fa fa-arrow-circle-right"></i></a></div></div><hr><divclass="copyright text-center text-gray"role="contentinfo"><iclass="fa fa-copyright"></i><spanclass="time">2016-2022,</span><aclass="text-gray"href="https://github.com/kubernetes-sigs"rel="noreferrer"target="_blank">Kubernetes SIGs</a> Revision <aclass="text-gray"href="https://github.com/kubernetes-sigs/node-feature-discovery/commit/"title=""rel="noreferrer"target="_blank"></a><br><divclass="generator"> Built with <ahref="https://pages.github.com"rel="noreferrer"target="_blank"title="github-pages v209">GitHub Pages</a> using a <ahref="https://github.com/rundocs/jekyll-rtd-theme"rel="noreferrer"target="_blank"title="rundocs/jekyll-rtd-theme v2.0.10">theme</a> provided by <ahref="https://rundocs.io"rel="noreferrer"target="_blank">RunDocs</a>. </div></div></div></div><divclass="addons-wrap d-flex flex-column overflow-y-auto"><divclass="status d-flex flex-justify-between p-2"><divclass="title p-1"><iclass="fa fa-book"></i> Node Feature Discovery </div><divclass="branch p-1"><spanclass="name"> v0.10 </span><iclass="fa fa-caret-down"></i></div></div><divclass="addons d-flex flex-column height-full p-2 d-none"><dlid="versions"><dt>Versions</dt><scriptsrc="/node-feature-discovery/versions.js"></script><script>vardt=document.getElementById('versions');varitems=getVersionListItems();for(vari=0;i<items.length;i++){vardd=document.createElement('dd');vara=dd.appendChild(document.createElement('a'));a.appendChild(document.createTextNode(items[i].name));a.href=items[i].url;dt.appendChild(dd);}</script></dl><dl><dt>GitHub</dt><dd><ahref="https://github.com/kubernetes-sigs/node-feature-discovery"title="Stars: 387"><iclass="fa fa-github"></i> Homepage </a></dd><dd><ahref="https://github.com/kubernetes-sigs/node-feature-discovery/issues"title="Open issues: 30"><iclass="fa fa-question-circle-o"></i> Issues </a></dd><dd><ahref="https://github.com/kubernetes-sigs/node-feature-discovery/zipball/gh-pages"title="Size: 81654 Kb"><iclass="fa fa-download"></i> Download </a></dd></dl><hr><divclass="license f6 pb-2"> This <ahref="/node-feature-discovery/v0.10/"title="Node Feature Discovery">Software</a> is under the terms of <ahref="https://github.com/kubernetes-sigs/node-feature-discovery">Apache License 2.0</a>. </div></div></div><scriptsrc="https://cdn.jsdelivr.net/gh/rundocs/jekyll-rtd-theme@2.0.10/assets/js/jquery.min.js"></script><scriptsrc="https://cdn.jsdelivr.net/gh/rundocs/jekyll-rtd-theme@2.0.10/assets/js/theme.min.js"></script></body></html>