Add support for basic cgroup management

This commit is contained in:
Buddha Prakash 2016-06-20 22:03:59 -07:00
parent ef905c8125
commit a5ead79d43
4 changed files with 309 additions and 0 deletions

View File

@ -0,0 +1,113 @@
/*
Copyright 2016 The Kubernetes Authors 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 cm
import (
"fmt"
libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
)
// cgroupManagerImpl implements the CgroupManager interface.
// Its a stateless object which can be used to
// update,create or delete any number of cgroups
// It uses the Libcontainer raw fs cgroup manager for cgroup management.
type cgroupManagerImpl struct {
// subsystems holds information about all the
// mounted cgroup subsytems on the node
subsystems *cgroupSubsystems
}
// Make sure that cgroupManagerImpl implements the CgroupManager interface
var _ CgroupManager = &cgroupManagerImpl{}
// NewCgroupManager is a factory method that returns a CgroupManager
func NewCgroupManager(cs *cgroupSubsystems) CgroupManager {
return &cgroupManagerImpl{
subsystems: cs,
}
}
// Destroy destroys the specified cgroup
func (m *cgroupManagerImpl) Destroy(cgroupConfig *CgroupConfig) error {
//cgroup name
name := cgroupConfig.Name
// get the fscgroup Manager with the specified cgroup configuration
fsCgroupManager, err := getLibcontainerCgroupManager(cgroupConfig, m.subsystems)
if err != nil {
return fmt.Errorf("Unable to destroy cgroup paths for cgroup %v : %v", name, err)
}
// Delete cgroups using libcontainers Managers Destroy() method
if err := fsCgroupManager.Destroy(); err != nil {
return fmt.Errorf("Unable to destroy cgroup paths for cgroup %v : %v", name, err)
}
return nil
}
// Update updates the cgroup with the specified Cgroup Configuration
func (m *cgroupManagerImpl) Update(cgroupConfig *CgroupConfig) error {
//cgroup name
name := cgroupConfig.Name
// get the fscgroup Manager with the specified cgroup configuration
fsCgroupManager, err := getLibcontainerCgroupManager(cgroupConfig, m.subsystems)
if err != nil {
return fmt.Errorf("Failed to update cgroup for %v : %v", name, err)
}
// get config object for passing to Set()
config := &libcontainerconfigs.Config{
Cgroups: fsCgroupManager.Cgroups,
}
// Update cgroup configuration using libcontainers Managers Set() method
if err := fsCgroupManager.Set(config); err != nil {
return fmt.Errorf("Failed to update cgroup for %v: %v", name, err)
}
return nil
}
// Create creates the specified cgroup
func (m *cgroupManagerImpl) Create(cgroupConfig *CgroupConfig) error {
//cgroup name
name := cgroupConfig.Name
// get the fscgroup Manager with the specified cgroup configuration
fsCgroupManager, err := getLibcontainerCgroupManager(cgroupConfig, m.subsystems)
if err != nil {
return fmt.Errorf("Failed to create cgroup for %v : %v", name, err)
}
// get config object for passing to libcontainer's Set() method
config := &libcontainerconfigs.Config{
Cgroups: fsCgroupManager.Cgroups,
}
//Apply(0) is a hack to create the cgroup directories for each resource
// subsystem. The function [cgroups.Manager.apply()] applies cgroup
// configuration to the process with the specified pid.
// It creates cgroup files for each subsytems and writes the pid
// in the tasks file. We use the function to create all the required
// cgroup files but not attach any "real" pid to the cgroup.
if err := fsCgroupManager.Apply(0); err != nil {
return fmt.Errorf("Failed to create cgroup for %v: %v", name, err)
}
// Update cgroup configuration using libcontainers Managers Set() method
if err := fsCgroupManager.Set(config); err != nil {
return fmt.Errorf("Failed to create cgroup for %v: %v", name, err)
}
return nil
}

View File

@ -0,0 +1,42 @@
// +build !linux
/*
Copyright 2016 The Kubernetes Authors 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 cm
import "fmt"
type unsupportedCgroupManager struct{}
// Make sure that unsupportedCgroupManager implements the CgroupManager interface
var _ CgroupManager = &unsupportedCgroupManager{}
func NewCgroupManager(_ *cgroupSubsystems) CgroupManager {
return &unsupportedCgroupManager{}
}
func (m *unsupportedCgroupManager) Destroy(_ *CgroupConfig) error {
return nil
}
func (m *unsupportedCgroupManager) Update(_ *CgroupConfig) error {
return nil
}
func (m *unsupportedCgroupManager) Create(_ *CgroupConfig) error {
return fmt.Errorf("Cgroup Manager is not supported in this build")
}

View File

@ -0,0 +1,98 @@
/*
Copyright 2016 The Kubernetes Authors 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 cm
import (
"fmt"
"path"
libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
)
// cgroupSubsystems holds information about the mounted cgroup subsytems
type cgroupSubsystems struct {
// Cgroup subsystem mounts.
// e.g.: "/sys/fs/cgroup/cpu" -> ["cpu", "cpuacct"]
mounts []libcontainercgroups.Mount
// Cgroup subsystem to their mount location.
// e.g.: "cpu" -> "/sys/fs/cgroup/cpu"
mountPoints map[string]string
}
// GetCgroupSubsystems returns information about the mounted cgroup subsystems
func getCgroupSubsystems() (*cgroupSubsystems, error) {
// Get all cgroup mounts.
allCgroups, err := libcontainercgroups.GetCgroupMounts()
if err != nil {
return &cgroupSubsystems{}, err
}
if len(allCgroups) == 0 {
return &cgroupSubsystems{}, fmt.Errorf("failed to find cgroup mounts")
}
//TODO(@dubstack) should we trim to only the supported ones
mountPoints := make(map[string]string, len(allCgroups))
for _, mount := range allCgroups {
for _, subsystem := range mount.Subsystems {
mountPoints[subsystem] = mount.Mountpoint
}
}
return &cgroupSubsystems{
mounts: allCgroups,
mountPoints: mountPoints,
}, nil
}
// getLibcontainerCgroupManager returns libcontainer's cgroups manager
// object with the specified cgroup configuration
func getLibcontainerCgroupManager(cgroupConfig *CgroupConfig, subsystems *cgroupSubsystems) (*cgroupfs.Manager, error) {
// get cgroup name
name := cgroupConfig.Name
// Get map of all cgroup paths on the system for the particular cgroup
cgroupPaths := make(map[string]string, len(subsystems.mountPoints))
for key, val := range subsystems.mountPoints {
cgroupPaths[key] = path.Join(val, name)
}
// Extract the cgroup resource parameters
resourceConfig := cgroupConfig.ResourceParameters
resources := &libcontainerconfigs.Resources{}
resources.AllowAllDevices = true
if resourceConfig.Memory != nil {
resources.Memory = *resourceConfig.Memory
}
if resourceConfig.CpuShares != nil {
resources.CpuShares = *resourceConfig.CpuShares
}
if resourceConfig.CpuQuota != nil {
resources.CpuQuota = *resourceConfig.CpuQuota
}
// Initialize libcontainer's cgroup config
libcontainerCgroupConfig := &libcontainerconfigs.Cgroup{
Name: path.Base(name),
Parent: path.Dir(name),
Resources: resources,
}
return &cgroupfs.Manager{
Cgroups: libcontainerCgroupConfig,
Paths: cgroupPaths,
}, nil
}

56
pkg/kubelet/cm/types.go Normal file
View File

@ -0,0 +1,56 @@
/*
Copyright 2016 The Kubernetes Authors 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 cm
// ResourceConfig holds information about all the supported cgroup resource parameters.
type ResourceConfig struct {
// Memory limit (in bytes).
Memory *int64
// CPU shares (relative weight vs. other containers).
CpuShares *int64
// CPU hardcap limit (in usecs). Allowed cpu time in a given period.
CpuQuota *int64
}
// CgroupConfig holds the cgroup configuration information.
// This is common object which is used to specify
// cgroup information to both systemd and raw cgroup fs
// implementation of the Cgroup Manager interface.
type CgroupConfig struct {
// We would expect systemd implementation to make appropriate
// name conversion. For example, if we pass /foo/bar
// then systemd should convert the name to something like
// foo.slice/foo-bar.slice
// Fully qualified name
Name string
// ResourceParameters contains various cgroups settings to apply.
ResourceParameters *ResourceConfig
}
// CgroupManager allows for cgroup management.
// Supports Cgroup Creation ,Deletion and Updates.
type CgroupManager interface {
// Create creates and applies the cgroup configurations on the cgroup.
// It just creates the leaf cgroups.
// It expects the parent cgroup to already exist.
Create(*CgroupConfig) error
// Destroys the cgroup.
Destroy(*CgroupConfig) error
// Update cgroup configuration.
Update(*CgroupConfig) error
}