Skip to content

Make resctrl optional/pluggable #3668

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 5, 2025
Merged
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
3 changes: 3 additions & 0 deletions cmd/cadvisor.go
Original file line number Diff line number Diff line change
@@ -41,6 +41,9 @@ import (
_ "github.com/google/cadvisor/utils/cloudinfo/azure"
_ "github.com/google/cadvisor/utils/cloudinfo/gce"

// Register resctrl plugin
_ "github.com/google/cadvisor/resctrl/intel/install"

"k8s.io/klog/v2"
)

4 changes: 2 additions & 2 deletions manager/manager.go
Original file line number Diff line number Diff line change
@@ -221,7 +221,7 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, HousekeepingConfi
return nil, err
}

newManager.resctrlManager, err = resctrl.NewManager(resctrlInterval, resctrl.Setup, machineInfo.CPUVendorID, inHostNamespace)
newManager.resctrlManager, err = resctrl.NewManager(resctrlInterval, machineInfo.CPUVendorID, inHostNamespace)
if err != nil {
klog.V(4).Infof("Cannot gather resctrl metrics: %v", err)
}
@@ -265,7 +265,7 @@ type manager struct {
eventsChannel chan watcher.ContainerEvent
collectorHTTPClient *http.Client
perfManager stats.Manager
resctrlManager resctrl.Manager
resctrlManager resctrl.ResControlManager
// List of raw container cgroup path prefix whitelist.
rawContainerCgroupPathPrefixWhiteList []string
// List of container env prefix whitelist, the matched container envs would be collected into metrics as extra labels.
58 changes: 58 additions & 0 deletions resctrl/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2025 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package resctrl

import (
"fmt"
"sync"
"time"

"github.com/google/cadvisor/stats"

"k8s.io/klog/v2"
)

type ResControlManager interface {
Destroy()
GetCollector(containerName string, getContainerPids func() ([]string, error), numberOfNUMANodes int) (stats.Collector, error)
}

// All registered auth provider plugins.
var pluginsLock sync.Mutex
var plugins = make(map[string]ResControlManagerPlugin)

type ResControlManagerPlugin interface {
NewManager(interval time.Duration, vendorID string, inHostNamespace bool) (ResControlManager, error)
}

func RegisterPlugin(name string, plugin ResControlManagerPlugin) error {
pluginsLock.Lock()
defer pluginsLock.Unlock()
if _, found := plugins[name]; found {
return fmt.Errorf("ResControlManagerPlugin %q was registered twice", name)
}
klog.V(4).Infof("Registered ResControlManagerPlugin %q", name)
plugins[name] = plugin
return nil
}

func NewManager(interval time.Duration, vendorID string, inHostNamespace bool) (ResControlManager, error) {
pluginsLock.Lock()
defer pluginsLock.Unlock()
for _, plugin := range plugins {
return plugin.NewManager(interval, vendorID, inHostNamespace)
}
return nil, fmt.Errorf("unable to find plugins for resctrl manager")
}
2 changes: 1 addition & 1 deletion resctrl/collector.go → resctrl/intel/collector.go
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
// limitations under the License.

// Collector of resctrl for a container.
package resctrl
package intel

import (
"fmt"
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
// limitations under the License.

// Collector tests.
package resctrl
package intel

import (
"fmt"
38 changes: 38 additions & 0 deletions resctrl/intel/install/install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2025 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package install

import (
"time"

"github.com/google/cadvisor/resctrl"
"github.com/google/cadvisor/resctrl/intel"

"k8s.io/klog/v2"
)

type managerplugin struct {
}

func (m *managerplugin) NewManager(interval time.Duration, vendorID string, inHostNamespace bool) (resctrl.ResControlManager, error) {
return intel.NewManager(interval, intel.Setup, vendorID, inHostNamespace)
}

func init() {
err := resctrl.RegisterPlugin("intel", &managerplugin{})
if err != nil {
klog.Fatalf("Failed to register intel resctrl plugin: %v", err)
}
}
12 changes: 4 additions & 8 deletions resctrl/manager.go → resctrl/intel/manager.go
Original file line number Diff line number Diff line change
@@ -15,8 +15,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Manager of resctrl for containers.
package resctrl
// ResControlManager of resctrl for containers.
package intel

import (
"errors"
@@ -25,14 +25,10 @@ import (
"k8s.io/klog/v2"

"github.com/google/cadvisor/container/raw"
"github.com/google/cadvisor/resctrl"
"github.com/google/cadvisor/stats"
)

type Manager interface {
Destroy()
GetCollector(containerName string, getContainerPids func() ([]string, error), numberOfNUMANodes int) (stats.Collector, error)
}

type manager struct {
stats.NoopDestroy
interval time.Duration
@@ -50,7 +46,7 @@ func (m *manager) GetCollector(containerName string, getContainerPids func() ([]
return collector, nil
}

func NewManager(interval time.Duration, setup func() error, vendorID string, inHostNamespace bool) (Manager, error) {
func NewManager(interval time.Duration, setup func() error, vendorID string, inHostNamespace bool) (resctrl.ResControlManager, error) {
err := setup()
if err != nil {
return &NoopManager{}, err
7 changes: 4 additions & 3 deletions resctrl/manager_test.go → resctrl/intel/manager_test.go
Original file line number Diff line number Diff line change
@@ -15,13 +15,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Manager tests.
package resctrl
// ResControlManager tests.
package intel

import (
"os"
"testing"

"github.com/google/cadvisor/resctrl"
"github.com/stretchr/testify/assert"
)

@@ -32,7 +33,7 @@ func TestNewManager(t *testing.T) {
enabledMBM bool
inHostNamespace bool
err string
expected Manager
expected resctrl.ResControlManager
}{
{
true,
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion resctrl/utils.go → resctrl/intel/utils.go
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
// limitations under the License.

// Utilities.
package resctrl
package intel

import (
"bufio"
2 changes: 1 addition & 1 deletion resctrl/utils_test.go → resctrl/intel/utils_test.go
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
// Mocked environment:
// - "container" first container with {1, 2, 3} processes.
// - "another" second container with {5, 6} processes.
package resctrl
package intel

import (
"fmt"