Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Unskip s3_request integration test. {pull}23887[23887]
- Add system.hostfs configuration option for system module. {pull}23831[23831]
- Fix GCP not able to request Cloudfunctions metrics if a region filter was set {pull}24218[24218]
- Allow cgroup self-monitoring to see alternate `hostfs` paths {pull}24334[24334]
Comment thread
fearful-symmetry marked this conversation as resolved.
Outdated

*Packetbeat*

Expand Down
5 changes: 4 additions & 1 deletion libbeat/cmd/instance/beat.go
Original file line number Diff line number Diff line change
Expand Up @@ -1083,13 +1083,16 @@ func initPaths(cfg *common.Config) error {
// the paths field. After we will unpack the complete configuration and keystore reference
// will be correctly replaced.
partialConfig := struct {
Path paths.Path `config:"path"`
Path paths.Path `config:"path"`
Hostfs string `config:"system.hostfs"`
Comment thread
jsoriano marked this conversation as resolved.
}{}

if err := cfg.Unpack(&partialConfig); err != nil {
return fmt.Errorf("error extracting default paths: %+v", err)
}

partialConfig.Path.Hostfs = partialConfig.Hostfs

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is this always safe? By introducing Hostfs to the Path struct we will allow users to overwrite the path in the configuration file already.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Maybe I'm missing something, but is that any different from -E flags?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Paths are configured twice I think. Once via --path.X on startup + --system.hostfs.

Then the config file is read and the path settings from the configuration file are applied again. The -E flags for path settings only become effective during the second phase. That is why the shim bash scripts just use --path.X CLI flags and we do not attempt to overwrite the defaults in the config.

The thing I was wondering: What if path.hostfs is configured, but system.hostfs is not? In that case you will set path.hostfs to an empty string here. Is this on purpose? Why not:

if partialConfig.Path.Hostfs == "" {
  partialConfig.Path.Hostfs = partialConfig.Hostfs
}

If the forced overwrite is on purpose a comment explaining the why would be helpful.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Okay, so, technically speaking, there is no path.hostfs. There's only system.hostfs, and we just expand the main Path struct type with hostfs, hence why that's being overwritten. Ideally it would only be path.hostfs, but I'm mostly worried about breaking changes here, since I'm considering this to be primarily a bugfix so we can properly set hostfs in the cgroup self-monitoring.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I see. It is still kinda "obscure" and I'm sure someone (me?, future you?) might change the logic on purpose or by accident. Can you please add a code comment about the why? Having the why in the PR review it will be lost.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah, good point.


if err := paths.InitPaths(&partialConfig.Path); err != nil {
return fmt.Errorf("error setting default paths: %+v", err)
}
Expand Down
3 changes: 3 additions & 0 deletions libbeat/cmd/instance/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/elastic/beats/v7/libbeat/metric/system/cpu"
"github.com/elastic/beats/v7/libbeat/metric/system/process"
"github.com/elastic/beats/v7/libbeat/monitoring"
"github.com/elastic/beats/v7/libbeat/paths"
"github.com/elastic/gosigar/cgroup"
)

Expand Down Expand Up @@ -284,7 +285,9 @@ func reportBeatCgroups(_ monitoring.Mode, V monitoring.Visitor) {
return
}


cgroups, err := cgroup.NewReaderOptions(cgroup.ReaderOptions{
RootfsMountpoint: paths.Paths.Hostfs,
IgnoreRootCgroups: true,
CgroupsHierarchyOverride: os.Getenv(libbeatMonitoringCgroupsHierarchyOverride),
})
Expand Down
41 changes: 36 additions & 5 deletions libbeat/paths/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
//
// path.config - Configuration files and Elasticsearch template default location
//
// system.hostfs - supplies an alternate filesystem root for containerized environments

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Wdyt about calling it path.hostfs now that it is another configurable path, and not only used by the system module?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yah, it might be worth it to have a second one for backwards compatibility?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yep, we would keep both at least till 8.0.

