{"id":922,"date":"2021-04-06T16:20:50","date_gmt":"2021-04-06T16:20:50","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=922"},"modified":"2021-04-06T16:20:50","modified_gmt":"2021-04-06T16:20:50","slug":"node-exporter-kubernetes","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=922","title":{"rendered":"How to Setup Prometheus Node Exporter on Kubernetes"},"content":{"rendered":"<p>If you want to know how the Kubernetes nodes perform or <a href=\"https:\/\/devopscube.com\/best-opensource-monitoring-tools\/\" rel=\"noreferrer noopener\">monitor system-level insights<\/a> of kubernetes nodes, you need to set up a Prometheus node exporter on Kubernetes cluster.<\/p>\n<p>This guide will walk you through the node-exporter setup on a <a href=\"https:\/\/devopscube.com\/kubernetes-tutorials-beginners\/\" rel=\"noreferrer noopener\">Kubernetes<\/a> cluster and integrate Prometheus scrape config to scrape the node metrics.<\/p>\n<p>It is also an important topics in the <a href=\"https:\/\/devopscube.com\/prometheus-certified-associate\/\" rel=\"noreferrer noopener\">Prometheus Certified Associate<\/a> Certification.<\/p>\n<h2 id=\"what-is-prometheus-node-exporter\">What is Prometheus Node Exporter?<\/h2>\n<p>Node exporter is an official <a href=\"https:\/\/prometheus.io\/docs\/instrumenting\/exporters\/?ref=devopscube.com\" rel=\"noreferrer noopener\">Prometheus exporter<\/a> for capturing all the <a href=\"https:\/\/devopscube.com\/list-linux-networking-troubleshooting-and-commands-beginners\/\" rel=\"noreferrer noopener\">Linux<\/a> system-related metrics.<\/p>\n<p>It collects all the hardware and Operating System level metrics that are exposed by the kernel.<\/p>\n<p>You can use the node exporter to collect the system metrics from all your Linux systems. Check this article on <a href=\"https:\/\/devopscube.com\/monitor-linux-servers-prometheus-node-exporter\/\" rel=\"noreferrer noopener\">node monitoring using node-exporter<\/a>.<\/p>\n<h2 id=\"why-do-we-need-node-exporter-on-kubernetes\">Why do we need Node Exporter on Kubernetes?<\/h2>\n<p>By default, most of the <a href=\"https:\/\/devopscube.com\/setup-kubernetes-cluster-kubeadm\/\" rel=\"noreferrer noopener\">Kubernetes cluster<\/a>s expose the metric server metrics (Cluster level metrics from the summary API) and Cadvisor (<a href=\"https:\/\/devopscube.com\/what-is-docker\/\" rel=\"noreferrer noopener\">Container<\/a> level metrics). It does not provide detailed node-level metrics.<\/p>\n<p>To get all the kubernetes node-level system metrics, you need to have a node-exporter running in all the kubernetes nodes. It collects all the Linux system metrics and exposes them via <code>\/metrics<\/code> endpoint on port <code>9100<\/code><\/p>\n<p>Similarly, you need to <a href=\"https:\/\/devopscube.com\/setup-kube-state-metrics\/\" rel=\"noreferrer noopener\">install Kube state metrics<\/a> to get all the metrics related to kubernetes objects.<\/p>\n<h2 id=\"kubernetes-manifests\">Kubernetes Manifests<\/h2>\n<p>The Kubernetes manifest used in this guide is present in the <a href=\"https:\/\/github.com\/bibinwilson\/kubernetes-node-exporter?ref=devopscube.com\" rel=\"noreferrer noopener\">Github repository<\/a>. Clone the repo to your local system.<\/p>\n<pre><code>git clone https:\/\/github.com\/bibinwilson\/kubernetes-node-exporter<\/code><\/pre>\n<h2 id=\"setup-node-exporter-on-kubernetes\">Setup Node Exporter on Kubernetes<\/h2>\n<div class=\"kg-card kg-callout-card kg-callout-card-grey\">\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Note:<\/strong><\/b> If you don&#8217;t have the Prometheus setup, please follow my guide on <a href=\"https:\/\/devopscube.com\/setup-prometheus-monitoring-on-kubernetes\/\" rel=\"noreferrer noopener\">setting up Prometheus on kubernetes<\/a>.<\/div>\n<\/div>\n<p>Here is what we are going to do.<\/p>\n<ol>\n<li>Deploy node exporter on all the Kubernetes nodes as a <code>daemonset<\/code>. Daemonset makes sure one instance of node-exporter is running in all the nodes. It exposes all the node metrics on port <code>9100<\/code> on the <code>\/metrics<\/code> endpoint<\/li>\n<li>Create a service that listens on port <code>9100<\/code> and points to all the daemonset node exporter pods. We would be monitoring the service endpoints (Node exporter pods)  from Prometheus using the endpoint job config. More explanation on this in the Prometheus config part.<\/li>\n<\/ol>\n<p>Lest get started with the setup.<\/p>\n<p><strong>Step 1:<\/strong> Create a file name <code>daemonset.yaml<\/code> and copy the following content.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-grey\">\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Note: <\/strong><\/b>This Daemonset will be deployed in the monitoring namespace. If you wish to deploy it in a different namespace, change it in the following YAML<\/div>\n<\/div>\n<pre><code>apiVersion: apps\/v1\nkind: DaemonSet\nmetadata:\n  labels:\n    app.kubernetes.io\/component: exporter\n    app.kubernetes.io\/name: node-exporter\n  name: node-exporter\n  namespace: monitoring\nspec:\n  selector:\n    matchLabels:\n      app.kubernetes.io\/component: exporter\n      app.kubernetes.io\/name: node-exporter\n  template:\n    metadata:\n      labels:\n        app.kubernetes.io\/component: exporter\n        app.kubernetes.io\/name: node-exporter\n    spec:\n      containers:\n      - args:\n        - --path.sysfs=\/host\/sys\n        - --path.rootfs=\/host\/root\n        - --no-collector.wifi\n        - --no-collector.hwmon\n        - --collector.filesystem.ignored-mount-points=^\/(dev|proc|sys|var\/lib\/docker\/.+|var\/lib\/kubelet\/pods\/.+)($|\/)\n        - --collector.netclass.ignored-devices=^(veth.*)$\n        name: node-exporter\n        image: prom\/node-exporter\n        ports:\n          - containerPort: 9100\n            protocol: TCP\n        resources:\n          limits:\n            cpu: 250m\n            memory: 180Mi\n          requests:\n            cpu: 102m\n            memory: 180Mi\n        volumeMounts:\n        - mountPath: \/host\/sys\n          mountPropagation: HostToContainer\n          name: sys\n          readOnly: true\n        - mountPath: \/host\/root\n          mountPropagation: HostToContainer\n          name: root\n          readOnly: true\n      volumes:\n      - hostPath:\n          path: \/sys\n        name: sys\n      - hostPath:\n          path: \/\n        name: root\n<\/code><\/pre>\n<p><strong>Step 2:<\/strong> Deploy the daemonset using the kubectl command.<\/p>\n<pre><code>kubectl create -f daemonset.yaml<\/code><\/pre>\n<p><strong>Step 3:<\/strong> List the <code>daemonset<\/code> in the monitoring namespace and make sure it is in the available state.<\/p>\n<pre><code>kubectl get daemonset -n monitoring<\/code><\/pre>\n<p><strong>Step 4: <\/strong>Create a file names <code>service.yaml <\/code>and copy the following contents.<\/p>\n<pre><code>---\nkind: Service\napiVersion: v1\nmetadata:\n  name: node-exporter\n  namespace: monitoring\n  annotations:\n      prometheus.io\/scrape: 'true'\n      prometheus.io\/port:   '9100'\nspec:\n  selector:\n      app.kubernetes.io\/component: exporter\n      app.kubernetes.io\/name: node-exporter\n  ports:\n  - name: node-exporter\n    protocol: TCP\n    port: 9100\n    targetPort: 9100<\/code><\/pre>\n<p><strong>Step 5:<\/strong> Create the service.<\/p>\n<pre><code>kubectl create -f service.yaml<\/code><\/pre>\n<p><strong>Step 6: <\/strong>Now, check the service&#8217;s endpoints and see if it is pointing to all the daemonset pods.<\/p>\n<pre><code>kubectl get endpoints -n monitoring <\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/endpoints-min-1.png\" class=\"kg-image\" alt=\"Prometheus node exporter daemonset\" loading=\"lazy\" width=\"1014\" height=\"386\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/endpoints-min-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/endpoints-min-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/endpoints-min-1.png 1014w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>As you can see from the above output,  the node-exporter service has three endpoints. Meaning three node-exporter pods running on three nodes as part of Daemonset.<\/p>\n<h2 id=\"node-exporter-prometheus-config\">Node-exporter Prometheus Config<\/h2>\n<p>We have the node-exporter daemonset running on port 9100 and a service pointing to all the node-exporter pods.<\/p>\n<p>You need to add a scrape config to the Prometheus config file to discover all the node-exporter pods.<\/p>\n<p>Let&#8217;s take a look at the Prometheus scrape config required to scrape the node-exporter metrics.<\/p>\n<pre><code>      - job_name: 'node-exporter'\n        kubernetes_sd_configs:\n          - role: endpoints\n        relabel_configs:\n        - source_labels: [__meta_kubernetes_endpoints_name]\n          regex: 'node-exporter'\n          action: keep<\/code><\/pre>\n<p>In this config, we mention the role as endpoints to scrape the endpoints with the name <code>node-exporter<\/code>.<\/p>\n<p>See <a href=\"https:\/\/github.com\/bibinwilson\/kubernetes-prometheus\/blob\/master\/config-map.yaml?ref=devopscube.com\" rel=\"noreferrer noopener\">Prometheus config map<\/a> file I have created for the Kubernetes monitoring stack. It includes all the scrape configs for kubernetes components.<\/p>\n<p>Once you add the scrape config to Prometheus, you will see the node-exporter targets in Prometheus, as shown below.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/prometheus-node-exporter-trget-min-1.png\" class=\"kg-image\" alt=\"Node exporter target state in prometheus\" loading=\"lazy\" width=\"1169\" height=\"249\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/prometheus-node-exporter-trget-min-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/prometheus-node-exporter-trget-min-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/prometheus-node-exporter-trget-min-1.png 1169w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"querying-node-exporter-metrics-in-prometheus\">Querying Node-exporter Metrics in Prometheus<\/h2>\n<p>Once you verify the node-exporter target state in Prometheus, you can query the Prometheus dashboard&#8217;s available node-exporter metrics.<\/p>\n<p>All the metrics from node-exporter is prefixed with <code>node_<\/code><\/p>\n<p>You can query the metrics with different PromQL expressions. See <a href=\"https:\/\/prometheus.io\/docs\/prometheus\/latest\/querying\/basics\/?ref=devopscube.com\" rel=\"noreferrer noopener\">querying basics<\/a> to learn about PromQL queries.<\/p>\n<p>If you type <code>node_<\/code> in the Prometheus dashboard, it will list all the available metrics as shown below.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/e-com-gif-maker-gif-1.gif\" class=\"kg-image\" alt=\"Querying node exporter metrics from Prometheus dashboard\" loading=\"lazy\" width=\"1728\" height=\"1080\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/e-com-gif-maker-gif-1.gif 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/e-com-gif-maker-gif-1.gif 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/e-com-gif-maker-gif-1.gif 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/e-com-gif-maker-gif-1.gif 1728w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"visualizing-prometheus-node-exporter-metrics-as-grafana-dashboards\">Visualizing Prometheus Node Exporter Metrics as Grafana Dashboards<\/h2>\n<p>Visualising the node exporter metrics on Grafana is not difficult as you think.<\/p>\n<p>A <a href=\"https:\/\/grafana.com\/grafana\/dashboards\/1860?ref=devopscube.com\" rel=\"noreferrer noopener\">community Grafana node exporter dashboard template <\/a>has a predefined dashboard with all the supported node exporter metrics.<\/p>\n<p>You can modify the template as per your project requirements.<\/p>\n<p>If you don&#8217;t know how to import a community template, please check my <a href=\"https:\/\/devopscube.com\/integrate-visualize-prometheus-grafana\/\" rel=\"noreferrer noopener\">Grafana Prometheus integration<\/a> article, where I have added the steps to import community dashboard templates.<\/p>\n<p>So here is how the node-exporter Grafana dashboard looks  for CPU\/memory and disk statistics.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/grafana-dashboard-min-1.png\" class=\"kg-image\" alt=\"node exporter grafana dashbaord\" loading=\"lazy\" width=\"2000\" height=\"995\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/grafana-dashboard-min-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/grafana-dashboard-min-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/grafana-dashboard-min-1.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w2400\/2025\/03\/grafana-dashboard-min-1.png 2400w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Once you have the dashboard, you will find the following sections. If you expand it, you will find all the metrics panel.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/panels-min-1.png\" class=\"kg-image\" alt=\"node exporter grafana metric panels\" loading=\"lazy\" width=\"638\" height=\"1078\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/panels-min-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/panels-min-1.png 638w\"><\/figure>\n<h2 id=\"more-references\">More References<\/h2>\n<ol>\n<li><a href=\"https:\/\/github.com\/prometheus\/node_exporter?ref=devopscube.com\" rel=\"noreferrer noopener\">Official Node exporter Github repository<\/a><\/li>\n<li><a href=\"https:\/\/prometheus.io\/docs\/guides\/node-exporter\/?ref=devopscube.com\" rel=\"noreferrer noopener\">Prometheus Linux host metrics guide<\/a><\/li>\n<li><a href=\"https:\/\/prometheus.io\/docs\/instrumenting\/exporters\/?ref=devopscube.com\" rel=\"noreferrer noopener\">Prometheus Exporters<\/a><\/li>\n<\/ol>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/node-exporter-kubernetes\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to Setup Prometheus Node Exporter on Kubernetes \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/node-exporter-kubernetes\/<\/p>\n","protected":false},"author":1,"featured_media":923,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-922","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/922","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=922"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/922\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/923"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=922"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=922"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=922"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}