Skip to content

Commit

Permalink
feat: cgroups host collector (#1581)
Browse files Browse the repository at this point in the history
Linux control groups host collector that detects whether the specified mountPoint is a cgroup filesystem and what version it is. The collector also collects information of the configured cgroup controllers.

Signed-off-by: Evans Mungai <evans@replicated.com>
  • Loading branch information
banjoh authored Jul 24, 2024
1 parent 22cc02c commit 01d5804
Show file tree
Hide file tree
Showing 13 changed files with 582 additions and 3 deletions.
9 changes: 9 additions & 0 deletions config/crds/troubleshoot.sh_hostcollectors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,15 @@ spec:
required:
- paths
type: object
cgroups:
properties:
collectorName:
type: string
exclude:
type: BoolString
mountPoint:
type: string
type: object
copy:
properties:
collectorName:
Expand Down
9 changes: 9 additions & 0 deletions config/crds/troubleshoot.sh_hostpreflights.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,15 @@ spec:
required:
- paths
type: object
cgroups:
properties:
collectorName:
type: string
exclude:
type: BoolString
mountPoint:
type: string
type: object
copy:
properties:
collectorName:
Expand Down
9 changes: 9 additions & 0 deletions config/crds/troubleshoot.sh_supportbundles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19839,6 +19839,15 @@ spec:
required:
- paths
type: object
cgroups:
properties:
collectorName:
type: string
exclude:
type: BoolString
mountPoint:
type: string
type: object
copy:
properties:
collectorName:
Expand Down
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ require (
github.com/ahmetalpbalkan/go-cursor v0.0.0-20131010032410-8136607ea412
github.com/apparentlymart/go-cidr v1.1.0
github.com/blang/semver/v4 v4.0.0
github.com/cilium/ebpf v0.11.0
github.com/containerd/cgroups/v3 v3.0.3
github.com/containers/image/v5 v5.31.1
github.com/distribution/distribution/v3 v3.0.0-beta.1
github.com/fatih/color v1.17.0
Expand Down Expand Up @@ -68,9 +70,9 @@ require (
github.com/Masterminds/squirrel v1.5.4 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/containerd/cgroups/v3 v3.0.3 // indirect
github.com/containerd/errdefs v0.1.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
Expand Down Expand Up @@ -207,7 +209,7 @@ require (
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d // indirect
github.com/nwaples/rardecode v1.1.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/opencontainers/runtime-spec v1.2.0
github.com/opencontainers/selinux v1.11.0 // indirect
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
Expand Down Expand Up @@ -235,7 +237,7 @@ require (
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/net v0.27.0
golang.org/x/oauth2 v0.20.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/sys v0.22.0
golang.org/x/term v0.22.0 // indirect
golang.org/x/text v0.16.0
golang.org/x/time v0.5.0 // indirect
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y=
github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
Expand Down Expand Up @@ -415,6 +417,7 @@ github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XE
github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
Expand Down Expand Up @@ -962,6 +965,8 @@ go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lI
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
Expand Down
8 changes: 8 additions & 0 deletions pkg/apis/troubleshoot/v1beta2/hostcollector_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ type HostCopy struct {
Path string `json:"path" yaml:"path"`
}

type HostCGroups struct {
HostCollectorMeta `json:",inline" yaml:",inline"`
MountPoint string `json:"mountPoint,omitempty" yaml:"mountPoint,omitempty"`
}

type HostTime struct {
HostCollectorMeta `json:",inline" yaml:",inline"`
}
Expand Down Expand Up @@ -219,8 +224,11 @@ type HostCollect struct {
HostRun *HostRun `json:"run,omitempty" yaml:"run,omitempty"`
HostCopy *HostCopy `json:"copy,omitempty" yaml:"copy,omitempty"`
HostKernelConfigs *HostKernelConfigs `json:"kernelConfigs,omitempty" yaml:"kernelConfigs,omitempty"`
HostCGroups *HostCGroups `json:"cgroups,omitempty" yaml:"cgroups,omitempty"`
}

// GetName gets the name of the collector
// Deprecated: This function is not used anywhere and should be removed. Do not use it.
func (c *HostCollect) GetName() string {
// TODO: Is this used anywhere? Should we just remove it?
var collector string
Expand Down
21 changes: 21 additions & 0 deletions pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

99 changes: 99 additions & 0 deletions pkg/collect/host_cgroup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// This Control Groups collector is heavily based on k0s'
// probes implementation https://github.com/k0sproject/k0s/blob/main/internal/pkg/sysinfo/probes/linux/cgroups.go

package collect

import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io"
"strings"

troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"k8s.io/klog/v2"
)

const hostCGroupsPath = `host-collectors/system/cgroups.json`

type CollectHostCGroups struct {
hostCollector *troubleshootv1beta2.HostCGroups
BundlePath string
}

type cgroupResult struct {
Enabled bool `json:"enabled"`
MountPoint string `json:"mountPoint"`
Controllers []string `json:"controllers"`
}

type cgroupsResult struct {
CGroupEnabled bool `json:"cgroup-enabled"`
CGroupV1 cgroupResult `json:"cgroup-v1"`
CGroupV2 cgroupResult `json:"cgroup-v2"`
// AllControllers is a list of all cgroup controllers found in the system
AllControllers []string `json:"allControllers"`
}

func (c *CollectHostCGroups) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "cgroups")
}

func (c *CollectHostCGroups) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}

func (c *CollectHostCGroups) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
// https://man7.org/linux/man-pages/man7/cgroups.7.html
// Implementation is based on https://github.com/k0sproject/k0s/blob/main/internal/pkg/sysinfo/probes/linux/cgroups.go

if c.hostCollector.MountPoint == "" {
c.hostCollector.MountPoint = "/sys/fs/cgroup"
}

results, err := discoverConfiguration(c.hostCollector.MountPoint)
if err != nil {
return nil, err
}

// Save the results
resultsJson, err := json.MarshalIndent(results, "", " ")
if err != nil {
return nil, err
}

output := NewResult()
err = output.SaveResult(c.BundlePath, hostCGroupsPath, bytes.NewBuffer(resultsJson))
if err != nil {
return nil, err
}

return output, nil
}

func parseV1ControllerNames(r io.Reader) ([]string, error) {
names := []string{}
var lineNo uint
lines := bufio.NewScanner(r)
for lines.Scan() {
lineNo = lineNo + 1
if err := lines.Err(); err != nil {
return nil, fmt.Errorf("failed to parse /proc/cgroups at line %d: %w ", lineNo, err)
}
text := lines.Text()
if len(text) == 0 {
continue
}

if text[0] != '#' {
parts := strings.Fields(text)
if len(parts) >= 4 && parts[3] != "0" {
names = append(names, parts[0])
}
}
}
klog.V(2).Info("cgroup v1 controllers loaded")

return names, nil
}
Loading

0 comments on commit 01d5804

Please sign in to comment.