//
// These settings can be set via the configuration file or via command line flags.
// The CLI flags overwrite the configuration file options.
//
Expand All @@ -38,27 +40,45 @@
package paths

import (
"flag"
"fmt"
"os"
"path/filepath"

"github.com/elastic/beats/v7/libbeat/common/cfgwarn"
)

var (
// TODO: remove this flag in 8.0 since it should be replaced by system.hostfs configuration option (config.HostFS)
// HostFS is an alternate mountpoint for the filesytem root, for when metricbeat is running inside a container.
Comment thread
fearful-symmetry marked this conversation as resolved.
hostFS = flag.String("system.hostfs", "", "mountpoint of the host's filesystem for use in monitoring a host from within a container")
)

// Path tracks user-configurable path locations and directories
type Path struct {
Home string
Config string
Data string
Logs string
Hostfs string
}

// FileType is an enumeration type representing the file types.
// Currently existing file types are: Home, Config, Data
type FileType string

const (
Home FileType = "home"
// Home is the "root" directory for the running beats instance
Home FileType = "home"
// Config is the path to the beat config
Config FileType = "config"
Data FileType = "data"
Logs FileType = "logs"
// Data is the path to the beat data directory
Data FileType = "data"
// Logs is the path to the beats logs directory
Logs FileType = "logs"
// Hostfs is an alternate path to the filesystem root,
// used for system metrics that interact with procfs and sysfs.
Hostfs FileType = "hostfs"
)

// Paths is the Path singleton on which the top level functions from this
Expand Down Expand Up @@ -115,15 +135,24 @@ func (paths *Path) initPaths(cfg *Path) error {
paths.Logs = filepath.Join(paths.Home, "logs")
}

if *hostFS != "" {
cfgwarn.Deprecate("8.0.0", "This flag will be removed in the future and replaced by a config value.")
paths.Hostfs = *hostFS
}

if paths.Hostfs == "" {
paths.Hostfs = "/"
}

return nil
}

