Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,23 @@ The node\_exporter is designed to monitor the host system. It's not recommended
to deploy it as Docker container because it requires access to the host system.
Be aware that any non-root mount points you want to monitor will need bind-mounted
into the container.
If you start container for host monitoring, specify `path.rootfs` argument.
This argument must match path in bind-mount of host root. The node\_exporter will use
`path.rootfs` as prefix to filter entries in ${path.procfs}/mounts and to
cleanup it from `mountpoint` label. You also need bind-mount host proc and host sys
with `path.procfs` and `path.sysfs` arguments.
Also you need to use `bind-propagation=rslave` option for bind-mount host rootfs to
propagate host mounts changes to container (option available since 17.05.0).

```bash
docker run -d \
--net="host" \
--pid="host" \
quay.io/prometheus/node-exporter
-v "/proc:/host/proc:ro" -v "/sys:/host/sys:ro" \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this PR with:

docker run -d \
   --net="host" \
   --pid="host" \
   -v "/:/host:ro,rslave" \
   node-exporter:pr-912 --path.rootfs=/host

I get the expected metrics and labels. It looks like there is no need to adjust the /proc and /sys mapping due to the --pid="host" option to docker.

--mount "type=bind,source=/,target=/rootfs,readonly,bind-propagation=rslave" \
quay.io/prometheus/node-exporter \
--path.procfs /host/proc --path.sysfs /host/sys \
--path.rootfs /rootfs
```

## Using a third-party repository for RHEL/CentOS/Fedora
Expand Down
10 changes: 7 additions & 3 deletions collector/filesystem_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
}

buf := new(syscall.Statfs_t)
err := syscall.Statfs(labels.mountPoint, buf)
err := syscall.Statfs(rootfsFilePath(labels.mountPoint), buf)
if err != nil {
stats = append(stats, filesystemStats{
labels: labels,
deviceError: 1,
})
log.Debugf("Error on statfs() system call for %q: %s", labels.mountPoint, err)
log.Debugf("Error on statfs() system call for %q: %s", rootfsFilePath(labels.mountPoint), err)
continue
}

Expand Down Expand Up @@ -87,9 +87,13 @@ func mountPointDetails() ([]filesystemLabels, error) {
scanner := bufio.NewScanner(file)
for scanner.Scan() {
parts := strings.Fields(scanner.Text())
// skip non rootfs paths if rootfsPath defined
if !rootfsPathDetect(parts[1]) {
continue
}
filesystems = append(filesystems, filesystemLabels{
device: parts[0],
mountPoint: parts[1],
mountPoint: rootfsStripPrefix(parts[1]),
fsType: parts[2],
})
}
Expand Down
33 changes: 31 additions & 2 deletions collector/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ package collector

import (
"path"
"strings"

"github.com/prometheus/procfs"
"gopkg.in/alecthomas/kingpin.v2"
)

var (
// The path of the proc filesystem.
procPath = kingpin.Flag("path.procfs", "procfs mountpoint.").Default(procfs.DefaultMountPoint).String()
sysPath = kingpin.Flag("path.sysfs", "sysfs mountpoint.").Default("/sys").String()
procPath = kingpin.Flag("path.procfs", "procfs mountpoint.").Default(procfs.DefaultMountPoint).String()
sysPath = kingpin.Flag("path.sysfs", "sysfs mountpoint.").Default("/sys").String()
rootfsPath = kingpin.Flag("path.rootfs", "rootfs mountpoint.").Default("").String()
)

func procFilePath(name string) string {
Expand All @@ -33,3 +35,30 @@ func procFilePath(name string) string {
func sysFilePath(name string) string {
return path.Join(*sysPath, name)
}

func rootfsFilePath(name string) string {
if name == "/" {
return *rootfsPath
}
return path.Join(*rootfsPath, name)
}

func rootfsStripPrefix(path string) string {
if path == *rootfsPath {
return "/"
}
if strings.HasPrefix(path, *rootfsPath) {
return strings.TrimPrefix(path, *rootfsPath)
}
return path
}

func rootfsPathDetect(path string) bool {
if *rootfsPath == "" {
return true
}
if strings.HasPrefix(path, *rootfsPath) {
return true
}
return false
}