// Resolve resolves a path to a location in one of the default
// folders. For example, Resolve(Home, "test") returns an absolute
// path for "test" in the home path.
func (paths *Path) Resolve(fileType FileType, path string) string {
// absolute paths are not changed
if filepath.IsAbs(path) {
// absolute paths are not changed for non-hostfs file types, since hostfs is a little odd
if filepath.IsAbs(path) && fileType != Hostfs {
return path
}

Expand All @@ -136,6 +165,8 @@ func (paths *Path) Resolve(fileType FileType, path string) string {
return filepath.Join(paths.Data, path)
case Logs:
return filepath.Join(paths.Logs, path)
case Hostfs:
return filepath.Join(paths.Hostfs, path)
default:
panic(fmt.Sprintf("Unknown file type: %s", fileType))
}
Expand Down
26 changes: 17 additions & 9 deletions metricbeat/module/system/diskio/diskio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,23 @@ import (

"github.com/stretchr/testify/assert"

"github.com/elastic/beats/v7/libbeat/paths"
mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing"
"github.com/elastic/beats/v7/metricbeat/module/system"
)

func setHostfs(pathString string) {
path := paths.Path{
Hostfs: pathString,
}
paths.InitPaths(&path)
}

func TestDataNameFilter(t *testing.T) {
oldFS := system.HostFS
newFS := "_meta/testdata"
system.HostFS = &newFS
oldFS := paths.Paths.Hostfs
setHostfs("_meta/testdata")

defer func() {
system.HostFS = oldFS
setHostfs(oldFS)
}()

conf := map[string]interface{}{
Expand All @@ -51,11 +58,11 @@ func TestDataNameFilter(t *testing.T) {
}

func TestDataEmptyFilter(t *testing.T) {
oldFS := system.HostFS
newFS := "_meta/testdata"
system.HostFS = &newFS
oldFS := paths.Paths.Hostfs
setHostfs("_meta/testdata")

defer func() {
system.HostFS = oldFS
setHostfs(oldFS)
}()

conf := map[string]interface{}{
Expand All @@ -67,6 +74,7 @@ func TestDataEmptyFilter(t *testing.T) {
data, errs := mbtest.ReportingFetchV2Error(f)
assert.Empty(t, errs)
assert.Equal(t, 10, len(data))

}

func TestFetch(t *testing.T) {
Expand Down
9 changes: 2 additions & 7 deletions metricbeat/module/system/entropy/entropy.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import (

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/libbeat/common/cfgwarn"
"github.com/elastic/beats/v7/libbeat/paths"
"github.com/elastic/beats/v7/metricbeat/mb"
"github.com/elastic/beats/v7/metricbeat/module/system"
)

// init registers the MetricSet with the central registry as soon as the program
Expand All @@ -55,12 +55,7 @@ type MetricSet struct {
func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
cfgwarn.Beta("The system entropy metricset is beta.")

systemModule, ok := base.Module().(*system.Module)
if !ok {
return nil, errors.New("unexpected module type")
}

totalPath := path.Join(systemModule.HostFS, "/proc/sys/kernel/random")
totalPath := paths.Resolve(paths.Hostfs, "/proc/sys/kernel/random")

return &MetricSet{
BaseMetricSet: base,
Expand Down
22 changes: 17 additions & 5 deletions metricbeat/module/system/entropy/entropy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,19 @@ import (

"github.com/stretchr/testify/assert"

"github.com/elastic/beats/v7/libbeat/paths"
mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing"
"github.com/elastic/beats/v7/metricbeat/module/system"
)

func TestData(t *testing.T) {
testdata := "./_meta/testdata"
system.HostFS = &testdata
testPath := paths.Path{
Hostfs: "./_meta/testdata",
}

if err := paths.InitPaths(&testPath); err != nil {
t.Errorf("error setting default paths: %+v", err)
t.FailNow()
}
f := mbtest.NewReportingMetricSetV2Error(t, getConfig())
err := mbtest.WriteEventsReporterV2Error(f, t, ".")
if err != nil {
Expand All @@ -39,8 +45,14 @@ func TestData(t *testing.T) {
}

func TestFetch(t *testing.T) {
testdata := "./_meta/testdata"
system.HostFS = &testdata
testPath := paths.Path{
Hostfs: "./_meta/testdata",
}

if err := paths.InitPaths(&testPath); err != nil {
t.Errorf("error setting default paths: %+v", err)
t.FailNow()
}
f := mbtest.NewReportingMetricSetV2Error(t, getConfig())
events, errs := mbtest.ReportingFetchV2Error(f)

Expand Down
5 changes: 2 additions & 3 deletions metricbeat/module/system/filesystem/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@ package filesystem
import (
"bufio"
"os"
"path"
"path/filepath"
"strings"
"time"

"runtime"

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/metricbeat/module/system"
"github.com/elastic/beats/v7/libbeat/paths"
sigar "github.com/elastic/gosigar"
)

Expand Down Expand Up @@ -194,7 +193,7 @@ func BuildTypeFilter(ignoreType ...string) Predicate {
func DefaultIgnoredTypes() (types []string) {
// If /proc/filesystems exist, default ignored types are all marked
// as nodev
fsListFile := path.Join(*system.HostFS, "/proc/filesystems")
fsListFile := paths.Resolve(paths.Hostfs, "/proc/filesystems")
if f, err := os.Open(fsListFile); err == nil {
scanner := bufio.NewScanner(f)
for scanner.Scan() {
Expand Down
5 changes: 3 additions & 2 deletions metricbeat/module/system/process/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/libbeat/logp"
"github.com/elastic/beats/v7/libbeat/metric/system/process"
"github.com/elastic/beats/v7/libbeat/paths"
"github.com/elastic/beats/v7/metricbeat/mb"
"github.com/elastic/beats/v7/metricbeat/mb/parse"
"github.com/elastic/beats/v7/metricbeat/module/system"
Expand Down Expand Up @@ -83,8 +84,8 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) {

if runtime.GOOS == "linux" {
if config.Cgroups == nil || *config.Cgroups {
debugf("process cgroup data collection is enabled, using hostfs='%v'", systemModule.HostFS)
m.cgroup, err = cgroup.NewReader(systemModule.HostFS, true)
debugf("process cgroup data collection is enabled, using hostfs='%v'", paths.Paths.Hostfs)
m.cgroup, err = cgroup.NewReader(paths.Paths.Hostfs, true)
if err != nil {
if err == cgroup.ErrCgroupsMissing {
logp.Warn("cgroup data collection will be disabled: %v", err)
Expand Down
8 changes: 2 additions & 6 deletions metricbeat/module/system/raid/raid.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import (
"github.com/prometheus/procfs"

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/libbeat/paths"
"github.com/elastic/beats/v7/metricbeat/mb"
"github.com/elastic/beats/v7/metricbeat/mb/parse"
"github.com/elastic/beats/v7/metricbeat/module/system"
"github.com/elastic/beats/v7/metricbeat/module/system/raid/blockinfo"
)

Expand All @@ -45,10 +45,6 @@ type MetricSet struct {

// New creates a new instance of the raid metricset.
func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
systemModule, ok := base.Module().(*system.Module)
if !ok {
return nil, errors.New("unexpected module type")
}

// Additional configuration options
config := struct {
Expand All @@ -60,7 +56,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
}

if config.MountPoint == "" {
config.MountPoint = systemModule.HostFS
config.MountPoint = paths.Paths.Hostfs
}

mountPoint := filepath.Join(config.MountPoint, procfs.DefaultMountPoint)
Expand Down
16 changes: 8 additions & 8 deletions metricbeat/module/system/socket/socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,17 @@ import (
"net"
"os"
"os/user"
"path/filepath"
"strconv"
"syscall"

"github.com/pkg/errors"

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/libbeat/logp"
"github.com/elastic/beats/v7/libbeat/paths"
sock "github.com/elastic/beats/v7/metricbeat/helper/socket"
"github.com/elastic/beats/v7/metricbeat/mb"
"github.com/elastic/beats/v7/metricbeat/mb/parse"
"github.com/elastic/beats/v7/metricbeat/module/system"
"github.com/elastic/gosigar/sys/linux"
)

Expand All @@ -50,6 +49,10 @@ func init() {
)
}

// MetricSet holds any configuration or state information. It must implement
// the mb.MetricSet interface. And this is best achieved by embedding
// mb.BaseMetricSet because it implements all of the required mb.MetricSet
// interface methods except for Fetch.
type MetricSet struct {
mb.BaseMetricSet
netlink *sock.NetlinkSession
Expand All @@ -62,18 +65,15 @@ type MetricSet struct {
users UserCache
}

// New creates a new instance of the MetricSet. New is responsible for unpacking
// any MetricSet specific configuration options if there are any.
func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
c := defaultConfig
if err := base.Module().UnpackConfig(&c); err != nil {
return nil, err
}

systemModule, ok := base.Module().(*system.Module)
if !ok {
return nil, errors.New("unexpected module type")
}

ptable, err := sock.NewProcTable(filepath.Join(systemModule.HostFS, "/proc"))
ptable, err := sock.NewProcTable(paths.Resolve(paths.Hostfs, "/proc"))
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion metricbeat/module/system/socket_summary/socket_summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error {
}

stats := calculateConnStats(conns)
newStats, err := applyEnhancements(stats, m)
newStats, err := applyEnhancements(stats)
if err != nil {
m.Logger().Debugf("error applying enhancements: %s", err)
newStats = stats
Expand Down
Loading